OSDN Git Service

* ifcvt.c (find_if_case_1): Reinstate 2005-01-04 change, now that
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 181a33e..a870ff3 100644 (file)
@@ -560,10 +560,25 @@ combine_validate_cost (rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat)
       new_i2_cost = 0;
     }
 
+  if (undobuf.other_insn)
+    {
+      int old_other_cost, new_other_cost;
+
+      old_other_cost = (INSN_UID (undobuf.other_insn) <= last_insn_cost
+                       ? uid_insn_cost[INSN_UID (undobuf.other_insn)] : 0);
+      new_other_cost = insn_rtx_cost (PATTERN (undobuf.other_insn));
+      if (old_other_cost > 0 && new_other_cost > 0)
+       {
+         old_cost += old_other_cost;
+         new_cost += new_other_cost;
+       }
+      else
+       old_cost = 0;
+    }
+
   /* Disallow this recombination if both new_cost and old_cost are
      greater than zero, and new_cost is greater than old cost.  */
-  if (!undobuf.other_insn
-      && old_cost > 0
+  if (old_cost > 0
       && new_cost > old_cost)
     {
       if (dump_file)
@@ -3968,10 +3983,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
       }
 
       /* Don't change the mode of the MEM if that would change the meaning
-        of the address.  */
+        of the address.  Similarly, don't allow widening, as that may
+        access memory outside the defined object or using an address
+        that is invalid for a wider mode.  */
       if (MEM_P (SUBREG_REG (x))
          && (MEM_VOLATILE_P (SUBREG_REG (x))
-             || mode_dependent_address_p (XEXP (SUBREG_REG (x), 0))))
+             || mode_dependent_address_p (XEXP (SUBREG_REG (x), 0))
+             || (GET_MODE_SIZE (mode)
+                 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))))
        return gen_rtx_CLOBBER (mode, const0_rtx);
 
       /* Note that we cannot do any narrowing for non-constants since
@@ -5774,6 +5793,9 @@ expand_compound_operation (rtx x)
 
     case ZERO_EXTRACT:
       unsignedp = 1;
+
+      /* ... fall through ...  */
+
     case SIGN_EXTRACT:
       /* If the operand is a CLOBBER, just return it.  */
       if (GET_CODE (XEXP (x, 0)) == CLOBBER)
@@ -9340,8 +9362,16 @@ gen_lowpart_for_combine (enum machine_mode omode, rtx x)
   if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
     {
       x = SUBREG_REG (x);
-      if (GET_MODE (x) == omode)
+
+      /* For use in case we fall down into the address adjustments
+        further below, we need to adjust the known mode and size of
+        x; imode and isize, since we just adjusted x.  */
+      imode = GET_MODE (x);
+
+      if (imode == omode)
        return x;
+
+      isize = GET_MODE_SIZE (imode);
     }
 
   result = gen_lowpart_common (omode, x);
@@ -11402,7 +11432,6 @@ mark_used_regs_combine (rtx x)
 
        while (GET_CODE (testreg) == SUBREG
               || GET_CODE (testreg) == ZERO_EXTRACT
-              || GET_CODE (testreg) == SIGN_EXTRACT
               || GET_CODE (testreg) == STRICT_LOW_PART)
          testreg = XEXP (testreg, 0);
 
@@ -12275,7 +12304,6 @@ distribute_links (rtx links)
 
       reg = SET_DEST (set);
       while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == ZERO_EXTRACT
-            || GET_CODE (reg) == SIGN_EXTRACT
             || GET_CODE (reg) == STRICT_LOW_PART)
        reg = XEXP (reg, 0);