mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-21 14:30:59 +08:00
re PR target/12900 (g++ ICE in rtl_verify_flow_info_1)
PR target/12900 * reg-stack (move_for_stack_reg): New prototype. Return whether a control flow insn was deleted. (subst_stack_regs_pat): Likewise, using the information provided by move_for_stack_reg. (subst_stack_regs): Likewise, using the information provided by subst_stack_regs_pat. (convert_regs_1): Record whether a control flow insn was deleted, using the information provided by subst_stack_regs. Purge dead edges only if a control flow insn was deleted. From-SVN: r73977
This commit is contained in:
parent
316d0b1981
commit
ecb63641ff
@ -1,3 +1,16 @@
|
||||
2003-11-27 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
PR target/12900
|
||||
* reg-stack (move_for_stack_reg): New prototype. Return
|
||||
whether a control flow insn was deleted.
|
||||
(subst_stack_regs_pat): Likewise, using the information provided
|
||||
by move_for_stack_reg.
|
||||
(subst_stack_regs): Likewise, using the information provided
|
||||
by subst_stack_regs_pat.
|
||||
(convert_regs_1): Record whether a control flow insn was deleted,
|
||||
using the information provided by subst_stack_regs. Purge dead
|
||||
edges only if a control flow insn was deleted.
|
||||
|
||||
2003-11-27 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
PR middle-end/8028
|
||||
|
@ -249,13 +249,13 @@ static void remove_regno_note (rtx, enum reg_note, unsigned int);
|
||||
static int get_hard_regnum (stack, rtx);
|
||||
static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where);
|
||||
static void emit_swap_insn (rtx, stack, rtx);
|
||||
static void move_for_stack_reg (rtx, stack, rtx);
|
||||
static bool move_for_stack_reg (rtx, stack, rtx);
|
||||
static int swap_rtx_condition_1 (rtx);
|
||||
static int swap_rtx_condition (rtx);
|
||||
static void compare_for_stack_reg (rtx, stack, rtx);
|
||||
static void subst_stack_regs_pat (rtx, stack, rtx);
|
||||
static bool subst_stack_regs_pat (rtx, stack, rtx);
|
||||
static void subst_asm_stack_regs (rtx, stack);
|
||||
static void subst_stack_regs (rtx, stack);
|
||||
static bool subst_stack_regs (rtx, stack);
|
||||
static void change_stack (rtx, stack, stack, enum emit_where);
|
||||
static int convert_regs_entry (void);
|
||||
static void convert_regs_exit (void);
|
||||
@ -1028,15 +1028,17 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg)
|
||||
}
|
||||
|
||||
/* Handle a move to or from a stack register in PAT, which is in INSN.
|
||||
REGSTACK is the current stack. */
|
||||
REGSTACK is the current stack. Return whether a control flow insn
|
||||
was deleted in the process. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
move_for_stack_reg (rtx insn, stack regstack, rtx pat)
|
||||
{
|
||||
rtx *psrc = get_true_reg (&SET_SRC (pat));
|
||||
rtx *pdest = get_true_reg (&SET_DEST (pat));
|
||||
rtx src, dest;
|
||||
rtx note;
|
||||
bool control_flow_insn_deleted = false;
|
||||
|
||||
src = *psrc; dest = *pdest;
|
||||
|
||||
@ -1066,21 +1068,17 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
|
||||
If so, just pop the src. */
|
||||
|
||||
if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
|
||||
emit_pop_insn (insn, regstack, src, EMIT_AFTER);
|
||||
else
|
||||
{
|
||||
emit_pop_insn (insn, regstack, src, EMIT_AFTER);
|
||||
|
||||
delete_insn (insn);
|
||||
return;
|
||||
regstack->reg[i] = REGNO (dest);
|
||||
SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
|
||||
CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
|
||||
}
|
||||
|
||||
regstack->reg[i] = REGNO (dest);
|
||||
|
||||
SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
|
||||
CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
|
||||
|
||||
control_flow_insn_deleted |= control_flow_insn_p (insn);
|
||||
delete_insn (insn);
|
||||
|
||||
return;
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
|
||||
/* The source reg does not die. */
|
||||
@ -1095,8 +1093,9 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
|
||||
if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
|
||||
emit_pop_insn (insn, regstack, dest, EMIT_AFTER);
|
||||
|
||||
control_flow_insn_deleted |= control_flow_insn_p (insn);
|
||||
delete_insn (insn);
|
||||
return;
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
|
||||
/* The destination ought to be dead. */
|
||||
@ -1165,6 +1164,8 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
|
||||
/* Swap the condition on a branch, if there is one. Return true if we
|
||||
@ -1376,12 +1377,14 @@ compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src)
|
||||
}
|
||||
|
||||
/* Substitute new registers in PAT, which is part of INSN. REGSTACK
|
||||
is the current register layout. */
|
||||
is the current register layout. Return whether a control flow insn
|
||||
was deleted in the process. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
|
||||
{
|
||||
rtx *dest, *src;
|
||||
bool control_flow_insn_deleted = false;
|
||||
|
||||
switch (GET_CODE (pat))
|
||||
{
|
||||
@ -1393,7 +1396,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
|
||||
&& find_regno_note (insn, REG_DEAD, REGNO (*src)))
|
||||
{
|
||||
emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
|
||||
return;
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
/* ??? Uninitialized USE should not happen. */
|
||||
else if (get_hard_regnum (regstack, *src) == -1)
|
||||
@ -1443,7 +1446,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
|
||||
FP_MODE_REG (REGNO (*dest), SFmode),
|
||||
nan);
|
||||
PATTERN (insn) = pat;
|
||||
move_for_stack_reg (insn, regstack, pat);
|
||||
control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
|
||||
}
|
||||
if (! note && COMPLEX_MODE_P (GET_MODE (*dest))
|
||||
&& get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1)
|
||||
@ -1452,7 +1455,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
|
||||
FP_MODE_REG (REGNO (*dest) + 1, SFmode),
|
||||
nan);
|
||||
PATTERN (insn) = pat;
|
||||
move_for_stack_reg (insn, regstack, pat);
|
||||
control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1475,7 +1478,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
|
||||
&& (GET_CODE (*src) == REG || GET_CODE (*src) == MEM
|
||||
|| GET_CODE (*src) == CONST_DOUBLE)))
|
||||
{
|
||||
move_for_stack_reg (insn, regstack, pat);
|
||||
control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1879,6 +1882,8 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
|
||||
/* Substitute hard regnums for any stack regs in INSN, which has
|
||||
@ -2176,12 +2181,14 @@ subst_asm_stack_regs (rtx insn, stack regstack)
|
||||
/* Substitute stack hard reg numbers for stack virtual registers in
|
||||
INSN. Non-stack register numbers are not changed. REGSTACK is the
|
||||
current stack content. Insns may be emitted as needed to arrange the
|
||||
stack for the 387 based on the contents of the insn. */
|
||||
stack for the 387 based on the contents of the insn. Return whether
|
||||
a control flow insn was deleted in the process. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
subst_stack_regs (rtx insn, stack regstack)
|
||||
{
|
||||
rtx *note_link, note;
|
||||
bool control_flow_insn_deleted = false;
|
||||
int i;
|
||||
|
||||
if (GET_CODE (insn) == CALL_INSN)
|
||||
@ -2222,25 +2229,27 @@ subst_stack_regs (rtx insn, stack regstack)
|
||||
Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */
|
||||
|
||||
subst_asm_stack_regs (insn, regstack);
|
||||
return;
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == PARALLEL)
|
||||
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
|
||||
{
|
||||
if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
|
||||
subst_stack_regs_pat (insn, regstack,
|
||||
XVECEXP (PATTERN (insn), 0, i));
|
||||
control_flow_insn_deleted
|
||||
|= subst_stack_regs_pat (insn, regstack,
|
||||
XVECEXP (PATTERN (insn), 0, i));
|
||||
}
|
||||
else
|
||||
subst_stack_regs_pat (insn, regstack, PATTERN (insn));
|
||||
control_flow_insn_deleted
|
||||
|= subst_stack_regs_pat (insn, regstack, PATTERN (insn));
|
||||
}
|
||||
|
||||
/* subst_stack_regs_pat may have deleted a no-op insn. If so, any
|
||||
REG_UNUSED will already have been dealt with, so just return. */
|
||||
|
||||
if (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn))
|
||||
return;
|
||||
return control_flow_insn_deleted;
|
||||
|
||||
/* If there is a REG_UNUSED note on a stack register on this insn,
|
||||
the indicated reg must be popped. The REG_UNUSED note is removed,
|
||||
@ -2256,6 +2265,8 @@ subst_stack_regs (rtx insn, stack regstack)
|
||||
}
|
||||
else
|
||||
note_link = &XEXP (note, 1);
|
||||
|
||||
return control_flow_insn_deleted;
|
||||
}
|
||||
|
||||
/* Change the organization of the stack so that it fits a new basic
|
||||
@ -2638,6 +2649,7 @@ convert_regs_1 (FILE *file, basic_block block)
|
||||
int deleted, inserted, reg;
|
||||
rtx insn, next;
|
||||
edge e, beste = NULL;
|
||||
bool control_flow_insn_deleted = false;
|
||||
|
||||
inserted = 0;
|
||||
deleted = 0;
|
||||
@ -2726,8 +2738,7 @@ convert_regs_1 (FILE *file, basic_block block)
|
||||
INSN_UID (insn));
|
||||
print_stack (file, ®stack);
|
||||
}
|
||||
subst_stack_regs (insn, ®stack);
|
||||
deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
|
||||
control_flow_insn_deleted |= subst_stack_regs (insn, ®stack);
|
||||
}
|
||||
}
|
||||
while (next);
|
||||
@ -2766,8 +2777,7 @@ convert_regs_1 (FILE *file, basic_block block)
|
||||
set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode),
|
||||
nan);
|
||||
insn = emit_insn_after (set, insn);
|
||||
subst_stack_regs (insn, ®stack);
|
||||
deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
|
||||
control_flow_insn_deleted |= subst_stack_regs (insn, ®stack);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2777,12 +2787,18 @@ convert_regs_1 (FILE *file, basic_block block)
|
||||
called at the end of convert_regs. The order in which we process the
|
||||
blocks ensures that we never delete an already processed edge.
|
||||
|
||||
Note that, at this point, the CFG may have been damaged by the emission
|
||||
of instructions after an abnormal call, which moves the basic block end
|
||||
(and is the reason why we call fixup_abnormal_edges later). So we must
|
||||
be sure that the trapping insn has been deleted before trying to purge
|
||||
dead edges, otherwise we risk purging valid edges.
|
||||
|
||||
??? We are normally supposed not to delete trapping insns, so we pretend
|
||||
that the insns deleted above don't actually trap. It would have been
|
||||
better to detect this earlier and avoid creating the EH edge in the first
|
||||
place, still, but we don't have enough information at that time. */
|
||||
|
||||
if (deleted)
|
||||
if (control_flow_insn_deleted)
|
||||
purge_dead_edges (block);
|
||||
|
||||
/* Something failed if the stack lives don't match. If we had malformed
|
||||
|
@ -1,3 +1,7 @@
|
||||
2003-11-27 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* g++.dg/opt/reg-stack4.C: New test.
|
||||
|
||||
2003-11-27 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* gcc.dg/builtin-apply2.c: New test.
|
||||
|
29
gcc/testsuite/g++.dg/opt/reg-stack4.C
Normal file
29
gcc/testsuite/g++.dg/opt/reg-stack4.C
Normal file
@ -0,0 +1,29 @@
|
||||
// PR target/12900
|
||||
// Origin: <snyder@fnal.gov>
|
||||
|
||||
// This used to fail on x86 because the reg-stack pass
|
||||
// deleted a valid edge.
|
||||
|
||||
// { dg-do compile }
|
||||
// { dg-options "-mtune=i586 -O2" { target i?86-*-* } }
|
||||
|
||||
struct array {
|
||||
double data;
|
||||
virtual ~array();
|
||||
};
|
||||
|
||||
double glob;
|
||||
double ext1(double);
|
||||
int nmuons;
|
||||
|
||||
void track_match()
|
||||
{
|
||||
array vecdca;
|
||||
if (glob < 10) return;
|
||||
double p = glob*5;
|
||||
double phi = vecdca.data;
|
||||
ext1 (vecdca.data-glob);
|
||||
ext1 (phi*2);
|
||||
if (1 < p)
|
||||
++nmuons;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user