Commit e90b336f by Jeff Law Committed by Jeff Law

re PR rtl-optimization/41619 (ICE in insert_save (caller-save.c) for SPEC CPU2000's 252.eon)


	PR rtl-optimization/41619
	* caller-save.c (setup_save_areas): Break out code to determine
	which hard regs are live across calls by examining the reload chains
	so that it is always used.
	Eliminate code which checked REG_N_CALLS_CROSSED.

	PR rtl-optimization/41619
	* gcc.dg/pr41619.c: New.

From-SVN: r169095
parent 3ffe07e1
2011-01-21 Jeff Law <law@redhat.com>
PR rtl-optimization/41619
* caller-save.c (setup_save_areas): Break out code to determine
which hard regs are live across calls by examining the reload chains
so that it is always used.
Eliminate code which checked REG_N_CALLS_CROSSED.
2011-01-21 Jakub Jelinek <jakub@redhat.com> 2011-01-21 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/47355 PR tree-optimization/47355
......
/* Save and restore call-clobbered registers which are live across a call. /* Save and restore call-clobbered registers which are live across a call.
Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998, 1999, 2000, Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -416,101 +416,93 @@ saved_hard_reg_compare_func (const void *v1p, const void *v2p) ...@@ -416,101 +416,93 @@ saved_hard_reg_compare_func (const void *v1p, const void *v2p)
void void
setup_save_areas (void) setup_save_areas (void)
{ {
int i, j, k; int i, j, k, freq;
unsigned int r;
HARD_REG_SET hard_regs_used; HARD_REG_SET hard_regs_used;
struct saved_hard_reg *saved_reg;
rtx insn;
struct insn_chain *chain, *next;
unsigned int regno;
HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets;
reg_set_iterator rsi;
/* Allocate space in the save area for the largest multi-register
pseudos first, then work backwards to single register
pseudos. */
/* Find and record all call-used hard-registers in this function. */
CLEAR_HARD_REG_SET (hard_regs_used); CLEAR_HARD_REG_SET (hard_regs_used);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0)
{
unsigned int regno = reg_renumber[i];
unsigned int endregno
= end_hard_regno (GET_MODE (regno_reg_rtx[i]), regno);
for (r = regno; r < endregno; r++)
if (call_used_regs[r])
SET_HARD_REG_BIT (hard_regs_used, r);
}
if (optimize && flag_ira_share_save_slots) /* Find every CALL_INSN and record which hard regs are live across the
call into HARD_REG_MAP and HARD_REGS_USED. */
initiate_saved_hard_regs ();
/* Create hard reg saved regs. */
for (chain = reload_insn_chain; chain != 0; chain = next)
{ {
rtx insn, slot; insn = chain->insn;
struct insn_chain *chain, *next; next = chain->next;
char *saved_reg_conflicts; if (!CALL_P (insn)
unsigned int regno; || find_reg_note (insn, REG_NORETURN, NULL))
int next_k, freq; continue;
struct saved_hard_reg *saved_reg, *saved_reg2, *saved_reg3; freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
int call_saved_regs_num; REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
struct saved_hard_reg *call_saved_regs[FIRST_PSEUDO_REGISTER]; &chain->live_throughout);
HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets; COPY_HARD_REG_SET (used_regs, call_used_reg_set);
reg_set_iterator rsi;
int best_slot_num; /* Record all registers set in this call insn. These don't
int prev_save_slots_num; need to be saved. N.B. the call insn might set a subreg
rtx prev_save_slots[FIRST_PSEUDO_REGISTER]; of a multi-hard-reg pseudo; then the pseudo is considered
live during the call, but the subreg that is set
initiate_saved_hard_regs (); isn't. */
/* Create hard reg saved regs. */ CLEAR_HARD_REG_SET (this_insn_sets);
for (chain = reload_insn_chain; chain != 0; chain = next) note_stores (PATTERN (insn), mark_set_regs, &this_insn_sets);
/* Sibcalls are considered to set the return value. */
if (SIBLING_CALL_P (insn) && crtl->return_rtx)
mark_set_regs (crtl->return_rtx, NULL_RTX, &this_insn_sets);
AND_COMPL_HARD_REG_SET (used_regs, call_fixed_reg_set);
AND_COMPL_HARD_REG_SET (used_regs, this_insn_sets);
AND_HARD_REG_SET (hard_regs_to_save, used_regs);
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
{
if (hard_reg_map[regno] != NULL)
hard_reg_map[regno]->call_freq += freq;
else
saved_reg = new_saved_hard_reg (regno, freq);
SET_HARD_REG_BIT (hard_regs_used, regno);
}
/* Look through all live pseudos, mark their hard registers. */
EXECUTE_IF_SET_IN_REG_SET
(&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
{ {
insn = chain->insn; int r = reg_renumber[regno];
next = chain->next; int bound;
if (!CALL_P (insn)
|| find_reg_note (insn, REG_NORETURN, NULL))
continue;
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
COPY_HARD_REG_SET (used_regs, call_used_reg_set);
/* Record all registers set in this call insn. These don't if (r < 0)
need to be saved. N.B. the call insn might set a subreg continue;
of a multi-hard-reg pseudo; then the pseudo is considered
live during the call, but the subreg that is set
isn't. */
CLEAR_HARD_REG_SET (this_insn_sets);
note_stores (PATTERN (insn), mark_set_regs, &this_insn_sets);
/* Sibcalls are considered to set the return value. */
if (SIBLING_CALL_P (insn) && crtl->return_rtx)
mark_set_regs (crtl->return_rtx, NULL_RTX, &this_insn_sets);
AND_COMPL_HARD_REG_SET (used_regs, call_fixed_reg_set); bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
AND_COMPL_HARD_REG_SET (used_regs, this_insn_sets); for (; r < bound; r++)
AND_HARD_REG_SET (hard_regs_to_save, used_regs); if (TEST_HARD_REG_BIT (used_regs, r))
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
{ {
if (hard_reg_map[regno] != NULL) if (hard_reg_map[r] != NULL)
hard_reg_map[regno]->call_freq += freq; hard_reg_map[r]->call_freq += freq;
else else
saved_reg = new_saved_hard_reg (regno, freq); saved_reg = new_saved_hard_reg (r, freq);
SET_HARD_REG_BIT (hard_regs_to_save, r);
SET_HARD_REG_BIT (hard_regs_used, r);
} }
/* Look through all live pseudos, mark their hard registers. */ }
EXECUTE_IF_SET_IN_REG_SET }
(&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
{
int r = reg_renumber[regno];
int bound;
if (r < 0) /* If requested, figure out which hard regs can share save slots. */
continue; if (optimize && flag_ira_share_save_slots)
{
rtx slot;
char *saved_reg_conflicts;
int next_k;
struct saved_hard_reg *saved_reg2, *saved_reg3;
int call_saved_regs_num;
struct saved_hard_reg *call_saved_regs[FIRST_PSEUDO_REGISTER];
int best_slot_num;
int prev_save_slots_num;
rtx prev_save_slots[FIRST_PSEUDO_REGISTER];
bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
for (; r < bound; r++)
if (TEST_HARD_REG_BIT (used_regs, r))
{
if (hard_reg_map[r] != NULL)
hard_reg_map[r]->call_freq += freq;
else
saved_reg = new_saved_hard_reg (r, freq);
SET_HARD_REG_BIT (hard_regs_to_save, r);
}
}
}
/* Find saved hard register conflicts. */ /* Find saved hard register conflicts. */
saved_reg_conflicts = (char *) xmalloc (saved_regs_num * saved_regs_num); saved_reg_conflicts = (char *) xmalloc (saved_regs_num * saved_regs_num);
memset (saved_reg_conflicts, 0, saved_regs_num * saved_regs_num); memset (saved_reg_conflicts, 0, saved_regs_num * saved_regs_num);
...@@ -668,8 +660,10 @@ setup_save_areas (void) ...@@ -668,8 +660,10 @@ setup_save_areas (void)
} }
else else
{ {
/* Now run through all the call-used hard-registers and allocate /* We are not sharing slots.
space for them in the caller-save area. Try to allocate space
Run through all the call-used hard-registers and allocate
space for each in the caller-save area. Try to allocate space
in a manner which allows multi-register saves/restores to be done. */ in a manner which allows multi-register saves/restores to be done. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
......
2011-01-21 Jeff Law <law@redhat.com>
PR rtl-optimization/41619
* gcc.dg/pr41619.c: New.
2011-01-21 Jakub Jelinek <jakub@redhat.com> 2011-01-21 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/47355 PR tree-optimization/47355
......
/* { dg-do compile } */
/* { dg-options "-O2 -fno-ira-share-save-slots" } */
struct A {};
int foo();
struct A bar(double x)
{
double y;
if (foo())
y = 1 / x;
return bar(y);
}
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