aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/IPO/Inliner.cpp3
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp19
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp53
-rw-r--r--lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp10
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp3
-rw-r--r--lib/Transforms/InstCombine/InstCombineWorklist.h4
-rw-r--r--lib/Transforms/Instrumentation/AddressSanitizer.cpp2
-rw-r--r--lib/Transforms/Instrumentation/GCOVProfiling.cpp58
-rw-r--r--lib/Transforms/Scalar/CMakeLists.txt1
-rw-r--r--lib/Transforms/Scalar/CodeGenPrepare.cpp133
-rw-r--r--lib/Transforms/Scalar/EarlyCSE.cpp6
-rw-r--r--lib/Transforms/Scalar/GVN.cpp2
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp5
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp40
-rw-r--r--lib/Transforms/Scalar/MemCpyOptimizer.cpp6
-rw-r--r--lib/Transforms/Scalar/ObjCARC.cpp26
-rw-r--r--lib/Transforms/Scalar/SROA.cpp3213
-rw-r--r--lib/Transforms/Scalar/Scalar.cpp1
-rw-r--r--lib/Transforms/Utils/AddrModeMatcher.cpp2
-rw-r--r--lib/Transforms/Utils/BypassSlowDivision.cpp2
-rw-r--r--lib/Transforms/Utils/CMakeLists.txt1
-rw-r--r--lib/Transforms/Utils/IntegerDivision.cpp312
-rw-r--r--lib/Transforms/Utils/Local.cpp38
-rw-r--r--lib/Transforms/Utils/MetaRenamer.cpp6
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp509
25 files changed, 4235 insertions, 220 deletions
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 69a22fb1e6..a9263baa44 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -210,7 +210,8 @@ unsigned Inliner::getInlineThreshold(CallSite CS) const {
Function *Caller = CS.getCaller();
bool OptSize = Caller && !Caller->isDeclaration() &&
Caller->hasFnAttr(Attribute::OptimizeForSize);
- if (!(InlineLimit.getNumOccurrences() > 0) && OptSize && OptSizeThreshold < thres)
+ if (!(InlineLimit.getNumOccurrences() > 0) && OptSize &&
+ OptSizeThreshold < thres)
thres = OptSizeThreshold;
// Listen to the inlinehint attribute when it would increase the threshold.
diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp
index 43b4ab5efa..c81b333813 100644
--- a/lib/Transforms/IPO/PassManagerBuilder.cpp
+++ b/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -40,6 +40,10 @@ UseGVNAfterVectorization("use-gvn-after-vectorization",
cl::init(false), cl::Hidden,
cl::desc("Run GVN instead of Early CSE after vectorization passes"));
+static cl::opt<bool> UseNewSROA("use-new-sroa",
+ cl::init(false), cl::Hidden,
+ cl::desc("Enable the new, experimental SROA pass"));
+
PassManagerBuilder::PassManagerBuilder() {
OptLevel = 2;
SizeLevel = 0;
@@ -100,7 +104,10 @@ void PassManagerBuilder::populateFunctionPassManager(FunctionPassManager &FPM) {
addInitialAliasAnalysisPasses(FPM);
FPM.add(createCFGSimplificationPass());
- FPM.add(createScalarReplAggregatesPass());
+ if (UseNewSROA)
+ FPM.add(createSROAPass());
+ else
+ FPM.add(createScalarReplAggregatesPass());
FPM.add(createEarlyCSEPass());
FPM.add(createLowerExpectIntrinsicPass());
}
@@ -147,7 +154,10 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
// Start of function pass.
// Break up aggregate allocas, using SSAUpdater.
- MPM.add(createScalarReplAggregatesPass(-1, false));
+ if (UseNewSROA)
+ MPM.add(createSROAPass(/*RequiresDomTree*/ false));
+ else
+ MPM.add(createScalarReplAggregatesPass(-1, false));
MPM.add(createEarlyCSEPass()); // Catch trivial redundancies
if (!DisableSimplifyLibCalls)
MPM.add(createSimplifyLibCallsPass()); // Library Call Optimizations
@@ -265,7 +275,10 @@ void PassManagerBuilder::populateLTOPassManager(PassManagerBase &PM,
PM.add(createInstructionCombiningPass());
PM.add(createJumpThreadingPass());
// Break up allocas
- PM.add(createScalarReplAggregatesPass());
+ if (UseNewSROA)
+ PM.add(createSROAPass());
+ else
+ PM.add(createScalarReplAggregatesPass());
// Run a few AA driven optimizations here and now, to cleanup the code.
PM.add(createFunctionAttrsPass()); // Add nocapture.
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index e7f3b21b15..23c08699ff 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -29,6 +29,26 @@ static Type *getPromotedType(Type *Ty) {
return Ty;
}
+/// reduceToSingleValueType - Given an aggregate type which ultimately holds a
+/// single scalar element, like {{{type}}} or [1 x type], return type.
+static Type *reduceToSingleValueType(Type *T) {
+ while (!T->isSingleValueType()) {
+ if (StructType *STy = dyn_cast<StructType>(T)) {
+ if (STy->getNumElements() == 1)
+ T = STy->getElementType(0);
+ else
+ break;
+ } else if (ArrayType *ATy = dyn_cast<ArrayType>(T)) {
+ if (ATy->getNumElements() == 1)
+ T = ATy->getElementType();
+ else
+ break;
+ } else
+ break;
+ }
+
+ return T;
+}
Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) {
unsigned DstAlign = getKnownAlignment(MI->getArgOperand(0), TD);
@@ -74,35 +94,34 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) {
// dest address will be promotable. See if we can find a better type than the
// integer datatype.
Value *StrippedDest = MI->getArgOperand(0)->stripPointerCasts();
+ MDNode *CopyMD = 0;
if (StrippedDest != MI->getArgOperand(0)) {
Type *SrcETy = cast<PointerType>(StrippedDest->getType())
->getElementType();
if (TD && SrcETy->isSized() && TD->getTypeStoreSize(SrcETy) == Size) {
// The SrcETy might be something like {{{double}}} or [1 x double]. Rip
// down through these levels if so.
- while (!SrcETy->isSingleValueType()) {
- if (StructType *STy = dyn_cast<StructType>(SrcETy)) {
- if (STy->getNumElements() == 1)
- SrcETy = STy->getElementType(0);
- else
- break;
- } else if (ArrayType *ATy = dyn_cast<ArrayType>(SrcETy)) {
- if (ATy->getNumElements() == 1)
- SrcETy = ATy->getElementType();
- else
- break;
- } else
- break;
- }
+ SrcETy = reduceToSingleValueType(SrcETy);
if (SrcETy->isSingleValueType()) {
NewSrcPtrTy = PointerType::get(SrcETy, SrcAddrSp);
NewDstPtrTy = PointerType::get(SrcETy, DstAddrSp);
+
+ // If the memcpy has metadata describing the members, see if we can
+ // get the TBAA tag describing our copy.
+ if (MDNode *M = MI->getMetadata(LLVMContext::MD_tbaa_struct)) {
+ if (M->getNumOperands() == 3 &&
+ isa<ConstantInt>(M->getOperand(0)) &&
+ cast<ConstantInt>(M->getOperand(0))->isNullValue() &&
+ isa<ConstantInt>(M->getOperand(1)) &&
+ cast<ConstantInt>(M->getOperand(1))->getValue() == Size &&
+ isa<MDNode>(M->getOperand(2)))
+ CopyMD = cast<MDNode>(M->getOperand(2));
+ }
}
}
}
-
// If the memcpy/memmove provides better alignment info than we can
// infer, use it.
SrcAlign = std::max(SrcAlign, CopyAlign);
@@ -112,8 +131,12 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) {
Value *Dest = Builder->CreateBitCast(MI->getArgOperand(0), NewDstPtrTy);
LoadInst *L = Builder->CreateLoad(Src, MI->isVolatile());
L->setAlignment(SrcAlign);
+ if (CopyMD)
+ L->setMetadata(LLVMContext::MD_tbaa, CopyMD);
StoreInst *S = Builder->CreateStore(L, Dest, MI->isVolatile());
S->setAlignment(DstAlign);
+ if (CopyMD)
+ S->setMetadata(LLVMContext::MD_tbaa, CopyMD);
// Set the size of the copy to 0, it will be deleted on the next iteration.
MI->setArgOperand(2, Constant::getNullValue(MemOpLength->getType()));
diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 6ecb4c52c4..5b6cf4a4a8 100644
--- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -246,12 +246,16 @@ Instruction *InstCombiner::visitAllocaInst(AllocaInst &AI) {
return &AI;
}
+ // If the alignment of the entry block alloca is 0 (unspecified),
+ // assign it the preferred alignment.
+ if (EntryAI->getAlignment() == 0)
+ EntryAI->setAlignment(
+ TD->getPrefTypeAlignment(EntryAI->getAllocatedType()));
// Replace this zero-sized alloca with the one at the start of the entry
// block after ensuring that the address will be aligned enough for both
// types.
- unsigned MaxAlign =
- std::max(TD->getPrefTypeAlignment(EntryAI->getAllocatedType()),
- TD->getPrefTypeAlignment(AI.getAllocatedType()));
+ unsigned MaxAlign = std::max(EntryAI->getAlignment(),
+ AI.getAlignment());
EntryAI->setAlignment(MaxAlign);
if (AI.getType() != EntryAI->getType())
return new BitCastInst(EntryAI, AI.getType());
diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 2a7182fc1d..3361a1e7fb 100644
--- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -477,7 +477,8 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
if (match(Op1, m_Shl(m_Power2(CI), m_Value(N))) ||
match(Op1, m_ZExt(m_Shl(m_Power2(CI), m_Value(N))))) {
if (*CI != 1)
- N = Builder->CreateAdd(N, ConstantInt::get(I.getType(),CI->logBase2()));
+ N = Builder->CreateAdd(N,
+ ConstantInt::get(N->getType(), CI->logBase2()));
if (ZExtInst *Z = dyn_cast<ZExtInst>(Op1))
N = Builder->CreateZExt(N, Z->getDestTy());
if (I.isExact())
diff --git a/lib/Transforms/InstCombine/InstCombineWorklist.h b/lib/Transforms/InstCombine/InstCombineWorklist.h
index 99a02fc0df..ea654ae9ed 100644
--- a/lib/Transforms/InstCombine/InstCombineWorklist.h
+++ b/lib/Transforms/InstCombine/InstCombineWorklist.h
@@ -26,8 +26,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombineWorklist {
SmallVector<Instruction*, 256> Worklist;
DenseMap<Instruction*, unsigned> WorklistMap;
- void operator=(const InstCombineWorklist&RHS); // DO NOT IMPLEMENT
- InstCombineWorklist(const InstCombineWorklist&); // DO NOT IMPLEMENT
+ void operator=(const InstCombineWorklist&RHS) LLVM_DELETED_FUNCTION;
+ InstCombineWorklist(const InstCombineWorklist&) LLVM_DELETED_FUNCTION;
public:
InstCombineWorklist() {}
diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 0775cf4a22..afa6a4b5e6 100644
--- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -392,7 +392,7 @@ bool AddressSanitizer::HasDynamicInitializer(GlobalVariable *G) {
}
void AddressSanitizer::instrumentMop(AsanFunctionContext &AFC, Instruction *I) {
- bool IsWrite;
+ bool IsWrite = false;
Value *Addr = isInterestingMemoryAccess(I, &IsWrite);
assert(Addr);
if (ClOpt && ClOptGlobals) {
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 9fcde316c0..bcee0c5f04 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -90,6 +90,7 @@ namespace {
// list.
void insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*, MDNode*> >);
void insertIndirectCounterIncrement();
+ void insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >);
std::string mangleName(DICompileUnit CU, const char *NewStem);
@@ -518,6 +519,7 @@ bool GCOVProfiler::emitProfileArcs() {
}
insertCounterWriteout(CountersBySP);
+ insertFlush(CountersBySP);
}
if (InsertIndCounterIncrCode)
@@ -630,13 +632,14 @@ GlobalVariable *GCOVProfiler::getEdgeStateValue() {
void GCOVProfiler::insertCounterWriteout(
ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
- FunctionType *WriteoutFTy =
- FunctionType::get(Type::getVoidTy(*Ctx), false);
- Function *WriteoutF = Function::Create(WriteoutFTy,
- GlobalValue::InternalLinkage,
- "__llvm_gcov_writeout", M);
+ FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
+ Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
+ if (!WriteoutF)
+ WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage,
+ "__llvm_gcov_writeout", M);
WriteoutF->setUnnamedAddr(true);
- BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF);
+
+ BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF);
IRBuilder<> Builder(BB);
Constant *StartFile = getStartFileFunc();
@@ -647,8 +650,8 @@ void GCOVProfiler::insertCounterWriteout(
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
if (CU_Nodes) {
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
- DICompileUnit compile_unit(CU_Nodes->getOperand(i));
- std::string FilenameGcda = mangleName(compile_unit, "gcda");
+ DICompileUnit CU(CU_Nodes->getOperand(i));
+ std::string FilenameGcda = mangleName(CU, "gcda");
Builder.CreateCall(StartFile,
Builder.CreateGlobalStringPtr(FilenameGcda));
for (ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator
@@ -744,3 +747,42 @@ void GCOVProfiler::insertIndirectCounterIncrement() {
Builder.SetInsertPoint(Exit);
Builder.CreateRetVoid();
}
+
+void GCOVProfiler::
+insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
+ Function *FlushF = M->getFunction("__gcov_flush");
+ if (!FlushF)
+ FlushF = Function::Create(FTy, GlobalValue::InternalLinkage,
+ "__gcov_flush", M);
+ else
+ FlushF->setLinkage(GlobalValue::InternalLinkage);
+ FlushF->setUnnamedAddr(true);
+
+ BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF);
+
+ // Write out the current counters.
+ Constant *WriteoutF = M->getFunction("__llvm_gcov_writeout");
+ assert(WriteoutF && "Need to create the writeout function first!");
+
+ IRBuilder<> Builder(Entry);
+ Builder.CreateCall(WriteoutF);
+
+ // Zero out the counters.
+ for (ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator
+ I = CountersBySP.begin(), E = CountersBySP.end();
+ I != E; ++I) {
+ GlobalVariable *GV = I->first;
+ Constant *Null = Constant::getNullValue(GV->getType()->getElementType());
+ Builder.CreateStore(Null, GV);
+ }
+
+ Type *RetTy = FlushF->getReturnType();
+ if (RetTy == Type::getVoidTy(*Ctx))
+ Builder.CreateRetVoid();
+ else if (RetTy->isIntegerTy())
+ // Used if __gcov_flush was implicitly declared.
+ Builder.CreateRet(ConstantInt::get(RetTy, 0));
+ else
+ report_fatal_error("invalid return type for __gcov_flush");
+}
diff --git a/lib/Transforms/Scalar/CMakeLists.txt b/lib/Transforms/Scalar/CMakeLists.txt
index 283758f395..06ef4b4a9b 100644
--- a/lib/Transforms/Scalar/CMakeLists.txt
+++ b/lib/Transforms/Scalar/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_library(LLVMScalarOpts
Reassociate.cpp
Reg2Mem.cpp
SCCP.cpp
+ SROA.cpp
Scalar.cpp
ScalarReplAggregates.cpp
SimplifyCFGPass.cpp
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;
+}
diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp
index 26271133e6..258a961df4 100644
--- a/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -274,7 +274,8 @@ private:
CallScope(*availableCalls) {}
private:
- NodeScope(const NodeScope&); // DO NOT IMPLEMENT
+ NodeScope(const NodeScope&) LLVM_DELETED_FUNCTION;
+ void operator=(const NodeScope&) LLVM_DELETED_FUNCTION;
ScopedHTType::ScopeTy Scope;
LoadHTType::ScopeTy LoadScope;
@@ -313,7 +314,8 @@ private:
void process() { Processed = true; }
private:
- StackNode(const StackNode&); // DO NOT IMPLEMENT
+ StackNode(const StackNode&) LLVM_DELETED_FUNCTION;
+ void operator=(const StackNode&) LLVM_DELETED_FUNCTION;
// Members.
unsigned CurrentGeneration;
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index 16ae6add86..e67d8af46c 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -632,7 +632,7 @@ INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_PASS_END(GVN, "gvn", "Global Value Numbering", false, false)
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void GVN::dump(DenseMap<uint32_t, Value*>& d) {
errs() << "{\n";
for (DenseMap<uint32_t, Value*>::iterator I = d.begin(),
diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index a72e288303..1553328c07 100644
--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -175,6 +175,11 @@ static void deleteIfDeadInstruction(Value *V, ScalarEvolution &SE,
bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
CurLoop = L;
+ // If the loop could not be converted to canonical form, it must have an
+ // indirectbr in it, just give up.
+ if (!L->getLoopPreheader())
+ return false;
+
// Disable loop idiom recognition if the function's name is a common idiom.
StringRef Name = L->getHeader()->getParent()->getName();
if (Name == "memset" || Name == "memcpy")
diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index d7495da5ef..1d3d156887 100644
--- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -121,7 +121,7 @@ void RegSortData::print(raw_ostream &OS) const {
OS << "[NumUses=" << UsedByIndices.count() << ']';
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void RegSortData::dump() const {
print(errs()); errs() << '\n';
}
@@ -416,7 +416,7 @@ void Formula::print(raw_ostream &OS) const {
}
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void Formula::dump() const {
print(errs()); errs() << '\n';
}
@@ -978,7 +978,7 @@ void Cost::print(raw_ostream &OS) const {
OS << ", plus " << SetupCost << " setup cost";
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void Cost::dump() const {
print(errs()); errs() << '\n';
}
@@ -1066,7 +1066,7 @@ void LSRFixup::print(raw_ostream &OS) const {
OS << ", Offset=" << Offset;
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void LSRFixup::dump() const {
print(errs()); errs() << '\n';
}
@@ -1260,7 +1260,7 @@ void LSRUse::print(raw_ostream &OS) const {
OS << ", widest fixup type: " << *WidestFixupType;
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void LSRUse::dump() const {
print(errs()); errs() << '\n';
}
@@ -3446,7 +3446,7 @@ void WorkItem::print(raw_ostream &OS) const {
<< " , add offset " << Imm;
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void WorkItem::dump() const {
print(errs()); errs() << '\n';
}
@@ -4464,17 +4464,21 @@ void LSRInstance::RewriteForPHI(PHINode *PN,
SplitLandingPadPredecessors(Parent, BB, "", "", P, NewBBs);
NewBB = NewBBs[0];
}
-
- // If PN is outside of the loop and BB is in the loop, we want to
- // move the block to be immediately before the PHI block, not
- // immediately after BB.
- if (L->contains(BB) && !L->contains(PN))
- NewBB->moveBefore(PN->getParent());
-
- // Splitting the edge can reduce the number of PHI entries we have.
- e = PN->getNumIncomingValues();
- BB = NewBB;
- i = PN->getBasicBlockIndex(BB);
+ // If NewBB==NULL, then SplitCriticalEdge refused to split because all
+ // phi predecessors are identical. The simple thing to do is skip
+ // splitting in this case rather than complicate the API.
+ if (NewBB) {
+ // If PN is outside of the loop and BB is in the loop, we want to
+ // move the block to be immediately before the PHI block, not
+ // immediately after BB.
+ if (L->contains(BB) && !L->contains(PN))
+ NewBB->moveBefore(PN->getParent());
+
+ // Splitting the edge can reduce the number of PHI entries we have.
+ e = PN->getNumIncomingValues();
+ BB = NewBB;
+ i = PN->getBasicBlockIndex(BB);
+ }
}
}
@@ -4743,7 +4747,7 @@ void LSRInstance::print(raw_ostream &OS) const {
print_uses(OS);
}
-#ifndef NDEBUG
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void LSRInstance::dump() const {
print(errs()); errs() << '\n';
}
diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 2a5ee33eb1..35acc79238 100644
--- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -38,7 +38,7 @@ STATISTIC(NumMemSetInfer, "Number of memsets inferred");
STATISTIC(NumMoveToCpy, "Number of memmoves converted to memcpy");
STATISTIC(NumCpyToSet, "Number of memcpys converted to memset");
-static int64_t GetOffsetFromIndex(const GetElementPtrInst *GEP, unsigned Idx,
+static int64_t GetOffsetFromIndex(const GEPOperator *GEP, unsigned Idx,
bool &VariableIdxFound, const TargetData &TD){
// Skip over the first indices.
gep_type_iterator GTI = gep_type_begin(GEP);
@@ -75,8 +75,8 @@ static bool IsPointerOffset(Value *Ptr1, Value *Ptr2, int64_t &Offset,
const TargetData &TD) {
Ptr1 = Ptr1->stripPointerCasts();
Ptr2 = Ptr2->stripPointerCasts();
- GetElementPtrInst *GEP1 = dyn_cast<GetElementPtrInst>(Ptr1);
- GetElementPtrInst *GEP2 = dyn_cast<GetElementPtrInst>(Ptr2);
+ GEPOperator *GEP1 = dyn_cast<GEPOperator>(Ptr1);
+ GEPOperator *GEP2 = dyn_cast<GEPOperator>(Ptr2);
bool VariableIdxFound = false;
diff --git a/lib/Transforms/Scalar/ObjCARC.cpp b/lib/Transforms/Scalar/ObjCARC.cpp
index dce8e8beb6..d83b069b1c 100644
--- a/lib/Transforms/Scalar/ObjCARC.cpp
+++ b/lib/Transforms/Scalar/ObjCARC.cpp
@@ -29,6 +29,7 @@
//===---------------------------------------------------------