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>
PR c/18715
......
......@@ -104,7 +104,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
life_analysis fills in certain vectors containing information about
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
doesn't modify the stack pointer. */
......@@ -1589,6 +1589,7 @@ allocate_reg_life_data (void)
REG_N_REFS (i) = 0;
REG_N_DEATHS (i) = 0;
REG_N_CALLS_CROSSED (i) = 0;
REG_N_THROWING_CALLS_CROSSED (i) = 0;
REG_LIVE_LENGTH (i) = 0;
REG_FREQ (i) = 0;
REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
......@@ -1820,6 +1821,9 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
reg_set_iterator rsi;
EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi)
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
......@@ -3512,7 +3516,11 @@ attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
that REGNO now crosses them. */
for (temp = insn; temp != incr; temp = NEXT_INSN (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. */
clear_reg_alias_info (q);
......
......@@ -465,7 +465,9 @@ global_alloc (FILE *file)
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! 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
&& reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
......
......@@ -61,6 +61,7 @@ typedef struct reg_info_def
int deaths; /* # of times (REG n) dies */
int live_length; /* # of instructions (REG n) is live */
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 */
} reg_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)
/* 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.
The larger this is, the less priority (REG n) gets for
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>
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