https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79666
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P3 |P1 Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot gnu.org --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Difference: <bb 3> [12.75%]: ... _41 = _40 & -124; g_lsm.15_57 = g; e_lsm.17_59 = e; b_a_lsm.19_61 = b.a; d_lsm.21_63 = d; _42 = f.0_1 <= 0; <bb 4>: ... if (f.0_1 != 0) goto <bb 5>; [50.00%] else goto <bb 6>; [50.00%] <bb 5>: _4 = g_lsm.15_35 ^ e_lsm.17_53; _5 = -1 / _4; ... - _100 = (signed char) _47; - _102 = ~_100; - _106 = _102 | _109; + _99 = (signed char) _47; + _101 = ~_99; + _105 = _101 | _110; + _107 = _41 & _105; <bb 6> [85.00%]: # iftmp.4_21 = PHI <_47(5), 0(4)> # g_lsm.15_32 = PHI <_6(5), g_lsm.15_35(4)> # g_lsm.16_51 = PHI <1(5), g_lsm.16_36(4)> - # prephitmp_107 = PHI <_106(5), -1(4)> - _17 = _41 & prephitmp_107; - _18 = ~_17; + # prephitmp_108 = PHI <_107(5), _41(4)> + _18 = ~prephitmp_108; _37 = _18 != 127; _27 = _37 | _42; if (_27 != 0) that looks ok to me. _41 & -1 is _41 (_41 is signed char). So the issue was latent and is elsewhere. In .optimized we can see we were able to optimize a conditional away. And if we disable VRP2 with -fdisable-tree-vrp2 the issue goes away. VRP2 diff shows new symbolic ranges: @@ -60,17 +60,16 @@ c.11_8: [-INF, 8] EQUIVALENCES: { } (0 elements) c.11_9: VARYING .MEM_10: VARYING -_17: [-INF(OVF), +INF(OVF)] -_18: [-INF(OVF), +INF(OVF)] +_18: [-_107 + -1, -_107 + -1] _19: [-2147483647, 9] -_20: [_41, _41] EQUIVALENCES: { _41 } (1 elements) +_20: [-_41 + -1, -_41 + -1] ... -Folding predicate _99 != 127 to 1 +Folding predicate _20 != 127 to 1 +Folding predicate _18 != 127 to 1 ... _37 = 1; _27 = _37 | _42; if (_27 != 0) goto <bb 7>; [19.94%] else goto <bb 6>; [80.06%] bah, it fails to optimize the conditional directly it seems. Folding statement: _37 = _18 != 127; Folding predicate _18 != 127 to 1 Folded into: _37 = 1; Folding statement: _27 = _37 | _42; Not folded Folding statement: if (_27 != 0) Not folded that's because the lattice isn't updated and/or VRP doesn't properly try match-and-simplify during propagation. _18: [-_107 + -1, -_107 + -1] so yes, for signed char _18 if it's -_107 + -1 it can't be 127 w/o invoking undefined behavior. But whoever created that symbolic range was probably not careful enough to avoid creating an expression that might involve undefined behavior. We have <bb 6> [42.50%]: # g_lsm.15_32 = PHI <_6(5)> # g_lsm.16_51 = PHI <1(5)> # prephitmp_108 = PHI <_107(5)> _18 = ~prephitmp_108; _37 = _18 != 127; _27 = _37 | _42; if (_27 != 0) goto <bb 8>; [19.94%] else goto <bb 7>; [80.06%] <bb 7> [34.03%]: _29 = ASSERT_EXPR <_18, _18 == 127>; <bb 8> [85.00%]: # g_lsm.15_33 = PHI <g_lsm.15_32(6), 0(7), g_lsm.15_50(13)> # g_lsm.16_52 = PHI <g_lsm.16_51(6), 1(7), g_lsm.16_22(13)> # _96 = PHI <_18(6), _29(7), _20(13)> and we can see from where that symbolic range comes from. _18 is ~_107 and we "trick" to use -_107 - 1 for that: void extract_range_from_unary_expr (value_range *vr, enum tree_code code, tree type, value_range *vr0_, tree op0_type) { ... else if (code == BIT_NOT_EXPR) { /* ~X is simply -1 - X, so re-use existing code that also handles anti-ranges fine. */ value_range minusone = VR_INITIALIZER; set_value_range_to_value (&minusone, build_int_cst (type, -1), NULL); extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &minusone, &vr0); return; That's also my code (but older), thus, mine.