re PR fortran/9974 (Test g77.f-torture/noncompile/check0.f fails)
PR fortran/9974 * gcse.c (reg_killed_on_egde): New function to test whether the given reg is overwritten by any instruction queued on an edge. (bypass_block): Ignore substitutions killed on incoming edges. Don't bypass outgoing edges that have queued instructions. * gcc.c-torture/execute/20030401-1.c: New test case. From-SVN: r65148
This commit is contained in:
parent
70ab763c5b
commit
e129b3f951
|
@ -1,3 +1,11 @@
|
|||
2003-04-01 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR fortran/9974
|
||||
* gcse.c (reg_killed_on_egde): New function to test whether the
|
||||
given reg is overwritten by any instruction queued on an edge.
|
||||
(bypass_block): Ignore substitutions killed on incoming edges.
|
||||
Don't bypass outgoing edges that have queued instructions.
|
||||
|
||||
2003-04-01 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* real.h (EXP_BITS): Make room for...
|
||||
|
|
54
gcc/gcse.c
54
gcc/gcse.c
|
@ -624,6 +624,7 @@ static void find_implicit_sets PARAMS ((void));
|
|||
static int one_cprop_pass PARAMS ((int, int, int));
|
||||
static bool constprop_register PARAMS ((rtx, rtx, rtx, int));
|
||||
static struct expr *find_bypass_set PARAMS ((int, int));
|
||||
static bool reg_killed_on_edge PARAMS ((rtx, edge));
|
||||
static int bypass_block PARAMS ((basic_block, rtx, rtx));
|
||||
static int bypass_conditional_jumps PARAMS ((void));
|
||||
static void alloc_pre_mem PARAMS ((int, int));
|
||||
|
@ -4768,11 +4769,35 @@ find_bypass_set (regno, bb)
|
|||
}
|
||||
|
||||
|
||||
/* Subroutine of bypass_block that checks whether a pseudo is killed by
|
||||
any of the instructions inserted on an edge. Jump bypassing places
|
||||
condition code setters on CFG edges using insert_insn_on_edge. This
|
||||
function is required to check that our data flow analysis is still
|
||||
valid prior to commit_edge_insertions. */
|
||||
|
||||
static bool
|
||||
reg_killed_on_edge (reg, e)
|
||||
rtx reg;
|
||||
edge e;
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
for (insn = e->insns; insn; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn) && reg_set_p (reg, insn))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Subroutine of bypass_conditional_jumps that attempts to bypass the given
|
||||
basic block BB which has more than one predecessor. If not NULL, SETCC
|
||||
is the first instruction of BB, which is immediately followed by JUMP_INSN
|
||||
JUMP. Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
|
||||
Returns nonzero if a change was made. */
|
||||
Returns nonzero if a change was made.
|
||||
|
||||
During the jump bypassing pass, we may place copies of SETCC instuctions
|
||||
on CFG edges. The following routine must be careful to pay attention to
|
||||
these inserted insns when performing its transformations. */
|
||||
|
||||
static int
|
||||
bypass_block (bb, setcc, jump)
|
||||
|
@ -4780,7 +4805,7 @@ bypass_block (bb, setcc, jump)
|
|||
rtx setcc, jump;
|
||||
{
|
||||
rtx insn, note;
|
||||
edge e, enext;
|
||||
edge e, enext, edest;
|
||||
int i, change;
|
||||
int may_be_loop_header;
|
||||
|
||||
|
@ -4835,6 +4860,10 @@ bypass_block (bb, setcc, jump)
|
|||
if (! set)
|
||||
continue;
|
||||
|
||||
/* Check the data flow is valid after edge insertions. */
|
||||
if (e->insns && reg_killed_on_edge (reg_used->reg_rtx, e))
|
||||
continue;
|
||||
|
||||
src = SET_SRC (pc_set (jump));
|
||||
|
||||
if (setcc != NULL)
|
||||
|
@ -4845,10 +4874,27 @@ bypass_block (bb, setcc, jump)
|
|||
new = simplify_replace_rtx (src, reg_used->reg_rtx,
|
||||
SET_SRC (set->expr));
|
||||
|
||||
/* Jump bypassing may have already placed instructions on
|
||||
edges of the CFG. We can't bypass an outgoing edge that
|
||||
has instructions associated with it, as these insns won't
|
||||
get executed if the incoming edge is redirected. */
|
||||
|
||||
if (new == pc_rtx)
|
||||
dest = FALLTHRU_EDGE (bb)->dest;
|
||||
{
|
||||
edest = FALLTHRU_EDGE (bb);
|
||||
dest = edest->insns ? NULL : edest->dest;
|
||||
}
|
||||
else if (GET_CODE (new) == LABEL_REF)
|
||||
dest = BLOCK_FOR_INSN (XEXP (new, 0));
|
||||
{
|
||||
dest = BLOCK_FOR_INSN (XEXP (new, 0));
|
||||
/* Don't bypass edges containing instructions. */
|
||||
for (edest = bb->succ; edest; edest = edest->succ_next)
|
||||
if (edest->dest == dest && edest->insns)
|
||||
{
|
||||
dest = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
dest = NULL;
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2003-04-01 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.c-torture/execute/20030401-1.c: New test case.
|
||||
|
||||
2003-04-01 Ziemowit Laski <zlaski@apple.com>
|
||||
|
||||
* objc.dg/defs.m: New.
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* Testcase for PR fortran/9974. This was a miscompilation of the g77
|
||||
front-end caused by the jump bypassing optimizations not handling
|
||||
instructions inserted on CFG edges. */
|
||||
|
||||
extern void abort ();
|
||||
|
||||
int bar ()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void foo (int x)
|
||||
{
|
||||
unsigned char error = 0;
|
||||
|
||||
if (! (error = ((x == 0) || bar ())))
|
||||
bar ();
|
||||
if (! error)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
foo (1);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue