On Tue, 29 Oct 2013, Jakub Jelinek wrote:

> On Tue, Oct 29, 2013 at 12:55:04PM +0100, Richard Biener wrote:
> > Surely you can't rely on CCP and VRP compute exactly the same
> > nonzero_bits.  As you don't record/compute zero_bits you can't
> > tell whether a not set bit in nonzer_bits is "don't know" or
> > if it is "zero".  And you cannot do an assert during iteration
> > (during iteration optimistically 'wrong' values can disappear).
> > 
> > During CCP iteration the rule is that bits may only be added to mask
> > (and obviously the constant itself on a CONSTANT lattice value may
> > not change).
> 
> > Factor this out to commonize with code in evaluate_stmt
> 
> Ok.
> 
> > > +   tem = val->mask.low;
> > > +   align = (tem & -tem);
> > > +   if (align > 1)
> > > +     set_ptr_info_alignment (get_ptr_info (name), align,
> > > +                             (TREE_INT_CST_LOW (val->value)
> > > +                              & (align - 1)));
> > > + }
> > > +      else
> > > + {
> > > +   double_int nonzero_bits = val->mask;
> > > +   nonzero_bits = nonzero_bits | tree_to_double_int (val->value);
> > > +   nonzero_bits &= get_nonzero_bits (name);
> > 
> > This looks odd to me - shouldn't it be simply
> > 
> >    nonzero_bits = ~val->mask & tree_to_double_int (val->value);
> 
> Bits set in the mask are for the bits where the value is unknown,
> so potentially nonzero bits.  Where bits are clear in the mask,
> but set in the value, those are surely nonzero bits.
> The only known zero bits are where both mask and value are zero,
> and as nonzero_bits is defined to be 1 where the bit may be non-zero,
> 0 where it must be zero (like it is for nonzero_bits* in RTL),
> I think val->mask | tree_to_double_int (val->value); is exactly
> what we want.

Ah, I think I missed that detail (1 in nonzero_bits means
maybe non-zero and 0 means must-be zero) - a bit odd, but yeah,
making it consistent with RTL sounds good.

> > ?  &= of get_nonzero_bits either is not necessary or shows the
> > lattice is unnecessarily conservative because you apply it too early
> > during propagation?
> >
> > > +   set_nonzero_bits (name, nonzero_bits);
> > > + }
> > >      }
> > >  
> > >    /* Perform substitutions based on the known constant values.  */
> > > @@ -1671,6 +1700,25 @@ evaluate_stmt (gimple stmt)
> > >        is_constant = (val.lattice_val == CONSTANT);
> > >      }
> > >  
> > > +  if (flag_tree_bit_ccp
> > > +      && !is_constant
> > ^^^
> > 
> > ah, so if the bit-CCP part figured out a set of known bits
> > then you don't do anything here while in fact you can
> > still remove bits from mask with get_nonzero_bits info.
> 
> Yeah, that was not to lose info for the case where the lattice
> is already CONSTANT.

CONSTANT and with mask == 0, sure.  Remember the lattice is
also CONSTANT if only some bits are known.

> Originally, I had code like:
> 
> --- tree-ssa-ccp.c.xx 2013-10-29 15:31:03.000000000 +0100
> +++ tree-ssa-ccp.c    2013-10-29 15:34:44.257977817 +0100
> @@ -1701,8 +1701,7 @@ evaluate_stmt (gimple stmt)
>      }
>  
>    if (flag_tree_bit_ccp
> -      && !is_constant
> -      && likelyvalue != UNDEFINED
> +      && (is_constant || likelyvalue != UNDEFINED)
>        && gimple_get_lhs (stmt)
>        && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME)
>      {
> @@ -1711,11 +1710,27 @@ evaluate_stmt (gimple stmt)
>        double_int mask = double_int::mask (TYPE_PRECISION (TREE_TYPE (lhs)));
>        if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
>       {
> -       val.lattice_val = CONSTANT;
> -       val.value = build_zero_cst (TREE_TYPE (lhs));
> -       /* CCP wants the bits above precision set.  */
> -       val.mask = nonzero_bits | ~mask;
> -       is_constant = true;
> +       if (!is_constant)
> +         {
> +           val.lattice_val = CONSTANT;
> +           val.value = build_zero_cst (TREE_TYPE (lhs));
> +           /* CCP wants the bits above precision set.  */
> +           val.mask = nonzero_bits | ~mask;
> +           is_constant = true;
> +         }
> +       else
> +         {
> +           double_int valv = tree_to_double_int (val.value);
> +           gcc_assert ((valv & ~val.mask
> +                       & ~nonzero_bits & mask).is_zero ());
> +           if (!(valv & ~nonzero_bits & mask).is_zero ())
> +             val.value = double_int_to_tree (TREE_TYPE (lhs),
> +                                             valv & nonzero_bits);
> +           if (nonzero_bits.is_zero ())
> +             val.mask = double_int_zero;
> +           else
> +             val.mask = val.mask & (nonzero_bits | ~mask);
> +         }
>       }
>      }
>  
> in the patch, but that breaks e.g. on
> void
> foo (unsigned int a, unsigned b, unsigned **c, void *d[8], int e)
> {
>   int i;
>   for (i = 0; i != e; i++);
>   if (a)
>     {
>       for (i = 0;;)
>       {
>         i--;
>         if (bar ())
>           goto lab2;
>       }
>     lab1:;
>       __builtin_printf ("%d\n", i < 0 ? -1 - i : i);
>       return;
>     }
> lab2:;
>   if (!d[b] && *c)
>     goto lab1;
> }
> at -O2 - VRP1 figures out:
>   if (i_3 < 0)
>     goto <bb 10>;
>   else
>     goto <bb 11>;
> 
>   <bb 10>:
>   # RANGE [0, 2147483647] NONZERO 0x0000000007fffffff
>   iftmp.0_23 = ~i_3;
> 
>   <bb 11>:
>   # RANGE [0, 2147483647] NONZERO 0x0000000007fffffff
>   # iftmp.0_4 = PHI <iftmp.0_23(10), i_3(9)>
> through the edge assertions, but CPP of course doesn't have edge
> assertions and during iterations just at some point assumes
> i_3 can be zero and processes bb 10 with that, which leads
> to value -1 that triggers the above assert.  So, I still have
> no clue how I could safely add the nonzero_bits info during the iteration
> (nor am I 100% sure if even the addition of the info for the VARYING
> case in evaluate_stmt is safe, but it at least survived bootstrap/regtest
> - even in that case, I bet we could have lattice for some SSA_NAME CONSTANT
> with one constant, then drop to VARYING and at that point mix in the
> non-zero bits info and set it to different CONSTANT with different mask.

I think you can safely apply it to all partially-constant or non-constant
lattice values.

Richard.

Reply via email to