[Bug middle-end/80422] [7 Regression] ICE on valid code at -O3 in 32-bit mode on x86_64-linux-gnu: in operator[], at vec.h:732
law at redhat dot com
gcc-bugzilla@gcc.gnu.org
Fri Apr 14 15:58:00 GMT 2017
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80422
--- Comment #2 from Jeffrey A. Law <law at redhat dot com> ---
This is a latent bug in cross jumping AFAICT.
Essentially a forwarder block becomes unreachable during cfg_cleanup. Later
we're cross jumping an indirect (via more forwarders) successor of the now
unreachable forwarder and walk up the CFG looking for hunks of equivalent
insns.
flow_find_cross_jump walks the insn chain backwards from two given points to
find identical insns for crossjumping. That walk can cross basic block
boundaries (by design, see walk_to_nondebug_insn).
As a result flow_find_cross_jump can return in F1 and F2 insns that are not in
blocks BB1 and BB2.
So given this code in try_crossjump_to_edge:
/* Likewise with dead code (possibly newly created by the other optimizations
of cfg_cleanup). */
if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0)
return false;
[ ... ]
/* ... and part the second. */
nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir);
osrc1 = src1;
osrc2 = src2;
if (newpos1 != NULL_RTX)
src1 = BLOCK_FOR_INSN (newpos1);
if (newpos2 != NULL_RTX)
src2 = BLOCK_FOR_INSN (newpos2);
The EDGE_COUNT checks verify that the original starting points for cross
jumping are reachable. But as we walk up the CFG we may run into cases where
flow_find_cross_jump walks us into one or more new blocks and we never check to
see if those new blocks are reachable or not.
A short time later we do this:
/* Avoid splitting if possible. We must always split when SRC2 has
EH predecessor edges, or we may end up with basic blocks with both
normal and EH predecessor edges. */
if (newpos2 == BB_HEAD (src2)
&& !(EDGE_PRED (src2, 0)->flags & EDGE_EH))
redirect_to = src2;
If SRC2 is unreachable, then EDGE_PRED will read outside the vec's boundary
triggering the fault.
I'm pretty sure the fix is to verify the both blocks are reachable after
flow_find_cross_jump as well.
More information about the Gcc-bugs
mailing list