diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-05 10:57:52 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-05 10:59:00 +0100 |
commit | 4615cde5d7ef281d4b554df411f82ad707f0a54d (patch) | |
tree | 69005f7b86e4e76b7fed0153ad53bb708f0966a6 | |
parent | 6b69738c1e30ec31cb11dce1d9209e7a5b92301b (diff) | |
download | gcc-4615cde5d7ef281d4b554df411f82ad707f0a54d.zip gcc-4615cde5d7ef281d4b554df411f82ad707f0a54d.tar.gz gcc-4615cde5d7ef281d4b554df411f82ad707f0a54d.tar.bz2 |
simplify-rtx: Optimize (x - 1) * y + y [PR98334]
We don't try to optimize for signed x, y (int) (x - 1U) * y + y
into x * y, we can't do that with signed x * y, because the former
is well defined for INT_MIN and -1, while the latter is not.
We could perhaps optimize it during isel or some very late optimization
where we'd turn magically flag_wrapv, but we don't do that yet.
This patch optimizes it in simplify-rtx.c, such that we can optimize
it during combine.
2021-01-05 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/98334
* simplify-rtx.c (simplify_context::simplify_binary_operation_1):
Optimize (X - 1) * Y + Y to X * Y or (X + 1) * Y - Y to X * Y.
* gcc.target/i386/pr98334.c: New test.
-rw-r--r-- | gcc/simplify-rtx.c | 56 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr98334.c | 36 |
2 files changed, 92 insertions, 0 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index e041b8e..571e233 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2602,6 +2602,42 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return (set_src_cost (tem, int_mode, speed) <= set_src_cost (orig, int_mode, speed) ? tem : 0); } + + /* Optimize (X - 1) * Y + Y to X * Y. */ + lhs = op0; + rhs = op1; + if (GET_CODE (op0) == MULT) + { + if (((GET_CODE (XEXP (op0, 0)) == PLUS + && XEXP (XEXP (op0, 0), 1) == constm1_rtx) + || (GET_CODE (XEXP (op0, 0)) == MINUS + && XEXP (XEXP (op0, 0), 1) == const1_rtx)) + && rtx_equal_p (XEXP (op0, 1), op1)) + lhs = XEXP (XEXP (op0, 0), 0); + else if (((GET_CODE (XEXP (op0, 1)) == PLUS + && XEXP (XEXP (op0, 1), 1) == constm1_rtx) + || (GET_CODE (XEXP (op0, 1)) == MINUS + && XEXP (XEXP (op0, 1), 1) == const1_rtx)) + && rtx_equal_p (XEXP (op0, 0), op1)) + lhs = XEXP (XEXP (op0, 1), 0); + } + else if (GET_CODE (op1) == MULT) + { + if (((GET_CODE (XEXP (op1, 0)) == PLUS + && XEXP (XEXP (op1, 0), 1) == constm1_rtx) + || (GET_CODE (XEXP (op1, 0)) == MINUS + && XEXP (XEXP (op1, 0), 1) == const1_rtx)) + && rtx_equal_p (XEXP (op1, 1), op0)) + rhs = XEXP (XEXP (op1, 0), 0); + else if (((GET_CODE (XEXP (op1, 1)) == PLUS + && XEXP (XEXP (op1, 1), 1) == constm1_rtx) + || (GET_CODE (XEXP (op1, 1)) == MINUS + && XEXP (XEXP (op1, 1), 1) == const1_rtx)) + && rtx_equal_p (XEXP (op1, 0), op0)) + rhs = XEXP (XEXP (op1, 1), 0); + } + if (lhs != op0 || rhs != op1) + return simplify_gen_binary (MULT, int_mode, lhs, rhs); } /* (plus (xor X C1) C2) is (xor X (C1^C2)) if C2 is signbit. */ @@ -2789,6 +2825,26 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return (set_src_cost (tem, int_mode, speed) <= set_src_cost (orig, int_mode, speed) ? tem : 0); } + + /* Optimize (X + 1) * Y - Y to X * Y. */ + lhs = op0; + if (GET_CODE (op0) == MULT) + { + if (((GET_CODE (XEXP (op0, 0)) == PLUS + && XEXP (XEXP (op0, 0), 1) == const1_rtx) + || (GET_CODE (XEXP (op0, 0)) == MINUS + && XEXP (XEXP (op0, 0), 1) == constm1_rtx)) + && rtx_equal_p (XEXP (op0, 1), op1)) + lhs = XEXP (XEXP (op0, 0), 0); + else if (((GET_CODE (XEXP (op0, 1)) == PLUS + && XEXP (XEXP (op0, 1), 1) == const1_rtx) + || (GET_CODE (XEXP (op0, 1)) == MINUS + && XEXP (XEXP (op0, 1), 1) == constm1_rtx)) + && rtx_equal_p (XEXP (op0, 0), op1)) + lhs = XEXP (XEXP (op0, 1), 0); + } + if (lhs != op0) + return simplify_gen_binary (MULT, int_mode, lhs, op1); } /* (a - (-b)) -> (a + b). True even for IEEE. */ diff --git a/gcc/testsuite/gcc.target/i386/pr98334.c b/gcc/testsuite/gcc.target/i386/pr98334.c new file mode 100644 index 0000000..283abc5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr98334.c @@ -0,0 +1,36 @@ +/* PR rtl-optimization/98334 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -fno-stack-protector" } */ +/* { dg-final { scan-assembler-not "\taddl\t" } } */ +/* { dg-final { scan-assembler-not "\tsubl\t" } } */ +/* { dg-final { scan-assembler-not "\tleal\t" } } */ + +int +foo (int i, unsigned int n) +{ + int result = 0; + while (n > 0) + { + result += i; + n -= 1; + } + return result; +} + +int +bar (int x, int y) +{ + return (int) (y - 1U) * x + x; +} + +int +baz (int x, int y) +{ + return (y - 1) * x + x; +} + +int +qux (int x, int y) +{ + return x * (int) (y + 1U) - x; +} |