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.

Reply via email to