OSDN Git Service

PR middle-end/30761
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 1ea559e..c86b2bd 100644 (file)
@@ -3105,35 +3105,15 @@ eliminate_regs_in_insn (rtx insn, int replace)
            if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
              to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),
                                    to_rtx);
-           if (offset == 0)
-             {
-               int num_clobbers;
-               /* We assume here that if we need a PARALLEL with
-                  CLOBBERs for this assignment, we can do with the
-                  MATCH_SCRATCHes that add_clobbers allocates.
-                  There's not much we can do if that doesn't work.  */
-               PATTERN (insn) = gen_rtx_SET (VOIDmode,
-                                             SET_DEST (old_set),
-                                             to_rtx);
-               num_clobbers = 0;
-               INSN_CODE (insn) = recog (PATTERN (insn), insn, &num_clobbers);
-               if (num_clobbers)
-                 {
-                   rtvec vec = rtvec_alloc (num_clobbers + 1);
-
-                   vec->elem[0] = PATTERN (insn);
-                   PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
-                   add_clobbers (PATTERN (insn), INSN_CODE (insn));
-                 }
-               gcc_assert (INSN_CODE (insn) >= 0);
-             }
            /* If we have a nonzero offset, and the source is already
               a simple REG, the following transformation would
               increase the cost of the insn by replacing a simple REG
               with (plus (reg sp) CST).  So try only when we already
               had a PLUS before.  */
-           else if (plus_src)
+           if (offset == 0 || plus_src)
              {
+               rtx new_src = plus_constant (to_rtx, offset);
+
                new_body = old_body;
                if (! replace)
                  {
@@ -3144,8 +3124,20 @@ eliminate_regs_in_insn (rtx insn, int replace)
                PATTERN (insn) = new_body;
                old_set = single_set (insn);
 
-               XEXP (SET_SRC (old_set), 0) = to_rtx;
-               XEXP (SET_SRC (old_set), 1) = GEN_INT (offset);
+               /* First see if this insn remains valid when we make the
+                  change.  If not, try to replace the whole pattern with
+                  a simple set (this may help if the original insn was a
+                  PARALLEL that was only recognized as single_set due to 
+                  REG_UNUSED notes).  If this isn't valid either, keep
+                  the INSN_CODE the same and let reload fix it up.  */
+               if (!validate_change (insn, &SET_SRC (old_set), new_src, 0))
+                 {
+                   rtx new_pat = gen_rtx_SET (VOIDmode,
+                                              SET_DEST (old_set), new_src);
+
+                   if (!validate_change (insn, &PATTERN (insn), new_pat, 0))
+                     SET_SRC (old_set) = new_src;
+                 }
              }
            else
              break;