Consider: int foo (int a) { int b; if (a == 0) b = 0; else b = 1; return b + 1; } I get: foo (a) { int b; <bb 0>: if (a_2 == 0) goto <L0>; else goto <L2>; <L0>:; # b_1 = PHI <1(0), 0(1)>; <L2>:; return b_1 + 1; } Note that PHI could absorb b_1 + 1. That is, we could do something like: foo (a) { int b; <bb 0>: if (a_2 == 0) goto <L0>; else goto <L2>; <L0>:; # b_1 = PHI <2(0), 1(1)>; <L2>:; return b_1; }
Really this should not propagate constants back to the PHI but change this code to, as this removes BB's and such, I know this example was to show what to do with PHI's but we can do better with this one (this part is a dup of a bug which I filed, bug 14466): int foo (int a) { int b; b = a != 0; return b + 1; } Anyways here is a better example as there is no way to convert the comparsion into the PHI: int foo (int a) { int b; if (a == 0) b = 700; else b = 200; return b + 1; } Confirmed.
I don't know where to draw a line. Even for the last example, i386 port converts the code to b = a != 0; b--; b &= 500; b += 201; but this would be a nightmare on ports without setcc (like h8). Maybe we could keep anything more complex than "c = a COND b" in the if-then-else form (assuming we don't want to introduce machine-dependent if-conversion pass at tree level). If we don't want to rely on rtl optimizers to do if-conversion, we could put a flag to "if" to indicate that that's an if-conversion candidate (just like tail-call flag) and then do the if-conversion at the expand time.
I also think we should keep anything more complex than c = a CMP b in the PHI form and that is what is done right now.
Seems like what I feared in comment #2 is going on. Specifically, for the original test case, I get: foo (a) { _Bool D.1130; _Bool D.1129; int b; int D.1120; <bb 0>: D.1129_5 = a_2 == 0; D.1130_6 = !D.1129_5; b_1 = (int) D.1130_6; D.1120_3 = b_1 + 1; return D.1120_3; } I don't know if it's correct to say PHI-OPT is run too early, but at least it is blocking us to obtain: # b_1 = PHI <2(0), 1(1)>;
Fixed via PRE for 4.0.0.