===================================================================
@@ -3136,6 +3136,75 @@ find_comparison_args (enum rtx_code code
return code;
}
+static rtx
+lookup_addr (rtx insn, rtx *loc, enum machine_mode mode)
+{
+ struct table_elt *elt, *p;
+ int regno;
+ int hash;
+ int base_cost;
+ rtx addr = *loc;
+ rtx exp;
+
+ /* Try to reuse existing registers for addresses, in hope of shortening
+ live ranges for the registers that compose the addresses. This happens
+ when you have
+
+ (set (reg C) (plus (reg A) (reg B))
+ (set (reg D) (mem (reg C)))
+ (set (reg E) (mem (plus (reg C) (const_int X))))
+
+ In this case fwprop will try to propagate into the addresses, but
+ if propagation into reg E fails, the only result will have been to
+ uselessly lengthen the live range of A and B. */
+
+ if (!REG_P (addr))
+ return;
+
+ regno = REGNO (addr);
+ if (regno == FRAME_POINTER_REGNUM
+ || regno == HARD_FRAME_POINTER_REGNUM
+ || regno == ARG_POINTER_REGNUM)
+ return;
+
+ /* If this address is not in the hash table, we can't look for equivalences
+ of the whole address. Also, ignore if volatile. */
+
+ {
+ int save_do_not_record = do_not_record;
+ int save_hash_arg_in_memory = hash_arg_in_memory;
+ int addr_volatile;
+
+ do_not_record = 0;
+ hash = HASH (addr, Pmode);
+ addr_volatile = do_not_record;
+ do_not_record = save_do_not_record;
+ hash_arg_in_memory = save_hash_arg_in_memory;
+
+ if (addr_volatile)
+ return;
+ }
+
+ /* Try to find a REG that holds the same address. */
+
+ elt = lookup (addr, hash, Pmode);
+ if (!elt)
+ return;
+
+ base_cost = address_cost (*loc, mode);
+ for (p = elt->first_same_value; p; p = p->next_same_value)
+ {
+ exp = p->exp;
+ if (REG_P (exp)
+ && exp_equiv_p (exp, exp, 1, false)
+ && address_cost (exp, mode) > base_cost)
+ break;
+ }
+
+ if (p)
+ validate_change (insn, loc, canon_reg (copy_rtx (exp), NULL_RTX), 0));
+}
+
/* If X is a nontrivial arithmetic operation on an argument for which
a constant value can be determined, return the result of operating
on that value, as a constant. Otherwise, return X, possibly with
@@ -3180,6 +3249,12 @@ fold_rtx (rtx x, rtx insn)
switch (code)
{
case MEM:
+ if ((new_rtx = equiv_constant (x)) != NULL_RTX)
+ return new_rtx;
+ if (insn)
+ lookup_addr (insn, &XEXP (x, 0), GET_MODE (x));
+ return x;
+
case SUBREG:
if ((new_rtx = equiv_constant (x)) != NULL_RTX)
return new_rtx;
===================================================================
@@ -1448,9 +1448,9 @@ init_optimization_passes (void)
}
NEXT_PASS (pass_web);
NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_rtl_fwprop_addr);
NEXT_PASS (pass_cse2);
NEXT_PASS (pass_rtl_dse1);
- NEXT_PASS (pass_rtl_fwprop_addr);
NEXT_PASS (pass_inc_dec);
NEXT_PASS (pass_initialize_regs);
NEXT_PASS (pass_ud_rtl_dce);