aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorAntonio Frighetto <me@antoniofrighetto.com>2024-08-26 22:03:11 +0200
committerAntonio Frighetto <me@antoniofrighetto.com>2024-09-02 09:33:23 +0200
commite4e0dfb0c24c9bcd4bef835bd6a162967f097584 (patch)
treee853a1e13337cf29c9f16d058e1f1c30fad82d06 /llvm/lib
parented6d9f6d2af7da90ac089cf648a1f8b2e8e4eb10 (diff)
downloadllvm-e4e0dfb0c24c9bcd4bef835bd6a162967f097584.zip
llvm-e4e0dfb0c24c9bcd4bef835bd6a162967f097584.tar.gz
llvm-e4e0dfb0c24c9bcd4bef835bd6a162967f097584.tar.bz2
[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.
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp48
1 files changed, 47 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 271a047..631cc26 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -2677,7 +2677,8 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) {
}
// From here on out we're working with named functions.
- if (!CI->getCalledFunction())
+ auto *Callee = CI->getCalledFunction();
+ if (!Callee)
return false;
// Lower all default uses of _chk calls. This is very similar
@@ -2692,6 +2693,51 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) {
return true;
}
+ // SCCP may have propagated, among other things, C++ static variables across
+ // calls. If this happens to be the case, we may want to undo it in order to
+ // avoid redundant pointer computation of the constant, as the function method
+ // returning the constant needs to be executed anyways.
+ auto GetUniformReturnValue = [](const Function *F) -> GlobalVariable * {
+ if (!F->getReturnType()->isPointerTy())
+ return nullptr;
+
+ GlobalVariable *UniformValue = nullptr;
+ for (auto &BB : *F) {
+ if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
+ if (auto *V = dyn_cast<GlobalVariable>(RI->getReturnValue())) {
+ if (!UniformValue)
+ UniformValue = V;
+ else if (V != UniformValue)
+ return nullptr;
+ } else {
+ return nullptr;
+ }
+ }
+ }
+
+ return UniformValue;
+ };
+
+ if (Callee->hasExactDefinition()) {
+ if (GlobalVariable *RV = GetUniformReturnValue(Callee)) {
+ bool MadeChange = false;
+ for (Use &U : make_early_inc_range(RV->uses())) {
+ auto *I = dyn_cast<Instruction>(U.getUser());
+ if (!I || I->getParent() != CI->getParent()) {
+ // Limit to the same basic block to avoid extending the call-site live
+ // range, which otherwise could increase register pressure.
+ continue;
+ }
+ if (CI->comesBefore(I)) {
+ U.set(CI);
+ MadeChange = true;
+ }
+ }
+
+ return MadeChange;
+ }
+ }
+
return false;
}