X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FScalar%2FTailRecursionElimination.cpp;h=65b1f1428213f6a48b04778777a5edb4c584dc5c;hb=5401ba7099b9f3cd32b3399276b549bea15e5d1e;hp=65427f261e7f688536d49eac0261ea54c34e26ba;hpb=096d8411b3c093e90e2509bab2fea4f7934e7f91;p=oota-llvm.git diff --git a/lib/Transforms/Scalar/TailRecursionElimination.cpp b/lib/Transforms/Scalar/TailRecursionElimination.cpp index 65427f261e7..65b1f142821 100644 --- a/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -63,7 +63,9 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -85,6 +87,7 @@ STATISTIC(NumAccumAdded, "Number of accumulators introduced"); namespace { struct TailCallElim : public FunctionPass { const TargetTransformInfo *TTI; + const DataLayout *DL; static char ID; // Pass identification, replacement for typeid TailCallElim() : FunctionPass(ID) { @@ -136,24 +139,28 @@ void TailCallElim::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); } -/// CanTRE - Scan the specified basic block for alloca instructions. -/// If it contains any that are variable-sized or not in the entry block, -/// returns false. -static bool CanTRE(AllocaInst *AI) { - // Because of PR962, we don't TRE allocas outside the entry block. - - // If this alloca is in the body of the function, or if it is a variable - // sized allocation, we cannot tail call eliminate calls marked 'tail' - // with this mechanism. - BasicBlock *BB = AI->getParent(); - return BB == &BB->getParent()->getEntryBlock() && - isa(AI->getArraySize()); +/// \brief Scan the specified function for alloca instructions. +/// If it contains any dynamic allocas, returns false. +static bool CanTRE(Function &F) { + // Because of PR962, we don't TRE dynamic allocas. + for (auto &BB : F) { + for (auto &I : BB) { + if (AllocaInst *AI = dyn_cast(&I)) { + if (!AI->isStaticAlloca()) + return false; + } + } + } + + return true; } bool TailCallElim::runOnFunction(Function &F) { if (skipOptnoneFunction(F)) return false; + DL = F.getParent()->getDataLayout(); + bool AllCallsAreTailCalls = false; bool Modified = markTails(F, AllCallsAreTailCalls); if (AllCallsAreTailCalls) @@ -172,7 +179,7 @@ struct AllocaDerivedValueTracker { auto AddUsesToWorklist = [&](Value *V) { for (auto &U : V->uses()) { - if (!Visited.insert(&U)) + if (!Visited.insert(&U).second) continue; Worklist.push_back(&U); } @@ -224,12 +231,10 @@ struct AllocaDerivedValueTracker { } void callUsesLocalStack(CallSite CS, bool IsNocapture) { - // Add it to the list of alloca users. If it's already there, skip further - // processing. - if (!AllocaUsers.insert(CS.getInstruction())) - return; + // Add it to the list of alloca users. + AllocaUsers.insert(CS.getInstruction()); - // If it's nocapture then it can't capture the alloca. + // If it's nocapture then it can't capture this alloca. if (IsNocapture) return; @@ -316,9 +321,9 @@ bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) { break; } if (SafeToTail) { - F.getContext().emitOptimizationRemark( - "tailcallelim", F, CI->getDebugLoc(), - "found readnone tail call candidate"); + emitOptimizationRemark( + F.getContext(), "tailcallelim", F, CI->getDebugLoc(), + "marked this readnone call a tail call candidate"); CI->setTailCall(); Modified = true; continue; @@ -363,8 +368,9 @@ bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) { if (Visited[CI->getParent()] != ESCAPED) { // If the escape point was part way through the block, calls after the // escape point wouldn't have been put into DeferredTails. - F.getContext().emitOptimizationRemark( - "tailcallelim", F, CI->getDebugLoc(), "found tail call candidate"); + emitOptimizationRemark(F.getContext(), "tailcallelim", F, + CI->getDebugLoc(), + "marked this call a tail call candidate"); CI->setTailCall(); Modified = true; } else { @@ -390,16 +396,7 @@ bool TailCallElim::runTRE(Function &F) { // marked with the 'tail' attribute, because doing so would cause the stack // size to increase (real TRE would deallocate variable sized allocas, TRE // doesn't). - bool CanTRETailMarkedCall = true; - - // Find dynamic allocas. - for (Function::iterator BB = F.begin(), EE = F.end(); BB != EE; ++BB) { - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - if (AllocaInst *AI = dyn_cast(I)) { - CanTRETailMarkedCall &= CanTRE(AI); - } - } - } + bool CanTRETailMarkedCall = CanTRE(F); // Change any tail recursive calls to loops. // @@ -457,7 +454,7 @@ bool TailCallElim::CanMoveAboveCall(Instruction *I, CallInst *CI) { // being loaded from. if (CI->mayWriteToMemory() || !isSafeToLoadUnconditionally(L->getPointerOperand(), L, - L->getAlignment())) + L->getAlignment(), DL)) return false; } } @@ -684,9 +681,8 @@ bool TailCallElim::EliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, BasicBlock *BB = Ret->getParent(); Function *F = BB->getParent(); - F->getContext().emitOptimizationRemark( - "tailcallelim", *F, CI->getDebugLoc(), - "transforming tail recursion to loop"); + emitOptimizationRemark(F->getContext(), "tailcallelim", *F, CI->getDebugLoc(), + "transforming tail recursion to loop"); // OK! We can transform this tail call. If this is the first one found, // create the new entry block, allowing us to branch back to the old entry.