The original implementation of the function loongarch_extend_comparands
only prevented op1 from being loaded into the register when op1 was
const0_rtx.  It has now been modified so that op1 is not loaded into
the register as long as op1 is an immediate value.  This allows
slt{u}i to be generated instead of slt{u} if the conditions are met.

gcc/ChangeLog:

        * config/loongarch/loongarch.cc
        (loongarch_canonicalize_int_order_test): Support GT GTU LT
        and LTU.
        (loongarch_extend_comparands): Expand the scope of op1 from
        0 to all immediate values.
        * config/loongarch/loongarch.md
        (*sge<u>_<X:mode><GPR:mode>): New template.

gcc/testsuite/ChangeLog:

        * gcc.target/loongarch/sign-extend-3.c: New test.

---
 gcc/config/loongarch/loongarch.cc             | 39 +++++++++++++------
 gcc/config/loongarch/loongarch.md             | 10 +++++
 .../gcc.target/loongarch/sign-extend-3.c      | 29 ++++++++++++++
 3 files changed, 66 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/sign-extend-3.c

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index d11fe496a01..064b251f9ca 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -5276,29 +5276,41 @@ loongarch_canonicalize_int_order_test (enum rtx_code 
*code, rtx *cmp1,
   if (loongarch_int_order_operand_ok_p (*code, *cmp1))
     return true;
 
-  if (CONST_INT_P (*cmp1))
     switch (*code)
       {
       case LE:
-       plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
-       if (INTVAL (*cmp1) < plus_one)
+       if (CONST_INT_P (*cmp1))
          {
-           *code = LT;
-           *cmp1 = force_reg (mode, GEN_INT (plus_one));
-           return true;
+           plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
+           if (INTVAL (*cmp1) < plus_one)
+             {
+               *code = LT;
+               *cmp1 = force_reg (mode, GEN_INT (plus_one));
+               return true;
+             }
          }
        break;
 
       case LEU:
-       plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
-       if (plus_one != 0)
+       if (CONST_INT_P (*cmp1))
          {
-           *code = LTU;
-           *cmp1 = force_reg (mode, GEN_INT (plus_one));
-           return true;
+           plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
+           if (plus_one != 0)
+             {
+               *code = LTU;
+               *cmp1 = force_reg (mode, GEN_INT (plus_one));
+               return true;
+             }
          }
        break;
 
+      case GT:
+      case GTU:
+      case LT:
+      case LTU:
+       *cmp1 = force_reg (mode, *cmp1);
+       break;
+
       default:
        break;
       }
@@ -5393,7 +5405,10 @@ loongarch_extend_comparands (rtx_code code, rtx *op0, 
rtx *op1)
       else
        {
          *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0);
-         if (*op1 != const0_rtx)
+         /* Regardless of whether *op1 is any immediate number, it is not
+            loaded into the register, in order to facilitate the generation
+            of slt{u}i.  */
+         if (!CONST_INT_P (*op1))
            *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1);
        }
     }
diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index 2f4817d885c..2bf63b5b008 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -518,6 +518,7 @@ (define_code_iterator equality_op [eq ne])
 
 ;; These code iterators allow the signed and unsigned scc operations to use
 ;; the same template.
+(define_code_iterator any_ge [ge geu])
 (define_code_iterator any_gt [gt gtu])
 (define_code_iterator any_lt [lt ltu])
 (define_code_iterator any_le [le leu])
@@ -3528,6 +3529,15 @@ (define_insn "*sne_zero_<X:mode><GPR:mode>"
   [(set_attr "type" "slt")
    (set_attr "mode" "<X:MODE>")])
 
+(define_insn "*sge<u>_<X:mode><GPR:mode>"
+  [(set (match_operand:GPR           0 "register_operand" "=r")
+       (any_ge:GPR (match_operand:X 1 "register_operand" " r")
+                   (const_int 1)))]
+  ""
+  "slti<u>\t%0,zero,%1"
+  [(set_attr "type" "slt")
+   (set_attr "mode" "<X:MODE>")])
+
 (define_insn "*sgt<u>_<X:mode><GPR:mode>"
   [(set (match_operand:GPR 0 "register_operand" "=r")
        (any_gt:GPR (match_operand:X 1 "register_operand" "r")
diff --git a/gcc/testsuite/gcc.target/loongarch/sign-extend-3.c 
b/gcc/testsuite/gcc.target/loongarch/sign-extend-3.c
new file mode 100644
index 00000000000..d20bd38486f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/sign-extend-3.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler "sltui" } } */
+
+union any {
+  int any_i32;
+};
+
+extern char *opname;
+extern void test1 (int, char *);
+extern int iterms;
+
+void
+test (union any cv)
+{
+  int i, on;
+  int ix = cv.any_i32;
+  for (i = 1; i < iterms; i++)
+    {
+      on = (ix == 0 || ix == 1) ? 0 : 1;
+      if (*opname == '!')
+       {
+         on = !on;
+         ++opname;
+       }
+      test1 (on, opname);
+    }
+}
+
-- 
2.34.1

Reply via email to