]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Implement sge and sgeu.
authorLulu Cheng <chenglulu@loongson.cn>
Thu, 12 Dec 2024 08:21:38 +0000 (16:21 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Fri, 7 Nov 2025 01:21:37 +0000 (09:21 +0800)
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
gcc/config/loongarch/loongarch.md
gcc/testsuite/gcc.target/loongarch/sign-extend-3.c [new file with mode: 0644]

index 4e53635a7b983756b5703e6025ddf5f18956656b..4a9604eb1eb079dff18edfc2c72f69526175b09d 100644 (file)
@@ -5289,29 +5289,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;
       }
@@ -5406,7 +5418,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);
        }
     }
index ba668880ba560c49a6e1c31b0b36d9b72aa279e6..e23c973c38b2c5cd735ee1055f09e3d45d862066 100644 (file)
 
 ;; 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])
   [(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 (file)
index 0000000..d20bd38
--- /dev/null
@@ -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);
+    }
+}
+