From f85aaf19177be467fdfee5dac59466749d9947a7 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 14 Feb 2019 23:35:53 +0000 Subject: [PATCH] [INLINER] allow inlining of address taken blocks as long as their uses does not contain calls to functions that capture the argument (potentially allowing the blockaddress to "escape" the lifetime of the caller). TODO: - add more tests - fix crash in llvm::updateCGAndAnalysisManagerForFunctionPass when invoking Transforms/Inline/blockaddress.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354079 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/BasicBlock.h | 5 +++++ lib/Analysis/InlineCost.cpp | 4 ++-- lib/IR/BasicBlock.cpp | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index fd9efb8417e..076adad7cf7 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -390,6 +390,11 @@ public: /// direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + /// Returns true if there are any uses of the address of this basic block + /// that are call instructions (which may allow the address of this basic + /// block to escape). + bool addressPotentiallyEscapesFunction(); + /// Update all phi nodes in this basic block's successors to refer to basic /// block \p New instead of to it. void replaceSuccessorsPhiUsesWith(BasicBlock *New); diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index 574a1b6c841..2f5aa4a2576 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -1832,7 +1832,7 @@ InlineResult CallAnalyzer::analyzeCall(CallSite CS) { // see an indirect branch that ends up being dead code at a particular call // site. If the blockaddress escapes the function, e.g., via a global // variable, inlining may lead to an invalid cross-function reference. - if (BB->hasAddressTaken()) + if (BB->hasAddressTaken() && BB->addressPotentiallyEscapesFunction()) return "blockaddress"; // Analyze the cost of this block. If we blow through the threshold, this @@ -2082,7 +2082,7 @@ InlineResult llvm::isInlineViable(Function &F) { if (isa(BI->getTerminator())) return "contains indirect branches"; - if (BI->hasAddressTaken()) + if (BI->hasAddressTaken() && BI->addressPotentiallyEscapesFunction()) return "uses block address"; for (auto &II : *BI) { diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp index 18e2fd898f7..7f2e762c29a 100644 --- a/lib/IR/BasicBlock.cpp +++ b/lib/IR/BasicBlock.cpp @@ -442,6 +442,14 @@ BasicBlock *BasicBlock::splitBasicBlock(iterator I, const Twine &BBName) { return New; } +bool BasicBlock::addressPotentiallyEscapesFunction() { + for (const Use& U : BlockAddress::get(this)->uses()) + if (const CallInst* CI = dyn_cast(U)) + if (!CI->paramHasAttr(U.getOperandNo(), Attribute::NoCapture)) + return true; + return false; +} + void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) { Instruction *TI = getTerminator(); if (!TI) -- 2.40.0