OSDN Git Service

* check.c (same_type_check): Typo fix in comment.
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 4d71b6d..e85e9d1 100644 (file)
@@ -128,6 +128,11 @@ static int total_attempts, total_merges, total_extras, total_successes;
    so modified, or null if none.  */
 
 static rtx replaced_rhs_insn;
+
+/* When REPLACED_RHS_INSN is nonnull, this is a copy of the new right
+   hand side.  */
+
+static rtx replaced_rhs_value;
 \f
 /* Vector mapping INSN_UIDs to cuids.
    The cuids are like uids but increase monotonically always.
@@ -928,6 +933,7 @@ combine_instructions (rtx f, unsigned int nregs)
                      rtx orig = SET_SRC (set);
                      SET_SRC (set) = note;
                      replaced_rhs_insn = temp;
+                     replaced_rhs_value = copy_rtx (note);
                      next = try_combine (insn, temp, NULL_RTX,
                                          &new_direct_jump_p);
                      replaced_rhs_insn = NULL;
@@ -6854,7 +6860,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
   nonzero = nonzero_bits (x, mode);
 
   /* If none of the bits in X are needed, return a zero.  */
-  if (! just_select && (nonzero & mask) == 0)
+  if (!just_select && (nonzero & mask) == 0 && !side_effects_p (x))
     x = const0_rtx;
 
   /* If X is a CONST_INT, return a new one.  Do this here since the
@@ -8631,14 +8637,14 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
              == 0))
        code = LSHIFTRT;
 
-      if (code == LSHIFTRT
-         && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-         && !(nonzero_bits (varop, shift_mode) >> count))
-       varop = const0_rtx;
-      if (code == ASHIFT
-         && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-         && !((nonzero_bits (varop, shift_mode) << count)
-              & GET_MODE_MASK (shift_mode)))
+      if (((code == LSHIFTRT
+           && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+           && !(nonzero_bits (varop, shift_mode) >> count))
+          || (code == ASHIFT
+              && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+              && !((nonzero_bits (varop, shift_mode) << count)
+                   & GET_MODE_MASK (shift_mode))))
+         && !side_effects_p (varop))
        varop = const0_rtx;
 
       switch (GET_CODE (varop))
@@ -9223,9 +9229,12 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
       if (outer_op == AND)
        x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const);
       else if (outer_op == SET)
-       /* This means that we have determined that the result is
-          equivalent to a constant.  This should be rare.  */
-       x = GEN_INT (outer_const);
+       {
+         /* This means that we have determined that the result is
+            equivalent to a constant.  This should be rare.  */
+         if (!side_effects_p (x))
+           x = GEN_INT (outer_const);
+       }
       else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
        x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
       else
@@ -12122,7 +12131,9 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
             In both cases, we must search to see if we can find a previous
             use of A and put the death note there.  */
 
-         if (from_insn && from_insn == replaced_rhs_insn)
+         if (from_insn
+             && from_insn == replaced_rhs_insn
+             && !reg_overlap_mentioned_p (XEXP (note, 0), replaced_rhs_value))
            tem = from_insn;
          else
            {
@@ -12154,12 +12165,14 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                      continue;
                    }
 
-                 /* If the register is being set at TEM, see if that is all
-                    TEM is doing.  If so, delete TEM.  Otherwise, make this
-                    into a REG_UNUSED note instead. Don't delete sets to
-                    global register vars.  */
-                 if ((REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER
-                      || !global_regs[REGNO (XEXP (note, 0))])
+                 /* If TEM is a (reaching) definition of the use to which the
+                    note was attached, see if that is all TEM is doing.  If so,
+                    delete TEM.  Otherwise, make this into a REG_UNUSED note
+                    instead.  Don't delete sets to global register vars.  */
+                 if ((!from_insn
+                      || INSN_CUID (tem) < INSN_CUID (from_insn))
+                     && (REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER
+                         || !global_regs[REGNO (XEXP (note, 0))])
                      && reg_set_p (XEXP (note, 0), PATTERN (tem)))
                    {
                      rtx set = single_set (tem);