diff options
Diffstat (limited to 'lib/Transforms/Scalar/CodeGenPrepare.cpp')
-rw-r--r-- | lib/Transforms/Scalar/CodeGenPrepare.cpp | 133 |
1 files changed, 121 insertions, 12 deletions
diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 59121078cb..495cdc6321 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -18,6 +18,7 @@ #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" @@ -126,6 +127,7 @@ namespace { bool OptimizeSelectInst(SelectInst *SI); bool DupRetToEnableTailCallOpts(ReturnInst *RI); bool PlaceDbgValues(Function &F); + bool ConvertLoadToSwitch(LoadInst *LI); }; } @@ -152,13 +154,9 @@ bool CodeGenPrepare::runOnFunction(Function &F) { /// This optimization identifies DIV instructions that can be /// profitably bypassed and carried out with a shorter, faster divide. if (TLI && TLI->isSlowDivBypassed()) { - const DenseMap<Type *, Type *> &BypassTypeMap = TLI->getBypassSlowDivTypes(); - - for (Function::iterator I = F.begin(); I != F.end(); I++) { - EverMadeChange |= bypassSlowDivision(F, - I, - BypassTypeMap); - } + const DenseMap<Type*, Type*> &BypassTypeMap = TLI->getBypassSlowDivTypes(); + for (Function::iterator I = F.begin(); I != F.end(); I++) + EverMadeChange |= bypassSlowDivision(F, I, BypassTypeMap); } // Eliminate blocks that contain only PHI nodes and an @@ -173,7 +171,7 @@ bool CodeGenPrepare::runOnFunction(Function &F) { bool MadeChange = true; while (MadeChange) { MadeChange = false; - for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { + for (Function::iterator I = F.begin(); I != F.end(); ) { BasicBlock *BB = I++; MadeChange |= OptimizeBlock(*BB); } @@ -662,6 +660,7 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) { /// DupRetToEnableTailCallOpts - Look for opportunities to duplicate return /// instructions to the predecessor to enable tail call optimizations. The /// case it is currently looking for is: +/// @code /// bb0: /// %tmp0 = tail call i32 @f0() /// br label %return @@ -674,9 +673,11 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) { /// return: /// %retval = phi i32 [ %tmp0, %bb0 ], [ %tmp1, %bb1 ], [ %tmp2, %bb2 ] /// ret i32 %retval +/// @endcode /// /// => /// +/// @code /// bb0: /// %tmp0 = tail call i32 @f0() /// ret i32 %tmp0 @@ -686,7 +687,7 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) { /// bb2: /// %tmp2 = tail call i32 @f2() /// ret i32 %tmp2 -/// +/// @endcode bool CodeGenPrepare::DupRetToEnableTailCallOpts(ReturnInst *RI) { if (!TLI) return false; @@ -1284,9 +1285,11 @@ bool CodeGenPrepare::OptimizeInst(Instruction *I) { return OptimizeCmpExpression(CI); if (LoadInst *LI = dyn_cast<LoadInst>(I)) { + bool Changed = false; if (TLI) - return OptimizeMemoryInst(I, I->getOperand(0), LI->getType()); - return false; + Changed |= OptimizeMemoryInst(I, I->getOperand(0), LI->getType()); + Changed |= ConvertLoadToSwitch(LI); + return Changed; } if (StoreInst *SI = dyn_cast<StoreInst>(I)) { @@ -1330,7 +1333,7 @@ bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) { bool MadeChange = false; CurInstIterator = BB.begin(); - for (BasicBlock::iterator E = BB.end(); CurInstIterator != E; ) + while (CurInstIterator != BB.end()) MadeChange |= OptimizeInst(CurInstIterator++); return MadeChange; @@ -1366,3 +1369,109 @@ 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; +} |