Copying from BZ:
The bug here is in reorg and its legacy of trying to compensate for the lack of a CFG. In particular it has a function skip_consecutive_labels. The idea (of course) is to have jumps target the last label if there's several in a row. The code looks something like this: for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn)) if (LABEL_P (insn)) label = insn; The loop termination condition allows the code to look through notes and other random crud. Now imagine if we have (code_label 1) (barrier) (code_label 2) (more code) The BARRIER after a CODE_LABEL can occur due to __builtin_unreachable. If a jump targets code_label 1, it will be redirected to code_label 2. That's fine from a runtime standpoint, but runs afoul of the CFI bits. Why? Consider if the jump which targeted label 1 did not have a prologue (we're shrink wrapping) and "more code" section is a shrink wrapped epilogue. The original paths to code_label 2 will have one CFI state while the new paths to code_label 1 will have a different CFI state and we trip the check. Ultimately the fix here is quite simple. Don't allow looking through a BARRIER when skipping "consecutive" labels. While this has bootstrapped and regression tested on x86_64, that's not a particularly useful test. More importantly, it's bootstrapped mipsisa32r2-linux-gnu and also built and regression tested on mips64-linux-gnu/mips64el-linux-gnu and a variety of other targets, some of which have delay slots. sparc64 is testing, but I won't have results for many many hours. Installing on the trunk. The testcase is flaky enough that I didn't bother to include it. Jeff
commit 7570fd592fccd12c67a294c65a4904c7e1c0a797 Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Wed Apr 3 16:03:37 2019 +0000 PR rtl-optimization/81025 * reorg.c (skip_consecutive_labels): Do not skip past a BARRIER. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@270129 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9149d9c9a9e..0d7c206de90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-04-03 Jeff Law <l...@redhat.com> + + PR rtl-optimization/81025 + * reorg.c (skip_consecutive_labels): Do not skip past a BARRIER. + 2019-04-03 Richard Biener <rguent...@suse.de> PR tree-optimization/84101 diff --git a/gcc/reorg.c b/gcc/reorg.c index 84128a4fe9e..81349382b81 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -137,7 +137,20 @@ skip_consecutive_labels (rtx label_or_return) rtx_insn *label = as_a <rtx_insn *> (label_or_return); - for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn)) + /* __builtin_unreachable can create a CODE_LABEL followed by a BARRIER. + + Since reaching the CODE_LABEL is undefined behavior, we can return + any code label and we're OK at runtime. + + However, if we return a CODE_LABEL which leads to a shrinked wrapped + epilogue, but the path does not have a prologue, then we will trip + a sanity check in the dwarf2 cfi code which wants to verify that + the CFIs are all the same on the traces leading to the epilogue. + + So we explicitly disallow looking through BARRIERS here. */ + for (insn = label; + insn != 0 && !INSN_P (insn) && !BARRIER_P (insn); + insn = NEXT_INSN (insn)) if (LABEL_P (insn)) label = insn;