re PR target/30230 (Incorrect ia64 EH info when an EH region ends in the middle of a bundle)

PR target/30230
	* config/ia64/ia64.c (ia64_add_bundle_selector_before): New function.
	(bundling): Use it.

	* g++.dg/eh/ia64-2.C: New test.

From-SVN: r120103
This commit is contained in:
Jakub Jelinek 2006-12-21 13:59:06 +01:00 committed by Jakub Jelinek
parent 970af86771
commit 4a4cd49c06
4 changed files with 119 additions and 8 deletions

View File

@ -1,3 +1,9 @@
2006-12-21 Jakub Jelinek <jakub@redhat.com>
PR target/30230
* config/ia64/ia64.c (ia64_add_bundle_selector_before): New function.
(bundling): Use it.
2006-12-21 Nathan Sidwell <nathan@codesourcery.com>
PR target/28966

View File

@ -7646,6 +7646,53 @@ get_next_important_insn (rtx insn, rtx tail)
return NULL_RTX;
}
/* Add a bundle selector TEMPLATE0 before INSN. */
static void
ia64_add_bundle_selector_before (int template0, rtx insn)
{
rtx b = gen_bundle_selector (GEN_INT (template0));
ia64_emit_insn_before (b, insn);
#if NR_BUNDLES == 10
if ((template0 == 4 || template0 == 5)
&& (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
{
int i;
rtx note = NULL_RTX;
/* In .mbb and .bbb bundles, check if CALL_INSN isn't in the
first or second slot. If it is and has REG_EH_NOTE set, copy it
to following nops, as br.call sets rp to the address of following
bundle and therefore an EH region end must be on a bundle
boundary. */
insn = PREV_INSN (insn);
for (i = 0; i < 3; i++)
{
do
insn = next_active_insn (insn);
while (GET_CODE (insn) == INSN
&& get_attr_empty (insn) == EMPTY_YES);
if (GET_CODE (insn) == CALL_INSN)
note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
else if (note)
{
int code;
gcc_assert ((code = recog_memoized (insn)) == CODE_FOR_nop
|| code == CODE_FOR_nop_b);
if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
note = NULL_RTX;
else
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0),
REG_NOTES (insn));
}
}
}
#endif
}
/* The following function does insn bundling. Bundling means
inserting templates and nop insns to fit insn groups into permitted
templates. Instruction scheduling uses NDFA (non-deterministic
@ -7927,8 +7974,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
/* We are at the start of a bundle: emit the template
(it should be defined). */
gcc_assert (template0 >= 0);
b = gen_bundle_selector (GEN_INT (template0));
ia64_emit_insn_before (b, nop);
ia64_add_bundle_selector_before (template0, nop);
/* If we have two bundle window, we make one bundle
rotation. Otherwise template0 will be undefined
(negative value). */
@ -7954,8 +8000,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
/* The current insn is at the bundle start: emit the
template. */
gcc_assert (template0 >= 0);
b = gen_bundle_selector (GEN_INT (template0));
ia64_emit_insn_before (b, insn);
ia64_add_bundle_selector_before (template0, insn);
b = PREV_INSN (insn);
insn = b;
/* See comment above in analogous place for emitting nops
@ -7977,8 +8022,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
/* See comment above in analogous place for emitting nops
after the insn. */
gcc_assert (template0 >= 0);
b = gen_bundle_selector (GEN_INT (template0));
ia64_emit_insn_before (b, insn);
ia64_add_bundle_selector_before (template0, insn);
b = PREV_INSN (insn);
insn = b;
template0 = template1;
@ -8072,8 +8116,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
}
/* Put the MM-insn in the same slot of a bundle with the
same template as the original one. */
ia64_emit_insn_before (gen_bundle_selector (GEN_INT (template0)),
insn);
ia64_add_bundle_selector_before (template0, insn);
/* To put the insn in the same slot, add necessary number
of nops. */
for (j = n; j > 0; j --)

View File

@ -1,3 +1,8 @@
2006-12-21 Jakub Jelinek <jakub@redhat.com>
PR target/30230
* g++.dg/eh/ia64-2.C: New test.
2006-12-21 Nathan Sidwell <nathan@codesourcery.com>
PR target/28966

View File

@ -0,0 +1,57 @@
// PR target/30230
// This testcase failed on IA-64, where end of an EH region ended
// in the middle of a bundle (with br.call insn in first or second
// slot of .bbb/.mbb bundles and EH region end right after it).
// But br.call returns to the start of the next bundlem so during
// unwinding the call was considered to be outside of the EH region
// while it should have been inside.
// { dg-options "-O2" }
// { dg-do run }
struct A {};
struct B { virtual ~B(); };
B::~B () {}
struct C { void foo (short &, B &); };
struct D { void *d1; C *d2; virtual void virt (void) {} };
struct E { D *e1; B *e2; };
struct F { void bar (void *, B &); };
F *p __attribute__((weak));
volatile int r;
void C::foo (short &x, B &)
{
if (r)
throw A ();
x = 1;
}
void F::bar (void *, B &)
{
throw A ();
}
void baz (E &x)
{
short g = 0;
B b = *x.e2;
x.e1->d2->foo (g, b);
if (g)
p->bar(x.e1->d1, b);
}
int main ()
{
F g;
D s;
E h;
p = &g;
h.e1 = &s;
try
{
baz (h);
}
catch (A &)
{
}
return 0;
}