[CFT] mostly fix opt/2692
Richard Henderson
rth@redhat.com
Fri Apr 12 02:02:00 GMT 2002
The largest problem here is lots of inline function calls that take
reference parameters, all of which want to put_var_into_stack. And
then we were being quite lame about doing that.
The original profile looks like
expand : 437.55 (63%) usr 0.06 ( 4%) sys 437.62 (63%) wall
reload CSE regs : 93.22 (14%) usr 0.02 ( 1%) sys 93.25 (13%) wall
global alloc : 77.21 (11%) usr 0.04 ( 3%) sys 77.25 (11%) wall
regmove : 46.49 ( 7%) usr 0.02 ( 1%) sys 46.50 ( 7%) wall
CSE : 11.21 ( 2%) usr 0.02 ( 1%) sys 11.25 ( 2%) wall
TOTAL : 690.08 1.59 697.00
23.67 177.68 177.68 346184136 0.00 0.00 fixup_var_refs_1
18.96 320.01 142.34 58977 0.00 0.01 fixup_var_refs_insns
9.57 391.89 71.88 346184136 0.00 0.00 fixup_var_refs_insn
8.67 456.94 65.05 17877 0.00 0.00 find_equiv_reg
6.96 509.17 52.23 19084 0.00 0.00 reg_is_remote_constant_p
Hmm. Very Suggestive. Why, yes, we are in fact iterating over the
insns of a very large function a gazillion times. Mark added some
nice hash-tabley things a while ago, but apparently only changed the
.addressof pass to use it, not initial variable expansion.
So I rearranged things a bit so we queue var refs fixups until the
end of function expansion and set up the hash table and now the
profile looks like
expand : 1.29 ( 1%) usr 0.04 ( 2%) sys 1.38 ( 1%) wall
reload CSE regs : 88.75 (36%) usr 0.02 ( 1%) sys 88.75 (34%) wall
global alloc : 77.34 (31%) usr 0.04 ( 2%) sys 77.38 (30%) wall
regmove : 46.00 (18%) usr 0.01 ( 1%) sys 46.00 (18%) wall
CSE : 11.43 ( 5%) usr 0.04 ( 2%) sys 11.62 ( 4%) wall
TOTAL : 249.21 1.86 259.25
22.84 58.81 58.81 17883 0.00 0.00 find_equiv_reg
19.87 109.99 51.18 20005 0.00 0.00 reg_is_remote_constant_p
16.23 151.79 41.80 111292090 0.00 0.00 cselib_invalidate_mem_1
I.e. fixup_var_refs has dropped completely off the map.
It looks very nice on paper. It'd be a real shame not to have this on
the branch -- if it works. It's a fairly invasive change to the order
in which things are done, and as such warrents some careful testing.
At this point I've done nothing with this patch but run one file through
it, and even that one I havn't executed. I'm about to start some overnight
tests and pop off to bed, but I thought I'd encourage some folks living
nearer GMT to test this as well.
r~
* function.h (struct function): Add fixup_var_refs_queue_p.
* function.c (push_function_context_to): Don't clear the queue.
(pop_function_context_from): Don't run the queue.
(schedule_fixup_var_refs): Rearrange arguments to match
fixup_var_refs; update all callers. Queue the fixup if
fixup_var_refs_queue_p.
(fixup_var_refs_insns_with_hash): If no hash table entry,
nothing to do.
(gen_mem_addressof): Use schedule_fixup_var_refs.
(prepare_function_start): Set fixup_var_refs_queue_p.
(fixup_queued_var_refs): New.
(expand_function_end): Call it.
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.347.2.3
diff -c -p -d -r1.347.2.3 function.c
*** function.c 3 Apr 2002 03:43:36 -0000 1.347.2.3
--- function.c 12 Apr 2002 08:38:25 -0000
*************** static void put_reg_into_stack PARAMS ((
*** 236,244 ****
enum machine_mode, enum machine_mode,
int, unsigned int, int,
struct hash_table *));
! static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree,
enum machine_mode,
! struct hash_table *));
static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx,
struct hash_table *));
static struct fixup_replacement
--- 236,245 ----
enum machine_mode, enum machine_mode,
int, unsigned int, int,
struct hash_table *));
! static void schedule_fixup_var_refs PARAMS ((struct function *, rtx,
enum machine_mode,
! int, struct hash_table *));
! static void fixup_queued_var_refs PARAMS ((void));
static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx,
struct hash_table *));
static struct fixup_replacement
*************** push_function_context_to (context)
*** 354,360 ****
p->outer = outer_function_chain;
outer_function_chain = p;
- p->fixup_var_refs_queue = 0;
if (save_lang_status)
(*save_lang_status) (p);
--- 355,360 ----
*************** pop_function_context_from (context)
*** 376,382 ****
tree context ATTRIBUTE_UNUSED;
{
struct function *p = outer_function_chain;
- struct var_refs_queue *queue;
cfun = p;
outer_function_chain = p->outer;
--- 376,381 ----
*************** pop_function_context_from (context)
*** 389,420 ****
if (restore_lang_status)
(*restore_lang_status) (p);
- /* Finish doing put_var_into_stack for any of our variables which became
- addressable during the nested function. If only one entry has to be
- fixed up, just do that one. Otherwise, first make a list of MEMs that
- are not to be unshared. */
- if (p->fixup_var_refs_queue == 0)
- ;
- else if (p->fixup_var_refs_queue->next == 0)
- fixup_var_refs (p->fixup_var_refs_queue->modified,
- p->fixup_var_refs_queue->promoted_mode,
- p->fixup_var_refs_queue->unsignedp,
- p->fixup_var_refs_queue->modified, 0);
- else
- {
- rtx list = 0;
-
- for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
- list = gen_rtx_EXPR_LIST (VOIDmode, queue->modified, list);
-
- for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
- fixup_var_refs (queue->modified, queue->promoted_mode,
- queue->unsignedp, list, 0);
-
- }
-
- p->fixup_var_refs_queue = 0;
-
/* Reset variables that have known state during rtx generation. */
rtx_equal_function_value_matters = 1;
virtuals_instantiated = 0;
--- 388,393 ----
*************** put_var_into_stack (decl)
*** 1475,1484 ****
XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
if (usedp)
{
! schedule_fixup_var_refs (function, reg, TREE_TYPE (decl),
! promoted_mode, 0);
! schedule_fixup_var_refs (function, lopart, part_type, part_mode, 0);
! schedule_fixup_var_refs (function, hipart, part_type, part_mode, 0);
}
}
else
--- 1448,1459 ----
XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
if (usedp)
{
! schedule_fixup_var_refs (function, reg, promoted_mode,
! TREE_UNSIGNED (TREE_TYPE (decl)), 0);
! schedule_fixup_var_refs (function, lopart, part_mode,
! TREE_UNSIGNED (part_type), 0);
! schedule_fixup_var_refs (function, hipart, part_mode,
! TREE_UNSIGNED (part_type), 0);
}
}
else
*************** put_reg_into_stack (function, reg, type,
*** 1537,1543 ****
}
if (used_p)
! schedule_fixup_var_refs (function, reg, type, promoted_mode, ht);
}
/* Make sure that all refs to the variable, previously made
--- 1512,1519 ----
}
if (used_p)
! schedule_fixup_var_refs (function, reg, promoted_mode,
! TREE_UNSIGNED (type), ht);
}
/* Make sure that all refs to the variable, previously made
*************** put_reg_into_stack (function, reg, type,
*** 1545,1565 ****
See function above for meaning of arguments. */
static void
! schedule_fixup_var_refs (function, reg, type, promoted_mode, ht)
struct function *function;
rtx reg;
- tree type;
enum machine_mode promoted_mode;
struct hash_table *ht;
{
! int unsigned_p = type ? TREE_UNSIGNED (type) : 0;
! if (function != 0)
! {
! struct var_refs_queue *temp;
! temp
! = (struct var_refs_queue *) ggc_alloc (sizeof (struct var_refs_queue));
temp->modified = reg;
temp->promoted_mode = promoted_mode;
temp->unsignedp = unsigned_p;
--- 1521,1542 ----
See function above for meaning of arguments. */
static void
! schedule_fixup_var_refs (function, reg, promoted_mode, unsigned_p, ht)
struct function *function;
rtx reg;
enum machine_mode promoted_mode;
+ int unsigned_p;
struct hash_table *ht;
{
! struct var_refs_queue *temp;
! if (function == 0)
! function = cfun;
! if (function->fixup_var_refs_queue_p)
! {
! temp = (struct var_refs_queue *)
! ggc_alloc (sizeof (struct var_refs_queue));
temp->modified = reg;
temp->promoted_mode = promoted_mode;
temp->unsignedp = unsigned_p;
*************** schedule_fixup_var_refs (function, reg,
*** 1567,1583 ****
function->fixup_var_refs_queue = temp;
}
else
- /* Variable is local; fix it up now. */
fixup_var_refs (reg, promoted_mode, unsigned_p, reg, ht);
}
static void
fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
- struct hash_table *ht;
rtx may_share;
{
tree pending;
rtx first_insn = get_insns ();
--- 1544,1596 ----
function->fixup_var_refs_queue = temp;
}
else
fixup_var_refs (reg, promoted_mode, unsigned_p, reg, ht);
}
+
+ /* Finish doing put_var_into_stack for any of our variables which became
+ addressable during compilation. */
+
+ static void
+ fixup_queued_var_refs ()
+ {
+ struct var_refs_queue *queue = cfun->fixup_var_refs_queue;
+
+ if (!queue)
+ return;
+
+ if (!queue->next)
+ fixup_var_refs (queue->modified, queue->promoted_mode,
+ queue->unsignedp, queue->modified, NULL);
+ else
+ {
+ rtx list;
+ struct hash_table ht;
+
+ hash_table_init (&ht, insns_for_mem_newfunc, insns_for_mem_hash,
+ insns_for_mem_comp);
+ compute_insns_for_mem (get_insns (), NULL_RTX, &ht);
+
+ list = NULL_RTX;
+ for (queue = cfun->fixup_var_refs_queue; queue; queue = queue->next)
+ list = alloc_EXPR_LIST (VOIDmode, queue->modified, list);
+
+ for (queue = cfun->fixup_var_refs_queue; queue; queue = queue->next)
+ fixup_var_refs (queue->modified, queue->promoted_mode,
+ queue->unsignedp, list, &ht);
+
+ hash_table_free (&ht);
+ }
+
+ cfun->fixup_var_refs_queue = NULL;
+ }
static void
fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
rtx may_share;
+ struct hash_table *ht;
{
tree pending;
rtx first_insn = get_insns ();
*************** fixup_var_refs_insns_with_hash (ht, var,
*** 1723,1728 ****
--- 1736,1744 ----
/*create=*/0, /*copy=*/0);
rtx insn_list;
+ if (!ime)
+ return;
+
for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1))
if (INSN_P (XEXP (insn_list, 0)))
fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode,
*************** gen_mem_addressof (reg, decl)
*** 2920,2929 ****
SET_DECL_RTL (decl, reg);
if (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0))
! fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), reg, 0);
}
else
! fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
return reg;
}
--- 2936,2946 ----
SET_DECL_RTL (decl, reg);
if (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0))
! schedule_fixup_var_refs (0, reg, GET_MODE (reg),
! TREE_UNSIGNED (type), 0);
}
else
! schedule_fixup_var_refs (0, reg, GET_MODE (reg), 0, 0);
return reg;
}
*************** prepare_function_start ()
*** 6214,6219 ****
--- 6231,6239 ----
current_function_uses_pic_offset_table = 0;
current_function_cannot_inline = 0;
+ /* Queue addressed variable fixups. */
+ cfun->fixup_var_refs_queue_p = true;
+
/* We have not yet needed to make a label to jump to for tail-recursion. */
tail_recursion_label = 0;
*************** expand_function_end (filename, line, end
*** 6851,6856 ****
--- 6871,6880 ----
while (in_sequence_p ())
end_sequence ();
+ /* Drop addressed variables to memory. */
+ fixup_queued_var_refs ();
+ cfun->fixup_var_refs_queue_p = false;
+
/* Outside function body, can't compute type's actual size
until next function's body starts. */
immediate_size_expand--;
*************** mark_function_status (p)
*** 7947,7953 ****
{
ggc_mark (q);
ggc_mark_rtx (q->modified);
! }
ggc_mark_rtx (p->x_nonlocal_goto_handler_slots);
ggc_mark_rtx (p->x_nonlocal_goto_handler_labels);
--- 7971,7977 ----
{
ggc_mark (q);
ggc_mark_rtx (q->modified);
! }
ggc_mark_rtx (p->x_nonlocal_goto_handler_slots);
ggc_mark_rtx (p->x_nonlocal_goto_handler_labels);
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.75
diff -c -p -d -r1.75 function.h
*** function.h 3 Jan 2002 17:39:59 -0000 1.75
--- function.h 12 Apr 2002 08:38:25 -0000
*************** struct function
*** 475,480 ****
--- 475,483 ----
/* Nonzero if code to initialize arg_pointer_save_area has been emited. */
unsigned int arg_pointer_save_area_init : 1;
+
+ /* Nonzero if addressable variable fixups should be queued. */
+ unsigned int fixup_var_refs_queue_p : 1;
};
/* The function currently being compiled. */
More information about the Gcc-patches
mailing list