[llvm] fb6153a - [CodeGen] Fix ShrinkWrap crash when FindIDom receives empty predecessor/successor list (#198995)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 03:08:14 PDT 2026
Author: 陈子昂
Date: 2026-06-03T18:08:09+08:00
New Revision: fb6153a65039b06319cb4b9ce2fafa84d75daa6b
URL: https://github.com/llvm/llvm-project/commit/fb6153a65039b06319cb4b9ce2fafa84d75daa6b
DIFF: https://github.com/llvm/llvm-project/commit/fb6153a65039b06319cb4b9ce2fafa84d75daa6b.diff
LOG: [CodeGen] Fix ShrinkWrap crash when FindIDom receives empty predecessor/successor list (#198995)
When using `-msave-restore` with `-ffixed-x5` on RISC-V,
`canUseAsPrologue` returns false for all blocks because the save-restore
prologue requires t0 (x5) which is reserved. This causes the shrink-wrap
loop to keep searching for a valid save point, eventually reaching the
entry block. On the next iteration, it calls FindIDom with the entry
block's empty predecessor list, triggering an assertion in
findNearestCommonDominator.
Fix by returning nullptr from FindIDom when the block list is empty,
which signals the caller to stop searching and give up the optimization.
Fixes #166759
Added:
llvm/test/CodeGen/RISCV/shrinkwrap-save-restore-fixed-reg.ll
Modified:
llvm/lib/CodeGen/ShrinkWrap.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/ShrinkWrap.cpp b/llvm/lib/CodeGen/ShrinkWrap.cpp
index ff71bb07dab05..92d3c2e59fcec 100644
--- a/llvm/lib/CodeGen/ShrinkWrap.cpp
+++ b/llvm/lib/CodeGen/ShrinkWrap.cpp
@@ -384,6 +384,8 @@ bool ShrinkWrapImpl::useOrDefCSROrFI(const MachineInstr &MI, RegScavenger *RS,
template <typename ListOfBBs, typename DominanceAnalysis>
static MachineBasicBlock *FindIDom(MachineBasicBlock &Block, ListOfBBs BBs,
DominanceAnalysis &Dom, bool Strict = true) {
+ if (BBs.begin() == BBs.end())
+ return Strict ? nullptr : &Block;
MachineBasicBlock *IDom = Dom.findNearestCommonDominator(iterator_range(BBs));
if (Strict && IDom == &Block)
return nullptr;
diff --git a/llvm/test/CodeGen/RISCV/shrinkwrap-save-restore-fixed-reg.ll b/llvm/test/CodeGen/RISCV/shrinkwrap-save-restore-fixed-reg.ll
new file mode 100644
index 0000000000000..2f51014c36742
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/shrinkwrap-save-restore-fixed-reg.ll
@@ -0,0 +1,38 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv64 -mattr=+save-restore,+reserve-x5 -verify-machineinstrs < %s \
+; RUN: | FileCheck %s
+
+; This test verifies that the shrink-wrap pass does not crash when the save
+; point reaches the entry block (which has no predecessors) while trying to find
+; a cheaper save point via FindIDom.
+
+ at a = global i32 0, align 4
+
+define signext i32 @shrinkwrap_entry_no_preds() {
+; CHECK-LABEL: shrinkwrap_entry_no_preds:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: call t0, __riscv_save_0
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: lui a0, %hi(a)
+; CHECK-NEXT: lw a0, %lo(a)(a0)
+; CHECK-NEXT: beqz a0, .LBB0_2
+; CHECK-NEXT: # %bb.1: # %if.then
+; CHECK-NEXT: call b
+; CHECK-NEXT: .LBB0_2: # %if.end
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: tail __riscv_restore_0
+entry:
+ %0 = load i32, ptr @a, align 4
+ %tobool.not = icmp eq i32 %0, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then:
+ tail call void @b()
+ br label %if.end
+
+if.end:
+ ret i32 0
+}
+
+declare void @b()
More information about the llvm-commits
mailing list