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
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,
}
}
+/* 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.
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)
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. */
&& 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;
&& 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);
&& (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);