diff options
author | Daniel Neilson <dneilson@azul.com> | 2017-07-27 16:49:39 +0000 |
---|---|---|
committer | Daniel Neilson <dneilson@azul.com> | 2017-07-27 16:49:39 +0000 |
commit | 2574d7cbf635076825ea7953b12b75593ba41024 (patch) | |
tree | fcc36834152304e66c0762fbe4b5184c96a49bf9 /llvm/lib | |
parent | ef5bbd61dac4abab34df4e79f6b3f5d167e7df04 (diff) | |
download | bcm5719-llvm-2574d7cbf635076825ea7953b12b75593ba41024.tar.gz bcm5719-llvm-2574d7cbf635076825ea7953b12b75593ba41024.zip |
All libcalls should be considered to be GC-leaf functions.
Summary:
It is possible for some passes to materialize a call to a libcall (ex: ldexp, exp2, etc),
but these passes will not mark the call as a gc-leaf-function. All libcalls are
actually gc-leaf-functions, so we change llvm::callsGCLeafFunction() to tell us that
available libcalls are equivalent to gc-leaf-function calls.
Reviewers: sanjoy, anna, reames
Reviewed By: anna
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D35840
llvm-svn: 309291
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 11 |
3 files changed, 36 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp index e47b636348e..2d0cb6fbf21 100644 --- a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -54,6 +54,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IntrinsicInst.h" @@ -113,6 +114,7 @@ struct PlaceBackedgeSafepointsImpl : public FunctionPass { ScalarEvolution *SE = nullptr; DominatorTree *DT = nullptr; LoopInfo *LI = nullptr; + TargetLibraryInfo *TLI = nullptr; PlaceBackedgeSafepointsImpl(bool CallSafepoints = false) : FunctionPass(ID), CallSafepointsEnabled(CallSafepoints) { @@ -131,6 +133,7 @@ struct PlaceBackedgeSafepointsImpl : public FunctionPass { SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); + TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); for (Loop *I : *LI) { runOnLoopAndSubLoops(I); } @@ -141,6 +144,7 @@ struct PlaceBackedgeSafepointsImpl : public FunctionPass { AU.addRequired<DominatorTreeWrapperPass>(); AU.addRequired<ScalarEvolutionWrapperPass>(); AU.addRequired<LoopInfoWrapperPass>(); + AU.addRequired<TargetLibraryInfoWrapperPass>(); // We no longer modify the IR at all in this pass. Thus all // analysis are preserved. AU.setPreservesAll(); @@ -165,6 +169,7 @@ struct PlaceSafepoints : public FunctionPass { // We modify the graph wholesale (inlining, block insertion, etc). We // preserve nothing at the moment. We could potentially preserve dom tree // if that was worth doing + AU.addRequired<TargetLibraryInfoWrapperPass>(); } }; } @@ -174,10 +179,11 @@ struct PlaceSafepoints : public FunctionPass { // callers job. static void InsertSafepointPoll(Instruction *InsertBefore, - std::vector<CallSite> &ParsePointsNeeded /*rval*/); + std::vector<CallSite> &ParsePointsNeeded /*rval*/, + const TargetLibraryInfo &TLI); -static bool needsStatepoint(const CallSite &CS) { - if (callsGCLeafFunction(CS)) +static bool needsStatepoint(const CallSite &CS, const TargetLibraryInfo &TLI) { + if (callsGCLeafFunction(CS, TLI)) return false; if (CS.isCall()) { CallInst *call = cast<CallInst>(CS.getInstruction()); @@ -194,7 +200,8 @@ static bool needsStatepoint(const CallSite &CS) { /// answer; i.e. false is always valid. static bool containsUnconditionalCallSafepoint(Loop *L, BasicBlock *Header, BasicBlock *Pred, - DominatorTree &DT) { + DominatorTree &DT, + const TargetLibraryInfo &TLI) { // In general, we're looking for any cut of the graph which ensures // there's a call safepoint along every edge between Header and Pred. // For the moment, we look only for the 'cuts' that consist of a single call @@ -217,7 +224,7 @@ static bool containsUnconditionalCallSafepoint(Loop *L, BasicBlock *Header, // unconditional poll. In practice, this is only a theoretical concern // since we don't have any methods with conditional-only safepoint // polls. - if (needsStatepoint(CS)) + if (needsStatepoint(CS, TLI)) return true; } @@ -321,7 +328,7 @@ bool PlaceBackedgeSafepointsImpl::runOnLoop(Loop *L) { continue; } if (CallSafepointsEnabled && - containsUnconditionalCallSafepoint(L, Header, Pred, *DT)) { + containsUnconditionalCallSafepoint(L, Header, Pred, *DT, *TLI)) { // Note: This is only semantically legal since we won't do any further // IPO or inlining before the actual call insertion.. If we hadn't, we // might latter loose this call safepoint. @@ -472,6 +479,9 @@ bool PlaceSafepoints::runOnFunction(Function &F) { if (!shouldRewriteFunction(F)) return false; + const TargetLibraryInfo &TLI = + getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); + bool Modified = false; // In various bits below, we rely on the fact that uses are reachable from @@ -578,7 +588,7 @@ bool PlaceSafepoints::runOnFunction(Function &F) { // safepoint polls themselves. for (Instruction *PollLocation : PollsNeeded) { std::vector<CallSite> RuntimeCalls; - InsertSafepointPoll(PollLocation, RuntimeCalls); + InsertSafepointPoll(PollLocation, RuntimeCalls, TLI); ParsePointNeeded.insert(ParsePointNeeded.end(), RuntimeCalls.begin(), RuntimeCalls.end()); } @@ -610,7 +620,8 @@ INITIALIZE_PASS_END(PlaceSafepoints, "place-safepoints", "Place Safepoints", static void InsertSafepointPoll(Instruction *InsertBefore, - std::vector<CallSite> &ParsePointsNeeded /*rval*/) { + std::vector<CallSite> &ParsePointsNeeded /*rval*/, + const TargetLibraryInfo &TLI) { BasicBlock *OrigBB = InsertBefore->getParent(); Module *M = InsertBefore->getModule(); assert(M && "must be part of a module"); @@ -669,7 +680,7 @@ InsertSafepointPoll(Instruction *InsertBefore, assert(ParsePointsNeeded.empty()); for (auto *CI : Calls) { // No safepoint needed or wanted - if (!needsStatepoint(CI)) + if (!needsStatepoint(CI, TLI)) continue; // These are likely runtime calls. Should we assert that via calling diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index f19d45329d2..24489157773 100644 --- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/CFG.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" @@ -103,6 +104,7 @@ struct RewriteStatepointsForGC : public ModulePass { // else. We could in theory preserve a lot more analyses here. AU.addRequired<DominatorTreeWrapperPass>(); AU.addRequired<TargetTransformInfoWrapperPass>(); + AU.addRequired<TargetLibraryInfoWrapperPass>(); } /// The IR fed into RewriteStatepointsForGC may have had attributes and @@ -2419,10 +2421,12 @@ bool RewriteStatepointsForGC::runOnFunction(Function &F) { DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); TargetTransformInfo &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); + const TargetLibraryInfo &TLI = + getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); - auto NeedsRewrite = [](Instruction &I) { + auto NeedsRewrite = [&TLI](Instruction &I) { if (ImmutableCallSite CS = ImmutableCallSite(&I)) - return !callsGCLeafFunction(CS) && !isStatepoint(CS); + return !callsGCLeafFunction(CS, TLI) && !isStatepoint(CS); return false; }; diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 74610613001..805d7155ec7 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1832,7 +1832,8 @@ unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To, return ::replaceDominatedUsesWith(From, To, BB, ProperlyDominates); } -bool llvm::callsGCLeafFunction(ImmutableCallSite CS) { +bool llvm::callsGCLeafFunction(ImmutableCallSite CS, + const TargetLibraryInfo &TLI) { // Check if the function is specifically marked as a gc leaf function. if (CS.hasFnAttr("gc-leaf-function")) return true; @@ -1846,6 +1847,14 @@ bool llvm::callsGCLeafFunction(ImmutableCallSite CS) { IID != Intrinsic::experimental_deoptimize; } + // Lib calls can be materialized by some passes, and won't be + // marked as 'gc-leaf-function.' All available Libcalls are + // GC-leaf. + LibFunc LF; + if (TLI.getLibFunc(CS, LF)) { + return TLI.has(LF); + } + return false; } |