Add a neg<mode>cc expansion for integral comparisons on RISC-V. The expansion implements:
X ? -X : X as: CMP = condition ? 1 : 0 MASK = -CMP RESULT = X ^ MASK RESULT += CMP This pattern can be used by existing if-conversion paths. Use a separate pseudo for the XOR result so that the output pseudo is assigned only once. Signed-off-by: Naveen <[email protected]> --- gcc/config/riscv/riscv.md | 26 +++++++++++++++++++ .../gcc.target/riscv/pr126245-negcc.c | 16 ++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/pr126245-negcc.c diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 8420b3d29e7..2f4a3686b70 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -3504,6 +3504,32 @@ FAIL; }) +(define_expand "neg<mode>cc" + [(set (match_operand:GPR 0 "register_operand") + (if_then_else:GPR (match_operand 1 "comparison_operator") + (neg:GPR (match_operand:GPR 2 "register_operand")) + (match_operand:GPR 3 "register_operand")))] + "" +{ + rtx cmp = operands[1]; + rtx cmp0 = XEXP (cmp, 0); + rtx cmp1 = XEXP (cmp, 1); + + if (!INTEGRAL_MODE_P (GET_MODE (cmp0)) + || !rtx_equal_p (operands[2], operands[3])) + FAIL; + + rtx cmp_result = gen_reg_rtx (<MODE>mode); + riscv_expand_int_scc (cmp_result, GET_CODE (cmp), cmp0, cmp1); + + rtx mask = gen_reg_rtx (<MODE>mode); + riscv_emit_unary (NEG, mask, cmp_result); + rtx xor_result = gen_reg_rtx (<MODE>mode); + riscv_emit_binary (XOR, xor_result, operands[2], mask); + riscv_emit_binary (PLUS, operands[0], xor_result, cmp_result); + DONE; +}) + (define_expand "add<mode>cc" [(match_operand:GPR 0 "register_operand") (match_operand 1 "comparison_operator") diff --git a/gcc/testsuite/gcc.target/riscv/pr126245-negcc.c b/gcc/testsuite/gcc.target/riscv/pr126245-negcc.c new file mode 100644 index 00000000000..5b791323ee2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr126245-negcc.c @@ -0,0 +1,16 @@ +/* PR target/126245. Test the RISC-V negcc expander through if-conversion. */ +/* { dg-do compile { target { ! riscv_abi_e } } } */ +/* { dg-options "-O2 -march=rv64g -mabi=lp64d -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-O2 -march=rv32g -mabi=ilp32d -fdump-rtl-ce1" { target { rv32 } } } */ + +long +f_negcc (long x, long y) +{ + return x < y ? 42 : -42; +} + +/* { dg-final { scan-assembler-times {\mslt\M} 1 } } */ +/* { dg-final { scan-assembler-times {\m(?:xor|xori)\M} 1 } } */ +/* { dg-final { scan-assembler-times {\madd\M} 1 } } */ +/* { dg-final { scan-assembler-not {\m(?:beq|bne|blt|bge|ble|bgt)(?:u|z)?\M} } } */ +/* { dg-final { scan-rtl-dump-times {if-conversion succeeded through noce_try_inverse_constants} 1 "ce1" } } */ -- 2.34.1
