Add new template muldi3_ui12 for mul(reg, ui12), which mode is DImode
and op2 is const_uns_arith_operand. And the template is matched when
the mul operation can not be optimized, such as slli, alsl et.
gcc/ChangeLog:
* config/loongarch/loongarch-protos.h
(loongarch_scalar_uimult_p): Func declaration.
* config/loongarch/loongarch.cc (loongarch_scalar_uimult_p):
Check func for new template.
* config/loongarch/loongarch.md (muldi3_ui12): New template.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/muld_d_ui12_1.c: New test.
* gcc.target/loongarch/muld_d_ui12_2.c: New test.
---
gcc/config/loongarch/loongarch-protos.h | 1 +
gcc/config/loongarch/loongarch.cc | 35 +++++++++++++++++++
gcc/config/loongarch/loongarch.md | 18 ++++++++++
.../gcc.target/loongarch/muld_d_ui12_1.c | 21 +++++++++++
.../gcc.target/loongarch/muld_d_ui12_2.c | 23 ++++++++++++
5 files changed, 98 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/loongarch/muld_d_ui12_1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/muld_d_ui12_2.c
diff --git a/gcc/config/loongarch/loongarch-protos.h
b/gcc/config/loongarch/loongarch-protos.h
index a84b708cc28..b564195e0ac 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -150,6 +150,7 @@ extern const char *loongarch_output_probe_stack_range (rtx,
rtx, rtx);
extern bool loongarch_hard_regno_rename_ok (unsigned int, unsigned int);
extern int loongarch_dspalu_bypass_p (rtx, rtx);
extern rtx loongarch_prefetch_cookie (rtx, rtx);
+extern bool loongarch_scalar_uimult_p (machine_mode, rtx, rtx);
extern bool loongarch_global_symbol_p (const_rtx);
extern bool loongarch_global_symbol_noweak_p (const_rtx);
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index fcca0ec8252..c5387aa39f0 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "function-abi.h"
#include "cfgloop.h"
#include "tree-vectorizer.h"
+#include "expmed.h"
/* This file should be included last. */
#include "target-def.h"
@@ -12098,6 +12099,40 @@ loongarch_option_same_function_versions (string_slice
str1, string_slice str2)
return feature_mask1 == feature_mask2;
}
+/* Check if the multiplication operation can be simplified, where op1 is
+ an 12bit unsigned integer. */
+bool
+loongarch_scalar_uimult_p (machine_mode mode, rtx op0, rtx op1)
+{
+ if (flag_trapv || !SCALAR_INT_MODE_P (mode))
+ return false;
+
+ /* Swap the two operands if OP0 would be constant. */
+ if (CONSTANT_P (op0))
+ std::swap (op0, op1);
+
+ HOST_WIDE_INT coeff = INTVAL (op1);
+ if (coeff < 0
+ || op1 == CONST0_RTX (mode) || op1 == CONST1_RTX (mode))
+ return true;
+
+ bool speed = optimize_insn_for_speed_p ();
+ int mode_bitsize = GET_MODE_UNIT_BITSIZE (mode);
+
+ /* Special case powers of two. */
+ if (pow2p_hwi (coeff)
+ && mode_bitsize <= HOST_BITS_PER_WIDE_INT)
+ return true;
+
+ enum mult_variant variant;
+ struct algorithm algorithm;
+ int max_cost = set_src_cost (gen_rtx_MULT (mode, op0, op1), mode, speed);
+ if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost))
+ return true;
+
+ return false;
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
diff --git a/gcc/config/loongarch/loongarch.md
b/gcc/config/loongarch/loongarch.md
index e23c973c38b..ca23306b76e 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -893,6 +893,24 @@ (define_insn "mulsi3_extend"
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
+(define_insn_and_split "muldi3_ui12"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "const_uns_arith_operand" "K")))]
+ "TARGET_64BIT && !flag_trapv
+ && loongarch_pre_reload_split ()
+ && !loongarch_scalar_uimult_p (E_DImode, operands[1], operands[2])"
+ "#"
+ "TARGET_64BIT && !flag_trapv && loongarch_pre_reload_split ()"
+ [(set (match_dup 3) (match_dup 2))
+ (set (match_dup 0) (mult:DI (match_dup 1) (match_dup 3)))]
+ {
+ operands[3] = gen_reg_rtx (DImode);
+ }
+ [(set_attr "type" "imul")
+ (set_attr "mode" "DI")]
+)
+
;;
;; ........................
;;
diff --git a/gcc/testsuite/gcc.target/loongarch/muld_d_ui12_1.c
b/gcc/testsuite/gcc.target/loongarch/muld_d_ui12_1.c
new file mode 100644
index 00000000000..11bb28dc83b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/muld_d_ui12_1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-cse1 -fdump-rtl-split1" } */
+
+struct LEN_744
+{
+ int arr1[100];
+ int arr2[80];
+ int arr3[6];
+};
+
+struct LEN_744 TEST_STRUCT[20];
+
+int
+foo (int index1, int index2)
+{
+ return TEST_STRUCT[index1].arr2[index2];
+}
+
+/* { dg-final { scan-rtl-dump "muldi3_ui12" "cse1" } } */
+/* { dg-final { scan-rtl-dump-not "muldi3_ui12" "split1" } } */
+/* { dg-final { scan-assembler "mul.d" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/muld_d_ui12_2.c
b/gcc/testsuite/gcc.target/loongarch/muld_d_ui12_2.c
new file mode 100644
index 00000000000..02022618da7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/muld_d_ui12_2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct LEN_744
+{
+ int arr1[100];
+ int arr2[80];
+ int arr3[4];
+ int s1;
+ int s2;
+};
+
+struct LEN_744 TEST_STRUCT[20];
+
+void
+foo (int index, int data)
+{
+ if (TEST_STRUCT[index].s1 < data)
+ TEST_STRUCT[index].s2 = data;
+ TEST_STRUCT[index].s1++;
+}
+
+/* { dg-final { scan-assembler-times "mul.d" 1 } } */
--
2.34.1