On Wed, 13 Jun 2018, Jakub Jelinek wrote:

> On Wed, Jun 13, 2018 at 10:22:29AM +0200, Jakub Jelinek wrote:
> > Random testcase for -Wduplicated-branches -fsanitize=shift:
> > int
> > foo (int x, int y)
> > {
> >   if (x)
> >     y = y << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1
> >           << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1
> >           << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1
> >           << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1;
> >   else
> >     y = y << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1
> >           << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1
> >           << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1
> >           << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 >> 1 << 1 
> > >> 1 << 1 >> 1;
> >   return y;
> > }
> > 
> > Though it seems we have that problem already in inchash::add_expr.  In that
> > case perhaps we could have a pointer to a hashmap in inchash::hash objects,
> > clear it in the ctors and destroy/clear in inchash::hash::end (), though we
> > have the add_commutative that has two separate hash objects.
> 
> It isn't specific to just -fsanitize=undefined, even without that there are
> cases we can end up with lots of nested SAVE_EXPRs, like
> -Wduplicated-branches:
> int bar (void);
> 
> void
> foo (int x, int *y)
> {
>   if (x)
>     y[0] += (y[1] += (y[2] += (y[3] += (y[4] += (y[5] += (y[6] += (y[7] += 
> (y[8] +=
>           (y[9] += (y[10] += (y[11] += (y[12] += (y[13] += (y[14] += (y[15] 
> += (y[16] +=
>           (y[17] += (y[18] += (y[19] += (y[20] += (y[21] += (y[22] += (y[23] 
> += (y[24] +=
>           (y[25] += (y[26] += (y[27] += (y[28] += (y[29] += (y[30] += (y[31] 
> += (y[32] +=
>           (y[33] += (y[34] += (y[35] += (y[36] += (y[37] += (y[38] += (y[39] 
> += (y[40] +=
>           (y[41] += (y[42] += (y[43] += (y[44] += (y[45] += (y[46] += (y[47] 
> += (y[48] +=
>           (y[49] += (y[50] += (y[51] += (y[52] += (y[53] += (y[54] += (y[55] 
> += (y[56] +=
>           (y[57] += (y[58] += (y[59] += (y[60] += (y[61] += (y[62] += (y[63] 
> += (y[64] += bar ()
>           ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
>   else
>     y[0] += (y[1] += (y[2] += (y[3] += (y[4] += (y[5] += (y[6] += (y[7] += 
> (y[8] +=
>           (y[9] += (y[10] += (y[11] += (y[12] += (y[13] += (y[14] += (y[15] 
> += (y[16] +=
>           (y[17] += (y[18] += (y[19] += (y[20] += (y[21] += (y[22] += (y[23] 
> += (y[24] +=
>           (y[25] += (y[26] += (y[27] += (y[28] += (y[29] += (y[30] += (y[31] 
> += (y[32] +=
>           (y[33] += (y[34] += (y[35] += (y[36] += (y[37] += (y[38] += (y[39] 
> += (y[40] +=
>           (y[41] += (y[42] += (y[43] += (y[44] += (y[45] += (y[46] += (y[47] 
> += (y[48] +=
>           (y[49] += (y[50] += (y[51] += (y[52] += (y[53] += (y[54] += (y[55] 
> += (y[56] +=
>           (y[57] += (y[58] += (y[59] += (y[60] += (y[61] += (y[62] += (y[63] 
> += (y[64] += bar ()
>           ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));
> }

Your concern is for compile-time, not for correctness, right?

I think that

  /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.
     We don't care about side effects in that case because the SAVE_EXPR
     takes care of that for us. In all other cases, two expressions are
     equal if they have no side effects.  If we have two identical
     expressions with side effects that should be treated the same due
     to the only side effects being identical SAVE_EXPR's, that will
     be detected in the recursive calls below.
     If we are taking an invariant address of two identical objects
     they are necessarily equal as well.  */
  if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
      && (TREE_CODE (arg0) == SAVE_EXPR
          || (flags & OEP_MATCH_SIDE_EFFECTS)
          || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
    return 1;

is supposed to handle == SAVE_EXPRs and thus the hunk should be
conditionalized on arg0 != arg1 or rather for OEP_LEXICOGRAPHIC
always return true for arg0 == arg1?

I also wondered why this change was necessary for the fix but
it looked safe correctness-wise.

Richard.

Reply via email to