diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/TargetTransformImpl.cpp | 7 | ||||
-rw-r--r-- | lib/Transforms/Scalar/CodeGenPrepare.cpp | 114 | ||||
-rw-r--r-- | lib/Transforms/Scalar/SimplifyCFGPass.cpp | 12 | ||||
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 21 |
4 files changed, 31 insertions, 123 deletions
diff --git a/lib/Target/TargetTransformImpl.cpp b/lib/Target/TargetTransformImpl.cpp index 27877a9..38c704f 100644 --- a/lib/Target/TargetTransformImpl.cpp +++ b/lib/Target/TargetTransformImpl.cpp @@ -49,6 +49,12 @@ unsigned ScalarTargetTransformImpl::getJumpBufSize() const { return TLI->getJumpBufSize(); } +bool ScalarTargetTransformImpl::shouldBuildLookupTables() const { + return TLI->supportJumpTables() && + (TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other)); +} + //===----------------------------------------------------------------------===// // // Calls used by the vectorizers. @@ -313,4 +319,3 @@ VectorTargetTransformImpl::getNumberOfParts(Type *Tp) const { getTypeLegalizationCost(Tp->getContext(), TLI->getValueType(Tp)); return LT.first; } - diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 74e310f..9cd5381 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -18,7 +18,6 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" -#include "llvm/GlobalVariable.h" #include "llvm/IRBuilder.h" #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" @@ -128,7 +127,6 @@ namespace { bool OptimizeSelectInst(SelectInst *SI); bool DupRetToEnableTailCallOpts(ReturnInst *RI); bool PlaceDbgValues(Function &F); - bool ConvertLoadToSwitch(LoadInst *LI); }; } @@ -1292,11 +1290,9 @@ bool CodeGenPrepare::OptimizeInst(Instruction *I) { return OptimizeCmpExpression(CI); if (LoadInst *LI = dyn_cast<LoadInst>(I)) { - bool Changed = false; if (TLI) - Changed |= OptimizeMemoryInst(I, I->getOperand(0), LI->getType()); - Changed |= ConvertLoadToSwitch(LI); - return Changed; + return OptimizeMemoryInst(I, I->getOperand(0), LI->getType()); + return false; } if (StoreInst *SI = dyn_cast<StoreInst>(I)) { @@ -1376,109 +1372,3 @@ bool CodeGenPrepare::PlaceDbgValues(Function &F) { } return MadeChange; } - -static bool TargetSupportsJumpTables(const TargetLowering &TLI) { - return TLI.supportJumpTables() && - (TLI.isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || - TLI.isOperationLegalOrCustom(ISD::BRIND, MVT::Other)); -} - -/// ConvertLoadToSwitch - Convert loads from constant lookup tables into -/// switches. This undos the switch-to-lookup table transformation in -/// SimplifyCFG for targets where that is inprofitable. -bool CodeGenPrepare::ConvertLoadToSwitch(LoadInst *LI) { - // This only applies to targets that don't support jump tables. - if (!TLI || TargetSupportsJumpTables(*TLI)) - return false; - - // FIXME: In the future, it would be desirable to have enough target - // information in SimplifyCFG, so we could decide at that stage whether to - // transform the switch to a lookup table or not, and this - // reverse-transformation could be removed. - - GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getPointerOperand()); - if (!GEP || !GEP->isInBounds() || GEP->getPointerAddressSpace()) - return false; - if (GEP->getNumIndices() != 2) - return false; - Value *FirstIndex = GEP->idx_begin()[0]; - ConstantInt *FirstIndexInt = dyn_cast<ConstantInt>(FirstIndex); - if (!FirstIndexInt || !FirstIndexInt->isZero()) - return false; - - Value *TableIndex = GEP->idx_begin()[1]; - IntegerType *TableIndexTy = cast<IntegerType>(TableIndex->getType()); - - GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getPointerOperand()); - if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) - return false; - - Constant *Arr = GV->getInitializer(); - uint64_t NumElements; - if (ConstantArray *CA = dyn_cast<ConstantArray>(Arr)) - NumElements = CA->getType()->getNumElements(); - else if (ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(Arr)) - NumElements = CDA->getNumElements(); - else - return false; - if (NumElements < 2) - return false; - - // Split the block. - BasicBlock *OriginalBB = LI->getParent(); - BasicBlock *PostSwitchBB = OriginalBB->splitBasicBlock(LI); - - // Replace OriginalBB's terminator with a switch. - IRBuilder<> Builder(OriginalBB->getTerminator()); - SwitchInst *Switch = Builder.CreateSwitch(TableIndex, PostSwitchBB, - NumElements - 1); - OriginalBB->getTerminator()->eraseFromParent(); - - // Count the frequency of each value to decide which to use as default. - SmallDenseMap<Constant*, uint64_t> ValueFreq; - for (uint64_t I = 0; I < NumElements; ++I) - ++ValueFreq[Arr->getAggregateElement(I)]; - uint64_t MaxCount = 0; - Constant *DefaultValue = NULL; - for (SmallDenseMap<Constant*, uint64_t>::iterator I = ValueFreq.begin(), - E = ValueFreq.end(); I != E; ++I) { - if (I->second > MaxCount) { - MaxCount = I->second; - DefaultValue = I->first; - } - } - assert(DefaultValue && "No values in the array?"); - - // Create the phi node in PostSwitchBB, which will replace the load. - Builder.SetInsertPoint(PostSwitchBB->begin()); - PHINode *PHI = Builder.CreatePHI(LI->getType(), NumElements); - PHI->addIncoming(DefaultValue, OriginalBB); - - // Build basic blocks to target with the switch. - for (uint64_t I = 0; I < NumElements; ++I) { - Constant *C = Arr->getAggregateElement(I); - if (C == DefaultValue) continue; // Already covered by the default case. - - BasicBlock *BB = BasicBlock::Create(PostSwitchBB->getContext(), - "lookup.bb", - PostSwitchBB->getParent(), - PostSwitchBB); - Switch->addCase(ConstantInt::get(TableIndexTy, I), BB); - Builder.SetInsertPoint(BB); - Builder.CreateBr(PostSwitchBB); - PHI->addIncoming(C, BB); - } - - // Remove the load. - LI->replaceAllUsesWith(PHI); - LI->eraseFromParent(); - - // Clean up. - if (GEP->use_empty()) - GEP->eraseFromParent(); - if (GV->hasUnnamedAddr() && GV->hasPrivateLinkage() && GV->use_empty()) - GV->eraseFromParent(); - - CurInstIterator = Switch; - return true; -} diff --git a/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/lib/Transforms/Scalar/SimplifyCFGPass.cpp index 84b820b..9f24bb6 100644 --- a/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -35,6 +35,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" +#include "llvm/TargetTransformInfo.h" using namespace llvm; STATISTIC(NumSimpl, "Number of blocks simplified"); @@ -293,7 +294,8 @@ static bool mergeEmptyReturnBlocks(Function &F) { /// iterativelySimplifyCFG - Call SimplifyCFG on all the blocks in the function, /// iterating until no more changes are made. -static bool iterativelySimplifyCFG(Function &F, const DataLayout *TD) { +static bool iterativelySimplifyCFG(Function &F, const DataLayout *TD, + const TargetTransformInfo *TTI) { bool Changed = false; bool LocalChange = true; while (LocalChange) { @@ -302,7 +304,7 @@ static bool iterativelySimplifyCFG(Function &F, const DataLayout *TD) { // Loop over all of the basic blocks and remove them if they are unneeded... // for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) { - if (SimplifyCFG(BBIt++, TD)) { + if (SimplifyCFG(BBIt++, TD, TTI)) { LocalChange = true; ++NumSimpl; } @@ -317,9 +319,11 @@ static bool iterativelySimplifyCFG(Function &F, const DataLayout *TD) { // bool CFGSimplifyPass::runOnFunction(Function &F) { const DataLayout *TD = getAnalysisIfAvailable<DataLayout>(); + const TargetTransformInfo *TTI = + getAnalysisIfAvailable<TargetTransformInfo>(); bool EverChanged = removeUnreachableBlocksFromFn(F); EverChanged |= mergeEmptyReturnBlocks(F); - EverChanged |= iterativelySimplifyCFG(F, TD); + EverChanged |= iterativelySimplifyCFG(F, TD, TTI); // If neither pass changed anything, we're done. if (!EverChanged) return false; @@ -333,7 +337,7 @@ bool CFGSimplifyPass::runOnFunction(Function &F) { return true; do { - EverChanged = iterativelySimplifyCFG(F, TD); + EverChanged = iterativelySimplifyCFG(F, TD, TTI); EverChanged |= removeUnreachableBlocksFromFn(F); } while (EverChanged); diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index f05a8ba..04ffc90 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -14,6 +14,7 @@ #define DEBUG_TYPE "simplifycfg" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Constants.h" +#include "llvm/DataLayout.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" #include "llvm/IRBuilder.h" @@ -39,7 +40,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/NoFolder.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/DataLayout.h" +#include "llvm/TargetTransformInfo.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include <algorithm> #include <set> @@ -82,6 +83,7 @@ namespace { class SimplifyCFGOpt { const DataLayout *const TD; + const TargetTransformInfo *const TTI; Value *isValueEqualityComparison(TerminatorInst *TI); BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI, @@ -101,7 +103,8 @@ class SimplifyCFGOpt { bool SimplifyCondBranch(BranchInst *BI, IRBuilder <>&Builder); public: - explicit SimplifyCFGOpt(const DataLayout *td) : TD(td) {} + SimplifyCFGOpt(const DataLayout *td, const TargetTransformInfo *tti) + : TD(td), TTI(tti) {} bool run(BasicBlock *BB); }; } @@ -3459,8 +3462,13 @@ static bool ShouldBuildLookupTable(SwitchInst *SI, /// replace the switch with lookup tables. static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, - const DataLayout* TD) { + const DataLayout* TD, + const TargetTransformInfo *TTI) { assert(SI->getNumCases() > 1 && "Degenerate switch?"); + + if (TTI && !TTI->getScalarTargetTransformInfo()->shouldBuildLookupTables()) + return false; + // FIXME: Handle unreachable cases. // FIXME: If the switch is too sparse for a lookup table, perhaps we could @@ -3619,7 +3627,7 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) { if (ForwardSwitchConditionToPHI(SI)) return SimplifyCFG(BB) | true; - if (SwitchToLookupTable(SI, Builder, TD)) + if (SwitchToLookupTable(SI, Builder, TD, TTI)) return SimplifyCFG(BB) | true; return false; @@ -3916,6 +3924,7 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) { /// eliminates unreachable basic blocks, and does other "peephole" optimization /// of the CFG. It returns true if a modification was made. /// -bool llvm::SimplifyCFG(BasicBlock *BB, const DataLayout *TD) { - return SimplifyCFGOpt(TD).run(BB); +bool llvm::SimplifyCFG(BasicBlock *BB, const DataLayout *TD, + const TargetTransformInfo *TTI) { + return SimplifyCFGOpt(TD, TTI).run(BB); } |