Skip to content

Commit bc9c37a

Browse files
committed
[FunctionnSpecializer] Do not mark function dead if any unexecutable callsite exists
1 parent ef5e65d commit bc9c37a

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ class FunctionSpecializer {
270270
return InstCostVisitor(GetBFI, F, M.getDataLayout(), TTI, Solver);
271271
}
272272

273+
bool isDeadFunction(Function *F) { return FullySpecialized.contains(F); }
274+
273275
private:
274276
Constant *getPromotableAlloca(AllocaInst *Alloca, CallInst *Call);
275277

llvm/lib/Transforms/IPO/FunctionSpecialization.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,15 @@ void FunctionSpecializer::removeDeadFunctions() {
844844
<< F->getName() << "\n");
845845
if (FAM)
846846
FAM->clear(*F, F->getName());
847+
848+
// Remove all the callsites that were proven unreachable once, and replace
849+
// them with poison.
850+
for (User *U : make_early_inc_range(F->users())) {
851+
assert((isa<CallInst>(U) || isa<InvokeInst>(U)) && "User of dead function must be call or invoke");
852+
Instruction *CS = cast<Instruction>(U);
853+
CS->replaceAllUsesWith(PoisonValue::get(CS->getType()));
854+
CS->eraseFromParent();
855+
}
847856
F->eraseFromParent();
848857
}
849858
FullySpecialized.clear();

llvm/lib/Transforms/IPO/SCCP.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ static bool runIPSCCP(
167167
// constants if we have found them to be of constant values.
168168
bool MadeChanges = false;
169169
for (Function &F : M) {
170-
if (F.isDeclaration())
170+
// Skip the dead functions marked by FunctionSpecializer, avoiding removing
171+
// blocks in dead functions.
172+
if (F.isDeclaration() || Specializer.isDeadFunction(&F))
171173
continue;
172174

173175
SmallVector<BasicBlock *, 512> BlocksToErase;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=ipsccp --funcspec-min-function-size=1 -S < %s | FileCheck %s
3+
4+
define i32 @caller() {
5+
; CHECK-LABEL: define i32 @caller() {
6+
; CHECK-NEXT: [[ENTRY:.*:]]
7+
; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee.specialized.1(i32 1)
8+
; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee.specialized.2(i32 0)
9+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 undef, 0
10+
; CHECK-NEXT: br i1 [[COND]], label %[[COMMON_RET:.*]], label %[[IF_THEN:.*]]
11+
; CHECK: [[COMMON_RET]]:
12+
; CHECK-NEXT: ret i32 0
13+
; CHECK: [[IF_THEN]]:
14+
; CHECK-NEXT: ret i32 0
15+
;
16+
entry:
17+
%call1 = call i32 @callee(i32 1)
18+
%call2 = call i32 @callee(i32 0)
19+
%cond = icmp eq i32 %call2, 0
20+
br i1 %cond, label %common.ret, label %if.then
21+
22+
common.ret: ; preds = %entry
23+
ret i32 0
24+
25+
if.then: ; preds = %entry
26+
%unreachable_call = call i32 @callee(i32 2)
27+
ret i32 %unreachable_call
28+
}
29+
30+
define internal i32 @callee(i32 %ac) {
31+
entry:
32+
br label %ai
33+
34+
ai: ; preds = %ai, %entry
35+
%add = or i32 0, 0
36+
%cond = icmp eq i32 %ac, 1
37+
br i1 %cond, label %aj, label %ai
38+
39+
aj: ; preds = %ai
40+
ret i32 0
41+
}

0 commit comments

Comments
 (0)