[llvm] fee67ee - [X86] Don't assert on EFLAGS copies in unreachable blocks (#203208)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 05:30:17 PDT 2026


Author: Paweł Bylica
Date: 2026-06-11T14:30:12+02:00
New Revision: fee67eec6d7f9e40d366c548aa7c59f98ca3b163

URL: https://github.com/llvm/llvm-project/commit/fee67eec6d7f9e40d366c548aa7c59f98ca3b163
DIFF: https://github.com/llvm/llvm-project/commit/fee67eec6d7f9e40d366c548aa7c59f98ca3b163.diff

LOG: [X86] Don't assert on EFLAGS copies in unreachable blocks (#203208)

X86FlagsCopyLowering collects the EFLAGS copies to lower using a
ReversePostOrderTraversal, which only visits blocks reachable from the
entry. Its end-of-pass verification, however, iterated over every block
in the function, so an EFLAGS copy left in an unreachable block (e.g.
produced by ISel for an always-taken branch whose other edge is dead)
tripped the "Unlowered EFLAGS copy!" assertion.

Such copies are harmless: the unreachable block is removed by the
unreachable-block elimination pass that runs right after this one,
before register allocation, so the copy never reaches a pass that cannot
handle it. Restrict the verification to reachable blocks (depth_first
from the entry) to match the set of blocks actually processed.

Found via fuzzing (llvm-isel-fuzzer).

Added: 
    llvm/test/CodeGen/X86/flags-copy-lowering-unreachable.mir

Modified: 
    llvm/lib/Target/X86/X86FlagsCopyLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index 93c7571d5c37f..36b17cab03ee9 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -708,8 +708,9 @@ bool X86FlagsCopyLoweringImpl::runOnMachineFunction(MachineFunction &MF) {
   }
 
 #ifndef NDEBUG
-  for (MachineBasicBlock &MBB : MF)
-    for (MachineInstr &MI : MBB)
+  // Check reachable blocks for unlowered EFLAGS copies.
+  for (MachineBasicBlock *MBB : depth_first(&MF))
+    for (MachineInstr &MI : *MBB)
       if (MI.getOpcode() == TargetOpcode::COPY &&
           (MI.getOperand(0).getReg() == X86::EFLAGS ||
            MI.getOperand(1).getReg() == X86::EFLAGS)) {

diff  --git a/llvm/test/CodeGen/X86/flags-copy-lowering-unreachable.mir b/llvm/test/CodeGen/X86/flags-copy-lowering-unreachable.mir
new file mode 100644
index 0000000000000..1854e95d60856
--- /dev/null
+++ b/llvm/test/CodeGen/X86/flags-copy-lowering-unreachable.mir
@@ -0,0 +1,29 @@
+# RUN: llc -mtriple=x86_64-- -run-pass=x86-flags-copy-lowering -verify-machineinstrs -o - %s | FileCheck %s
+#
+# An EFLAGS copy stranded in a block that is unreachable from the entry must
+# not trip the "Unlowered EFLAGS copy!" assertion. The pass collects copies to
+# lower with a reverse-post-order traversal, which only visits reachable
+# blocks, so such copies are intentionally left in place (a later pass removes
+# the unreachable block). The verification at the end of the pass must use the
+# same notion of reachability.
+---
+name:            stranded_eflags_copy
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    RET 0
+
+  ; bb.1 has no predecessors, so it is unreachable from bb.0. The save/recheck
+  ; EFLAGS copies below are left untouched rather than crashing the pass.
+  bb.1:
+    ; CHECK-LABEL: bb.1:
+    ; CHECK: %1:gr64 = COPY $eflags
+    ; CHECK: $eflags = COPY %1
+    %0:gr64 = IMPLICIT_DEF
+    TEST64rr %0, %0, implicit-def $eflags
+    %1:gr64 = COPY $eflags
+    TEST64rr %0, %0, implicit-def $eflags
+    $eflags = COPY %1
+    SETCCm $noreg, 1, $noreg, 0, $noreg, 4, implicit $eflags :: (store (s8) into `ptr null`)
+    RET 0
+...


        


More information about the llvm-commits mailing list