Skip to content

Commit e4e0dfb

Browse files
[CGP] Undo constant propagation of pointers across calls
It may be profitable to revert SCCP propagation of C++ static values, if such constants are pointers, in order to avoid redundant pointer computation, since the method returning the constant is non-removable.
1 parent ed6d9f6 commit e4e0dfb

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2677,7 +2677,8 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) {
26772677
}
26782678

26792679
// From here on out we're working with named functions.
2680-
if (!CI->getCalledFunction())
2680+
auto *Callee = CI->getCalledFunction();
2681+
if (!Callee)
26812682
return false;
26822683

26832684
// Lower all default uses of _chk calls. This is very similar
@@ -2692,6 +2693,51 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) {
26922693
return true;
26932694
}
26942695

2696+
// SCCP may have propagated, among other things, C++ static variables across
2697+
// calls. If this happens to be the case, we may want to undo it in order to
2698+
// avoid redundant pointer computation of the constant, as the function method
2699+
// returning the constant needs to be executed anyways.
2700+
auto GetUniformReturnValue = [](const Function *F) -> GlobalVariable * {
2701+
if (!F->getReturnType()->isPointerTy())
2702+
return nullptr;
2703+
2704+
GlobalVariable *UniformValue = nullptr;
2705+
for (auto &BB : *F) {
2706+
if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
2707+
if (auto *V = dyn_cast<GlobalVariable>(RI->getReturnValue())) {
2708+
if (!UniformValue)
2709+
UniformValue = V;
2710+
else if (V != UniformValue)
2711+
return nullptr;
2712+
} else {
2713+
return nullptr;
2714+
}
2715+
}
2716+
}
2717+
2718+
return UniformValue;
2719+
};
2720+
2721+
if (Callee->hasExactDefinition()) {
2722+
if (GlobalVariable *RV = GetUniformReturnValue(Callee)) {
2723+
bool MadeChange = false;
2724+
for (Use &U : make_early_inc_range(RV->uses())) {
2725+
auto *I = dyn_cast<Instruction>(U.getUser());
2726+
if (!I || I->getParent() != CI->getParent()) {
2727+
// Limit to the same basic block to avoid extending the call-site live
2728+
// range, which otherwise could increase register pressure.
2729+
continue;
2730+
}
2731+
if (CI->comesBefore(I)) {
2732+
U.set(CI);
2733+
MadeChange = true;
2734+
}
2735+
}
2736+
2737+
return MadeChange;
2738+
}
2739+
}
2740+
26952741
return false;
26962742
}
26972743

llvm/test/Transforms/CodeGenPrepare/revert-constant-ptr-propagation-on-calls.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ entry:
6060
define i32 @caller_1() {
6161
; CHECK-LABEL: @caller_1(
6262
; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS()
63-
; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS)
63+
; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr [[GETS_PTR]])
6464
; CHECK-NEXT: ret i32 [[GETI]]
6565
;
6666
%getS_ptr = call ptr @getS()

0 commit comments

Comments
 (0)