https://gcc.gnu.org/g:8535b42901bd772896fe4989efe5741ba5fc4bb9

commit r17-528-g8535b42901bd772896fe4989efe5741ba5fc4bb9
Author: Xi Ruoyao <[email protected]>
Date:   Sat May 2 22:51:10 2026 +0800

    LoongArch: add spaceship expanders
    
    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.

Diff:
---
 gcc/config/loongarch/loongarch.md                  | 41 +++++++++++
 .../gcc.target/loongarch/la64/spaceship.c          | 79 ++++++++++++++++++++++
 2 files changed, 120 insertions(+)

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index 35a53dd0773f..32d837d1e2da 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -3823,6 +3823,47 @@
   [(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;
+})
+
 
 ;;
 ;;  ....................
diff --git a/gcc/testsuite/gcc.target/loongarch/la64/spaceship.c 
b/gcc/testsuite/gcc.target/loongarch/la64/spaceship.c
new file mode 100644
index 000000000000..0c2f891b58a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/la64/spaceship.c
@@ -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
+*/

Reply via email to