OSDN Git Service

(i386_return_pops_args): Libcalls ignore TARGET_RTD.
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 506edb0..cc27b58 100644 (file)
@@ -2312,6 +2312,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
   enum machine_mode lmode, rmode, lnmode, rnmode;
   int lunsignedp, runsignedp;
   int lvolatilep = 0, rvolatilep = 0;
+  int alignment;
   tree linner, rinner;
   tree mask;
   tree offset;
@@ -2320,7 +2321,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
      if the same as the size of the underlying object, we aren't doing an
      extraction at all and so can do nothing.  */
   linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
-                               &lunsignedp, &lvolatilep);
+                               &lunsignedp, &lvolatilep, &alignment);
   if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
       || offset != 0)
     return 0;
@@ -2329,8 +2330,8 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
    {
      /* If this is not a constant, we can only do something if bit positions,
        sizes, and signedness are the same.   */
-     rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset,
-                                  &rmode, &runsignedp, &rvolatilep);
+     rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
+                                  &runsignedp, &rvolatilep, &alignment);
 
      if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
         || lunsignedp != runsignedp || offset != 0)
@@ -2503,6 +2504,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
   tree mask, inner, offset;
   tree unsigned_type;
   int precision;
+  int alignment;
 
   /* All the optimizations using this function assume integer fields.  
      There are problems with FP fields since the type_for_size call
@@ -2523,7 +2525,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
 
 
   inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
-                              punsignedp, pvolatilep);
+                              punsignedp, pvolatilep, &alignment);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0)
     return 0;
@@ -2974,7 +2976,7 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
       /* If they don't overlap, the result is the first range.  If the
         second range is a subset of the first, we can't describe this as
         a single range unless both ranges end at the same place.  If both
-        ranges also start in the same place, then the result is false.
+        ranges start in the same place, then the result is false.
         Otherwise, we go from the start of the first range to just before
         the start of the second.  */
       if (no_overlap)
@@ -2983,9 +2985,8 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
               && integer_zerop (range_binop (EQ_EXPR, integer_type_node,
                                              high0, 1, high1, 0)))
        return 0;
-      else if (subset
-              && integer_onep (range_binop (EQ_EXPR, integer_type_node,
-                                            low0, 0, low1, 0)))
+      else if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
+                                         low0, 0, low1, 0)))
        in_p = 0, low = high = 0;
       else
        {
@@ -3127,18 +3128,28 @@ unextend (c, p, unsignedp, mask)
   if (p == modesize || unsignedp)
     return c;
 
-  if (TREE_UNSIGNED (type))
-    c = convert (signed_type (type), c);
-
   /* We work by getting just the sign bit into the low-order bit, then
      into the high-order bit, then sign-extend.  We then XOR that value
      with C.  */
   temp = const_binop (RSHIFT_EXPR, c, size_int (p - 1), 0);
   temp = const_binop (BIT_AND_EXPR, temp, size_int (1), 0);
+
+  /* We must use a signed type in order to get an arithmetic right shift.
+     However, we must also avoid introducing accidental overflows, so that
+     a subsequent call to integer_zerop will work.  Hence we must 
+     do the type conversion here.  At this point, the constant is either
+     zero or one, and the conversion to a signed type can never overflow.
+     We could get an overflow if this conversion is done anywhere else.  */
+  if (TREE_UNSIGNED (type))
+    temp = convert (signed_type (type), temp);
+
   temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
   temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
   if (mask != 0)
     temp = const_binop (BIT_AND_EXPR, temp, convert (TREE_TYPE (c), mask), 0);
+  /* If necessary, convert the type back to match the type of C.  */
+  if (TREE_UNSIGNED (type))
+    temp = convert (type, temp);
 
   return convert (type, const_binop (BIT_XOR_EXPR, c, temp, 0));
 }