[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