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

Reply via email to