diff mbox

Use unsigned(-1) for lshift

Message ID alpine.DEB.2.02.1305232137430.26811@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse May 23, 2013, 7:47 p.m. UTC
Hello,

this is a simple patch to reduce a bit the noise in PR57324 (undefined 
behavior flagged by clang). I only handled some of the most obvious ones.
Passes bootstrap+testsuite on x86_64-linux-gnu.


2013-05-24  Marc Glisse  <marc.glisse@inria.fr>

 	PR other/57324
 	* expmed.c (expand_smod_pow2): Use an unsigned -1 for lshift.
 	* fold-const.c (fold_unary_loc): Likewise.
 	* double-int.c (rshift_double, lshift_double): Likewise.
 	* cse.c (cse_insn): Likewise.
 	* tree.c (integer_pow2p, tree_log2, tree_floor_log2): Likewise.
 	* tree-ssa-structalias.c (UNKNOWN_OFFSET): Shift 1 instead of -1.

Comments

Richard Biener May 24, 2013, 8:15 a.m. UTC | #1
On Thu, May 23, 2013 at 9:47 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> this is a simple patch to reduce a bit the noise in PR57324 (undefined
> behavior flagged by clang). I only handled some of the most obvious ones.
> Passes bootstrap+testsuite on x86_64-linux-gnu.

Hm, so ISO C99 says in 6.5.7/4 that (E1 << E2) "If E1 has signed type
and nonnegative
value, and E1 * 2^E2 is representable in the result type, then that is the
resulting value; otherwise, the behavior is undefined."

While seriously underspecified for signed negative values (always undefined?!
or well-defined?!), I wonder why CLang requires

> -      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count -
> HOST_BITS_PER_WIDE_INT));
> +      *hv &= ~((unsigned HOST_WIDE_INT) (-1)
> +              << (prec - count - HOST_BITS_PER_WIDE_INT));

here.

That is, isn't this a bug in CLang?

Richard.



>
> 2013-05-24  Marc Glisse  <marc.glisse@inria.fr>
>
>         PR other/57324
>         * expmed.c (expand_smod_pow2): Use an unsigned -1 for lshift.
>         * fold-const.c (fold_unary_loc): Likewise.
>         * double-int.c (rshift_double, lshift_double): Likewise.
>         * cse.c (cse_insn): Likewise.
>         * tree.c (integer_pow2p, tree_log2, tree_floor_log2): Likewise.
>         * tree-ssa-structalias.c (UNKNOWN_OFFSET): Shift 1 instead of -1.
>
> --
> Marc Glisse
> Index: gcc/double-int.c
> ===================================================================
> --- gcc/double-int.c    (revision 199256)
> +++ gcc/double-int.c    (working copy)
> @@ -264,21 +264,22 @@ rshift_double (unsigned HOST_WIDE_INT l1
>
>    if (count >= prec)
>      {
>        *hv = signmask;
>        *lv = signmask;
>      }
>    else if ((prec - count) >= HOST_BITS_PER_DOUBLE_INT)
>      ;
>    else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
>      {
> -      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count -
> HOST_BITS_PER_WIDE_INT));
> +      *hv &= ~((unsigned HOST_WIDE_INT) (-1)
> +              << (prec - count - HOST_BITS_PER_WIDE_INT));
>        *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
>      }
>    else
>      {
>        *hv = signmask;
>        *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));
>        *lv |= signmask << (prec - count);
>      }
>  }
>
> @@ -321,21 +322,21 @@ lshift_double (unsigned HOST_WIDE_INT l1
>
>    signmask = -((prec > HOST_BITS_PER_WIDE_INT
>                 ? ((unsigned HOST_WIDE_INT) *hv
>                    >> (prec - HOST_BITS_PER_WIDE_INT - 1))
>                 : (*lv >> (prec - 1))) & 1);
>
>    if (prec >= HOST_BITS_PER_DOUBLE_INT)
>      ;
>    else if (prec >= HOST_BITS_PER_WIDE_INT)
>      {
> -      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
> +      *hv &= ~((unsigned HOST_WIDE_INT) -1 << (prec -
> HOST_BITS_PER_WIDE_INT));
>        *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
>      }
>    else
>      {
>        *hv = signmask;
>        *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
>        *lv |= signmask << prec;
>      }
>  }
>
> Index: gcc/tree-ssa-structalias.c
> ===================================================================
> --- gcc/tree-ssa-structalias.c  (revision 199256)
> +++ gcc/tree-ssa-structalias.c  (working copy)
> @@ -475,21 +475,21 @@ struct constraint_expr
>
>    /* Offset, in bits, of this constraint from the beginning of
>       variables it ends up referring to.
>
>       IOW, in a deref constraint, we would deref, get the result set,
>       then add OFFSET to each member.   */
>    HOST_WIDE_INT offset;
>  };
>
>  /* Use 0x8000... as special unknown offset.  */
> -#define UNKNOWN_OFFSET ((HOST_WIDE_INT)-1 << (HOST_BITS_PER_WIDE_INT-1))
> +#define UNKNOWN_OFFSET ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT-1))
>
>  typedef struct constraint_expr ce_s;
>  static void get_constraint_for_1 (tree, vec<ce_s> *, bool, bool);
>  static void get_constraint_for (tree, vec<ce_s> *);
>  static void get_constraint_for_rhs (tree, vec<ce_s> *);
>  static void do_deref (vec<ce_s> *);
>
>  /* Our set constraints are made up of two constraint expressions, one
>     LHS, and one RHS.
>
> Index: gcc/cse.c
> ===================================================================
> --- gcc/cse.c   (revision 199256)
> +++ gcc/cse.c   (working copy)
> @@ -5374,21 +5374,21 @@ cse_insn (rtx insn)
>          may not equal what was stored, due to truncation.  */
>
>        if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT)
>         {
>           rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
>
>           if (src_const != 0 && CONST_INT_P (src_const)
>               && CONST_INT_P (width)
>               && INTVAL (width) < HOST_BITS_PER_WIDE_INT
>               && ! (INTVAL (src_const)
> -                   & ((HOST_WIDE_INT) (-1) << INTVAL (width))))
> +                   & ((unsigned HOST_WIDE_INT) (-1) << INTVAL (width))))
>             /* Exception: if the value is constant,
>                and it won't be truncated, record it.  */
>             ;
>           else
>             {
>               /* This is chosen so that the destination will be invalidated
>                  but no new value will be recorded.
>                  We must invalidate because sometimes constant
>                  values can be recorded for bitfields.  */
>               sets[i].src_elt = 0;
> Index: gcc/expmed.c
> ===================================================================
> --- gcc/expmed.c        (revision 199256)
> +++ gcc/expmed.c        (working copy)
> @@ -3688,39 +3688,39 @@ expand_smod_pow2 (enum machine_mode mode
>      }
>
>    /* Mask contains the mode's signbit and the significant bits of the
>       modulus.  By including the signbit in the operation, many targets
>       can avoid an explicit compare operation in the following comparison
>       against zero.  */
>
>    masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
>    if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
>      {
> -      masklow |= (HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) - 1);
> +      masklow |= (unsigned HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) -
> 1);
>        maskhigh = -1;
>      }
>    else
> -    maskhigh = (HOST_WIDE_INT) -1
> +    maskhigh = (unsigned HOST_WIDE_INT) -1
>                  << (GET_MODE_BITSIZE (mode) - HOST_BITS_PER_WIDE_INT - 1);
>
>    temp = expand_binop (mode, and_optab, op0,
>                        immed_double_const (masklow, maskhigh, mode),
>                        result, 1, OPTAB_LIB_WIDEN);
>    if (temp != result)
>      emit_move_insn (result, temp);
>
>    label = gen_label_rtx ();
>    do_cmp_and_jump (result, const0_rtx, GE, mode, label);
>
>    temp = expand_binop (mode, sub_optab, result, const1_rtx, result,
>                        0, OPTAB_LIB_WIDEN);
> -  masklow = (HOST_WIDE_INT) -1 << logd;
> +  masklow = (unsigned HOST_WIDE_INT) -1 << logd;
>    maskhigh = -1;
>    temp = expand_binop (mode, ior_optab, temp,
>                        immed_double_const (masklow, maskhigh, mode),
>                        result, 1, OPTAB_LIB_WIDEN);
>    temp = expand_binop (mode, add_optab, temp, const1_rtx, result,
>                        0, OPTAB_LIB_WIDEN);
>    if (temp != result)
>      emit_move_insn (result, temp);
>    emit_label (label);
>    return result;
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c  (revision 199256)
> +++ gcc/tree.c  (working copy)
> @@ -1935,26 +1935,26 @@ integer_pow2p (const_tree expr)
>    prec = TYPE_PRECISION (TREE_TYPE (expr));
>    high = TREE_INT_CST_HIGH (expr);
>    low = TREE_INT_CST_LOW (expr);
>
>    /* First clear all bits that are beyond the type's precision in case
>       we've been sign extended.  */
>
>    if (prec == HOST_BITS_PER_DOUBLE_INT)
>      ;
>    else if (prec > HOST_BITS_PER_WIDE_INT)
> -    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
> +    high &= ~((unsigned HOST_WIDE_INT) (-1) << (prec -
> HOST_BITS_PER_WIDE_INT));
>    else
>      {
>        high = 0;
>        if (prec < HOST_BITS_PER_WIDE_INT)
> -       low &= ~((HOST_WIDE_INT) (-1) << prec);
> +       low &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
>      }
>
>    if (high == 0 && low == 0)
>      return 0;
>
>    return ((high == 0 && (low & (low - 1)) == 0)
>           || (low == 0 && (high & (high - 1)) == 0));
>  }
>
>  /* Return 1 if EXPR is an integer constant other than zero or a
> @@ -1999,26 +1999,26 @@ tree_log2 (const_tree expr)
>    prec = TYPE_PRECISION (TREE_TYPE (expr));
>    high = TREE_INT_CST_HIGH (expr);
>    low = TREE_INT_CST_LOW (expr);
>
>    /* First clear all bits that are beyond the type's precision in case
>       we've been sign extended.  */
>
>    if (prec == HOST_BITS_PER_DOUBLE_INT)
>      ;
>    else if (prec > HOST_BITS_PER_WIDE_INT)
> -    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
> +    high &= ~((unsigned HOST_WIDE_INT) (-1) << (prec -
> HOST_BITS_PER_WIDE_INT));
>    else
>      {
>        high = 0;
>        if (prec < HOST_BITS_PER_WIDE_INT)
> -       low &= ~((HOST_WIDE_INT) (-1) << prec);
> +       low &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
>      }
>
>    return (high != 0 ? HOST_BITS_PER_WIDE_INT + exact_log2 (high)
>           : exact_log2 (low));
>  }
>
>  /* Similar, but return the largest integer Y such that 2 ** Y is less
>     than or equal to EXPR.  */
>
>  int
> @@ -2036,26 +2036,26 @@ tree_floor_log2 (const_tree expr)
>    high = TREE_INT_CST_HIGH (expr);
>    low = TREE_INT_CST_LOW (expr);
>
>    /* First clear all bits that are beyond the type's precision in case
>       we've been sign extended.  Ignore if type's precision hasn't been set
>       since what we are doing is setting it.  */
>
>    if (prec == HOST_BITS_PER_DOUBLE_INT || prec == 0)
>      ;
>    else if (prec > HOST_BITS_PER_WIDE_INT)
> -    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
> +    high &= ~((unsigned HOST_WIDE_INT) (-1) << (prec -
> HOST_BITS_PER_WIDE_INT));
>    else
>      {
>        high = 0;
>        if (prec < HOST_BITS_PER_WIDE_INT)
> -       low &= ~((HOST_WIDE_INT) (-1) << prec);
> +       low &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
>      }
>
>    return (high != 0 ? HOST_BITS_PER_WIDE_INT + floor_log2 (high)
>           : floor_log2 (low));
>  }
>
>  /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
>     decimal float constants, so don't return 1 for them.  */
>
>  int
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    (revision 199256)
> +++ gcc/fold-const.c    (working copy)
> @@ -8049,21 +8049,21 @@ fold_unary_loc (location_t loc, enum tre
>               || (TYPE_PRECISION (type)
>                   <= TYPE_PRECISION (TREE_TYPE (and_expr))))
>             change = 1;
>           else if (TYPE_PRECISION (TREE_TYPE (and1))
>                    <= HOST_BITS_PER_WIDE_INT
>                    && host_integerp (and1, 1))
>             {
>               unsigned HOST_WIDE_INT cst;
>
>               cst = tree_low_cst (and1, 1);
> -             cst &= (HOST_WIDE_INT) -1
> +             cst &= (unsigned HOST_WIDE_INT) -1
>                      << (TYPE_PRECISION (TREE_TYPE (and1)) - 1);
>               change = (cst == 0);
>  #ifdef LOAD_EXTEND_OP
>               if (change
>                   && !flag_syntax_only
>                   && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
>                       == ZERO_EXTEND))
>                 {
>                   tree uns = unsigned_type_for (TREE_TYPE (and0));
>                   and0 = fold_convert_loc (loc, uns, and0);
>
Marc Glisse May 24, 2013, 8:33 a.m. UTC | #2
On Fri, 24 May 2013, Richard Biener wrote:

> On Thu, May 23, 2013 at 9:47 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
>> Hello,
>>
>> this is a simple patch to reduce a bit the noise in PR57324 (undefined
>> behavior flagged by clang). I only handled some of the most obvious ones.
>> Passes bootstrap+testsuite on x86_64-linux-gnu.
>
> Hm, so ISO C99 says in 6.5.7/4 that (E1 << E2) "If E1 has signed type
> and nonnegative
> value, and E1 * 2^E2 is representable in the result type, then that is the
> resulting value; otherwise, the behavior is undefined."

I guess if the architecture only has logical shifts and uses another 
representation than 2's complement...

> While seriously underspecified for signed negative values (always undefined?!
> or well-defined?!), I wonder why CLang requires
>
>> -      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count -
>> HOST_BITS_PER_WIDE_INT));
>> +      *hv &= ~((unsigned HOST_WIDE_INT) (-1)
>> +              << (prec - count - HOST_BITS_PER_WIDE_INT));
>
> here.
>
> That is, isn't this a bug in CLang?

Note that my set of changes may not exactly match clang's report. Since 
that was done on 4.8, I relied on grep quite a bit, and there didn't seem 
to be any harm in adding unsigned there. If we consider that the standard 
says that any lshift of a negative number is undefined, why do you find 
this particular change surprising?
Richard Biener May 24, 2013, 8:40 a.m. UTC | #3
On Fri, May 24, 2013 at 10:33 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Fri, 24 May 2013, Richard Biener wrote:
>
>> On Thu, May 23, 2013 at 9:47 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
>>>
>>> Hello,
>>>
>>> this is a simple patch to reduce a bit the noise in PR57324 (undefined
>>> behavior flagged by clang). I only handled some of the most obvious ones.
>>> Passes bootstrap+testsuite on x86_64-linux-gnu.
>>
>>
>> Hm, so ISO C99 says in 6.5.7/4 that (E1 << E2) "If E1 has signed type
>> and nonnegative
>> value, and E1 * 2^E2 is representable in the result type, then that is the
>> resulting value; otherwise, the behavior is undefined."
>
>
> I guess if the architecture only has logical shifts and uses another
> representation than 2's complement...
>
>
>> While seriously underspecified for signed negative values (always
>> undefined?!
>> or well-defined?!), I wonder why CLang requires
>>
>>> -      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count -
>>> HOST_BITS_PER_WIDE_INT));
>>> +      *hv &= ~((unsigned HOST_WIDE_INT) (-1)
>>> +              << (prec - count - HOST_BITS_PER_WIDE_INT));
>>
>>
>> here.
>>
>> That is, isn't this a bug in CLang?
>
>
> Note that my set of changes may not exactly match clang's report. Since that
> was done on 4.8, I relied on grep quite a bit, and there didn't seem to be
> any harm in adding unsigned there. If we consider that the standard says
> that any lshift of a negative number is undefined, why do you find this
> particular change surprising?

I'm not dure what the standard says here - I'd equally well may interpret
the standard in that all left-shifts of negative values are well-defined
(there must be a reason for the pattern to use -1 << instead of 1 <<).

Richard.

> --
> Marc Glisse
Jakub Jelinek May 24, 2013, 8:44 a.m. UTC | #4
On Fri, May 24, 2013 at 10:15:29AM +0200, Richard Biener wrote:
> On Thu, May 23, 2013 at 9:47 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> > Hello,
> >
> > this is a simple patch to reduce a bit the noise in PR57324 (undefined
> > behavior flagged by clang). I only handled some of the most obvious ones.
> > Passes bootstrap+testsuite on x86_64-linux-gnu.
> 
> Hm, so ISO C99 says in 6.5.7/4 that (E1 << E2) "If E1 has signed type
> and nonnegative
> value, and E1 * 2^E2 is representable in the result type, then that is the
> resulting value; otherwise, the behavior is undefined."
> 
> While seriously underspecified for signed negative values (always undefined?!
> or well-defined?!), I wonder why CLang requires

By strict reading of the standard, left shift of negative signed value by
any amount is undefined behavior in ISO C99 (no idea if it hasn't been
changed later on, Joseph?).
In C++98, in [expr.shift] it doesn't seem to mention E1 << E2 where E1 has
signed type at all, the is implementation defined sentence only in the
second paragraph, so one would expect that it applies to >> only.
C++11 [expr.shift] already has the wording of C99 (thus making it undefined
behavior?).

BTW, we have HOST_WIDE_INT_1 and HOST_WIDE_INT_C(X) macros, don't we want
also HOST_WIDE_INT_m1 for HOST_WIDE_INT_C(-1) and HOST_WIDE_INT_UC(X)
for HOST_WIDE_INT_C(X##U) (or whatever works for __int64) and
HOST_WIDE_INT_1U, HOST_WIDE_INT_m1U ?  It would be more compact and could
make code more readable.

	Jakub
Joseph Myers May 24, 2013, 3:08 p.m. UTC | #5
On Fri, 24 May 2013, Richard Biener wrote:

> On Thu, May 23, 2013 at 9:47 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> > Hello,
> >
> > this is a simple patch to reduce a bit the noise in PR57324 (undefined
> > behavior flagged by clang). I only handled some of the most obvious ones.
> > Passes bootstrap+testsuite on x86_64-linux-gnu.
> 
> Hm, so ISO C99 says in 6.5.7/4 that (E1 << E2) "If E1 has signed type
> and nonnegative
> value, and E1 * 2^E2 is representable in the result type, then that is the
> resulting value; otherwise, the behavior is undefined."
> 
> While seriously underspecified for signed negative values (always undefined?!
> or well-defined?!), I wonder why CLang requires

Always undefined for signed negative values (compared to the 
implementation-defined of C90; DR#081).
diff mbox

Patch

Index: gcc/double-int.c
===================================================================
--- gcc/double-int.c	(revision 199256)
+++ gcc/double-int.c	(working copy)
@@ -264,21 +264,22 @@  rshift_double (unsigned HOST_WIDE_INT l1
 
   if (count >= prec)
     {
       *hv = signmask;
       *lv = signmask;
     }
   else if ((prec - count) >= HOST_BITS_PER_DOUBLE_INT)
     ;
   else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
     {
-      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT));
+      *hv &= ~((unsigned HOST_WIDE_INT) (-1)
+	       << (prec - count - HOST_BITS_PER_WIDE_INT));
       *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
     }
   else
     {
       *hv = signmask;
       *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));
       *lv |= signmask << (prec - count);
     }
 }
 
@@ -321,21 +322,21 @@  lshift_double (unsigned HOST_WIDE_INT l1
 
   signmask = -((prec > HOST_BITS_PER_WIDE_INT
 		? ((unsigned HOST_WIDE_INT) *hv
 		   >> (prec - HOST_BITS_PER_WIDE_INT - 1))
 		: (*lv >> (prec - 1))) & 1);
 
   if (prec >= HOST_BITS_PER_DOUBLE_INT)
     ;
   else if (prec >= HOST_BITS_PER_WIDE_INT)
     {
-      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+      *hv &= ~((unsigned HOST_WIDE_INT) -1 << (prec - HOST_BITS_PER_WIDE_INT));
       *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
     }
   else
     {
       *hv = signmask;
       *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
       *lv |= signmask << prec;
     }
 }
 
Index: gcc/tree-ssa-structalias.c
===================================================================
--- gcc/tree-ssa-structalias.c	(revision 199256)
+++ gcc/tree-ssa-structalias.c	(working copy)
@@ -475,21 +475,21 @@  struct constraint_expr
 
   /* Offset, in bits, of this constraint from the beginning of
      variables it ends up referring to.
 
      IOW, in a deref constraint, we would deref, get the result set,
      then add OFFSET to each member.   */
   HOST_WIDE_INT offset;
 };
 
 /* Use 0x8000... as special unknown offset.  */
-#define UNKNOWN_OFFSET ((HOST_WIDE_INT)-1 << (HOST_BITS_PER_WIDE_INT-1))
+#define UNKNOWN_OFFSET ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT-1))
 
 typedef struct constraint_expr ce_s;
 static void get_constraint_for_1 (tree, vec<ce_s> *, bool, bool);
 static void get_constraint_for (tree, vec<ce_s> *);
 static void get_constraint_for_rhs (tree, vec<ce_s> *);
 static void do_deref (vec<ce_s> *);
 
 /* Our set constraints are made up of two constraint expressions, one
    LHS, and one RHS.
 
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	(revision 199256)
+++ gcc/cse.c	(working copy)
@@ -5374,21 +5374,21 @@  cse_insn (rtx insn)
 	 may not equal what was stored, due to truncation.  */
 
       if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT)
 	{
 	  rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
 
 	  if (src_const != 0 && CONST_INT_P (src_const)
 	      && CONST_INT_P (width)
 	      && INTVAL (width) < HOST_BITS_PER_WIDE_INT
 	      && ! (INTVAL (src_const)
-		    & ((HOST_WIDE_INT) (-1) << INTVAL (width))))
+		    & ((unsigned HOST_WIDE_INT) (-1) << INTVAL (width))))
 	    /* Exception: if the value is constant,
 	       and it won't be truncated, record it.  */
 	    ;
 	  else
 	    {
 	      /* This is chosen so that the destination will be invalidated
 		 but no new value will be recorded.
 		 We must invalidate because sometimes constant
 		 values can be recorded for bitfields.  */
 	      sets[i].src_elt = 0;
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 199256)
+++ gcc/expmed.c	(working copy)
@@ -3688,39 +3688,39 @@  expand_smod_pow2 (enum machine_mode mode
     }
 
   /* Mask contains the mode's signbit and the significant bits of the
      modulus.  By including the signbit in the operation, many targets
      can avoid an explicit compare operation in the following comparison
      against zero.  */
 
   masklow = ((HOST_WIDE_INT) 1 << logd) - 1;
   if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
     {
-      masklow |= (HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) - 1);
+      masklow |= (unsigned HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) - 1);
       maskhigh = -1;
     }
   else
-    maskhigh = (HOST_WIDE_INT) -1
+    maskhigh = (unsigned HOST_WIDE_INT) -1
 		 << (GET_MODE_BITSIZE (mode) - HOST_BITS_PER_WIDE_INT - 1);
 
   temp = expand_binop (mode, and_optab, op0,
 		       immed_double_const (masklow, maskhigh, mode),
 		       result, 1, OPTAB_LIB_WIDEN);
   if (temp != result)
     emit_move_insn (result, temp);
 
   label = gen_label_rtx ();
   do_cmp_and_jump (result, const0_rtx, GE, mode, label);
 
   temp = expand_binop (mode, sub_optab, result, const1_rtx, result,
 		       0, OPTAB_LIB_WIDEN);
-  masklow = (HOST_WIDE_INT) -1 << logd;
+  masklow = (unsigned HOST_WIDE_INT) -1 << logd;
   maskhigh = -1;
   temp = expand_binop (mode, ior_optab, temp,
 		       immed_double_const (masklow, maskhigh, mode),
 		       result, 1, OPTAB_LIB_WIDEN);
   temp = expand_binop (mode, add_optab, temp, const1_rtx, result,
 		       0, OPTAB_LIB_WIDEN);
   if (temp != result)
     emit_move_insn (result, temp);
   emit_label (label);
   return result;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 199256)
+++ gcc/tree.c	(working copy)
@@ -1935,26 +1935,26 @@  integer_pow2p (const_tree expr)
   prec = TYPE_PRECISION (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
   /* First clear all bits that are beyond the type's precision in case
      we've been sign extended.  */
 
   if (prec == HOST_BITS_PER_DOUBLE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
-    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+    high &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
   else
     {
       high = 0;
       if (prec < HOST_BITS_PER_WIDE_INT)
-	low &= ~((HOST_WIDE_INT) (-1) << prec);
+	low &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
     }
 
   if (high == 0 && low == 0)
     return 0;
 
   return ((high == 0 && (low & (low - 1)) == 0)
 	  || (low == 0 && (high & (high - 1)) == 0));
 }
 
 /* Return 1 if EXPR is an integer constant other than zero or a
@@ -1999,26 +1999,26 @@  tree_log2 (const_tree expr)
   prec = TYPE_PRECISION (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
   /* First clear all bits that are beyond the type's precision in case
      we've been sign extended.  */
 
   if (prec == HOST_BITS_PER_DOUBLE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
-    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+    high &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
   else
     {
       high = 0;
       if (prec < HOST_BITS_PER_WIDE_INT)
-	low &= ~((HOST_WIDE_INT) (-1) << prec);
+	low &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
     }
 
   return (high != 0 ? HOST_BITS_PER_WIDE_INT + exact_log2 (high)
 	  : exact_log2 (low));
 }
 
 /* Similar, but return the largest integer Y such that 2 ** Y is less
    than or equal to EXPR.  */
 
 int
@@ -2036,26 +2036,26 @@  tree_floor_log2 (const_tree expr)
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
   /* First clear all bits that are beyond the type's precision in case
      we've been sign extended.  Ignore if type's precision hasn't been set
      since what we are doing is setting it.  */
 
   if (prec == HOST_BITS_PER_DOUBLE_INT || prec == 0)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
-    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+    high &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
   else
     {
       high = 0;
       if (prec < HOST_BITS_PER_WIDE_INT)
-	low &= ~((HOST_WIDE_INT) (-1) << prec);
+	low &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
     }
 
   return (high != 0 ? HOST_BITS_PER_WIDE_INT + floor_log2 (high)
 	  : floor_log2 (low));
 }
 
 /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
    decimal float constants, so don't return 1 for them.  */
 
 int
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 199256)
+++ gcc/fold-const.c	(working copy)
@@ -8049,21 +8049,21 @@  fold_unary_loc (location_t loc, enum tre
 	      || (TYPE_PRECISION (type)
 		  <= TYPE_PRECISION (TREE_TYPE (and_expr))))
 	    change = 1;
 	  else if (TYPE_PRECISION (TREE_TYPE (and1))
 		   <= HOST_BITS_PER_WIDE_INT
 		   && host_integerp (and1, 1))
 	    {
 	      unsigned HOST_WIDE_INT cst;
 
 	      cst = tree_low_cst (and1, 1);
-	      cst &= (HOST_WIDE_INT) -1
+	      cst &= (unsigned HOST_WIDE_INT) -1
 		     << (TYPE_PRECISION (TREE_TYPE (and1)) - 1);
 	      change = (cst == 0);
 #ifdef LOAD_EXTEND_OP
 	      if (change
 		  && !flag_syntax_only
 		  && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
 		      == ZERO_EXTEND))
 		{
 		  tree uns = unsigned_type_for (TREE_TYPE (and0));
 		  and0 = fold_convert_loc (loc, uns, and0);