Commit fe9b4957 by Mark Mitchell

function.c: Include hash.h.

	* function.c: Include hash.h.
	(insns_for_mem_entry): New struct.
	(put_reg_into_stack): Take an optional hash-table mapping MEMs to
	the INSNs that use them.
	(fixup_var_refs): Likewise.
	(put_addressof_into_stack): Likewise.
	(purge_addressof_1): Likewise.  Keep the hash-table up to date if
	we add new instructions.
	(fixup_var_refs_insns): Use it to avoid searching the entire
	instruction chain.
	(insns_for_mem_newfunc): New function.
	(insns_for_mem_comp): Likewise.
	(insns_for_mem_walk): Likewise.
	(compute_insns_for_mem): Likewise.
	(pop_function_context_from): Pass NULL for the hash-table.
	(put_var_into_stack): Likewise.
	(gen_mem_addressof): Likewise.
	(flush_addressof): Likewise.
	(purge_addressof): Call compute_insns_for_mem to pre-compute the
	hash table.
	* Makefile.in (OBJS): Include hash.o.
	(function.o): Depend on hash.h.
	* Makefile.in (OBJS): Don't mention hash.o.
	(OBJDEPS): Likewise.

From-SVN: r25922
parent 9ee9b555
Tue Mar 23 07:50:20 1999 Mark Mitchell <mark@codesourcery.com>
* function.c: Include hash.h.
(insns_for_mem_entry): New struct.
(put_reg_into_stack): Take an optional hash-table mapping MEMs to
the INSNs that use them.
(fixup_var_refs): Likewise.
(put_addressof_into_stack): Likewise.
(purge_addressof_1): Likewise. Keep the hash-table up to date if
we add new instructions.
(fixup_var_refs_insns): Use it to avoid searching the entire
instruction chain.
(insns_for_mem_newfunc): New function.
(insns_for_mem_comp): Likewise.
(insns_for_mem_walk): Likewise.
(compute_insns_for_mem): Likewise.
(pop_function_context_from): Pass NULL for the hash-table.
(put_var_into_stack): Likewise.
(gen_mem_addressof): Likewise.
(flush_addressof): Likewise.
(purge_addressof): Call compute_insns_for_mem to pre-compute the
hash table.
* Makefile.in (OBJS): Include hash.o.
(function.o): Depend on hash.h.
Tue Mar 23 00:39:14 1999 Jeffrey A Law (law@cygnus.com) Tue Mar 23 00:39:14 1999 Jeffrey A Law (law@cygnus.com)
* crtstuff.c: Use ANSI function definitions. Fix minor whitespace * crtstuff.c: Use ANSI function definitions. Fix minor whitespace
......
...@@ -679,7 +679,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ ...@@ -679,7 +679,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \ insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \ insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \
profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \ profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \
mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o
# GEN files are listed separately, so they can be built before doing parallel # GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load # makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
...@@ -1452,7 +1452,7 @@ varasm.o : varasm.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h \ ...@@ -1452,7 +1452,7 @@ varasm.o : varasm.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h \
xcoffout.h output.h c-pragma.h toplev.h except.h dbxout.h sdbout.h xcoffout.h output.h c-pragma.h toplev.h except.h dbxout.h sdbout.h
function.o : function.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \ function.o : function.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
function.h insn-flags.h insn-codes.h $(EXPR_H) $(REGS_H) hard-reg-set.h \ function.h insn-flags.h insn-codes.h $(EXPR_H) $(REGS_H) hard-reg-set.h \
insn-config.h $(RECOG_H) output.h toplev.h except.h insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h
stmt.o : stmt.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \ stmt.o : stmt.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \
insn-flags.h insn-config.h insn-codes.h hard-reg-set.h $(EXPR_H) except.h \ insn-flags.h insn-config.h insn-codes.h hard-reg-set.h $(EXPR_H) except.h \
loop.h $(RECOG_H) toplev.h output.h varray.h loop.h $(RECOG_H) toplev.h output.h varray.h
......
1999-03-23 Mark Mitchell <mark@codesourcery.com>
* Makefile.in (OBJS): Don't mention hash.o.
(OBJDEPS): Likewise.
1999-03-23 Jason Merrill <jason@yorick.cygnus.com> 1999-03-23 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (finish_file): Set at_eof to 2 after expanding ctors. * decl2.c (finish_file): Set at_eof to 2 after expanding ctors.
...@@ -60,6 +65,7 @@ ...@@ -60,6 +65,7 @@
* decl.c (start_function): Suppress normal linkage heuristics * decl.c (start_function): Suppress normal linkage heuristics
for #pragma interface under MULTIPLE_SYMBOL_SPACES. for #pragma interface under MULTIPLE_SYMBOL_SPACES.
>>>>>>> 1.947
1999-03-19 Alexandre Oliva <oliva@dcc.unicamp.br> 1999-03-19 Alexandre Oliva <oliva@dcc.unicamp.br>
* Make-lang.in: ($(INTL_TARGETS)): depend on cp/parse.c * Make-lang.in: ($(INTL_TARGETS)): depend on cp/parse.c
......
...@@ -191,8 +191,8 @@ CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \ ...@@ -191,8 +191,8 @@ CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
repo.o @extra_cxx_objs@ repo.o @extra_cxx_objs@
# Language-independent object files. # Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o ../hash.o OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o ../hash.o OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
compiler: ../cc1plus$(exeext) compiler: ../cc1plus$(exeext)
../cc1plus$(exeext): $(P) $(OBJDEPS) $(CXX_OBJS) $(LIBDEPS) ../cc1plus$(exeext): $(P) $(OBJDEPS) $(CXX_OBJS) $(LIBDEPS)
......
...@@ -56,6 +56,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -56,6 +56,7 @@ Boston, MA 02111-1307, USA. */
#include "basic-block.h" #include "basic-block.h"
#include "obstack.h" #include "obstack.h"
#include "toplev.h" #include "toplev.h"
#include "hash.h"
#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY #if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY #define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
...@@ -451,6 +452,13 @@ struct fixup_replacement ...@@ -451,6 +452,13 @@ struct fixup_replacement
struct fixup_replacement *next; struct fixup_replacement *next;
}; };
struct insns_for_mem_entry {
/* The KEY in HE will be a MEM. */
struct hash_entry he;
/* These are the INSNS which reference the MEM. */
rtx insns;
};
/* Forward declarations. */ /* Forward declarations. */
static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT, static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT,
...@@ -460,12 +468,14 @@ static rtx assign_stack_temp_for_type PROTO ((enum machine_mode, HOST_WIDE_INT, ...@@ -460,12 +468,14 @@ static rtx assign_stack_temp_for_type PROTO ((enum machine_mode, HOST_WIDE_INT,
static struct temp_slot *find_temp_slot_from_address PROTO((rtx)); static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree, static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode, enum machine_mode, enum machine_mode,
int, int, int)); int, int, int,
static void fixup_var_refs PROTO((rtx, enum machine_mode, int)); struct hash_table *));
static void fixup_var_refs PROTO((rtx, enum machine_mode, int,
struct hash_table *));
static struct fixup_replacement static struct fixup_replacement
*find_fixup_replacement PROTO((struct fixup_replacement **, rtx)); *find_fixup_replacement PROTO((struct fixup_replacement **, rtx));
static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int, static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,
rtx, int)); rtx, int, struct hash_table *));
static void fixup_var_refs_1 PROTO((rtx, enum machine_mode, rtx *, rtx, static void fixup_var_refs_1 PROTO((rtx, enum machine_mode, rtx *, rtx,
struct fixup_replacement **)); struct fixup_replacement **));
static rtx fixup_memory_subreg PROTO((rtx, rtx, int)); static rtx fixup_memory_subreg PROTO((rtx, rtx, int));
...@@ -492,8 +502,17 @@ static int all_blocks PROTO((tree, tree *)); ...@@ -492,8 +502,17 @@ static int all_blocks PROTO((tree, tree *));
static int *record_insns PROTO((rtx)); static int *record_insns PROTO((rtx));
static int contains PROTO((rtx, int *)); static int contains PROTO((rtx, int *));
#endif /* HAVE_prologue || HAVE_epilogue */ #endif /* HAVE_prologue || HAVE_epilogue */
static void put_addressof_into_stack PROTO((rtx)); static void put_addressof_into_stack PROTO((rtx, struct hash_table *));
static void purge_addressof_1 PROTO((rtx *, rtx, int, int)); static void purge_addressof_1 PROTO((rtx *, rtx, int, int,
struct hash_table *));
static struct hash_entry *insns_for_mem_newfunc PROTO((struct hash_entry *,
struct hash_table *,
hash_table_key));
static unsigned long insns_for_mem_hash PROTO ((hash_table_key));
static boolean insns_for_mem_comp PROTO ((hash_table_key, hash_table_key));
static int insns_for_mem_walk PROTO ((rtx *, void *));
static void compute_insns_for_mem PROTO ((rtx, rtx, struct hash_table *));
/* Pointer to chain of `struct function' for containing functions. */ /* Pointer to chain of `struct function' for containing functions. */
struct function *outer_function_chain; struct function *outer_function_chain;
...@@ -683,7 +702,8 @@ pop_function_context_from (context) ...@@ -683,7 +702,8 @@ pop_function_context_from (context)
/* Finish doing put_var_into_stack for any of our variables /* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */ which became addressable during the nested function. */
for (queue = p->fixup_var_refs_queue; queue; queue = queue->next) for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp); fixup_var_refs (queue->modified, queue->promoted_mode,
queue->unsignedp, 0);
free (p); free (p);
...@@ -1569,8 +1589,8 @@ put_var_into_stack (decl) ...@@ -1569,8 +1589,8 @@ put_var_into_stack (decl)
put_reg_into_stack (function, reg, TREE_TYPE (decl), put_reg_into_stack (function, reg, TREE_TYPE (decl),
promoted_mode, decl_mode, promoted_mode, decl_mode,
TREE_SIDE_EFFECTS (decl), 0, TREE_SIDE_EFFECTS (decl), 0,
TREE_USED (decl) TREE_USED (decl) || DECL_INITIAL (decl) != 0,
|| DECL_INITIAL (decl) != 0); 0);
} }
else if (GET_CODE (reg) == CONCAT) else if (GET_CODE (reg) == CONCAT)
{ {
...@@ -1582,17 +1602,21 @@ put_var_into_stack (decl) ...@@ -1582,17 +1602,21 @@ put_var_into_stack (decl)
/* Since part 0 should have a lower address, do it second. */ /* Since part 0 should have a lower address, do it second. */
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode, put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0, part_mode, TREE_SIDE_EFFECTS (decl), 0,
TREE_USED (decl) || DECL_INITIAL (decl) != 0); TREE_USED (decl) || DECL_INITIAL (decl) != 0,
0);
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode, put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0, part_mode, TREE_SIDE_EFFECTS (decl), 0,
TREE_USED (decl) || DECL_INITIAL (decl) != 0); TREE_USED (decl) || DECL_INITIAL (decl) != 0,
0);
#else #else
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode, put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0, part_mode, TREE_SIDE_EFFECTS (decl), 0,
TREE_USED (decl) || DECL_INITIAL (decl) != 0); TREE_USED (decl) || DECL_INITIAL (decl) != 0,
0);
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode, put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0, part_mode, TREE_SIDE_EFFECTS (decl), 0,
TREE_USED (decl) || DECL_INITIAL (decl) != 0); TREE_USED (decl) || DECL_INITIAL (decl) != 0,
0);
#endif #endif
/* Change the CONCAT into a combined MEM for both parts. */ /* Change the CONCAT into a combined MEM for both parts. */
...@@ -1628,7 +1652,7 @@ put_var_into_stack (decl) ...@@ -1628,7 +1652,7 @@ put_var_into_stack (decl)
static void static void
put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p, put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
original_regno, used_p) original_regno, used_p, ht)
struct function *function; struct function *function;
rtx reg; rtx reg;
tree type; tree type;
...@@ -1636,6 +1660,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p, ...@@ -1636,6 +1660,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
int volatile_p; int volatile_p;
int original_regno; int original_regno;
int used_p; int used_p;
struct hash_table *ht;
{ {
rtx new = 0; rtx new = 0;
int regno = original_regno; int regno = original_regno;
...@@ -1698,14 +1723,15 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p, ...@@ -1698,14 +1723,15 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
} }
else if (used_p) else if (used_p)
/* Variable is local; fix it up now. */ /* Variable is local; fix it up now. */
fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type)); fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type), ht);
} }
static void static void
fixup_var_refs (var, promoted_mode, unsignedp) fixup_var_refs (var, promoted_mode, unsignedp, ht)
rtx var; rtx var;
enum machine_mode promoted_mode; enum machine_mode promoted_mode;
int unsignedp; int unsignedp;
struct hash_table *ht;
{ {
tree pending; tree pending;
rtx first_insn = get_insns (); rtx first_insn = get_insns ();
...@@ -1713,14 +1739,18 @@ fixup_var_refs (var, promoted_mode, unsignedp) ...@@ -1713,14 +1739,18 @@ fixup_var_refs (var, promoted_mode, unsignedp)
tree rtl_exps = rtl_expr_chain; tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */ /* Must scan all insns for stack-refs that exceed the limit. */
fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0); fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn,
stack == 0, ht);
/* If there's a hash table, it must record all uses of VAR. */
if (ht)
return;
/* Scan all pending sequences too. */ /* Scan all pending sequences too. */
for (; stack; stack = stack->next) for (; stack; stack = stack->next)
{ {
push_to_sequence (stack->first); push_to_sequence (stack->first);
fixup_var_refs_insns (var, promoted_mode, unsignedp, fixup_var_refs_insns (var, promoted_mode, unsignedp,
stack->first, stack->next != 0); stack->first, stack->next != 0, 0);
/* Update remembered end of sequence /* Update remembered end of sequence
in case we added an insn at the end. */ in case we added an insn at the end. */
stack->last = get_last_insn (); stack->last = get_last_insn ();
...@@ -1734,14 +1764,16 @@ fixup_var_refs (var, promoted_mode, unsignedp) ...@@ -1734,14 +1764,16 @@ fixup_var_refs (var, promoted_mode, unsignedp)
if (seq != const0_rtx && seq != 0) if (seq != const0_rtx && seq != 0)
{ {
push_to_sequence (seq); push_to_sequence (seq);
fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0); fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0,
0);
end_sequence (); end_sequence ();
} }
} }
/* Scan the catch clauses for exception handling too. */ /* Scan the catch clauses for exception handling too. */
push_to_sequence (catch_clauses); push_to_sequence (catch_clauses);
fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses, 0); fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses,
0, 0);
end_sequence (); end_sequence ();
} }
...@@ -1777,14 +1809,26 @@ find_fixup_replacement (replacements, x) ...@@ -1777,14 +1809,26 @@ find_fixup_replacement (replacements, x)
main chain of insns for the current function. */ main chain of insns for the current function. */
static void static void
fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel) fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel, ht)
rtx var; rtx var;
enum machine_mode promoted_mode; enum machine_mode promoted_mode;
int unsignedp; int unsignedp;
rtx insn; rtx insn;
int toplevel; int toplevel;
struct hash_table *ht;
{ {
rtx call_dest = 0; rtx call_dest = 0;
rtx insn_list;
/* If we already know which INSNs reference VAR there's no need
to walk the entire instruction chain. */
if (ht)
{
insn_list = ((struct insns_for_mem_entry *)
hash_lookup (ht, var, /*create=*/0, /*copy=*/0))->insns;
insn = insn_list ? XEXP (insn_list, 0) : NULL_RTX;
insn_list = XEXP (insn_list, 1);
}
while (insn) while (insn)
{ {
...@@ -1957,7 +2001,16 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel) ...@@ -1957,7 +2001,16 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
XEXP (note, 0) XEXP (note, 0)
= walk_fixup_memory_subreg (XEXP (note, 0), insn, 1); = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
} }
if (!ht)
insn = next; insn = next;
else if (insn_list)
{
insn = XEXP (insn_list, 0);
insn_list = XEXP (insn_list, 1);
}
else
insn = NULL_RTX;
} }
} }
...@@ -2929,7 +2982,7 @@ gen_mem_addressof (reg, decl) ...@@ -2929,7 +2982,7 @@ gen_mem_addressof (reg, decl)
MEM_ALIAS_SET (reg) = get_alias_set (decl); MEM_ALIAS_SET (reg) = get_alias_set (decl);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0) if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type)); fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
return reg; return reg;
} }
...@@ -2945,14 +2998,15 @@ flush_addressof (decl) ...@@ -2945,14 +2998,15 @@ flush_addressof (decl)
&& GET_CODE (DECL_RTL (decl)) == MEM && GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG) && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
put_addressof_into_stack (XEXP (DECL_RTL (decl), 0)); put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
} }
/* Force the register pointed to by R, an ADDRESSOF rtx, into the stack. */ /* Force the register pointed to by R, an ADDRESSOF rtx, into the stack. */
static void static void
put_addressof_into_stack (r) put_addressof_into_stack (r, ht)
rtx r; rtx r;
struct hash_table *ht;
{ {
tree decl = ADDRESSOF_DECL (r); tree decl = ADDRESSOF_DECL (r);
rtx reg = XEXP (r, 0); rtx reg = XEXP (r, 0);
...@@ -2963,7 +3017,7 @@ put_addressof_into_stack (r) ...@@ -2963,7 +3017,7 @@ put_addressof_into_stack (r)
put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg), put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
DECL_MODE (decl), TREE_SIDE_EFFECTS (decl), DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
ADDRESSOF_REGNO (r), ADDRESSOF_REGNO (r),
TREE_USED (decl) || DECL_INITIAL (decl) != 0); TREE_USED (decl) || DECL_INITIAL (decl) != 0, ht);
} }
/* List of replacements made below in purge_addressof_1 when creating /* List of replacements made below in purge_addressof_1 when creating
...@@ -2975,10 +3029,11 @@ static rtx purge_addressof_replacements; ...@@ -2975,10 +3029,11 @@ static rtx purge_addressof_replacements;
the stack. */ the stack. */
static void static void
purge_addressof_1 (loc, insn, force, store) purge_addressof_1 (loc, insn, force, store, ht)
rtx *loc; rtx *loc;
rtx insn; rtx insn;
int force, store; int force, store;
struct hash_table *ht;
{ {
rtx x; rtx x;
RTX_CODE code; RTX_CODE code;
...@@ -3032,7 +3087,7 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3032,7 +3087,7 @@ purge_addressof_1 (loc, insn, force, store)
if (GET_CODE (sub) == REG if (GET_CODE (sub) == REG
&& (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode)) && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
{ {
put_addressof_into_stack (XEXP (x, 0)); put_addressof_into_stack (XEXP (x, 0), ht);
return; return;
} }
else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub)) else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
...@@ -3111,7 +3166,7 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3111,7 +3166,7 @@ purge_addressof_1 (loc, insn, force, store)
if (store) if (store)
{ {
rtx p; rtx p = PREV_INSN (insn);
start_sequence (); start_sequence ();
val = gen_reg_rtx (GET_MODE (x)); val = gen_reg_rtx (GET_MODE (x));
...@@ -3125,6 +3180,8 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3125,6 +3180,8 @@ purge_addressof_1 (loc, insn, force, store)
seq = gen_sequence (); seq = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_before (seq, insn); emit_insn_before (seq, insn);
compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
insn, ht);
start_sequence (); start_sequence ();
store_bit_field (sub, size_x, 0, GET_MODE (x), store_bit_field (sub, size_x, 0, GET_MODE (x),
...@@ -3143,10 +3200,16 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3143,10 +3200,16 @@ purge_addressof_1 (loc, insn, force, store)
seq = gen_sequence (); seq = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_after (seq, insn); p = emit_insn_after (seq, insn);
if (NEXT_INSN (insn))
compute_insns_for_mem (NEXT_INSN (insn),
p ? NEXT_INSN (p) : NULL_RTX,
ht);
} }
else else
{ {
rtx p = PREV_INSN (insn);
start_sequence (); start_sequence ();
val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX, val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
GET_MODE (x), GET_MODE (x), GET_MODE (x), GET_MODE (x),
...@@ -3164,6 +3227,8 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3164,6 +3227,8 @@ purge_addressof_1 (loc, insn, force, store)
seq = gen_sequence (); seq = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_before (seq, insn); emit_insn_before (seq, insn);
compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
insn, ht);
} }
/* Remember the replacement so that the same one can be done /* Remember the replacement so that the same one can be done
...@@ -3192,13 +3257,13 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3192,13 +3257,13 @@ purge_addressof_1 (loc, insn, force, store)
} }
else if (code == ADDRESSOF) else if (code == ADDRESSOF)
{ {
put_addressof_into_stack (x); put_addressof_into_stack (x, ht);
return; return;
} }
else if (code == SET) else if (code == SET)
{ {
purge_addressof_1 (&SET_DEST (x), insn, force, 1); purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht);
purge_addressof_1 (&SET_SRC (x), insn, force, 0); purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht);
return; return;
} }
...@@ -3207,10 +3272,127 @@ purge_addressof_1 (loc, insn, force, store) ...@@ -3207,10 +3272,127 @@ purge_addressof_1 (loc, insn, force, store)
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
{ {
if (*fmt == 'e') if (*fmt == 'e')
purge_addressof_1 (&XEXP (x, i), insn, force, 0); purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht);
else if (*fmt == 'E') else if (*fmt == 'E')
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0); purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht);
}
}
/* Return a new hash table entry in HT. */
static struct hash_entry *
insns_for_mem_newfunc (he, ht, k)
struct hash_entry *he;
struct hash_table *ht;
hash_table_key k ATTRIBUTE_UNUSED;
{
struct insns_for_mem_entry *ifmhe;
if (he)
return he;
ifmhe = ((struct insns_for_mem_entry *)
hash_allocate (ht, sizeof (struct insns_for_mem_entry)));
ifmhe->insns = NULL_RTX;
return &ifmhe->he;
}
/* Return a hash value for K, a REG. */
static unsigned long
insns_for_mem_hash (k)
hash_table_key k;
{
/* K is really a RTX. Just use the address as the hash value. */
return (unsigned long) k;
}
/* Return non-zero if K1 and K2 (two REGs) are the same. */
static boolean
insns_for_mem_comp (k1, k2)
hash_table_key k1;
hash_table_key k2;
{
return k1 == k2;
}
struct insns_for_mem_walk_info {
/* The hash table that we are using to record which INSNs use which
MEMs. */
struct hash_table *ht;
/* The INSN we are currently proessing. */
rtx insn;
/* Zero if we are walking to find ADDRESSOFs, one if we are walking
to find the insns that use the REGs in the ADDRESSOFs. */
int pass;
};
/* Called from compute_insns_for_mem via for_each_rtx. If R is a REG
that might be used in an ADDRESSOF expression, record this INSN in
the hash table given by DATA (which is really a pointer to an
insns_for_mem_walk_info structure). */
static int
insns_for_mem_walk (r, data)
rtx *r;
void *data;
{
struct insns_for_mem_walk_info *ifmwi
= (struct insns_for_mem_walk_info *) data;
if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF
&& GET_CODE (XEXP (*r, 0)) == REG)
hash_lookup (ifmwi->ht, XEXP (*r, 0), /*create=*/1, /*copy=*/0);
else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG)
{
/* Lookup this MEM in the hashtable, creating it if necessary. */
struct insns_for_mem_entry *ifme
= (struct insns_for_mem_entry *) hash_lookup (ifmwi->ht,
*r,
/*create=*/0,
/*copy=*/0);
/* If we have not already recorded this INSN, do so now. Since
we process the INSNs in order, we know that if we have
recorded it it must be at the front of the list. */
if (ifme && (!ifme->insns || XEXP (ifme->insns, 0) != ifmwi->insn))
{
/* We do the allocation on the same obstack as is used for
the hash table since this memory will not be used once
the hash table is deallocated. */
push_obstacks (&ifmwi->ht->memory, &ifmwi->ht->memory);
ifme->insns = gen_rtx_EXPR_LIST (VOIDmode, ifmwi->insn,
ifme->insns);
pop_obstacks ();
}
}
return 0;
}
/* Walk the INSNS, until we reach LAST_INSN, recording which INSNs use
which REGs in HT. */
static void
compute_insns_for_mem (insns, last_insn, ht)
rtx insns;
rtx last_insn;
struct hash_table *ht;
{
rtx insn;
struct insns_for_mem_walk_info ifmwi;
ifmwi.ht = ht;
for (ifmwi.pass = 0; ifmwi.pass < 2; ++ifmwi.pass)
for (insn = insns; insn != last_insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
ifmwi.insn = insn;
for_each_rtx (&insn, insns_for_mem_walk, &ifmwi);
} }
} }
...@@ -3223,14 +3405,32 @@ purge_addressof (insns) ...@@ -3223,14 +3405,32 @@ purge_addressof (insns)
rtx insns; rtx insns;
{ {
rtx insn; rtx insn;
struct hash_table ht;
/* When we actually purge ADDRESSOFs, we turn REGs into MEMs. That
requires a fixup pass over the instruction stream to correct
INSNs that depended on the REG being a REG, and not a MEM. But,
these fixup passes are slow. Furthermore, more MEMs are not
mentioned in very many instructions. So, we speed up the process
by pre-calculating which REGs occur in which INSNs; that allows
us to perform the fixup passes much more quickly. */
hash_table_init (&ht,
insns_for_mem_newfunc,
insns_for_mem_hash,
insns_for_mem_comp);
compute_insns_for_mem (insns, NULL_RTX, &ht);
for (insn = insns; insn; insn = NEXT_INSN (insn)) for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN) || GET_CODE (insn) == CALL_INSN)
{ {
purge_addressof_1 (&PATTERN (insn), insn, purge_addressof_1 (&PATTERN (insn), insn,
asm_noperands (PATTERN (insn)) > 0, 0); asm_noperands (PATTERN (insn)) > 0, 0, &ht);
purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0); purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, &ht);
} }
/* Clean up. */
hash_table_free (&ht);
purge_addressof_replacements = 0; purge_addressof_replacements = 0;
} }
......
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