https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100922
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rguenth at gcc dot gnu.org --- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #1) > Pre takes: > <bb 5> [local count: 1073741824]: > # str_9 = PHI <str_27(4), str_16(8)> > # out_10 = PHI <str_27(4), out_20(8)> > str_16 = str_9 + 1; > c_17 = *str_9; > _5 = (sizetype) c_17; > _6 = keep_lut_14(D) + _5; > inc_18 = *_6; > *out_10 = c_17; > _7 = (sizetype) inc_18; > out_20 = out_10 + _7; > if (c_17 != 0) > goto <bb 8>; [89.00%] > else > goto <bb 6>; [11.00%] > > <bb 8> [local count: 955630224]: > goto <bb 5>; [100.00%] > > Changes it to: > <bb 5> [local count: 1073741824]: > # str_9 = PHI <str_27(4), str_16(6)> > # out_10 = PHI <str_27(4), out_20(6)> > # prephitmp_60 = PHI <prephitmp_54(4), pretmp_59(6)> > str_16 = str_9 + 1; > c_17 = *str_9; > _5 = (sizetype) c_17; > _6 = keep_lut_14(D) + _5; > *out_10 = c_17; > _7 = (sizetype) prephitmp_60; > out_20 = out_10 + _7; > if (c_17 != 0) > goto <bb 6>; [89.00%] > else > goto <bb 7>; [11.00%] > > <bb 6> [local count: 955630224]: > pretmp_55 = MEM[(char *)str_9 + 1B]; > _57 = (sizetype) pretmp_55; > _58 = keep_lut_14(D) + _57; > pretmp_59 = *_58; > goto <bb 5>; [100.00%] > > And then ch_vect changes it to (basically undoing the PRE): > <bb 14> [local count: 850510900]: > > <bb 6> [local count: 955630224]: > # str_42 = PHI <str_41(14), str_27(13)> > # str_41 = PHI <str_16(14), str_47(13)> > # out_38 = PHI <out_20(14), out_43(13)> > pretmp_55 = MEM[(char *)str_42 + 1B]; > _57 = (sizetype) pretmp_55; > _58 = keep_lut_14(D) + _57; > pretmp_59 = *_58; > str_16 = str_41 + 1; > c_17 = *str_41; > *out_38 = c_17; > _7 = (sizetype) pretmp_59; > out_20 = out_38 + _7; > if (c_17 != 0) > goto <bb 14>; [89.00%] > else > goto <bb 7>; [11.00%] > > And then IVOPTS comes around and does: > <bb 14> [local count: 850510900]: > > <bb 6> [local count: 955630224]: > # str_41 = PHI <str_16(14), str_47(13)> > # out_38 = PHI <out_20(14), out_43(13)> > pretmp_55 = MEM[(char *)str_41]; > _57 = (sizetype) pretmp_55; > _58 = keep_lut_14(D) + _57; > pretmp_59 = *_58; > str_16 = str_41 + 1; > c_17 = MEM[(char *)str_16 + -1B]; > *out_38 = c_17; > _7 = (sizetype) pretmp_59; > out_20 = out_38 + _7; > if (c_17 != 0) > goto <bb 14>; [89.00%] > else > goto <bb 7>; [11.00%] > > Which is fine except FRE (and DOM), don't recognize the MEM[(char *)str_16 + > -1B] and MEM[(char *)str_41] being the same. For FRE, it almost looks like > TARGET_MEM_REF is not handled .... TARGET_MEM_REF is handled but what is not is "forwarding" the str_16 definition to the str_16 + -1B TARGET_MEM_REF - vn_reference_maybe_forwprop_address only forwards to MEM_REFs (see the caller in valueize_refs_1 - the TARGET_MEM_REF representation is different enough to make a trivial patch impossible). Now, there's code to fold TARGET_MEM_REF back to MEM_REF, but it doesn't trigger here as /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. ??? As IVOPTs does not follow restrictions to where the base pointer may point to create a MEM_REF only if we know that base is valid. */ if ((TREE_CODE (base) == ADDR_EXPR || TREE_CODE (base) == INTEGER_CST) I _think_ that IVOPTs is fixed, but I'm not 100% sure ...