#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
char LoopUnswitch::ID = 0;
static RegisterPass<LoopUnswitch> X("loop-unswitch", "Unswitch loops");
-LoopPass *llvm::createLoopUnswitchPass(bool Os) {
+Pass *llvm::createLoopUnswitchPass(bool Os) {
return new LoopUnswitch(Os);
}
/// Otherwise, return null.
static Value *FindLIVLoopCondition(Value *Cond, Loop *L, bool &Changed) {
// Constants should be folded, not unswitched on!
- if (isa<Constant>(Cond)) return false;
+ if (isa<Constant>(Cond)) return 0;
// TODO: Handle: br (VARIANT|INVARIANT).
- // TODO: Hoist simple expressions out of loops.
- if (L->isLoopInvariant(Cond)) return Cond;
-
+
+ // Hoist simple values out.
+ if (L->makeLoopInvariant(Cond, Changed))
+ return Cond;
+
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Cond))
if (BO->getOpcode() == Instruction::And ||
BO->getOpcode() == Instruction::Or) {
bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) {
LI = &getAnalysis<LoopInfo>();
LPM = &LPM_Ref;
- DF = getAnalysisToUpdate<DominanceFrontier>();
- DT = getAnalysisToUpdate<DominatorTree>();
+ DF = getAnalysisIfAvailable<DominanceFrontier>();
+ DT = getAnalysisIfAvailable<DominatorTree>();
currentLoop = L;
Function *F = currentLoop->getHeader()->getParent();
bool Changed = false;
Value *LoopCond = FindLIVLoopCondition(BI->getCondition(),
currentLoop, Changed);
if (LoopCond && UnswitchIfProfitable(LoopCond,
- ConstantInt::getTrue())) {
+ Context->getConstantIntTrue())) {
++NumBranches;
return true;
}
Value *LoopCond = FindLIVLoopCondition(SI->getCondition(),
currentLoop, Changed);
if (LoopCond && UnswitchIfProfitable(LoopCond,
- ConstantInt::getTrue())) {
+ Context->getConstantIntTrue())) {
++NumSelects;
return true;
}
// Okay, everything after this looks good, check to make sure that this block
// doesn't include any side effects.
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
- if (I->mayWriteToMemory())
+ if (I->mayHaveSideEffects())
return false;
return true;
// this.
if ((LoopExitBB = isTrivialLoopExitBlock(currentLoop,
BI->getSuccessor(0)))) {
- if (Val) *Val = ConstantInt::getTrue();
+ if (Val) *Val = Context->getConstantIntTrue();
} else if ((LoopExitBB = isTrivialLoopExitBlock(currentLoop,
BI->getSuccessor(1)))) {
- if (Val) *Val = ConstantInt::getFalse();
+ if (Val) *Val = Context->getConstantIntFalse();
}
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(HeaderTerm)) {
// If this isn't a switch on Cond, we can't handle it.
// part of the loop that the code *would* execute. We already checked the
// tail, check the header now.
for (BasicBlock::iterator I = Header->begin(), E = Header->end(); I != E; ++I)
- if (I->mayWriteToMemory())
+ if (I->mayHaveSideEffects())
return false;
return true;
}
initLoopData();
Function *F = loopHeader->getParent();
- // Do not unswitch if the function is optimized for size.
- if (!F->isDeclaration() && F->hasFnAttr(Attribute::OptimizeForSize))
- return false;
// Check to see if it would be profitable to unswitch current loop.
unsigned Cost = getLoopUnswitchCost(LoopCond);
// Do not do non-trivial unswitch while optimizing for size.
if (Cost && OptimizeForSize)
return false;
+ if (Cost && !F->isDeclaration() && F->hasFnAttr(Attribute::OptimizeForSize))
+ return false;
if (Cost > Threshold) {
// FIXME: this should estimate growth by the amount of code shared by the
// code is the true version and the new code is the false version.
Value *BranchVal = LIC;
if (!isa<ConstantInt>(Val) || Val->getType() != Type::Int1Ty)
- BranchVal = new ICmpInst(ICmpInst::ICMP_EQ, LIC, Val, "tmp", InsertPt);
- else if (Val != ConstantInt::getTrue())
+ BranchVal = new ICmpInst(InsertPt, ICmpInst::ICMP_EQ, LIC, Val, "tmp");
+ else if (Val != Context->getConstantIntTrue())
// We want to enter the new loop when the condition is true.
std::swap(TrueDest, FalseDest);
BasicBlock* EndBlock;
if (NewExitBlock->getSinglePredecessor() == ExitBlock) {
EndBlock = NewExitBlock;
- NewExitBlock = EndBlock->getSinglePredecessor();;
+ NewExitBlock = EndBlock->getSinglePredecessor();
} else {
EndBlock = ExitBlock;
}
// Anything that uses the instructions in this basic block should have their
// uses replaced with undefs.
if (!I->use_empty())
- I->replaceAllUsesWith(UndefValue::get(I->getType()));
+ I->replaceAllUsesWith(Context->getUndef(I->getType()));
}
// If this is the edge to the header block for a loop, remove the loop and
// Remove phi node entries in successors for this block.
TerminatorInst *TI = BB->getTerminator();
- std::vector<BasicBlock*> Succs;
+ SmallVector<BasicBlock*, 4> Succs;
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
Succs.push_back(TI->getSuccessor(i));
TI->getSuccessor(i)->removePredecessor(BB);
}
// Unique the successors, remove anything with multiple uses.
- std::sort(Succs.begin(), Succs.end());
+ array_pod_sort(Succs.begin(), Succs.end());
Succs.erase(std::unique(Succs.begin(), Succs.end()), Succs.end());
// Remove the basic block, including all of the instructions contained in it.
if (IsEqual)
Replacement = Val;
else
- Replacement = ConstantInt::get(Type::Int1Ty,
+ Replacement = Context->getConstantInt(Type::Int1Ty,
!cast<ConstantInt>(Val)->getZExtValue());
for (unsigned i = 0, e = Users.size(); i != e; ++i)
Instruction* OldTerm = Old->getTerminator();
BranchInst::Create(Split, SISucc,
- ConstantInt::getTrue(), OldTerm);
+ Context->getConstantIntTrue(), OldTerm);
LPM->deleteSimpleAnalysisValue(Old->getTerminator(), L);
Old->getTerminator()->eraseFromParent();
Worklist.pop_back();
// Simple constant folding.
- if (Constant *C = ConstantFoldInstruction(I)) {
+ if (Constant *C = ConstantFoldInstruction(I, Context)) {
ReplaceUsesOfWith(I, C, Worklist, L, LPM);
continue;
}