Hi! As mentioned in the PR, shrink-wrapping disqualifies for prologue placement basic blocks that have EDGE_CROSSING incoming edge. I don't see why that is necessary, those edges seem to be redirected just fine, both on x86_64 and powerpc64. In the former case, they are usually conditional jumps that patch_jump_insn can handle just fine, after all, they were previously crossing and will be crossing after the redirection too, just to a different label. And in the powerpc64 case, it is a simple_jump instead that again seems to be handled by patch_jump_insn just fine. Sure, redirecting an edge that was previously not crossing to be crossing or vice versa can fail, but that is not what shrink-wrapping needs. Also tested in GCC 8 with this patch and don't see ICEs there either (though, of course, I'm not suggesting we should backport this to release branches).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-12-16 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/98289 * shrink-wrap.c (can_get_prologue): Don't punt on EDGE_CROSSING incoming edges. * gcc.target/i386/pr98289.c: New test. * gcc.dg/torture/pr98289.c: New test. --- gcc/shrink-wrap.c.jj 2020-07-28 15:39:09.983756571 +0200 +++ gcc/shrink-wrap.c 2020-12-15 19:15:00.213861334 +0100 @@ -494,7 +494,7 @@ can_get_prologue (basic_block pro, HARD_ edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, pro->preds) - if (e->flags & (EDGE_COMPLEX | EDGE_CROSSING) + if (e->flags & EDGE_COMPLEX && !dominated_by_p (CDI_DOMINATORS, e->src, pro)) return false; --- gcc/testsuite/gcc.target/i386/pr98289.c.jj 2020-12-16 13:15:08.579847596 +0100 +++ gcc/testsuite/gcc.target/i386/pr98289.c 2020-12-16 14:26:16.863157527 +0100 @@ -0,0 +1,54 @@ +/* PR rtl-optimization/98289 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-require-effective-target freorder } */ +/* { dg-options "-O2 -freorder-blocks-and-partition -fdump-rtl-pro_and_epilogue-details" } */ +/* { dg-final { scan-rtl-dump-times "Performing shrink-wrapping" 4 "pro_and_epilogue" } } */ + +int bar (void) __attribute__((cold)); + +void +foo (int x) +{ + if (x) + __builtin_abort (); +} + +void +baz (int x) +{ + if (__builtin_expect (x, 0)) + { + bar (); + bar (); + bar (); + } +} + +void +qux (int x, int y, int z, int w) +{ + if (x || y || z || w) + __builtin_abort (); +} + +int +corge (int x, int y, int z, int w, int u) +{ + if (__builtin_expect (x, 0)) + goto lab; + u++; + if (__builtin_expect (y, 0)) + goto lab; + u *= 2; + if (__builtin_expect (z, 0)) + goto lab; + u |= 42; + if (__builtin_expect (w, 0)) + { + lab:; + bar (); + bar (); + if (bar () > 32) goto lab; + } + return u; +} --- gcc/testsuite/gcc.dg/torture/pr98289.c.jj 2020-12-16 14:27:01.391659297 +0100 +++ gcc/testsuite/gcc.dg/torture/pr98289.c 2020-12-16 14:27:29.442345443 +0100 @@ -0,0 +1,52 @@ +/* PR rtl-optimization/98289 */ +/* { dg-do compile { target freorder } } */ +/* { dg-options "-O2 -freorder-blocks-and-partition" } */ + +int bar (void) __attribute__((cold)); + +void +foo (int x) +{ + if (x) + __builtin_abort (); +} + +void +baz (int x) +{ + if (__builtin_expect (x, 0)) + { + bar (); + bar (); + bar (); + } +} + +void +qux (int x, int y, int z, int w) +{ + if (x || y || z || w) + __builtin_abort (); +} + +int +corge (int x, int y, int z, int w, int u) +{ + if (__builtin_expect (x, 0)) + goto lab; + u++; + if (__builtin_expect (y, 0)) + goto lab; + u *= 2; + if (__builtin_expect (z, 0)) + goto lab; + u |= 42; + if (__builtin_expect (w, 0)) + { + lab:; + bar (); + bar (); + if (bar () > 32) goto lab; + } + return u; +} Jakub