On Fri, 1 Nov 2013, Richard Sandiford wrote:

> I'm building one target for each supported CPU and comparing the wide-int
> assembly output of gcc.c-torture, gcc.dg and g++.dg with the corresponding
> output from the merge point.  This patch removes all the differences I saw
> for alpha-linux-gnu in gcc.c-torture.
> 
> Hunk 1: Preserve the current trunk behaviour in which the shift count
> is truncated if SHIFT_COUNT_TRUNCATED and not otherwise.  This was by
> inspection after hunk 5.
> 
> Hunks 2 and 3: Two cases where force_fit_to_type could extend to wider
> types and where we weren't extending according to the sign of the source.
> We should probably assert that the input is at least as wide as the type...
> 
> Hunk 4: The "&" in:
> 
>             if ((TREE_INT_CST_HIGH (arg1) & mask_hi) == mask_hi
>                 && (TREE_INT_CST_LOW (arg1) & mask_lo) == mask_lo)
> 
> had got dropped during the conversion.
> 
> Hunk 5: The old code was:
> 
>         if (shift > 0)
>           {
>             *mask = r1mask.llshift (shift, TYPE_PRECISION (type));
>             *val = r1val.llshift (shift, TYPE_PRECISION (type));
>           }
>         else if (shift < 0)
>           {
>             shift = -shift;
>             *mask = r1mask.rshift (shift, TYPE_PRECISION (type), !uns);
>             *val = r1val.rshift (shift, TYPE_PRECISION (type), !uns);
>           }
> 
> and these precision arguments had two purposes: to control which
> bits of the first argument were shifted, and to control the truncation
> mask for SHIFT_TRUNCATED.  We need to pass a width to the shift functions
> for the second.
> 
> (BTW, I'm running the comparisons with CONST_WIDE_INT locally moved to the
> end of the !GENERATOR_FILE list in rtl.def, since the current position caused
> some spurious differences.  The "problem" AFAICT is that hash_rtx hashes
> on code, RTL PRE creates registers in the hash order of the associated
> expressions, RA uses register numbers as a tie-breaker during ordering,
> and so the order of rtx_code can indirectly influence register allocation.
> First time I'd realised that could happen, so just thought I'd mention it.
> I think we should keep rtl.def in the current (logical) order though.)
> 
> Tested on x86_64-linux-gnu and powerpc64-linux-gnu.  OK for wide-int?

Bah - can you instead try removing the use of SHIFT_COUNT_TRUNCATED
from double-int.c on the trunk?  If not then putting this at the
callers of wi::rshift and friends is clearly asking for future
mistakes.

Oh, and I think that honoring SHIFT_COUNT_TRUNCATED anywhere else
than in machine instruction patterns was a mistake in the past.

Thanks,
Richard.

[btw, please use diff -p to get us at least some context if you
are not writing changelogs ...]

> Thanks,
> Richard
> 
> 
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c  (revision 204247)
> +++ gcc/fold-const.c  (working copy)
> @@ -1008,9 +1008,12 @@
>          The following code ignores overflow; perhaps a C standard
>          interpretation ruling is needed.  */
>       res = wi::rshift (arg1, arg2, sign,
> -                       GET_MODE_BITSIZE (TYPE_MODE (type)));
> +                       SHIFT_COUNT_TRUNCATED
> +                       ? GET_MODE_BITSIZE (TYPE_MODE (type)) : 0);
>        else
> -     res = wi::lshift (arg1, arg2, GET_MODE_BITSIZE (TYPE_MODE (type)));
> +     res = wi::lshift (arg1, arg2,
> +                       SHIFT_COUNT_TRUNCATED
> +                       ? GET_MODE_BITSIZE (TYPE_MODE (type)) : 0);
>        break;
>        
>      case RROTATE_EXPR:
> @@ -6870,7 +6873,8 @@
>      return NULL_TREE;
>  
>    if (TREE_CODE (arg1) == INTEGER_CST)
> -    arg1 = force_fit_type (inner_type, arg1, 0, TREE_OVERFLOW (arg1));
> +    arg1 = force_fit_type (inner_type, wi::to_widest (arg1), 0,
> +                        TREE_OVERFLOW (arg1));
>    else
>      arg1 = fold_convert_loc (loc, inner_type, arg1);
>  
> @@ -8081,7 +8085,8 @@
>           }
>         if (change)
>           {
> -           tem = force_fit_type (type, and1, 0, TREE_OVERFLOW (and1));
> +           tem = force_fit_type (type, wi::to_widest (and1), 0,
> +                                 TREE_OVERFLOW (and1));
>             return fold_build2_loc (loc, BIT_AND_EXPR, type,
>                                     fold_convert_loc (loc, type, and0), tem);
>           }
> @@ -14098,12 +14103,13 @@
>               (inner_width, outer_width - inner_width, false, 
>                TYPE_PRECISION (TREE_TYPE (arg1)));
>  
> -           if (mask == arg1)
> +           wide_int common = mask & arg1;
> +           if (common == mask)
>               {
>                 tem_type = signed_type_for (TREE_TYPE (tem));
>                 tem = fold_convert_loc (loc, tem_type, tem);
>               }
> -           else if ((mask & arg1) == 0)
> +           else if (common == 0)
>               {
>                 tem_type = unsigned_type_for (TREE_TYPE (tem));
>                 tem = fold_convert_loc (loc, tem_type, tem);
> Index: gcc/tree-ssa-ccp.c
> ===================================================================
> --- gcc/tree-ssa-ccp.c        (revision 204247)
> +++ gcc/tree-ssa-ccp.c        (working copy)
> @@ -1238,15 +1238,20 @@
>                 else
>                   code = RSHIFT_EXPR;
>               }
> +           int shift_precision = SHIFT_COUNT_TRUNCATED ? width : 0;
>             if (code == RSHIFT_EXPR)
>               {
> -               *mask = wi::rshift (wi::ext (r1mask, width, sgn), shift, sgn);
> -               *val = wi::rshift (wi::ext (r1val, width, sgn), shift, sgn);
> +               *mask = wi::rshift (wi::ext (r1mask, width, sgn),
> +                                   shift, sgn, shift_precision);
> +               *val = wi::rshift (wi::ext (r1val, width, sgn),
> +                                  shift, sgn, shift_precision);
>               }
>             else
>               {
> -               *mask = wi::sext (wi::lshift (r1mask, shift), width);
> -               *val = wi::sext (wi::lshift (r1val, shift), width);
> +               *mask = wi::ext (wi::lshift (r1mask, shift, shift_precision),
> +                                width, sgn);
> +               *val = wi::ext (wi::lshift (r1val, shift, shift_precision),
> +                               width, sgn);
>               }
>           }
>       }
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend

Reply via email to