diff options
author | Antonio Frighetto <me@antoniofrighetto.com> | 2024-08-26 22:03:11 +0200 |
---|---|---|
committer | Antonio Frighetto <me@antoniofrighetto.com> | 2024-09-02 09:33:23 +0200 |
commit | e4e0dfb0c24c9bcd4bef835bd6a162967f097584 (patch) | |
tree | e853a1e13337cf29c9f16d058e1f1c30fad82d06 /llvm/lib | |
parent | ed6d9f6d2af7da90ac089cf648a1f8b2e8e4eb10 (diff) | |
download | llvm-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.cpp | 48 |
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; } |