OSDN Git Service

gcc/:
[pf3gnuchains/gcc-fork.git] / gcc / postreload.c
index 2c6a8c5..0a70b20 100644 (file)
@@ -528,7 +528,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
          if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
            continue;
 
-         SET_REGNO (testreg, regno);
+         SET_REGNO_RAW (testreg, regno);
          PUT_MODE (testreg, mode);
 
          /* We found a register equal to this operand.  Now look for all
@@ -573,6 +573,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
                     alternative yet and the operand being replaced is not
                     a cheap CONST_INT.  */
                  if (op_alt_regno[i][j] == -1
+                     && recog_data.alternative_enabled_p[j]
                      && reg_fits_class_p (testreg, rclass, 0, mode)
                      && (!CONST_INT_P (recog_data.operand[i])
                          || (rtx_cost (recog_data.operand[i], SET,
@@ -871,6 +872,61 @@ fixup_debug_insns (rtx reg, rtx replacement, rtx from, rtx to)
     }
 }
 
+/* Subroutine of reload_combine_recognize_const_pattern.  Try to replace REG
+   with SRC in the insn described by USE, taking costs into account.  Return
+   true if we made the replacement.  */
+
+static bool
+try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
+{
+  rtx use_insn = use->insn;
+  rtx mem = use->containing_mem;
+  bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
+
+  if (mem != NULL_RTX)
+    {
+      addr_space_t as = MEM_ADDR_SPACE (mem);
+      rtx oldaddr = XEXP (mem, 0);
+      rtx newaddr = NULL_RTX;
+      int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
+      int new_cost;
+
+      newaddr = simplify_replace_rtx (oldaddr, reg, src);
+      if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
+       {
+         XEXP (mem, 0) = newaddr;
+         new_cost = address_cost (newaddr, GET_MODE (mem), as, speed);
+         XEXP (mem, 0) = oldaddr;
+         if (new_cost <= old_cost
+             && validate_change (use_insn,
+                                 &XEXP (mem, 0), newaddr, 0))
+           return true;
+       }
+    }
+  else
+    {
+      rtx new_set = single_set (use_insn);
+      if (new_set
+         && REG_P (SET_DEST (new_set))
+         && GET_CODE (SET_SRC (new_set)) == PLUS
+         && REG_P (XEXP (SET_SRC (new_set), 0))
+         && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
+       {
+         rtx new_src;
+         int old_cost = rtx_cost (SET_SRC (new_set), SET, speed);
+
+         gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
+         new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
+
+         if (rtx_cost (new_src, SET, speed) <= old_cost
+             && validate_change (use_insn, &SET_SRC (new_set),
+                                 new_src, 0))
+           return true;
+       }
+    }
+  return false;
+}
+
 /* Called by reload_combine when scanning INSN.  This function tries to detect
    patterns where a constant is added to a register, and the result is used
    in an address.
@@ -940,10 +996,9 @@ reload_combine_recognize_const_pattern (rtx insn)
 
       if (use && GET_MODE (*use->usep) == Pmode)
        {
+         bool delete_add = false;
          rtx use_insn = use->insn;
          int use_ruid = use->ruid;
-         rtx mem = use->containing_mem;
-         bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
 
          /* Avoid moving the add insn past a jump.  */
          if (must_move_add && use_ruid <= last_jump_ruid)
@@ -957,81 +1012,37 @@ reload_combine_recognize_const_pattern (rtx insn)
 
          gcc_assert (reg_state[regno].store_ruid <= use_ruid);
          /* Avoid moving a use of ADDREG past a point where it is stored.  */
-         if (reg_state[REGNO (addreg)].store_ruid >= use_ruid)
+         if (reg_state[REGNO (addreg)].store_ruid > use_ruid)
            break;
 
-         if (mem != NULL_RTX)
+         /* We also must not move the addition past an insn that sets
+            the same register, unless we can combine two add insns.  */
+         if (must_move_add && reg_state[regno].store_ruid == use_ruid)
            {
-             addr_space_t as = MEM_ADDR_SPACE (mem);
-             rtx oldaddr = XEXP (mem, 0);
-             rtx newaddr = NULL_RTX;
-             int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed);
-             int new_cost;
-
-             newaddr = simplify_replace_rtx (oldaddr, reg, src);
-             if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as))
-               {
-                 XEXP (mem, 0) = newaddr;
-                 new_cost = address_cost (newaddr, GET_MODE (mem), as, speed);
-                 XEXP (mem, 0) = oldaddr;
-                 if (new_cost <= old_cost
-                     && validate_change (use_insn,
-                                         &XEXP (mem, 0), newaddr, 0))
-                   {
-                     reload_combine_purge_insn_uses (use_insn);
-                     reload_combine_note_use (&PATTERN (use_insn), use_insn,
-                                              use_ruid, NULL_RTX);
-
-                     if (must_move_add)
-                       {
-                         add_moved_after_insn = use_insn;
-                         add_moved_after_ruid = use_ruid;
-                       }
-                     continue;
-                   }
-               }
+             if (use->containing_mem == NULL_RTX)
+               delete_add = true;
+             else
+               break;
            }
-         else
-           {
-             rtx new_set = single_set (use_insn);
-             if (new_set
-                 && REG_P (SET_DEST (new_set))
-                 && GET_CODE (SET_SRC (new_set)) == PLUS
-                 && REG_P (XEXP (SET_SRC (new_set), 0))
-                 && CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
-               {
-                 rtx new_src;
-                 int old_cost = rtx_cost (SET_SRC (new_set), SET, speed);
-
-                 gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
-                 new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
 
-                 if (rtx_cost (new_src, SET, speed) <= old_cost
-                     && validate_change (use_insn, &SET_SRC (new_set),
-                                         new_src, 0))
-                   {
-                     reload_combine_purge_insn_uses (use_insn);
-                     reload_combine_note_use (&SET_SRC (new_set), use_insn,
-                                              use_ruid, NULL_RTX);
+         if (try_replace_in_use (use, reg, src))
+           {
+             reload_combine_purge_insn_uses (use_insn);
+             reload_combine_note_use (&PATTERN (use_insn), use_insn,
+                                      use_ruid, NULL_RTX);
 
-                     if (must_move_add)
-                       {
-                         /* See if that took care of the add insn.  */
-                         if (rtx_equal_p (SET_DEST (new_set), reg))
-                           {
-                             fixup_debug_insns (reg, src, insn, use_insn);
-                             delete_insn (insn);
-                             return true;
-                           }
-                         else
-                           {
-                             add_moved_after_insn = use_insn;
-                             add_moved_after_ruid = use_ruid;
-                           }
-                       }
-                     continue;
-                   }
+             if (delete_add)
+               {
+                 fixup_debug_insns (reg, src, insn, use_insn);
+                 delete_insn (insn);
+                 return true;
                }
+             if (must_move_add)
+               {
+                 add_moved_after_insn = use_insn;
+                 add_moved_after_ruid = use_ruid;
+               }
+             continue;
            }
        }
       /* If we get here, we couldn't handle this use.  */
@@ -1103,7 +1114,7 @@ reload_combine_recognize_pattern (rtx insn)
       && last_label_ruid < reg_state[regno].use_ruid)
     {
       rtx base = XEXP (src, 1);
-      rtx prev = prev_nonnote_insn (insn);
+      rtx prev = prev_nonnote_nondebug_insn (insn);
       rtx prev_set = prev ? single_set (prev) : NULL_RTX;
       rtx index_reg = NULL_RTX;
       rtx reg_sum = NULL_RTX;
@@ -1842,7 +1853,7 @@ reload_cse_move2add (rtx first)
                       && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg),
                                                 reg_mode[REGNO (src)]))
                {
-                 rtx next = next_nonnote_insn (insn);
+                 rtx next = next_nonnote_nondebug_insn (insn);
                  rtx set = NULL_RTX;
                  if (next)
                    set = single_set (next);
@@ -2093,15 +2104,17 @@ move2add_note_store (rtx dst, const_rtx set, void *data)
                       && (MODES_OK_FOR_MOVE2ADD
                           (dst_mode, reg_mode[REGNO (XEXP (src, 1))])))
                {
-                 if (reg_base_reg[REGNO (XEXP (src, 1))] < 0)
+                 if (reg_base_reg[REGNO (XEXP (src, 1))] < 0
+                     && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX)
                    offset = reg_offset[REGNO (XEXP (src, 1))];
                  /* Maybe the first register is known to be a
                     constant.  */
                  else if (reg_set_luid[REGNO (base_reg)]
                           > move2add_last_label_luid
                           && (MODES_OK_FOR_MOVE2ADD
-                              (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))
-                          && reg_base_reg[REGNO (base_reg)] < 0)
+                              (dst_mode, reg_mode[REGNO (base_reg)]))
+                          && reg_base_reg[REGNO (base_reg)] < 0
+                          && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX)
                    {
                      offset = reg_offset[REGNO (base_reg)];
                      base_reg = XEXP (src, 1);