Consider: int foo (int length, const char *fmt) { int i; for (i = length; i >= 0; i--) { switch (fmt[i]) { case 48: break; default: return 1; } } return 0; }
I get: foo (length, fmt) { unsigned int D.1180; unsigned int ivtmp.5; int D.1146; <bb 0>: if (length >= 0) goto <L15>; else goto <L6>; <L15>:; ivtmp.5 = 0; <L0>:; D.1180 = (unsigned int) length; switch (*((const char *) ivtmp.5 + fmt + (const char *) D.1180)) { case 48: goto <L1>; default : goto <L16>; } <L16>:; D.1146 = 1; goto <bb 6> (<L17>); <L1>:; ivtmp.5 = ivtmp.5 - 1; if (ivtmp.5 != D.1180 * 0ffffffff + 0ffffffff) goto <L0>; else goto <L6>; <L6>:; D.1146 = 0; <L17>:; return D.1146; } The following should be hoisted out of the loop. D.1180 = (unsigned int) length; This D.1180 * 0ffffffff + 0ffffffff should be folded to ~D.1180 and of course hoisted out of the loop. The folding part is also mentioned in PR 20130. RTL optimizers hoist ~D.1180 out of the loop. Having said all this, the induction variable should be counting down toward 0. That is, instead of ivtmp.5 = 0; : : switch (*((const char *) ivtmp.5 + fmt + (const char *) D.1180)) : : ivtmp.5 = ivtmp.5 - 1; if (ivtmp.5 != D.1180 * 0ffffffff + 0ffffffff) goto <L0>; else goto <L6>; we should be doing ivtmp.5 = (unsigned int) D.1180; : : switch (*((const char *) ivtmp.5 + fmt)) : : ivtmp.5 = ivtmp.5 - 1; if (ivtmp.5 >= 0) goto <L0>; else goto <L6>; This way, we don't have to keep D.1180 in the loop. And we can compare against 0 at the end. -- Summary: Pessimization of induction variable and missed hoisting opportunity Product: gcc Version: unknown Status: UNCONFIRMED Keywords: missed-optimization, TREE Severity: enhancement Priority: P2 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: kazu at cs dot umass dot edu CC: gcc-bugs at gcc dot gnu dot org OtherBugsDependingO 19721 nThis: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20132