Commit 23b33725 by Richard Sandiford Committed by Richard Sandiford

emit-rtl.h (replace_equiv_address, [...]): Add an inplace argument.

gcc/
	* emit-rtl.h (replace_equiv_address, replace_equiv_address_nv): Add an
	inplace argument.  Store the new address in the original MEM when true.
	* emit-rtl.c (change_address_1): Likewise.
	(adjust_address_1, adjust_automodify_address_1, offset_address):
	Update accordingly.
	* rtl.h (plus_constant): Add an inplace argument.
	* explow.c (plus_constant): Likewise.  Try to reuse the original PLUS
	when true.  Avoid generating (plus X (const_int 0)).
	* function.c (instantiate_virtual_regs_in_rtx): Adjust the PLUS
	in-place.  Pass true to plus_constant.
	(instantiate_virtual_regs_in_insn): Pass true to replace_equiv_address.

From-SVN: r210543
parent e16db399
2014-05-17 Richard Sandiford <rdsandiford@googlemail.com>
* emit-rtl.h (replace_equiv_address, replace_equiv_address_nv): Add an
inplace argument. Store the new address in the original MEM when true.
* emit-rtl.c (change_address_1): Likewise.
(adjust_address_1, adjust_automodify_address_1, offset_address):
Update accordingly.
* rtl.h (plus_constant): Add an inplace argument.
* explow.c (plus_constant): Likewise. Try to reuse the original PLUS
when true. Avoid generating (plus X (const_int 0)).
* function.c (instantiate_virtual_regs_in_rtx): Adjust the PLUS
in-place. Pass true to plus_constant.
(instantiate_virtual_regs_in_insn): Pass true to replace_equiv_address.
2014-05-16 Dehao Chen <dehao@google.com> 2014-05-16 Dehao Chen <dehao@google.com>
* tree-cfg.c (gimple_merge_blocks): Updates bb count with max count. * tree-cfg.c (gimple_merge_blocks): Updates bb count with max count.
......
...@@ -145,7 +145,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) ...@@ -145,7 +145,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
#define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid) #define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid)
#define first_label_num (crtl->emit.x_first_label_num) #define first_label_num (crtl->emit.x_first_label_num)
static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
static void set_used_decls (tree); static void set_used_decls (tree);
static void mark_label_nuses (rtx); static void mark_label_nuses (rtx);
static hashval_t const_int_htab_hash (const void *); static hashval_t const_int_htab_hash (const void *);
...@@ -2010,11 +2009,15 @@ clear_mem_size (rtx mem) ...@@ -2010,11 +2009,15 @@ clear_mem_size (rtx mem)
/* Return a memory reference like MEMREF, but with its mode changed to MODE /* Return a memory reference like MEMREF, but with its mode changed to MODE
and its address changed to ADDR. (VOIDmode means don't change the mode. and its address changed to ADDR. (VOIDmode means don't change the mode.
NULL for ADDR means don't change the address.) VALIDATE is nonzero if the NULL for ADDR means don't change the address.) VALIDATE is nonzero if the
returned memory location is required to be valid. The memory returned memory location is required to be valid. INPLACE is true if any
attributes are not changed. */ changes can be made directly to MEMREF or false if MEMREF must be treated
as immutable.
The memory attributes are not changed. */
static rtx static rtx
change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate) change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate,
bool inplace)
{ {
addr_space_t as; addr_space_t as;
rtx new_rtx; rtx new_rtx;
...@@ -2042,6 +2045,12 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate) ...@@ -2042,6 +2045,12 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref)) if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
return memref; return memref;
if (inplace)
{
XEXP (memref, 0) = addr;
return memref;
}
new_rtx = gen_rtx_MEM (mode, addr); new_rtx = gen_rtx_MEM (mode, addr);
MEM_COPY_ATTRIBUTES (new_rtx, memref); MEM_COPY_ATTRIBUTES (new_rtx, memref);
return new_rtx; return new_rtx;
...@@ -2053,7 +2062,7 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate) ...@@ -2053,7 +2062,7 @@ change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
rtx rtx
change_address (rtx memref, enum machine_mode mode, rtx addr) change_address (rtx memref, enum machine_mode mode, rtx addr)
{ {
rtx new_rtx = change_address_1 (memref, mode, addr, 1); rtx new_rtx = change_address_1 (memref, mode, addr, 1, false);
enum machine_mode mmode = GET_MODE (new_rtx); enum machine_mode mmode = GET_MODE (new_rtx);
struct mem_attrs attrs, *defattrs; struct mem_attrs attrs, *defattrs;
...@@ -2166,7 +2175,7 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, ...@@ -2166,7 +2175,7 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
addr = plus_constant (address_mode, addr, offset); addr = plus_constant (address_mode, addr, offset);
} }
new_rtx = change_address_1 (memref, mode, addr, validate); new_rtx = change_address_1 (memref, mode, addr, validate, false);
/* If the address is a REG, change_address_1 rightfully returns memref, /* If the address is a REG, change_address_1 rightfully returns memref,
but this would destroy memref's MEM_ATTRS. */ but this would destroy memref's MEM_ATTRS. */
...@@ -2236,7 +2245,7 @@ rtx ...@@ -2236,7 +2245,7 @@ rtx
adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr, adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr,
HOST_WIDE_INT offset, int validate) HOST_WIDE_INT offset, int validate)
{ {
memref = change_address_1 (memref, VOIDmode, addr, validate); memref = change_address_1 (memref, VOIDmode, addr, validate, false);
return adjust_address_1 (memref, mode, offset, validate, 0, 0, 0); return adjust_address_1 (memref, mode, offset, validate, 0, 0, 0);
} }
...@@ -2272,7 +2281,7 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) ...@@ -2272,7 +2281,7 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
} }
update_temp_slot_address (XEXP (memref, 0), new_rtx); update_temp_slot_address (XEXP (memref, 0), new_rtx);
new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1); new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1, false);
/* If there are no changes, just return the original memory reference. */ /* If there are no changes, just return the original memory reference. */
if (new_rtx == memref) if (new_rtx == memref)
...@@ -2292,23 +2301,25 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) ...@@ -2292,23 +2301,25 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
/* Return a memory reference like MEMREF, but with its address changed to /* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as to is the same, just the form of the address is being changed, such as
by putting something into a register. */ by putting something into a register. INPLACE is true if any changes
can be made directly to MEMREF or false if MEMREF must be treated as
immutable. */
rtx rtx
replace_equiv_address (rtx memref, rtx addr) replace_equiv_address (rtx memref, rtx addr, bool inplace)
{ {
/* change_address_1 copies the memory attribute structure without change /* change_address_1 copies the memory attribute structure without change
and that's exactly what we want here. */ and that's exactly what we want here. */
update_temp_slot_address (XEXP (memref, 0), addr); update_temp_slot_address (XEXP (memref, 0), addr);
return change_address_1 (memref, VOIDmode, addr, 1); return change_address_1 (memref, VOIDmode, addr, 1, inplace);
} }
/* Likewise, but the reference is not required to be valid. */ /* Likewise, but the reference is not required to be valid. */
rtx rtx
replace_equiv_address_nv (rtx memref, rtx addr) replace_equiv_address_nv (rtx memref, rtx addr, bool inplace)
{ {
return change_address_1 (memref, VOIDmode, addr, 0); return change_address_1 (memref, VOIDmode, addr, 0, inplace);
} }
/* Return a memory reference like MEMREF, but with its mode widened to /* Return a memory reference like MEMREF, but with its mode widened to
......
...@@ -52,10 +52,10 @@ extern tree get_spill_slot_decl (bool); ...@@ -52,10 +52,10 @@ extern tree get_spill_slot_decl (bool);
ADDR. The caller is asserting that the actual piece of memory pointed ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as to is the same, just the form of the address is being changed, such as
by putting something into a register. */ by putting something into a register. */
extern rtx replace_equiv_address (rtx, rtx); extern rtx replace_equiv_address (rtx, rtx, bool = false);
/* Likewise, but the reference is not required to be valid. */ /* Likewise, but the reference is not required to be valid. */
extern rtx replace_equiv_address_nv (rtx, rtx); extern rtx replace_equiv_address_nv (rtx, rtx, bool = false);
extern rtx gen_blockage (void); extern rtx gen_blockage (void);
extern rtvec gen_rtvec (int, ...); extern rtvec gen_rtvec (int, ...);
......
...@@ -74,10 +74,12 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode) ...@@ -74,10 +74,12 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
} }
/* Return an rtx for the sum of X and the integer C, given that X has /* Return an rtx for the sum of X and the integer C, given that X has
mode MODE. */ mode MODE. INPLACE is true if X can be modified inplace or false
if it must be treated as immutable. */
rtx rtx
plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c) plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c,
bool inplace)
{ {
RTX_CODE code; RTX_CODE code;
rtx y; rtx y;
...@@ -116,6 +118,8 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c) ...@@ -116,6 +118,8 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
case CONST: case CONST:
/* If adding to something entirely constant, set a flag /* If adding to something entirely constant, set a flag
so that we can add a CONST around the result. */ so that we can add a CONST around the result. */
if (inplace && shared_const_p (x))
inplace = false;
x = XEXP (x, 0); x = XEXP (x, 0);
all_constant = 1; all_constant = 1;
goto restart; goto restart;
...@@ -136,19 +140,25 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c) ...@@ -136,19 +140,25 @@ plus_constant (enum machine_mode mode, rtx x, HOST_WIDE_INT c)
if (CONSTANT_P (XEXP (x, 1))) if (CONSTANT_P (XEXP (x, 1)))
{ {
x = gen_rtx_PLUS (mode, XEXP (x, 0), rtx term = plus_constant (mode, XEXP (x, 1), c, inplace);
plus_constant (mode, XEXP (x, 1), c)); if (term == const0_rtx)
x = XEXP (x, 0);
else if (inplace)
XEXP (x, 1) = term;
else
x = gen_rtx_PLUS (mode, XEXP (x, 0), term);
c = 0; c = 0;
} }
else if (find_constant_term_loc (&y)) else if (rtx *const_loc = find_constant_term_loc (&y))
{ {
/* We need to be careful since X may be shared and we can't if (!inplace)
modify it in place. */ {
rtx copy = copy_rtx (x); /* We need to be careful since X may be shared and we can't
rtx *const_loc = find_constant_term_loc (&copy); modify it in place. */
x = copy_rtx (x);
*const_loc = plus_constant (mode, *const_loc, c); const_loc = find_constant_term_loc (&x);
x = copy; }
*const_loc = plus_constant (mode, *const_loc, c, true);
c = 0; c = 0;
} }
break; break;
......
...@@ -1459,8 +1459,8 @@ instantiate_virtual_regs_in_rtx (rtx *loc, void *data) ...@@ -1459,8 +1459,8 @@ instantiate_virtual_regs_in_rtx (rtx *loc, void *data)
new_rtx = instantiate_new_reg (XEXP (x, 0), &offset); new_rtx = instantiate_new_reg (XEXP (x, 0), &offset);
if (new_rtx) if (new_rtx)
{ {
new_rtx = plus_constant (GET_MODE (x), new_rtx, offset); XEXP (x, 0) = new_rtx;
*loc = simplify_gen_binary (PLUS, GET_MODE (x), new_rtx, XEXP (x, 1)); *loc = plus_constant (GET_MODE (x), x, offset, true);
if (changed) if (changed)
*changed = true; *changed = true;
return -1; return -1;
...@@ -1622,7 +1622,7 @@ instantiate_virtual_regs_in_insn (rtx insn) ...@@ -1622,7 +1622,7 @@ instantiate_virtual_regs_in_insn (rtx insn)
continue; continue;
start_sequence (); start_sequence ();
x = replace_equiv_address (x, addr); x = replace_equiv_address (x, addr, true);
/* It may happen that the address with the virtual reg /* It may happen that the address with the virtual reg
was valid (e.g. based on the virtual stack reg, which might was valid (e.g. based on the virtual stack reg, which might
be acceptable to the predicates with all offsets), whereas be acceptable to the predicates with all offsets), whereas
...@@ -1635,7 +1635,7 @@ instantiate_virtual_regs_in_insn (rtx insn) ...@@ -1635,7 +1635,7 @@ instantiate_virtual_regs_in_insn (rtx insn)
if (!safe_insn_predicate (insn_code, i, x)) if (!safe_insn_predicate (insn_code, i, x))
{ {
addr = force_reg (GET_MODE (addr), addr); addr = force_reg (GET_MODE (addr), addr);
x = replace_equiv_address (x, addr); x = replace_equiv_address (x, addr, true);
} }
seq = get_insns (); seq = get_insns ();
end_sequence (); end_sequence ();
......
...@@ -1952,7 +1952,7 @@ extern int currently_expanding_to_rtl; ...@@ -1952,7 +1952,7 @@ extern int currently_expanding_to_rtl;
/* In explow.c */ /* In explow.c */
extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, enum machine_mode); extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, enum machine_mode);
extern rtx plus_constant (enum machine_mode, rtx, HOST_WIDE_INT); extern rtx plus_constant (enum machine_mode, rtx, HOST_WIDE_INT, bool = false);
/* In rtl.c */ /* In rtl.c */
extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL); extern rtx rtx_alloc_stat (RTX_CODE MEM_STAT_DECL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment