Hi all, Currently the functions: int f1(int x, int t) { if (x == -1 || x == -2) t = 1; return t; }
int f2(int x, int t) { if (x == -1 || x == -2) return 1; return t; } generate different code on AArch64 even though they have identical functionality: f1: add w0, w0, 2 cmp w0, 1 csinc w0, w1, wzr, hi ret f2: cmn w0, #2 csinc w0, w1, wzr, cc ret The problem is that f2 performs the comparison (LTU w0 -2) whereas f1 performs (GTU (PLUS w0 2) 1). I think it is possible to simplify the f1 form to the f2 form with the simplify-rtx.c rule added in this patch. With this patch the codegen for both f1 and f2 on aarch64 at -O2 is identical (CMN, CSINC). Bootstrapped and tested on arm-none-linux-gnueabihf, aarch64-none-linux-gnu, x86_64. What do you think? Is this a correct generalisation of this issue? If so, ok for trunk? Thanks, Kyrill 2016-09-16 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * simplify-rtx.c (simplify_relational_operation_1): Add transformation (GTU (PLUS a C) (C - 1)) --> (LTU a -C). 2016-09-16 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * gcc.target/aarch64/gtu_to_ltu_cmp_1.c: New test.
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 14302ea06eccc099ef356ab6c63ac020dd083b0c..4153c7335680068ed3ce08410400ac6abaf30c89 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -4663,6 +4663,19 @@ simplify_relational_operation_1 (enum rtx_code code, machine_mode mode, cmp_mode, XEXP (op0, 0), new_cmp); } + /* (GTU (PLUS a C) (C - 1)) where C is a non-zero constant can be + transformed into (LTU a -C). */ + if (code == GTU && GET_CODE (op0) == PLUS && CONST_INT_P (op1) + && CONST_INT_P (XEXP (op0, 1)) + && (UINTVAL (op1) == UINTVAL (XEXP (op0, 1)) - 1) + && XEXP (op0, 1) != const0_rtx) + { + rtx new_cmp + = simplify_gen_unary (NEG, cmp_mode, XEXP (op0, 1), cmp_mode); + return simplify_gen_relational (LTU, mode, cmp_mode, + XEXP (op0, 0), new_cmp); + } + /* Canonicalize (LTU/GEU (PLUS a b) b) as (LTU/GEU (PLUS a b) a). */ if ((code == LTU || code == GEU) && GET_CODE (op0) == PLUS diff --git a/gcc/testsuite/gcc.target/aarch64/gtu_to_ltu_cmp_1.c b/gcc/testsuite/gcc.target/aarch64/gtu_to_ltu_cmp_1.c new file mode 100644 index 0000000000000000000000000000000000000000..81c536c90afe38932c48ed0af24f55e73eeff80e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/gtu_to_ltu_cmp_1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int +f1 (int x, int t) +{ + if (x == -1 || x == -2) + t = 1; + + return t; +} + +/* { dg-final { scan-assembler-times "cmn\\tw\[0-9\]+, #2" 1 } } */