Commit 27004606 by Jakub Jelinek Committed by Jakub Jelinek

re PR rtl-optimization/23478 (Miscompilation due to reloading of a var that is also used in EH pad)

	PR rtl-optimization/23478
	* regs.h (reg_info): Add throw_calls_crossed.
	(REG_N_THROWING_CALLS_CROSSED): Define.
	* flow.c (allocate_reg_life_data): Initialize
	REG_N_THROWING_CALLS_CROSSED.
	(propagate_one_insn, attempt_auto_inc): Update
	REG_N_THROWING_CALLS_CROSSED.
	* global.c (global_alloc): Don't allocate pseudos across
	calls that may throw.

	* g++.dg/opt/pr23478.C: New test.

From-SVN: r103348
parent ad685e81
2005-08-22 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/23478
* regs.h (reg_info): Add throw_calls_crossed.
(REG_N_THROWING_CALLS_CROSSED): Define.
* flow.c (allocate_reg_life_data): Initialize
REG_N_THROWING_CALLS_CROSSED.
(propagate_one_insn, attempt_auto_inc): Update
REG_N_THROWING_CALLS_CROSSED.
* global.c (global_alloc): Don't allocate pseudos across
calls that may throw.
2005-08-22 Andrew Pinski <pinskia@physics.uc.edu> 2005-08-22 Andrew Pinski <pinskia@physics.uc.edu>
PR c/18715 PR c/18715
......
...@@ -104,7 +104,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -104,7 +104,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
life_analysis fills in certain vectors containing information about life_analysis fills in certain vectors containing information about
register usage: REG_N_REFS, REG_N_DEATHS, REG_N_SETS, REG_LIVE_LENGTH, register usage: REG_N_REFS, REG_N_DEATHS, REG_N_SETS, REG_LIVE_LENGTH,
REG_N_CALLS_CROSSED and REG_BASIC_BLOCK. REG_N_CALLS_CROSSED, REG_N_THROWING_CALLS_CROSSED and REG_BASIC_BLOCK.
life_analysis sets current_function_sp_is_unchanging if the function life_analysis sets current_function_sp_is_unchanging if the function
doesn't modify the stack pointer. */ doesn't modify the stack pointer. */
...@@ -1589,6 +1589,7 @@ allocate_reg_life_data (void) ...@@ -1589,6 +1589,7 @@ allocate_reg_life_data (void)
REG_N_REFS (i) = 0; REG_N_REFS (i) = 0;
REG_N_DEATHS (i) = 0; REG_N_DEATHS (i) = 0;
REG_N_CALLS_CROSSED (i) = 0; REG_N_CALLS_CROSSED (i) = 0;
REG_N_THROWING_CALLS_CROSSED (i) = 0;
REG_LIVE_LENGTH (i) = 0; REG_LIVE_LENGTH (i) = 0;
REG_FREQ (i) = 0; REG_FREQ (i) = 0;
REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN; REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
...@@ -1820,6 +1821,9 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn) ...@@ -1820,6 +1821,9 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
reg_set_iterator rsi; reg_set_iterator rsi;
EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi) EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi)
REG_N_CALLS_CROSSED (i)++; REG_N_CALLS_CROSSED (i)++;
if (can_throw_internal (insn))
EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi)
REG_N_THROWING_CALLS_CROSSED (i)++;
} }
/* Record sets. Do this even for dead instructions, since they /* Record sets. Do this even for dead instructions, since they
...@@ -3512,7 +3516,11 @@ attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn, ...@@ -3512,7 +3516,11 @@ attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
that REGNO now crosses them. */ that REGNO now crosses them. */
for (temp = insn; temp != incr; temp = NEXT_INSN (temp)) for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
if (CALL_P (temp)) if (CALL_P (temp))
REG_N_CALLS_CROSSED (regno)++; {
REG_N_CALLS_CROSSED (regno)++;
if (can_throw_internal (temp))
REG_N_THROWING_CALLS_CROSSED (regno)++;
}
/* Invalidate alias info for Q since we just changed its value. */ /* Invalidate alias info for Q since we just changed its value. */
clear_reg_alias_info (q); clear_reg_alias_info (q);
......
...@@ -465,7 +465,9 @@ global_alloc (FILE *file) ...@@ -465,7 +465,9 @@ global_alloc (FILE *file)
/* Don't allocate pseudos that cross calls, /* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */ if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label && (! current_function_has_nonlocal_label
|| REG_N_CALLS_CROSSED (i) == 0)) || REG_N_CALLS_CROSSED (i) == 0)
/* Don't allocate pseudos that cross calls that may throw. */
&& REG_N_THROWING_CALLS_CROSSED (i) == 0)
{ {
if (reg_renumber[i] < 0 if (reg_renumber[i] < 0
&& reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0) && reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
......
...@@ -61,6 +61,7 @@ typedef struct reg_info_def ...@@ -61,6 +61,7 @@ typedef struct reg_info_def
int deaths; /* # of times (REG n) dies */ int deaths; /* # of times (REG n) dies */
int live_length; /* # of instructions (REG n) is live */ int live_length; /* # of instructions (REG n) is live */
int calls_crossed; /* # of calls (REG n) is live across */ int calls_crossed; /* # of calls (REG n) is live across */
int throw_calls_crossed; /* # of calls that may throw (REG n) is live across */
int basic_block; /* # of basic blocks (REG n) is used in */ int basic_block; /* # of basic blocks (REG n) is used in */
} reg_info; } reg_info;
...@@ -125,6 +126,12 @@ extern varray_type reg_n_info; ...@@ -125,6 +126,12 @@ extern varray_type reg_n_info;
#define REG_N_CALLS_CROSSED(N) (VARRAY_REG (reg_n_info, N)->calls_crossed) #define REG_N_CALLS_CROSSED(N) (VARRAY_REG (reg_n_info, N)->calls_crossed)
/* Indexed by N, gives number of CALL_INSNS that may throw, across which
(REG n) is live. */
#define REG_N_THROWING_CALLS_CROSSED(N) \
(VARRAY_REG (reg_n_info, N)->throw_calls_crossed)
/* Total number of instructions at which (REG n) is live. /* Total number of instructions at which (REG n) is live.
The larger this is, the less priority (REG n) gets for The larger this is, the less priority (REG n) gets for
allocation in a hard register (in global-alloc). allocation in a hard register (in global-alloc).
......
2005-08-22 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/23478
* g++.dg/opt/pr23478.C: New test.
2005-08-22 Andrew Pinski <pinskia@physics.uc.edu> 2005-08-22 Andrew Pinski <pinskia@physics.uc.edu>
PR c/18715 PR c/18715
......
// PR rtl-optimization/23478
// { dg-do run }
// { dg-options "-O2" }
extern "C" void abort ();
bool tthrow;
struct C3 { int i; };
class C14 {};
struct C7
{
virtual ~C7 ();
};
C7::~C7 ()
{
asm volatile ("" : : : "memory");
}
class C2 : public C7 {};
template <class X> class C13
{
bool ma;
X *mb;
public:
explicit C13 (X *p = 0) throw () : ma (p != 0), mb (p) {}
~C13 ();
};
template <class X>
C13<X>::~C13 ()
{
asm volatile ("" : : "r" (ma), "r" (mb) : "memory");
}
struct C1
{
C1 (const C3 &, const C3 &, const C3 &, const C3 *&);
};
C1::C1 (const C3 &, const C3 &, const C3 &, const C3 *&)
{
if (!tthrow)
throw 24;
}
struct C8
{
struct C15 {};
typedef C15 *C9;
virtual void f1 (C2 &, long *, void *, C3 &, void *, bool) = 0;
virtual C13<C14> f3 () const = 0;
virtual ~C8 () {}
};
bool
xx14 ()
{
bool b = false;
if (tthrow)
throw 6;
asm volatile ("" : : "r" (&b) : "memory");
return b;
}
bool
xx2 ()
{
bool b = false;
if (tthrow)
throw 6;
asm volatile ("" : : "r" (&b) : "memory");
return b;
}
C13<C7>
xx9 ()
{
return C13<C7>();
}
C2 &
xx10 ()
{
static C2 c2;
return c2;
}
C3 &
xx12 ()
{
static C3 c3 = { 1 };
return c3;
}
const C3 &
xx5 ()
{
static const C3 c3 = { 2 };
return c3;
}
const C3 *&
xx4 ()
{
static const C3 *p;
if (tthrow)
throw 6;
return p;
}
long ll13;
long
xx13 ()
{
long ret;
asm volatile ("" : "=r" (ret) : "r" (ll13));
return ret;
}
void
xx15 (C3 &x, C13<C1> &y)
{
asm volatile ("" : : "r" (&x), "r" (&y) : "memory");
}
long
xx16 (const void *x)
{
long ret;
asm volatile ("" : "=r" (ret) : "0" (1), "r" (x) : "memory");
return ret;
}
void
xx1 (C13<C14> x)
{
asm volatile ("" : : "r" (&x) : "memory");
if (tthrow)
throw 6;
}
void
xx3 (const C7 *x)
{
if (x)
abort ();
}
void
xx7 ()
{
asm volatile ("" : : : "memory");
}
struct C5
{
C13<C7> f2 (C3 &v1, const void *v2, C8 *v6);
C7 *m2[2];
long m1[2];
};
C13<C7>
C5::f2 (C3 &v1, const void *v2, C8 *v6)
{
C13<C7> v13 = xx9 ();
C2 &v9 = xx10 ();
for (long i = 1; i < 2; i++)
xx3 (m2[i]);
const C3 &ld = xx5 ();
xx7 ();
if (xx2 ())
throw "";
xx4 ();
C3 &si = xx12 ();
for (long i = 0; i < xx16 (v2); ++i)
{
C13<C1> sk (new C1 (xx5 (), ld, xx5 (), xx4 ()));
xx15 (si, sk);
}
long v4 = xx13 ();
for (long i = v4 - 1; i >= 0; --i)
m1[i] = i;
bool v8 = xx2 ();
for (long i = 0; i < 2 && !xx14 (); i++)
{
v6[i].f1 (v9, 0, __null, v1, __null, v8);
if (v8)
xx1 (v6[i].f3 ());
}
return v13;
}
int
main (void)
{
C5 c5 = { { __null, __null }, { 0, 0 } };
bool seen = false;
try
{
c5.f2 (xx12 (), __null, __null);
}
catch (int n)
{
if (n != 24)
abort ();
seen = true;
}
if (!seen)
abort ();
}
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