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;
 

Reply via email to