PATCH for purge_addressof sluggishness
Mark Mitchell
mark@codesourcery.com
Wed Mar 31 18:59:00 GMT 1999
>>>>> "Richard" == Richard Henderson <rth@cygnus.com> writes:
Richard> Certainly you could do a three pass scheme -- look for
Richard> addressof, look for pseudo uses, convert addressof. That
Richard> would probably minimize memory usage for only a little
Richard> extra work.
This seemed worth doing, and wasn't hard. So, I put in the attached
patch.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Mon Mar 22 10:53:59 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.
1999-03-22 Mark Mitchell <mark@codesourcery.com>
* Makefile.in (OBJS): Don't mention hash.o.
(OBJDEPS): Likewise.
Index: function.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.c,v
retrieving revision 1.80
diff -c -p -r1.80 function.c
*** function.c 1999/03/17 12:17:02 1.80
--- function.c 1999/03/23 15:45:11
*************** Boston, MA 02111-1307, USA. */
*** 56,61 ****
--- 56,62 ----
#include "basic-block.h"
#include "obstack.h"
#include "toplev.h"
+ #include "hash.h"
#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
*************** struct fixup_replacement
*** 451,456 ****
--- 452,464 ----
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. */
static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT,
*************** static rtx assign_stack_temp_for_type PR
*** 460,471 ****
static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
! int, int, int));
! static void fixup_var_refs PROTO((rtx, enum machine_mode, int));
static struct fixup_replacement
*find_fixup_replacement PROTO((struct fixup_replacement **, rtx));
static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,
! rtx, int));
static void fixup_var_refs_1 PROTO((rtx, enum machine_mode, rtx *, rtx,
struct fixup_replacement **));
static rtx fixup_memory_subreg PROTO((rtx, rtx, int));
--- 468,481 ----
static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
! int, int, int,
! struct hash_table *));
! static void fixup_var_refs PROTO((rtx, enum machine_mode, int,
! struct hash_table *));
static struct fixup_replacement
*find_fixup_replacement PROTO((struct fixup_replacement **, rtx));
static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,
! rtx, int, struct hash_table *));
static void fixup_var_refs_1 PROTO((rtx, enum machine_mode, rtx *, rtx,
struct fixup_replacement **));
static rtx fixup_memory_subreg PROTO((rtx, rtx, int));
*************** static int all_blocks PROTO((tree, tree
*** 492,499 ****
static int *record_insns PROTO((rtx));
static int contains PROTO((rtx, int *));
#endif /* HAVE_prologue || HAVE_epilogue */
! static void put_addressof_into_stack PROTO((rtx));
! static void purge_addressof_1 PROTO((rtx *, rtx, int, int));
/* Pointer to chain of `struct function' for containing functions. */
struct function *outer_function_chain;
--- 502,518 ----
static int *record_insns PROTO((rtx));
static int contains PROTO((rtx, int *));
#endif /* HAVE_prologue || HAVE_epilogue */
! static void put_addressof_into_stack PROTO((rtx, struct hash_table *));
! 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. */
struct function *outer_function_chain;
*************** pop_function_context_from (context)
*** 683,689 ****
/* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */
for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
! fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
free (p);
--- 702,709 ----
/* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */
for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
! fixup_var_refs (queue->modified, queue->promoted_mode,
! queue->unsignedp, 0);
free (p);
*************** put_var_into_stack (decl)
*** 1569,1576 ****
put_reg_into_stack (function, reg, TREE_TYPE (decl),
promoted_mode, decl_mode,
TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl)
! || DECL_INITIAL (decl) != 0);
}
else if (GET_CODE (reg) == CONCAT)
{
--- 1589,1596 ----
put_reg_into_stack (function, reg, TREE_TYPE (decl),
promoted_mode, decl_mode,
TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0,
! 0);
}
else if (GET_CODE (reg) == CONCAT)
{
*************** put_var_into_stack (decl)
*** 1582,1598 ****
/* Since part 0 should have a lower address, do it second. */
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0);
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0);
#else
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0);
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0);
#endif
/* Change the CONCAT into a combined MEM for both parts. */
--- 1602,1622 ----
/* Since part 0 should have a lower address, do it second. */
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0,
! 0);
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0,
! 0);
#else
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0,
! 0);
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
! TREE_USED (decl) || DECL_INITIAL (decl) != 0,
! 0);
#endif
/* Change the CONCAT into a combined MEM for both parts. */
*************** put_var_into_stack (decl)
*** 1628,1634 ****
static void
put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
! original_regno, used_p)
struct function *function;
rtx reg;
tree type;
--- 1652,1658 ----
static void
put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
! original_regno, used_p, ht)
struct function *function;
rtx reg;
tree type;
*************** put_reg_into_stack (function, reg, type,
*** 1636,1641 ****
--- 1660,1666 ----
int volatile_p;
int original_regno;
int used_p;
+ struct hash_table *ht;
{
rtx new = 0;
int regno = original_regno;
*************** put_reg_into_stack (function, reg, type,
*** 1698,1711 ****
}
else if (used_p)
/* Variable is local; fix it up now. */
! fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type));
}
static void
! fixup_var_refs (var, promoted_mode, unsignedp)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
{
tree pending;
rtx first_insn = get_insns ();
--- 1723,1737 ----
}
else if (used_p)
/* Variable is local; fix it up now. */
! fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type), ht);
}
static void
! fixup_var_refs (var, promoted_mode, unsignedp, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
+ struct hash_table *ht;
{
tree pending;
rtx first_insn = get_insns ();
*************** fixup_var_refs (var, promoted_mode, unsi
*** 1713,1726 ****
tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */
! fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
{
push_to_sequence (stack->first);
fixup_var_refs_insns (var, promoted_mode, unsignedp,
! stack->first, stack->next != 0);
/* Update remembered end of sequence
in case we added an insn at the end. */
stack->last = get_last_insn ();
--- 1739,1756 ----
tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */
! 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. */
for (; stack; stack = stack->next)
{
push_to_sequence (stack->first);
fixup_var_refs_insns (var, promoted_mode, unsignedp,
! stack->first, stack->next != 0, 0);
/* Update remembered end of sequence
in case we added an insn at the end. */
stack->last = get_last_insn ();
*************** fixup_var_refs (var, promoted_mode, unsi
*** 1734,1747 ****
if (seq != const0_rtx && seq != 0)
{
push_to_sequence (seq);
! fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0);
end_sequence ();
}
}
/* Scan the catch clauses for exception handling too. */
push_to_sequence (catch_clauses);
! fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses, 0);
end_sequence ();
}
--- 1764,1779 ----
if (seq != const0_rtx && seq != 0)
{
push_to_sequence (seq);
! fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0,
! 0);
end_sequence ();
}
}
/* Scan the catch clauses for exception handling too. */
push_to_sequence (catch_clauses);
! fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses,
! 0, 0);
end_sequence ();
}
*************** find_fixup_replacement (replacements, x)
*** 1777,1791 ****
main chain of insns for the current function. */
static void
! fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
rtx insn;
int toplevel;
{
rtx call_dest = 0;
while (insn)
{
rtx next = NEXT_INSN (insn);
--- 1809,1835 ----
main chain of insns for the current function. */
static void
! fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
rtx insn;
int toplevel;
+ struct hash_table *ht;
{
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)
{
rtx next = NEXT_INSN (insn);
*************** fixup_var_refs_insns (var, promoted_mode
*** 1957,1963 ****
XEXP (note, 0)
= walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
}
! insn = next;
}
}
--- 2001,2016 ----
XEXP (note, 0)
= walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
}
!
! if (!ht)
! insn = next;
! else if (insn_list)
! {
! insn = XEXP (insn_list, 0);
! insn_list = XEXP (insn_list, 1);
! }
! else
! insn = NULL_RTX;
}
}
*************** gen_mem_addressof (reg, decl)
*** 2929,2935 ****
MEM_ALIAS_SET (reg) = get_alias_set (decl);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
! fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type));
return reg;
}
--- 2982,2988 ----
MEM_ALIAS_SET (reg) = get_alias_set (decl);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
! fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
return reg;
}
*************** flush_addressof (decl)
*** 2945,2958 ****
&& GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
! put_addressof_into_stack (XEXP (DECL_RTL (decl), 0));
}
/* Force the register pointed to by R, an ADDRESSOF rtx, into the stack. */
static void
! put_addressof_into_stack (r)
rtx r;
{
tree decl = ADDRESSOF_DECL (r);
rtx reg = XEXP (r, 0);
--- 2998,3012 ----
&& GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
! put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
}
/* Force the register pointed to by R, an ADDRESSOF rtx, into the stack. */
static void
! put_addressof_into_stack (r, ht)
rtx r;
+ struct hash_table *ht;
{
tree decl = ADDRESSOF_DECL (r);
rtx reg = XEXP (r, 0);
*************** put_addressof_into_stack (r)
*** 2963,2969 ****
put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
ADDRESSOF_REGNO (r),
! TREE_USED (decl) || DECL_INITIAL (decl) != 0);
}
/* List of replacements made below in purge_addressof_1 when creating
--- 3017,3023 ----
put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
ADDRESSOF_REGNO (r),
! TREE_USED (decl) || DECL_INITIAL (decl) != 0, ht);
}
/* List of replacements made below in purge_addressof_1 when creating
*************** static rtx purge_addressof_replacements;
*** 2975,2984 ****
the stack. */
static void
! purge_addressof_1 (loc, insn, force, store)
rtx *loc;
rtx insn;
int force, store;
{
rtx x;
RTX_CODE code;
--- 3029,3039 ----
the stack. */
static void
! purge_addressof_1 (loc, insn, force, store, ht)
rtx *loc;
rtx insn;
int force, store;
+ struct hash_table *ht;
{
rtx x;
RTX_CODE code;
*************** purge_addressof_1 (loc, insn, force, sto
*** 3032,3038 ****
if (GET_CODE (sub) == REG
&& (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
{
! put_addressof_into_stack (XEXP (x, 0));
return;
}
else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
--- 3087,3093 ----
if (GET_CODE (sub) == REG
&& (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
{
! put_addressof_into_stack (XEXP (x, 0), ht);
return;
}
else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
*************** purge_addressof_1 (loc, insn, force, sto
*** 3111,3117 ****
if (store)
{
! rtx p;
start_sequence ();
val = gen_reg_rtx (GET_MODE (x));
--- 3166,3172 ----
if (store)
{
! rtx p = PREV_INSN (insn);
start_sequence ();
val = gen_reg_rtx (GET_MODE (x));
*************** purge_addressof_1 (loc, insn, force, sto
*** 3125,3130 ****
--- 3180,3187 ----
seq = gen_sequence ();
end_sequence ();
emit_insn_before (seq, insn);
+ compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
+ insn, ht);
start_sequence ();
store_bit_field (sub, size_x, 0, GET_MODE (x),
*************** purge_addressof_1 (loc, insn, force, sto
*** 3143,3152 ****
seq = gen_sequence ();
end_sequence ();
! emit_insn_after (seq, insn);
}
else
{
start_sequence ();
val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
GET_MODE (x), GET_MODE (x),
--- 3200,3215 ----
seq = gen_sequence ();
end_sequence ();
! 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
{
+ rtx p = PREV_INSN (insn);
+
start_sequence ();
val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
GET_MODE (x), GET_MODE (x),
*************** purge_addressof_1 (loc, insn, force, sto
*** 3164,3169 ****
--- 3227,3234 ----
seq = gen_sequence ();
end_sequence ();
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
*************** purge_addressof_1 (loc, insn, force, sto
*** 3192,3204 ****
}
else if (code == ADDRESSOF)
{
! put_addressof_into_stack (x);
return;
}
else if (code == SET)
{
! purge_addressof_1 (&SET_DEST (x), insn, force, 1);
! purge_addressof_1 (&SET_SRC (x), insn, force, 0);
return;
}
--- 3257,3269 ----
}
else if (code == ADDRESSOF)
{
! put_addressof_into_stack (x, ht);
return;
}
else if (code == SET)
{
! purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht);
! purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht);
return;
}
*************** purge_addressof_1 (loc, insn, force, sto
*** 3207,3219 ****
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
{
if (*fmt == 'e')
! purge_addressof_1 (&XEXP (x, i), insn, force, 0);
else if (*fmt == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
! purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0);
}
}
/* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining
(MEM (ADDRESSOF)) patterns, and force any needed registers into the
stack. */
--- 3272,3401 ----
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
{
if (*fmt == 'e')
! purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht);
else if (*fmt == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
! 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);
+ }
+ }
+
/* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining
(MEM (ADDRESSOF)) patterns, and force any needed registers into the
stack. */
*************** purge_addressof (insns)
*** 3223,3236 ****
rtx insns;
{
rtx insn;
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN)
{
purge_addressof_1 (&PATTERN (insn), insn,
! asm_noperands (PATTERN (insn)) > 0, 0);
! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0);
}
purge_addressof_replacements = 0;
}
--- 3405,3436 ----
rtx insns;
{
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))
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN)
{
purge_addressof_1 (&PATTERN (insn), insn,
! asm_noperands (PATTERN (insn)) > 0, 0, &ht);
! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht);
}
+
+ /* Clean up. */
+ hash_table_free (&ht);
purge_addressof_replacements = 0;
}
Index: Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/Makefile.in,v
retrieving revision 1.243
diff -c -p -r1.243 Makefile.in
*** Makefile.in 1999/03/18 21:59:34 1.243
--- Makefile.in 1999/03/23 15:45:13
*************** OBJS = toplev.o version.o tree.o print-t
*** 679,685 ****
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 \
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
# 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
--- 679,685 ----
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 \
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 hash.o
# 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
*************** varasm.o : varasm.c $(CONFIG_H) system.h
*** 1452,1458 ****
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.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
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 \
loop.h $(RECOG_H) toplev.h output.h varray.h
--- 1452,1458 ----
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.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 hash.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 \
loop.h $(RECOG_H) toplev.h output.h varray.h
Index: cp/Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Makefile.in,v
retrieving revision 1.47
diff -c -p -r1.47 Makefile.in
*** Makefile.in 1999/03/14 17:43:56 1.47
--- Makefile.in 1999/03/23 15:45:14
*************** CXX_OBJS = call.o decl.o errfn.o expr.o
*** 191,198 ****
repo.o @extra_cxx_objs@
# Language-independent object files.
! OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o ../hash.o
! OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o ../hash.o
compiler: ../cc1plus$(exeext)
../cc1plus$(exeext): $(P) $(OBJDEPS) $(CXX_OBJS) $(LIBDEPS)
--- 191,198 ----
repo.o @extra_cxx_objs@
# Language-independent object files.
! OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
! OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
compiler: ../cc1plus$(exeext)
../cc1plus$(exeext): $(P) $(OBJDEPS) $(CXX_OBJS) $(LIBDEPS)
More information about the Gcc-patches
mailing list