diff options
author | Andrew Pinski <quic_apinski@quicinc.com> | 2024-09-30 16:44:44 +0000 |
---|---|---|
committer | Andrew Pinski <quic_apinski@quicinc.com> | 2024-10-01 07:09:35 -0700 |
commit | 698e0ec89bc0960e074d2222208bffe47f5addd9 (patch) | |
tree | 3e524dc0fadc73f9745f8af66f99399b11859566 | |
parent | 8273e31adfa1ba5f0722eb37bcc8aeca8718a472 (diff) | |
download | gcc-698e0ec89bc0960e074d2222208bffe47f5addd9.zip gcc-698e0ec89bc0960e074d2222208bffe47f5addd9.tar.gz gcc-698e0ec89bc0960e074d2222208bffe47f5addd9.tar.bz2 |
phi-opt: Improve factor heurstic with constants and conversions from bool [PR116890]
Take:
```
if (t_3(D) != 0)
goto <bb 3>;
else
goto <bb 4>;
<bb 3>
_8 = c_4(D) != 0;
_9 = (int) _8;
<bb 4>
# e_2 = PHI <_9(3), 0(2)>
```
We should factor out the conversion here as that will allow a simplfication to
`(t_3 != 0) & (c_4 != 0)`. Unlike most other types; `a ? b : CST` will simplify
for boolean result type to either `a | b` or `a & b` so allowing this conversion
for all operations will be always profitable.
Bootstrapped and tested on x86_64-linux-gnu with no regressions.
Note on the phi-opt-7.c testcase change, we are now able to optimize this
and remove the if due to the factoring out now so this is an improvement.
PR tree-optimization/116890
gcc/ChangeLog:
* tree-ssa-phiopt.cc (factor_out_conditional_operation): Conversions
from bool is also should be considered as wanting to happen.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/phi-opt-7.c: Update testcase for no ifs left.
* gcc.dg/tree-ssa/phi-opt-42.c: New test.
* gcc.dg/tree-ssa/phi-opt-43.c: New test.
Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/phi-opt-42.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/phi-opt-43.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-phiopt.cc | 10 |
4 files changed, 50 insertions, 4 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-42.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-42.c new file mode 100644 index 0000000..6255694 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-42.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* PR tree-optimization/116890 */ + +int f(int a, int b, int c) +{ + int x; + if (c) x = a == 0; + else x = 0; + return x; +} + + +/* The if should have been removed as the the conversion from bool to int should have been factored out. */ +/* { dg-final { scan-tree-dump-not "if" "optimized" } }*/ +/* { dg-final { scan-tree-dump-times "\[^\r\n\]*_\[0-9\]* = a_\[0-9\]*.D. == 0" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\r\n\]*_\[0-9\]* = c_\[0-9\]*.D. != 0" 1 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-43.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-43.c new file mode 100644 index 0000000..1d16f28 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-43.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* PR tree-optimization/116890 */ + +int f(_Bool a, _Bool b, int c) +{ + int x; + if (c) x = a & b; + else x = 0; + return x; +} + + +/* The if should have been removed as the the conversion from bool to int should have been factored out. */ +/* { dg-final { scan-tree-dump-not "if" "optimized" } }*/ +/* { dg-final { scan-tree-dump-times "\[^\r\n\]*_\[0-9\]* = a_\[0-9\]*.D. & b_\[0-9\]*.D." 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\r\n\]*_\[0-9\]* = c_\[0-9\]*.D. != 0" 1 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c index 51e1f6d..3ee43e5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c @@ -15,8 +15,8 @@ int f(int t, int c) return g(d,e); } -/* There should be one ifs as one of them should be changed into - a conditional and the other should be there still. */ -/* { dg-final { scan-tree-dump-times "if" 1 "optimized" } }*/ +/* There should be no ifs as this is converted into `(t != 0) & (c != 0)`. +/* { dg-final { scan-tree-dump-not "if" "optimized" } }*/ /* { dg-final { scan-tree-dump-times "\[^\r\n\]*_\[0-9\]* = c_\[0-9\]*.D. != 0" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\r\n\]*_\[0-9\]* = t_\[0-9\]*.D. != 0" 1 "optimized" } } */ diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index d43832b..bd7f960 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -345,9 +345,17 @@ factor_out_conditional_operation (edge e0, edge e1, gphi *phi, if (gassign *assign = dyn_cast <gassign *> (stmt)) { tree lhs = gimple_assign_lhs (assign); + tree lhst = TREE_TYPE (lhs); enum tree_code ass_code = gimple_assign_rhs_code (assign); - if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) + if (ass_code != MAX_EXPR && ass_code != MIN_EXPR + /* Conversions from boolean like types is ok + as `a?1:b` and `a?0:b` will always simplify + to `a & b` or `a | b`. + See PR 116890. */ + && !(INTEGRAL_TYPE_P (lhst) + && TYPE_UNSIGNED (lhst) + && TYPE_PRECISION (lhst) == 1)) return NULL; if (lhs != gimple_assign_rhs1 (arg0_def_stmt)) return NULL; |