]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: add spaceship expanders
authorXi Ruoyao <xry111@xry111.site>
Sat, 2 May 2026 14:51:10 +0000 (22:51 +0800)
committerXi Ruoyao <xry111@xry111.site>
Fri, 15 May 2026 09:48:52 +0000 (17:48 +0800)
This helps to optimize certain nested ternary operation producing -1, 0,
or 1 to slt[u]-slt[u]-sub.

gcc/

* config/loongarch/loongarch.md (spaceship<mode>4): New
define_expand.

gcc/testsuite/

* gcc.target/loongarch/la64/spaceship.c: New test.

gcc/config/loongarch/loongarch.md
gcc/testsuite/gcc.target/loongarch/la64/spaceship.c [new file with mode: 0644]

index 35a53dd0773f921bdb6fd0e47be100e65c8af97a..32d837d1e2dabacb13d1b7a04a9bdbf33f81ce72 100644 (file)
   [(set_attr "type" "slt")
    (set_attr "mode" "<X:MODE>")])
 
+(define_expand "spaceship<mode>4"
+  [(match_operand:SI   0 "register_operand")
+   (match_operand:QHWD 1 "register_operand")
+   (match_operand:QHWD 2 "reg_or_0_operand")
+   (match_operand:SI   3 "const_int_operand")]
+  ""
+{
+  gcc_assert (operands[3] == const1_rtx || operands[3] == constm1_rtx);
+
+  if (GET_MODE_SIZE (<MODE>mode) < GET_MODE_SIZE (word_mode))
+    {
+      auto extend = (operands[3] == const1_rtx ? ZERO_EXTEND
+                                              : SIGN_EXTEND);
+      for (int i: {1, 2})
+       if (operands[i] != const0_rtx)
+         operands[i] = force_reg (word_mode,
+                                  gen_rtx_fmt_e (extend, word_mode,
+                                                 operands[i]));
+    }
+
+  auto lt_code = (operands[3] == const1_rtx ? LTU : LT);
+  auto gt_code = (operands[3] == const1_rtx ? GTU : GT);
+  rtx lt = gen_rtx_fmt_ee (lt_code, word_mode, operands[1], operands[2]);
+  rtx gt = gen_rtx_fmt_ee (gt_code, word_mode, operands[1], operands[2]);
+
+  gt = force_reg (word_mode, gt);
+  lt = force_reg (word_mode, lt);
+
+  rtx diff = gen_rtx_MINUS (word_mode, gt, lt);
+  if (TARGET_64BIT)
+    {
+      diff = force_reg (DImode, diff);
+      diff = gen_lowpart (SImode, diff);
+      SUBREG_PROMOTED_VAR_P (diff) = 1;
+      SUBREG_PROMOTED_SET (diff, SRP_SIGNED);
+    }
+
+  emit_move_insn (operands[0], diff);
+  DONE;
+})
+
 \f
 ;;
 ;;  ....................
diff --git a/gcc/testsuite/gcc.target/loongarch/la64/spaceship.c b/gcc/testsuite/gcc.target/loongarch/la64/spaceship.c
new file mode 100644 (file)
index 0000000..0c2f891
--- /dev/null
@@ -0,0 +1,79 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define TEST(T) \
+  int test_##T(T a, T b) \
+    { return (a == b) ? 0 : (a < b) ? -1 : 1; } \
+  int test_u##T(unsigned T a, unsigned T b) \
+    { return (a == b) ? 0 : (a < b) ? -1 : 1; }
+
+TEST(char)
+TEST(short)
+TEST(int)
+TEST(long)
+
+/*
+** test_char:
+**     slt     .*
+**     slt     .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_uchar:
+**     sltu    .*
+**     sltu    .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_short:
+**     slt     .*
+**     slt     .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_ushort:
+**     sltu    .*
+**     sltu    .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_int:
+**     slt     .*
+**     slt     .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_uint:
+**     bstrpick\.d     .*,31,0
+**     bstrpick\.d     .*,31,0
+**     sltu    .*
+**     sltu    .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_long:
+**     slt     .*
+**     slt     .*
+**     sub\.d  .*
+**     jr      \$r1
+*/
+
+/*
+** test_ulong:
+**     sltu    .*
+**     sltu    .*
+**     sub\.d  .*
+**     jr      \$r1
+*/