re PR middle-end/40021 (Revision 146817 miscompiled DAXPY in BLAS)
PR middle-end/40021 * cfgexpand.c (maybe_cleanup_end_of_block): New static function. (expand_gimple_cond): Use it to cleanup CFG and superfluous jumps. * gfortran.dg/pr40021.f: New test. From-SVN: r147186
This commit is contained in:
parent
8ba50c2c9e
commit
529ff44101
@ -1,3 +1,9 @@
|
|||||||
|
2009-05-06 Michael Matz <matz@suse.de>
|
||||||
|
|
||||||
|
PR middle-end/40021
|
||||||
|
* cfgexpand.c (maybe_cleanup_end_of_block): New static function.
|
||||||
|
(expand_gimple_cond): Use it to cleanup CFG and superfluous jumps.
|
||||||
|
|
||||||
2009-05-06 Rafael Avila de Espindola <espindola@google.com>
|
2009-05-06 Rafael Avila de Espindola <espindola@google.com>
|
||||||
|
|
||||||
* Makefile.in (install-plugin): Fix srcdir handling.
|
* Makefile.in (install-plugin): Fix srcdir handling.
|
||||||
|
@ -1724,6 +1724,52 @@ label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* A subroutine of expand_gimple_cond. Given E, a fallthrough edge
|
||||||
|
of a basic block where we just expanded the conditional at the end,
|
||||||
|
possibly clean up the CFG and instruction sequence. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_cleanup_end_of_block (edge e)
|
||||||
|
{
|
||||||
|
/* Special case: when jumpif decides that the condition is
|
||||||
|
trivial it emits an unconditional jump (and the necessary
|
||||||
|
barrier). But we still have two edges, the fallthru one is
|
||||||
|
wrong. purge_dead_edges would clean this up later. Unfortunately
|
||||||
|
we have to insert insns (and split edges) before
|
||||||
|
find_many_sub_basic_blocks and hence before purge_dead_edges.
|
||||||
|
But splitting edges might create new blocks which depend on the
|
||||||
|
fact that if there are two edges there's no barrier. So the
|
||||||
|
barrier would get lost and verify_flow_info would ICE. Instead
|
||||||
|
of auditing all edge splitters to care for the barrier (which
|
||||||
|
normally isn't there in a cleaned CFG), fix it here. */
|
||||||
|
if (BARRIER_P (get_last_insn ()))
|
||||||
|
{
|
||||||
|
basic_block bb = e->src;
|
||||||
|
rtx insn;
|
||||||
|
remove_edge (e);
|
||||||
|
/* Now, we have a single successor block, if we have insns to
|
||||||
|
insert on the remaining edge we potentially will insert
|
||||||
|
it at the end of this block (if the dest block isn't feasible)
|
||||||
|
in order to avoid splitting the edge. This insertion will take
|
||||||
|
place in front of the last jump. But we might have emitted
|
||||||
|
multiple jumps (conditional and one unconditional) to the
|
||||||
|
same destination. Inserting in front of the last one then
|
||||||
|
is a problem. See PR 40021. We fix this by deleting all
|
||||||
|
jumps except the last unconditional one. */
|
||||||
|
insn = PREV_INSN (get_last_insn ());
|
||||||
|
/* Make sure we have an unconditional jump. Otherwise we're
|
||||||
|
confused. */
|
||||||
|
gcc_assert (JUMP_P (insn) && !any_condjump_p (insn));
|
||||||
|
for (insn = PREV_INSN (insn); insn != BB_HEAD (bb);)
|
||||||
|
{
|
||||||
|
insn = PREV_INSN (insn);
|
||||||
|
if (JUMP_P (NEXT_INSN (insn)))
|
||||||
|
delete_insn (NEXT_INSN (insn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* A subroutine of expand_gimple_basic_block. Expand one GIMPLE_COND.
|
/* A subroutine of expand_gimple_basic_block. Expand one GIMPLE_COND.
|
||||||
Returns a new basic block if we've terminated the current basic
|
Returns a new basic block if we've terminated the current basic
|
||||||
block and created a new one. */
|
block and created a new one. */
|
||||||
@ -1767,19 +1813,7 @@ expand_gimple_cond (basic_block bb, gimple stmt)
|
|||||||
true_edge->goto_block = NULL;
|
true_edge->goto_block = NULL;
|
||||||
false_edge->flags |= EDGE_FALLTHRU;
|
false_edge->flags |= EDGE_FALLTHRU;
|
||||||
ggc_free (pred);
|
ggc_free (pred);
|
||||||
/* Special case: when jumpif decides that the condition is
|
maybe_cleanup_end_of_block (false_edge);
|
||||||
trivial it emits an unconditional jump (and the necessary
|
|
||||||
barrier). But we still have two edges, the fallthru one is
|
|
||||||
wrong. purge_dead_edges would clean this up later. Unfortunately
|
|
||||||
we have to insert insns (and split edges) before
|
|
||||||
find_many_sub_basic_blocks and hence before purge_dead_edges.
|
|
||||||
But splitting edges might create new blocks which depend on the
|
|
||||||
fact that if there are two edges there's no barrier. So the
|
|
||||||
barrier would get lost and verify_flow_info would ICE. Instead
|
|
||||||
of auditing all edge splitters to care for the barrier (which
|
|
||||||
normally isn't there in a cleaned CFG), fix it here. */
|
|
||||||
if (BARRIER_P (get_last_insn ()))
|
|
||||||
remove_edge (false_edge);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (true_edge->dest == bb->next_bb)
|
if (true_edge->dest == bb->next_bb)
|
||||||
@ -1796,8 +1830,7 @@ expand_gimple_cond (basic_block bb, gimple stmt)
|
|||||||
false_edge->goto_block = NULL;
|
false_edge->goto_block = NULL;
|
||||||
true_edge->flags |= EDGE_FALLTHRU;
|
true_edge->flags |= EDGE_FALLTHRU;
|
||||||
ggc_free (pred);
|
ggc_free (pred);
|
||||||
if (BARRIER_P (get_last_insn ()))
|
maybe_cleanup_end_of_block (true_edge);
|
||||||
remove_edge (true_edge);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2009-05-06 Michael Matz <matz@suse.de>
|
||||||
|
|
||||||
|
* gfortran.dg/pr40021.f: New test.
|
||||||
|
|
||||||
2009-05-06 Le-Chun Wu <lcwu@google.com>
|
2009-05-06 Le-Chun Wu <lcwu@google.com>
|
||||||
|
|
||||||
* lib/plugin-support.exp: New file containing support procs for
|
* lib/plugin-support.exp: New file containing support procs for
|
||||||
|
42
gcc/testsuite/gfortran.dg/pr40021.f
Normal file
42
gcc/testsuite/gfortran.dg/pr40021.f
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
! { dg-do run { target i?86-*-* x86_64-*-* } }
|
||||||
|
! { dg-require-effective-target ilp32 }
|
||||||
|
! { dg-options "-O2 -ftree-vectorize -msse2 -mfpmath=sse -ffast-math" }
|
||||||
|
PROGRAM test
|
||||||
|
DOUBLE PRECISION DA
|
||||||
|
INTEGER I, N
|
||||||
|
DOUBLE PRECISION DX(9),DY(9)
|
||||||
|
|
||||||
|
EXTERNAL DAXPY
|
||||||
|
N=5
|
||||||
|
DA=1.0
|
||||||
|
DATA DX/-2, -1, -3, -4, 1, 2, 10, 15, 14/
|
||||||
|
DATA DY/0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0/
|
||||||
|
CALL DAXPY (N,DA,DX,DY)
|
||||||
|
DO 10 I = 1, N
|
||||||
|
if (DX(I).ne.DY(I)) call abort
|
||||||
|
10 CONTINUE
|
||||||
|
STOP
|
||||||
|
END
|
||||||
|
|
||||||
|
SUBROUTINE DAXPY(N,DA,DX,DY)
|
||||||
|
DOUBLE PRECISION DA
|
||||||
|
INTEGER N
|
||||||
|
DOUBLE PRECISION DX(*),DY(*)
|
||||||
|
INTEGER I,IX,IY,M,MP1
|
||||||
|
INTRINSIC MOD
|
||||||
|
IF (N.LE.0) RETURN
|
||||||
|
20 M = MOD(N,4)
|
||||||
|
IF (M.EQ.0) GO TO 40
|
||||||
|
DO 30 I = 1,M
|
||||||
|
DY(I) = DY(I) + DA*DX(I)
|
||||||
|
30 CONTINUE
|
||||||
|
IF (N.LT.4) RETURN
|
||||||
|
40 MP1 = M + 1
|
||||||
|
DO 50 I = MP1,N,4
|
||||||
|
DY(I) = DY(I) + DA*DX(I)
|
||||||
|
DY(I+1) = DY(I+1) + DA*DX(I+1)
|
||||||
|
DY(I+2) = DY(I+2) + DA*DX(I+2)
|
||||||
|
DY(I+3) = DY(I+3) + DA*DX(I+3)
|
||||||
|
50 CONTINUE
|
||||||
|
RETURN
|
||||||
|
END
|
Loading…
Reference in New Issue
Block a user