Add cselib; use it in loop and reload_cse_regs
From-SVN: r32538
This commit is contained in:
parent
4bdf01f210
commit
eab5c70a03
@ -1,3 +1,67 @@
|
|||||||
|
2000-03-14 Bernd Schmidt <bernds@cygnus.co.uk>
|
||||||
|
|
||||||
|
* cselib.h: New file.
|
||||||
|
* alias.c: Include "cselib.h".
|
||||||
|
(fixed_scalar_and_varying_struct_p): Accept the addresses of the
|
||||||
|
MEMs as two new arguments.
|
||||||
|
(get_addr): New static function.
|
||||||
|
(find_base_term): Handle VALUEs.
|
||||||
|
(memrefs_conflict_p): Likewise.
|
||||||
|
(true_dependence): Call get_addr on the addresses.
|
||||||
|
Call fixed_scalar_and_varying_struct_p with addresses that have been
|
||||||
|
passed through get_addr and canon_rtx.
|
||||||
|
(write_dependence_p): Move DIFFERENT_ALIAS_SETS_P test for consistency
|
||||||
|
with true_dependence.
|
||||||
|
Call get_addr on the addresses; don't call canon_rtx on the MEMs.
|
||||||
|
* loop.c: Include "cselib.h".
|
||||||
|
(load_mems): Process extended basic block that enters the loop with
|
||||||
|
cselib. Use that information to change initialization of the shadow
|
||||||
|
register so that a constant equivalence is seen by later passes.
|
||||||
|
* reload1.c: Include "cselib.h".
|
||||||
|
(reload_cse_invalidate_regno): Delete function.
|
||||||
|
(reload_cse_mem_conflict_p): Likewise.
|
||||||
|
(reload_cse_invalidate_mem): Likewise.
|
||||||
|
(reload_cse_invalidate_rtx): Likewise.
|
||||||
|
(reload_cse_regno_equal_p): Likewise.
|
||||||
|
(reload_cse_check_clobber): Likewise.
|
||||||
|
(reload_cse_record_set): Likewise.
|
||||||
|
(reg_values): Delete static variable.
|
||||||
|
(invalidate_regno_rtx): Likewise.
|
||||||
|
(reload_cse_delete_noop_set): New static function.
|
||||||
|
(reload_cse_simplify): New static function, broken out of
|
||||||
|
reload_cse_regs_1.
|
||||||
|
(reload_cse_noop_set_p): Delete unused argument INSN.
|
||||||
|
Just call rtx_equal_for_cselib_p on set source and destination.
|
||||||
|
(reload_cse_regs_1): Break out some code into reload_cse_simplify and
|
||||||
|
reload_cse_delete_noop_set. Delete code to keep track of values; use
|
||||||
|
cselib functions instead. Delete code to push/pop obstacks.
|
||||||
|
(reload_cse_simplify_set): Use cselib to find equivalent values.
|
||||||
|
Delete code to push/pop obstacks.
|
||||||
|
(reload_cse_simplify_operands): Likewise.
|
||||||
|
* rtl.def (VALUE): New rtx code.
|
||||||
|
* rtl.h (union rtunion_def): New elt rt_cselib.
|
||||||
|
(X0CSELIB, CSELIB_VAL_PTR): New macros.
|
||||||
|
* simplify_rtx.c: Include "ggc.h", "obstack.h", "cselib.h".
|
||||||
|
(new_elt_list, new_elt_loc_list, unchain_one_value, clear_table,
|
||||||
|
unchain_one_elt_list, unchain_one_elt_loc_list, check_useless_values,
|
||||||
|
discard_useless_locs, discard_useless_values, entry_and_rtx_equal_p,
|
||||||
|
hash_rtx, new_cselib_val, add_mem_for_addr, get_value_hash,
|
||||||
|
cselib_lookup_mem, cselib_subst_to_values, cselib_invalidate_regno,
|
||||||
|
cselib_mem_conflict_p, cselib_invalidate_mem, cselib_invalidate_rtx,
|
||||||
|
cselib_record_set, cselib_record_sets): New static functions.
|
||||||
|
(cselib_lookup, cselib_update_varray_sizes, cselib_init,
|
||||||
|
cselib_finish, cselib_process_insn, rtx_equal_for_cselib_p,
|
||||||
|
references_value_p): New functions.
|
||||||
|
(MAX_USELESS_VALUES, REG_VALUES): New macros.
|
||||||
|
(table, cselib_current_insn, next_unknown_value, cselib_nregs,
|
||||||
|
n_useless_values, reg_values, callmem, cselib_obstack,
|
||||||
|
cselib_startobj, empty_vals, empty_elt_lists, empty_elt_loc_lists):
|
||||||
|
New static variables.
|
||||||
|
* varray.h (union varray_data_tag): New elt te.
|
||||||
|
(VARRAY_ELT_LIST_INIT, VARRAY_ELT_LIST): New macros.
|
||||||
|
* Makefile.in (reload1.o, loop.o, simplify-rtx.o, alias.o): Update
|
||||||
|
dependencies.
|
||||||
|
|
||||||
2000-03-14 Nick Clifton <nickc@cygnus.com>
|
2000-03-14 Nick Clifton <nickc@cygnus.com>
|
||||||
|
|
||||||
* gcc.c (do_spec_1): Catch the case where %* is used in a
|
* gcc.c (do_spec_1): Catch the case where %* is used in a
|
||||||
|
@ -1556,7 +1556,7 @@ jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
|
|||||||
|
|
||||||
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) \
|
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) \
|
||||||
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
|
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
|
||||||
output.h function.h
|
output.h function.h cselib.h ggc.h $(srcdir)/../include/obstack.h
|
||||||
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
|
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
|
||||||
real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h ggc.h
|
real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h ggc.h
|
||||||
gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
|
gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
|
||||||
@ -1574,7 +1574,7 @@ profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-flags.h \
|
|||||||
ggc.h
|
ggc.h
|
||||||
loop.o : loop.c $(CONFIG_H) system.h $(RTL_H) flags.h $(LOOP_H) insn-config.h \
|
loop.o : loop.c $(CONFIG_H) system.h $(RTL_H) flags.h $(LOOP_H) insn-config.h \
|
||||||
insn-flags.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) real.h \
|
insn-flags.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) real.h \
|
||||||
$(BASIC_BLOCK_H) function.h toplev.h varray.h except.h
|
$(BASIC_BLOCK_H) function.h toplev.h varray.h except.h cselib.h
|
||||||
unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h function.h \
|
unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h function.h \
|
||||||
$(INTEGRATE_H) $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) $(LOOP_H) toplev.h \
|
$(INTEGRATE_H) $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) $(LOOP_H) toplev.h \
|
||||||
varray.h
|
varray.h
|
||||||
@ -1600,7 +1600,7 @@ reload.o : reload.c $(CONFIG_H) system.h $(RTL_H) flags.h output.h $(EXPR_H) \
|
|||||||
function.h real.h toplev.h
|
function.h real.h toplev.h
|
||||||
reload1.o : reload1.c $(CONFIG_H) system.h $(RTL_H) real.h flags.h $(EXPR_H) \
|
reload1.o : reload1.c $(CONFIG_H) system.h $(RTL_H) real.h flags.h $(EXPR_H) \
|
||||||
reload.h $(REGS_H) hard-reg-set.h insn-config.h insn-flags.h insn-codes.h \
|
reload.h $(REGS_H) hard-reg-set.h insn-config.h insn-flags.h insn-codes.h \
|
||||||
$(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h
|
$(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h cselib.h
|
||||||
caller-save.o : caller-save.c $(CONFIG_H) system.h $(RTL_H) flags.h \
|
caller-save.o : caller-save.c $(CONFIG_H) system.h $(RTL_H) flags.h \
|
||||||
$(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \
|
$(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \
|
||||||
$(RECOG_H) reload.h $(EXPR_H) toplev.h
|
$(RECOG_H) reload.h $(EXPR_H) toplev.h
|
||||||
@ -1608,7 +1608,8 @@ reorg.o : reorg.c $(CONFIG_H) system.h $(RTL_H) conditions.h hard-reg-set.h \
|
|||||||
$(BASIC_BLOCK_H) $(REGS_H) insn-config.h insn-attr.h insn-flags.h \
|
$(BASIC_BLOCK_H) $(REGS_H) insn-config.h insn-attr.h insn-flags.h \
|
||||||
$(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h
|
$(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h
|
||||||
alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
|
alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
|
||||||
$(REGS_H) toplev.h output.h $(EXPR_H) insn-flags.h ggc.h function.h
|
$(REGS_H) toplev.h output.h $(EXPR_H) insn-flags.h ggc.h function.h \
|
||||||
|
cselib.h
|
||||||
regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
|
regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
|
||||||
$(RECOG_H) output.h reload.h $(REGS_H) hard-reg-set.h flags.h function.h \
|
$(RECOG_H) output.h reload.h $(REGS_H) hard-reg-set.h flags.h function.h \
|
||||||
$(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
|
$(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
|
||||||
|
89
gcc/alias.c
89
gcc/alias.c
@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
|
|||||||
#include "flags.h"
|
#include "flags.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "toplev.h"
|
#include "toplev.h"
|
||||||
|
#include "cselib.h"
|
||||||
#include "splay-tree.h"
|
#include "splay-tree.h"
|
||||||
#include "ggc.h"
|
#include "ggc.h"
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ typedef struct alias_set_entry
|
|||||||
static rtx canon_rtx PARAMS ((rtx));
|
static rtx canon_rtx PARAMS ((rtx));
|
||||||
static int rtx_equal_for_memref_p PARAMS ((rtx, rtx));
|
static int rtx_equal_for_memref_p PARAMS ((rtx, rtx));
|
||||||
static rtx find_symbolic_term PARAMS ((rtx));
|
static rtx find_symbolic_term PARAMS ((rtx));
|
||||||
|
static rtx get_addr PARAMS ((rtx));
|
||||||
static int memrefs_conflict_p PARAMS ((int, rtx, int, rtx,
|
static int memrefs_conflict_p PARAMS ((int, rtx, int, rtx,
|
||||||
HOST_WIDE_INT));
|
HOST_WIDE_INT));
|
||||||
static void record_set PARAMS ((rtx, rtx, void *));
|
static void record_set PARAMS ((rtx, rtx, void *));
|
||||||
@ -91,7 +93,8 @@ static rtx find_base_value PARAMS ((rtx));
|
|||||||
static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
|
static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
|
||||||
static int insert_subset_children PARAMS ((splay_tree_node, void*));
|
static int insert_subset_children PARAMS ((splay_tree_node, void*));
|
||||||
static alias_set_entry get_alias_set_entry PARAMS ((int));
|
static alias_set_entry get_alias_set_entry PARAMS ((int));
|
||||||
static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, int (*)(rtx)));
|
static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
|
||||||
|
int (*)(rtx)));
|
||||||
static int aliases_everything_p PARAMS ((rtx));
|
static int aliases_everything_p PARAMS ((rtx));
|
||||||
static int write_dependence_p PARAMS ((rtx, rtx, int));
|
static int write_dependence_p PARAMS ((rtx, rtx, int));
|
||||||
static int nonlocal_reference_p PARAMS ((rtx));
|
static int nonlocal_reference_p PARAMS ((rtx));
|
||||||
@ -737,6 +740,9 @@ static rtx
|
|||||||
find_base_term (x)
|
find_base_term (x)
|
||||||
register rtx x;
|
register rtx x;
|
||||||
{
|
{
|
||||||
|
cselib_val *val;
|
||||||
|
struct elt_loc_list *l;
|
||||||
|
|
||||||
switch (GET_CODE (x))
|
switch (GET_CODE (x))
|
||||||
{
|
{
|
||||||
case REG:
|
case REG:
|
||||||
@ -751,6 +757,13 @@ find_base_term (x)
|
|||||||
case POST_DEC:
|
case POST_DEC:
|
||||||
return find_base_term (XEXP (x, 0));
|
return find_base_term (XEXP (x, 0));
|
||||||
|
|
||||||
|
case VALUE:
|
||||||
|
val = CSELIB_VAL_PTR (x);
|
||||||
|
for (l = val->locs; l; l = l->next)
|
||||||
|
if ((x = find_base_term (l->loc)) != 0)
|
||||||
|
return x;
|
||||||
|
return 0;
|
||||||
|
|
||||||
case CONST:
|
case CONST:
|
||||||
x = XEXP (x, 0);
|
x = XEXP (x, 0);
|
||||||
if (GET_CODE (x) != PLUS && GET_CODE (x) != MINUS)
|
if (GET_CODE (x) != PLUS && GET_CODE (x) != MINUS)
|
||||||
@ -905,6 +918,30 @@ base_alias_check (x, y, x_mode, y_mode)
|
|||||||
return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
|
return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert the address X into something we can use. This is done by returning
|
||||||
|
it unchanged unless it is a value; in the latter case we call cselib to get
|
||||||
|
a more useful rtx. */
|
||||||
|
static rtx
|
||||||
|
get_addr (x)
|
||||||
|
rtx x;
|
||||||
|
{
|
||||||
|
cselib_val *v;
|
||||||
|
struct elt_loc_list *l;
|
||||||
|
|
||||||
|
if (GET_CODE (x) != VALUE)
|
||||||
|
return x;
|
||||||
|
v = CSELIB_VAL_PTR (x);
|
||||||
|
for (l = v->locs; l; l = l->next)
|
||||||
|
if (CONSTANT_P (l->loc))
|
||||||
|
return l->loc;
|
||||||
|
for (l = v->locs; l; l = l->next)
|
||||||
|
if (GET_CODE (l->loc) != REG && GET_CODE (l->loc) != MEM)
|
||||||
|
return l->loc;
|
||||||
|
if (v->locs)
|
||||||
|
return v->locs->loc;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the address of the (N_REFS + 1)th memory reference to ADDR
|
/* Return the address of the (N_REFS + 1)th memory reference to ADDR
|
||||||
where SIZE is the size in bytes of the memory reference. If ADDR
|
where SIZE is the size in bytes of the memory reference. If ADDR
|
||||||
is not modified by the memory reference then ADDR is returned. */
|
is not modified by the memory reference then ADDR is returned. */
|
||||||
@ -961,13 +998,16 @@ addr_side_effect_eval (addr, size, n_refs)
|
|||||||
Nice to notice that varying addresses cannot conflict with fp if no
|
Nice to notice that varying addresses cannot conflict with fp if no
|
||||||
local variables had their addresses taken, but that's too hard now. */
|
local variables had their addresses taken, but that's too hard now. */
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
memrefs_conflict_p (xsize, x, ysize, y, c)
|
memrefs_conflict_p (xsize, x, ysize, y, c)
|
||||||
register rtx x, y;
|
register rtx x, y;
|
||||||
int xsize, ysize;
|
int xsize, ysize;
|
||||||
HOST_WIDE_INT c;
|
HOST_WIDE_INT c;
|
||||||
{
|
{
|
||||||
|
if (GET_CODE (x) == VALUE)
|
||||||
|
x = get_addr (x);
|
||||||
|
if (GET_CODE (y) == VALUE)
|
||||||
|
y = get_addr (y);
|
||||||
if (GET_CODE (x) == HIGH)
|
if (GET_CODE (x) == HIGH)
|
||||||
x = XEXP (x, 0);
|
x = XEXP (x, 0);
|
||||||
else if (GET_CODE (x) == LO_SUM)
|
else if (GET_CODE (x) == LO_SUM)
|
||||||
@ -1185,17 +1225,15 @@ read_dependence (mem, x)
|
|||||||
MEM2 if vice versa. Otherwise, returns NULL_RTX. If a non-NULL
|
MEM2 if vice versa. Otherwise, returns NULL_RTX. If a non-NULL
|
||||||
value is returned MEM1 and MEM2 can never alias. VARIES_P is used
|
value is returned MEM1 and MEM2 can never alias. VARIES_P is used
|
||||||
to decide whether or not an address may vary; it should return
|
to decide whether or not an address may vary; it should return
|
||||||
nonzero whenever variation is possible. */
|
nonzero whenever variation is possible.
|
||||||
|
MEM1_ADDR and MEM2_ADDR are the addresses of MEM1 and MEM2. */
|
||||||
|
|
||||||
static rtx
|
static rtx
|
||||||
fixed_scalar_and_varying_struct_p (mem1, mem2, varies_p)
|
fixed_scalar_and_varying_struct_p (mem1, mem2, mem1_addr, mem2_addr, varies_p)
|
||||||
rtx mem1;
|
rtx mem1, mem2;
|
||||||
rtx mem2;
|
rtx mem1_addr, mem2_addr;
|
||||||
int (*varies_p) PARAMS ((rtx));
|
int (*varies_p) PARAMS ((rtx));
|
||||||
{
|
{
|
||||||
rtx mem1_addr = XEXP (mem1, 0);
|
|
||||||
rtx mem2_addr = XEXP (mem2, 0);
|
|
||||||
|
|
||||||
if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
|
if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
|
||||||
&& !varies_p (mem1_addr) && varies_p (mem2_addr))
|
&& !varies_p (mem1_addr) && varies_p (mem2_addr))
|
||||||
/* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
|
/* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
|
||||||
@ -1260,11 +1298,14 @@ true_dependence (mem, mem_mode, x, varies)
|
|||||||
if (mem_mode == VOIDmode)
|
if (mem_mode == VOIDmode)
|
||||||
mem_mode = GET_MODE (mem);
|
mem_mode = GET_MODE (mem);
|
||||||
|
|
||||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x), mem_mode))
|
x_addr = get_addr (XEXP (x, 0));
|
||||||
|
mem_addr = get_addr (XEXP (mem, 0));
|
||||||
|
|
||||||
|
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
x_addr = canon_rtx (XEXP (x, 0));
|
x_addr = canon_rtx (x_addr);
|
||||||
mem_addr = canon_rtx (XEXP (mem, 0));
|
mem_addr = canon_rtx (mem_addr);
|
||||||
|
|
||||||
if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
|
if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
|
||||||
SIZE_FOR_MODE (x), x_addr, 0))
|
SIZE_FOR_MODE (x), x_addr, 0))
|
||||||
@ -1283,7 +1324,8 @@ true_dependence (mem, mem_mode, x, varies)
|
|||||||
if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
|
if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return !fixed_scalar_and_varying_struct_p (mem, x, varies);
|
return ! fixed_scalar_and_varying_struct_p (mem, x, mem_addr, x_addr,
|
||||||
|
varies);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns non-zero if a write to X might alias a previous read from
|
/* Returns non-zero if a write to X might alias a previous read from
|
||||||
@ -1301,31 +1343,32 @@ write_dependence_p (mem, x, writep)
|
|||||||
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
|
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (DIFFERENT_ALIAS_SETS_P (x, mem))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* If MEM is an unchanging read, then it can't possibly conflict with
|
/* If MEM is an unchanging read, then it can't possibly conflict with
|
||||||
the store to X, because there is at most one store to MEM, and it must
|
the store to X, because there is at most one store to MEM, and it must
|
||||||
have occurred somewhere before MEM. */
|
have occurred somewhere before MEM. */
|
||||||
if (!writep && RTX_UNCHANGING_P (mem))
|
if (!writep && RTX_UNCHANGING_P (mem))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x),
|
x_addr = get_addr (XEXP (x, 0));
|
||||||
|
mem_addr = get_addr (XEXP (mem, 0));
|
||||||
|
|
||||||
|
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x),
|
||||||
GET_MODE (mem)))
|
GET_MODE (mem)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
x = canon_rtx (x);
|
x_addr = canon_rtx (x_addr);
|
||||||
mem = canon_rtx (mem);
|
mem_addr = canon_rtx (mem_addr);
|
||||||
|
|
||||||
if (DIFFERENT_ALIAS_SETS_P (x, mem))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
x_addr = XEXP (x, 0);
|
|
||||||
mem_addr = XEXP (mem, 0);
|
|
||||||
|
|
||||||
if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
|
if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
|
||||||
SIZE_FOR_MODE (x), x_addr, 0))
|
SIZE_FOR_MODE (x), x_addr, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fixed_scalar
|
fixed_scalar
|
||||||
= fixed_scalar_and_varying_struct_p (mem, x, rtx_addr_varies_p);
|
= fixed_scalar_and_varying_struct_p (mem, x, mem_addr, x_addr,
|
||||||
|
rtx_addr_varies_p);
|
||||||
|
|
||||||
return (!(fixed_scalar == mem && !aliases_everything_p (x))
|
return (!(fixed_scalar == mem && !aliases_everything_p (x))
|
||||||
&& !(fixed_scalar == x && !aliases_everything_p (mem)));
|
&& !(fixed_scalar == x && !aliases_everything_p (mem)));
|
||||||
|
66
gcc/cselib.h
Normal file
66
gcc/cselib.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* Common subexpression elimination for GNU compiler.
|
||||||
|
Copyright (C) 1987, 88, 89, 92-7, 1998, 1999 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU CC.
|
||||||
|
|
||||||
|
GNU CC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GNU CC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GNU CC; see the file COPYING. If not, write to
|
||||||
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
/* Describe a value. */
|
||||||
|
typedef struct cselib_val_struct
|
||||||
|
{
|
||||||
|
/* The hash value. */
|
||||||
|
unsigned int value;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
/* A VALUE rtx that points back to this structure. */
|
||||||
|
rtx val_rtx;
|
||||||
|
/* Used to keep a list of free cselib_val structures. */
|
||||||
|
struct cselib_val_struct *next_free;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
/* All rtl expressions that hold this value at the current time during a
|
||||||
|
scan. */
|
||||||
|
struct elt_loc_list *locs;
|
||||||
|
/* If this value is used as an address, points to a list of values that
|
||||||
|
use it as an address in a MEM. */
|
||||||
|
struct elt_list *addr_list;
|
||||||
|
} cselib_val;
|
||||||
|
|
||||||
|
/* A list of rtl expressions that hold the same value. */
|
||||||
|
struct elt_loc_list
|
||||||
|
{
|
||||||
|
/* Next element in the list. */
|
||||||
|
struct elt_loc_list *next;
|
||||||
|
/* An rtl expression that holds the value. */
|
||||||
|
rtx loc;
|
||||||
|
/* The insn that made the equivalence. */
|
||||||
|
rtx setting_insn;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A list of cselib_val structures. */
|
||||||
|
struct elt_list
|
||||||
|
{
|
||||||
|
struct elt_list *next;
|
||||||
|
cselib_val *elt;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern cselib_val *cselib_lookup PARAMS ((rtx, enum machine_mode, int));
|
||||||
|
extern void cselib_update_varray_sizes PARAMS ((void));
|
||||||
|
extern void cselib_init PARAMS ((void));
|
||||||
|
extern void cselib_finish PARAMS ((void));
|
||||||
|
extern void cselib_process_insn PARAMS ((rtx));
|
||||||
|
extern int rtx_equal_for_cselib_p PARAMS ((rtx, rtx));
|
||||||
|
extern int references_value_p PARAMS ((rtx, int));
|
62
gcc/loop.c
62
gcc/loop.c
@ -51,6 +51,7 @@ Boston, MA 02111-1307, USA. */
|
|||||||
#include "flags.h"
|
#include "flags.h"
|
||||||
#include "real.h"
|
#include "real.h"
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
|
#include "cselib.h"
|
||||||
#include "except.h"
|
#include "except.h"
|
||||||
#include "toplev.h"
|
#include "toplev.h"
|
||||||
|
|
||||||
@ -9773,6 +9774,19 @@ load_mems (loop)
|
|||||||
if (loop_mems_idx == 0)
|
if (loop_mems_idx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Find start of the extended basic block that enters the loop. */
|
||||||
|
for (p = loop->start;
|
||||||
|
PREV_INSN (p) && GET_CODE (p) != CODE_LABEL;
|
||||||
|
p = PREV_INSN (p))
|
||||||
|
;
|
||||||
|
|
||||||
|
cselib_init ();
|
||||||
|
|
||||||
|
/* Build table of mems that get set to constant values before the
|
||||||
|
loop. */
|
||||||
|
for (; p != loop->start; p = NEXT_INSN (p))
|
||||||
|
cselib_process_insn (p);
|
||||||
|
|
||||||
/* Check to see if it's possible that some instructions in the
|
/* Check to see if it's possible that some instructions in the
|
||||||
loop are never executed. */
|
loop are never executed. */
|
||||||
for (p = next_insn_in_loop (loop, loop->scan_start);
|
for (p = next_insn_in_loop (loop, loop->scan_start);
|
||||||
@ -9924,13 +9938,49 @@ load_mems (loop)
|
|||||||
loop_mems[i].optimize = 0;
|
loop_mems[i].optimize = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int j;
|
|
||||||
rtx set;
|
|
||||||
|
|
||||||
/* Load the memory immediately before LOOP->START, which is
|
/* Load the memory immediately before LOOP->START, which is
|
||||||
the NOTE_LOOP_BEG. */
|
the NOTE_LOOP_BEG. */
|
||||||
set = gen_move_insn (reg, mem);
|
cselib_val *e = cselib_lookup (mem, VOIDmode, 0);
|
||||||
emit_insn_before (set, loop->start);
|
rtx set;
|
||||||
|
rtx best = mem;
|
||||||
|
int j;
|
||||||
|
struct elt_loc_list *const_equiv = 0;
|
||||||
|
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
struct elt_loc_list *equiv;
|
||||||
|
struct elt_loc_list *best_equiv = 0;
|
||||||
|
for (equiv = e->locs; equiv; equiv = equiv->next)
|
||||||
|
{
|
||||||
|
if (CONSTANT_P (equiv->loc))
|
||||||
|
const_equiv = equiv;
|
||||||
|
else if (GET_CODE (equiv->loc) == REG)
|
||||||
|
best_equiv = equiv;
|
||||||
|
}
|
||||||
|
/* Use the constant equivalence if that is cheap enough. */
|
||||||
|
if (! best_equiv)
|
||||||
|
best_equiv = const_equiv;
|
||||||
|
else if (const_equiv
|
||||||
|
&& (rtx_cost (const_equiv->loc, SET)
|
||||||
|
<= rtx_cost (best_equiv->loc, SET)))
|
||||||
|
{
|
||||||
|
best_equiv = const_equiv;
|
||||||
|
const_equiv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If best_equiv is nonzero, we know that MEM is set to a
|
||||||
|
constant or register before the loop. We will use this
|
||||||
|
knowledge to initialize the shadow register with that
|
||||||
|
constant or reg rather than by loading from MEM. */
|
||||||
|
if (best_equiv)
|
||||||
|
best = copy_rtx (best_equiv->loc);
|
||||||
|
}
|
||||||
|
set = gen_move_insn (reg, best);
|
||||||
|
set = emit_insn_before (set, loop->start);
|
||||||
|
if (const_equiv)
|
||||||
|
REG_NOTES (set) = gen_rtx_EXPR_LIST (REG_EQUAL,
|
||||||
|
copy_rtx (const_equiv->loc),
|
||||||
|
REG_NOTES (set));
|
||||||
|
|
||||||
if (written)
|
if (written)
|
||||||
{
|
{
|
||||||
@ -9992,6 +10042,8 @@ load_mems (loop)
|
|||||||
JUMP_LABEL (p) = label;
|
JUMP_LABEL (p) = label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cselib_finish ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For communication between note_reg_stored and its caller. */
|
/* For communication between note_reg_stored and its caller. */
|
||||||
|
894
gcc/reload1.c
894
gcc/reload1.c
File diff suppressed because it is too large
Load Diff
@ -530,6 +530,9 @@ DEF_RTL_EXPR(CONST, "const", "e", 'o')
|
|||||||
by a SET whose first operand is (PC). */
|
by a SET whose first operand is (PC). */
|
||||||
DEF_RTL_EXPR(PC, "pc", "", 'o')
|
DEF_RTL_EXPR(PC, "pc", "", 'o')
|
||||||
|
|
||||||
|
/* Used in the cselib routines to describe a value. */
|
||||||
|
DEF_RTL_EXPR(VALUE, "value", "0", 'o')
|
||||||
|
|
||||||
/* A register. The "operand" is the register number, accessed with
|
/* A register. The "operand" is the register number, accessed with
|
||||||
the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
|
the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
|
||||||
than a hardware register is being referred to. The second operand
|
than a hardware register is being referred to. The second operand
|
||||||
|
@ -92,6 +92,7 @@ typedef union rtunion_def
|
|||||||
struct rtvec_def *rtvec;
|
struct rtvec_def *rtvec;
|
||||||
enum machine_mode rttype;
|
enum machine_mode rttype;
|
||||||
addr_diff_vec_flags rt_addr_diff_vec_flags;
|
addr_diff_vec_flags rt_addr_diff_vec_flags;
|
||||||
|
struct cselib_val_struct *rt_cselib;
|
||||||
struct bitmap_head_def *rtbit;
|
struct bitmap_head_def *rtbit;
|
||||||
union tree_node *rttree;
|
union tree_node *rttree;
|
||||||
struct basic_block_def *bb;
|
struct basic_block_def *bb;
|
||||||
@ -330,6 +331,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
|
|||||||
#define X0TREE(RTX, N) (RTL_CHECK1(RTX, N, '0').rttree)
|
#define X0TREE(RTX, N) (RTL_CHECK1(RTX, N, '0').rttree)
|
||||||
#define X0BBDEF(RTX, N) (RTL_CHECK1(RTX, N, '0').bb)
|
#define X0BBDEF(RTX, N) (RTL_CHECK1(RTX, N, '0').bb)
|
||||||
#define X0ADVFLAGS(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_addr_diff_vec_flags)
|
#define X0ADVFLAGS(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_addr_diff_vec_flags)
|
||||||
|
#define X0CSELIB(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_cselib)
|
||||||
|
|
||||||
#define XCWINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtwint)
|
#define XCWINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtwint)
|
||||||
#define XCINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtint)
|
#define XCINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtint)
|
||||||
@ -341,6 +343,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
|
|||||||
#define XCTREE(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rttree)
|
#define XCTREE(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rttree)
|
||||||
#define XCBBDEF(RTX, N, C) (RTL_CHECKC1(RTX, N, C).bb)
|
#define XCBBDEF(RTX, N, C) (RTL_CHECKC1(RTX, N, C).bb)
|
||||||
#define XCADVFLAGS(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rt_addr_diff_vec_flags)
|
#define XCADVFLAGS(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rt_addr_diff_vec_flags)
|
||||||
|
#define XCCSELIB(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rt_cselib)
|
||||||
|
|
||||||
#define XCVECEXP(RTX, N, M, C) RTVEC_ELT (XCVEC (RTX, N, C), M)
|
#define XCVECEXP(RTX, N, M, C) RTVEC_ELT (XCVEC (RTX, N, C), M)
|
||||||
#define XCVECLEN(RTX, N, C) GET_NUM_ELEM (XCVEC (RTX, N, C))
|
#define XCVECLEN(RTX, N, C) GET_NUM_ELEM (XCVEC (RTX, N, C))
|
||||||
@ -470,6 +473,8 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
|
|||||||
|
|
||||||
#define ADDR_DIFF_VEC_FLAGS(RTX) X0ADVFLAGS(RTX, 4)
|
#define ADDR_DIFF_VEC_FLAGS(RTX) X0ADVFLAGS(RTX, 4)
|
||||||
|
|
||||||
|
#define CSELIB_VAL_PTR(RTX) X0CSELIB(RTX, 0)
|
||||||
|
|
||||||
/* Don't forget to change reg_note_name in rtl.c. */
|
/* Don't forget to change reg_note_name in rtl.c. */
|
||||||
enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
|
enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
|
||||||
REG_EQUAL = 5, REG_RETVAL = 6, REG_LIBCALL = 7,
|
REG_EQUAL = 5, REG_RETVAL = 6, REG_LIBCALL = 7,
|
||||||
|
1230
gcc/simplify-rtx.c
1230
gcc/simplify-rtx.c
File diff suppressed because it is too large
Load Diff
@ -76,6 +76,7 @@ typedef union varray_data_tag {
|
|||||||
struct reg_info_def *reg[1];
|
struct reg_info_def *reg[1];
|
||||||
struct const_equiv_data const_equiv[1];
|
struct const_equiv_data const_equiv[1];
|
||||||
struct basic_block_def *bb[1];
|
struct basic_block_def *bb[1];
|
||||||
|
struct elt_list *te[1];
|
||||||
} varray_data;
|
} varray_data;
|
||||||
|
|
||||||
/* Virtual array of pointers header. */
|
/* Virtual array of pointers header. */
|
||||||
@ -152,6 +153,9 @@ extern varray_type varray_init PARAMS ((size_t, size_t, const char *));
|
|||||||
#define VARRAY_BB_INIT(va, num, name) \
|
#define VARRAY_BB_INIT(va, num, name) \
|
||||||
va = varray_init (num, sizeof (struct basic_block_def *), name)
|
va = varray_init (num, sizeof (struct basic_block_def *), name)
|
||||||
|
|
||||||
|
#define VARRAY_ELT_LIST_INIT(va, num, name) \
|
||||||
|
va = varray_init (num, sizeof (struct elt_list *), name)
|
||||||
|
|
||||||
/* Free up memory allocated by the virtual array, but do not free any of the
|
/* Free up memory allocated by the virtual array, but do not free any of the
|
||||||
elements involved. */
|
elements involved. */
|
||||||
#define VARRAY_FREE(vp) \
|
#define VARRAY_FREE(vp) \
|
||||||
@ -219,6 +223,7 @@ extern void varray_check_failed PARAMS ((varray_type, size_t,
|
|||||||
#define VARRAY_REG(VA, N) VARRAY_CHECK (VA, N, reg)
|
#define VARRAY_REG(VA, N) VARRAY_CHECK (VA, N, reg)
|
||||||
#define VARRAY_CONST_EQUIV(VA, N) VARRAY_CHECK (VA, N, const_equiv)
|
#define VARRAY_CONST_EQUIV(VA, N) VARRAY_CHECK (VA, N, const_equiv)
|
||||||
#define VARRAY_BB(VA, N) VARRAY_CHECK (VA, N, bb)
|
#define VARRAY_BB(VA, N) VARRAY_CHECK (VA, N, bb)
|
||||||
|
#define VARRAY_ELT_LIST(VA, N) VARRAY_CHECK (VA, N, te)
|
||||||
|
|
||||||
/* Push a new element on the end of VA, extending it if necessary. */
|
/* Push a new element on the end of VA, extending it if necessary. */
|
||||||
#define VARRAY_PUSH_CHAR(VA, X) VARRAY_PUSH (VA, c, X)
|
#define VARRAY_PUSH_CHAR(VA, X) VARRAY_PUSH (VA, c, X)
|
||||||
|
Loading…
Reference in New Issue
Block a user