Skip to content

Commit 83a292c

Browse files
committed
[Transforms][CodeExtraction] bug fix regions with stackrestore
Ensure code extraction for outlining to a function does not create a function with tail-call i.e. using stacksave of caller to restore stack. Code Extractor can include all other basic blocks without such stack restore blocks. symmetric scenario with stacksave with out-of-fn use
1 parent c8b7ec2 commit 83a292c

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,31 @@ bool CodeExtractor::isEligible() const {
627627
return false;
628628
}
629629
}
630+
// stacksave as input implies stackrestore in the outlined function
631+
// This can confuse prologue epilogue insertion phase
632+
// stacksave's uses must not cross outlined function
633+
for (BasicBlock *BB : Blocks) {
634+
for (Instruction &II : *BB) {
635+
if (IntrinsicInst *Intrin = dyn_cast<IntrinsicInst>(&II)) {
636+
if (Intrin->getIntrinsicID() == Intrinsic::stacksave) {
637+
for (User *U : Intrin->users())
638+
if (!definedInRegion(Blocks, U)) {
639+
return false; // stack-restore outside outlined region
640+
}
641+
}
642+
}
643+
for (auto &OI : II.operands()) {
644+
Value *V = OI;
645+
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(V)) {
646+
if (II->getIntrinsicID() == Intrinsic::stacksave) {
647+
if (definedInCaller(Blocks, V)) {
648+
return false;
649+
}
650+
}
651+
}
652+
}
653+
}
654+
}
630655
return true;
631656
}
632657

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; RUN: opt -S -passes=hotcoldsplit -hotcoldsplit-max-params=1 < %s | FileCheck %s
2+
3+
target datalayout = "E-m:a-p:32:32-i64:64-n32"
4+
target triple = "powerpc64-ibm-aix7.2.0.0"
5+
6+
define void @foo(i32 %cond) {
7+
; CHECK-LABEL: define {{.*}}@foo(
8+
; CHECK: if.then:
9+
; CHECK: if.then1:
10+
; CHECK: if.else:
11+
; CHECK: call {{.*}}@sink
12+
; CHECK: if.end:
13+
; CHECK: if.end2:
14+
;
15+
entry:
16+
%cond.addr = alloca i32
17+
store i32 %cond, ptr %cond.addr
18+
%0 = load i32, ptr %cond.addr
19+
%stks = tail call ptr @llvm.stacksave.p0()
20+
%tobool = icmp ne i32 %0, 0
21+
br i1 %tobool, label %if.then, label %if.end2
22+
23+
if.then: ; preds = %entry
24+
%1 = load i32, ptr %cond.addr
25+
call void @sink(i32 %0)
26+
%cmp = icmp sgt i32 %1, 10
27+
br i1 %cmp, label %if.then1, label %if.else
28+
29+
if.then1: ; preds = %if.then
30+
call void @sideeffect(i32 2)
31+
br label %if.end
32+
33+
if.else: ; preds = %if.then
34+
call void @sink(i32 0)
35+
call void @sideeffect(i32 0)
36+
call void @llvm.stackrestore.p0(ptr %stks)
37+
br label %if.end
38+
39+
40+
if.end: ; preds = %if.else, %if.then1
41+
br label %if.end2
42+
43+
if.end2: ; preds = %entry
44+
call void @sideeffect(i32 1)
45+
ret void
46+
}
47+
48+
49+
declare void @sideeffect(i32)
50+
51+
declare void @sink(i32) cold

0 commit comments

Comments
 (0)