Hi all, This patch improves codegen for expressions of the form: (x ? y + c1 : y + c2) when |c1 - c2| == 1
It matches the if_then_else of the two plus-immediates, performs one of them, then generates a conditional increment operation. Thus, for the code in the testcase we generate a single add, compare and cinc instruction rather than two adds, a compare and a csel. Bootstrapped and tested on aarch64. Ok for trunk? Thanks, Kyrill 2015-07-16 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * config/aarch64/aarch64.md (*csel_plus<mode>6): New define_insn_and_split. (*csinc2<mode>_insn): Rename to... (csinc2<mode>_insn): ... This. 2015-07-16 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * gcc.target/aarch64/cinc_common_1.c: New test.
commit a2dca37d3227ef4c9d3a8cc8277dd31529df74fd Author: Kyrylo Tkachov <kyrylo.tkac...@arm.com> Date: Tue Jul 14 10:33:04 2015 +0100 [AArch64] Use cinc for if_then_else of plus-immediates diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 381bb1d..39282b7 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -2843,6 +2843,48 @@ (define_expand "cmov<mode>6" " ) +/* Catch cases where we do: + add x2, x1, #n + add x3, x1, #(n + 1) + csel x4, x2, x3, cond + and transform it into: + add x2, x1, #n + cinc x4, x2, !cond. */ + +(define_insn_and_split "*csel_plus<mode>6" + [(set (match_operand:GPI 0 "register_operand" "=r") + (if_then_else:GPI + (match_operator 1 "aarch64_comparison_operator" + [(match_operand 2 "cc_register" "") (const_int 0)]) + (plus:GPI (match_operand:GPI 3 "aarch64_reg_or_imm" "r") + (match_operand:GPI 4 "aarch64_plus_immediate" "n")) + (plus:GPI (match_dup 3) + (match_operand:GPI 5 "aarch64_plus_immediate" "n"))))] + "optimize > 0 + && ((INTVAL (operands[4]) == INTVAL (operands[5]) + 1) + || (INTVAL (operands[5]) == INTVAL (operands[4]) + 1))" + "#" + "&& !reload_completed" + [(const_int 0)] + { + bool swap_p = INTVAL (operands[5]) > INTVAL (operands[4]); + enum rtx_code code = GET_CODE (operands[1]); + if (swap_p) + { + code = REVERSE_CONDITION (code, GET_MODE (operands[2])); + std::swap (operands[4], operands[5]); + } + + rtx tmp = gen_reg_rtx (<MODE>mode); + emit_insn (gen_add<mode>3 (tmp, operands[3], operands[5])); + rtx comp = gen_rtx_fmt_ee (code, VOIDmode, operands[2], const0_rtx); + + emit_insn (gen_csinc2<mode>_insn (operands[0], tmp, comp)); + DONE; + } +) + + (define_insn "*cmov<mode>_insn" [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r") (if_then_else:ALLI @@ -3030,7 +3072,7 @@ (define_insn "aarch64_<crc_variant>" [(set_attr "type" "crc")] ) -(define_insn "*csinc2<mode>_insn" +(define_insn "csinc2<mode>_insn" [(set (match_operand:GPI 0 "register_operand" "=r") (plus:GPI (match_operand 2 "aarch64_comparison_operation" "") (match_operand:GPI 1 "register_operand" "r")))] diff --git a/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c b/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c new file mode 100644 index 0000000..d041263 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cinc_common_1.c @@ -0,0 +1,64 @@ +/* { dg-do run } */ +/* { dg-options "-save-temps -O2 -fno-inline" } */ + +extern void abort (void); + +int +foosi (int x) +{ + return x > 100 ? x - 2 : x - 1; +} + +int +barsi (int x) +{ + return x > 100 ? x + 4 : x + 3; +} + +long +foodi (long x) +{ + return x > 100 ? x - 2 : x - 1; +} + +long +bardi (long x) +{ + return x > 100 ? x + 4 : x + 3; +} + +/* { dg-final { scan-assembler-times "cs?inc\tw\[0-9\]*" 2 } } */ +/* { dg-final { scan-assembler-times "cs?inc\tx\[0-9\]*" 2 } } */ + +int +main (void) +{ + if (foosi (105) != 103) + abort (); + + if (foosi (95) != 94) + abort (); + + if (barsi (105) != 109) + abort (); + + if (barsi (95) != 98) + abort (); + + if (foodi (105) != 103) + abort (); + + if (foodi (95) != 94) + abort (); + + if (bardi (105) != 109) + abort (); + + if (bardi (95) != 98) + abort (); + + return 0; +} + +/* { dg-final { scan-assembler-not "csel\tx\[0-9\]*.*" } } */ +/* { dg-final { scan-assembler-not "csel\tw\[0-9\]*.*" } } */