The following three functions should result in the same assembly (the last is the best, branchless and only does one compare): int f(int i, int j, int l) { int k = 0; if (i) k = 1; if (j) k = 1; if (l) k = 1; return k; } int f1(int i, int j, int l) { int k = 0; if (i) k = 1; else if (j) k = 1; else if (l) k = 1; return k; } int f2(int i, int j, int l) { return i||j||l; } Note I came up with this testcase after adding code like the above code to gcc and I was wondering how we optimizated it.
Confirmed.
I will take care of this one too.
Here is another testcase which should produce the same code: int f3(int i, int j, int l) { int t = i | j; _Bool t1 = l != 0; _Bool t2 = t ? 1 : t1; return t2; } int f4(int i, int j, int l) { int t = i | j; _Bool t1 = l != 0; _Bool t2; if (t) t2 = 1; else t2 = t1; return t2; } --- CUT ---- Note f1, f2, f3 and f4 all produce the same code now. f comes close now, but still requires work: orr w0, w0, w1 cmp w0, 0 cset w0, ne cmp w2, 0 csinc w0, w0, wzr, eq it does an ifcvt on the rtl level to get the csinc. f4 is exactly what f2 looks like at the .optimized as the input to the gimple and reassoc can optimize this case but only if we sink l != 0 into the if statement. So this is another improvement needed for reassoc really. I will look at this next week or the week after.
Take f4, if we compile with -O1 -fno-tree-sink, you will see the behavior we get for f.
Looks like only f is broken now. in phiopt3: _8 = i_4(D) != 0; _9 = (int) _8; if (j_5(D) != 0) goto <bb 3>; [50.00%] else goto <bb 4>; [50.00%] <bb 3> [local count: 536870913]: <bb 4> [local count: 1073741824]: # k_2 = PHI <_9(2), 1(3)> if (l_6(D) != 0) goto <bb 5>; [50.00%] else goto <bb 6>; [50.00%] <bb 5> [local count: 536870913]: <bb 6> [local count: 1073741824]: # k_3 = PHI <k_2(4), 1(5)> Hmm, this looks like it could be fixed with PR 96923. I will test it again once I fix that one.
The patch simple which fixes PR 89263.
Patch submitted: https://gcc.gnu.org/pipermail/gcc-patches/2023-June/620829.html
The trunk branch has been updated by Andrew Pinski <pinskia@gcc.gnu.org>: https://gcc.gnu.org/g:64d90d06d2db43538c8a45adbb3d74842f7868ae commit r14-1597-g64d90d06d2db43538c8a45adbb3d74842f7868ae Author: Andrew Pinski <apinski@marvell.com> Date: Wed May 24 07:08:45 2023 +0000 Add match patterns for `a ? onezero : onezero` where one of the two operands are constant This adds a match pattern that are for boolean values that optimizes `a ? onezero : 0` to `a & onezero` and `a ? 1 : onezero` to `a | onezero`. This was reported a few times and I thought I would finally add the match pattern for this. This hits a few times in GCC itself too. Notes on the testcases: * phi-opt-2.c: This now is optimized to `a & b` in phiopt rather than ifcombine * phi-opt-25b.c: The test part that was failing was parity which now gets `x & y` treatment. * ssa-thread-21.c: there is no longer a threading opportunity, so need to disable phiopt. Note PR 109957 is filed for the now missing optimization in that testcase too. gcc/ChangeLog: PR tree-optimization/89263 PR tree-optimization/99069 PR tree-optimization/20083 PR tree-optimization/94898 * match.pd: Add patterns to optimize `a ? onezero : onezero` with one of the operands are constant. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/phi-opt-2.c: Adjust the testcase. * gcc.dg/tree-ssa/phi-opt-25b.c: Adjust the testcase. * gcc.dg/tree-ssa/ssa-thread-21.c: Disable phiopt. * gcc.dg/tree-ssa/phi-opt-27.c: New test. * gcc.dg/tree-ssa/phi-opt-28.c: New test. * gcc.dg/tree-ssa/phi-opt-29.c: New test. * gcc.dg/tree-ssa/phi-opt-30.c: New test. * gcc.dg/tree-ssa/phi-opt-31.c: New test. * gcc.dg/tree-ssa/phi-opt-32.c: New test.
Fixed finally (after 18 years) of messing around with PHI-OPT :).