When TARGET_SALT is configured in the Xtensa ISA, a Boolean evaluation of
LT/GT[U] between address (GP) registers can be done in a single machine
instruction, making it easy to implement the spaceship operator by sub-
tracting one from the other result.

    /* examples */
    int test0(int a, int b) {
      return a == b ? 0 : (a > b ? 1 : -1);
    }
    int test1(unsigned int a, unsigned int b) {
      return a == b ? 0 : (a > b ? 1 : -1);
    }

    ;; before (-msalt)
    test0:
        entry   sp, 32
        mov.n   a8, a2
        movi.n  a2, 0
        beq     a8, a3, .L1
        movi.n  a2, -1
        bge     a3, a8, .L1
        movi.n  a2, 1
    .L1:
        retw.n
    test1:
        entry   sp, 32
        mov.n   a8, a2
        movi.n  a2, 0
        beq     a8, a3, .L6
        movi.n  a2, -1
        bgeu    a3, a8, .L6
        movi.n  a2, 1
    .L6:
        retw.n

    ;; after (-msalt)
    test0:
        entry   sp, 32
        salt    a8, a2, a3
        salt    a2, a3, a2
        sub     a2, a2, a8
        retw.n
    test1:
        entry   sp, 32
        saltu   a8, a2, a3
        saltu   a2, a3, a2
        sub     a2, a2, a8
        retw.n

gcc/ChangeLog:

        * config/xtensa/xtensa.md (spaceshipsi4):
        New RTL generation pattern.
---
 gcc/config/xtensa/xtensa.md | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 1e52bba1a46..639a5788cb3 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -2315,6 +2315,23 @@
    (set_attr "mode"  "SI")
    (set_attr "length"        "3")])
+(define_expand "spaceshipsi4"
+  [(match_operand:SI 0 "register_operand")
+   (match_operand:SI 1 "register_operand")
+   (match_operand:SI 2 "register_operand")
+   (match_operand:SI 3 "const_int_operand")]
+  "TARGET_SALT"
+{
+  rtx (*gen_op)(rtx, rtx, rtx);
+  rtx temp0, temp1;
+  gcc_assert (operands[3] == const1_rtx || operands[3] == constm1_rtx);
+  gen_op = (operands[3] == const1_rtx) ? gen_saltu : gen_salt;
+  emit_insn (gen_op (temp0 = gen_reg_rtx (SImode), operands[1], operands[2]));
+  emit_insn (gen_op (temp1 = gen_reg_rtx (SImode), operands[2], operands[1]));
+  emit_insn (gen_subsi3 (operands[0], temp1, temp0));
+  DONE;
+})
+
 (define_expand "cstoresf4"
   [(match_operand:SI 0 "register_operand")
    (match_operator:SI 1 "comparison_operator"
--
2.39.5

Reply via email to