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 +*/
