Skip to content

Commit fb6153a

Browse files
[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
1 parent 5d00743 commit fb6153a

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

llvm/lib/CodeGen/ShrinkWrap.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,8 @@ bool ShrinkWrapImpl::useOrDefCSROrFI(const MachineInstr &MI, RegScavenger *RS,
384384
template <typename ListOfBBs, typename DominanceAnalysis>
385385
static MachineBasicBlock *FindIDom(MachineBasicBlock &Block, ListOfBBs BBs,
386386
DominanceAnalysis &Dom, bool Strict = true) {
387+
if (BBs.begin() == BBs.end())
388+
return Strict ? nullptr : &Block;
387389
MachineBasicBlock *IDom = Dom.findNearestCommonDominator(iterator_range(BBs));
388390
if (Strict && IDom == &Block)
389391
return nullptr;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv64 -mattr=+save-restore,+reserve-x5 -verify-machineinstrs < %s \
3+
; RUN: | FileCheck %s
4+
5+
; This test verifies that the shrink-wrap pass does not crash when the save
6+
; point reaches the entry block (which has no predecessors) while trying to find
7+
; a cheaper save point via FindIDom.
8+
9+
@a = global i32 0, align 4
10+
11+
define signext i32 @shrinkwrap_entry_no_preds() {
12+
; CHECK-LABEL: shrinkwrap_entry_no_preds:
13+
; CHECK: # %bb.0: # %entry
14+
; CHECK-NEXT: call t0, __riscv_save_0
15+
; CHECK-NEXT: .cfi_def_cfa_offset 16
16+
; CHECK-NEXT: .cfi_offset ra, -8
17+
; CHECK-NEXT: lui a0, %hi(a)
18+
; CHECK-NEXT: lw a0, %lo(a)(a0)
19+
; CHECK-NEXT: beqz a0, .LBB0_2
20+
; CHECK-NEXT: # %bb.1: # %if.then
21+
; CHECK-NEXT: call b
22+
; CHECK-NEXT: .LBB0_2: # %if.end
23+
; CHECK-NEXT: li a0, 0
24+
; CHECK-NEXT: tail __riscv_restore_0
25+
entry:
26+
%0 = load i32, ptr @a, align 4
27+
%tobool.not = icmp eq i32 %0, 0
28+
br i1 %tobool.not, label %if.end, label %if.then
29+
30+
if.then:
31+
tail call void @b()
32+
br label %if.end
33+
34+
if.end:
35+
ret i32 0
36+
}
37+
38+
declare void @b()

0 commit comments

Comments
 (0)