Newer
Older
//===-- LoopUnswitch.cpp - Hoist loop-invariant conditionals in loop ------===//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
//
// This pass transforms loops that contain branches on loop-invariant conditions
// to have multiple loops. For example, it turns the left into the right code:
//
// for (...) if (lic)
// A for (...)
// if (lic) A; B; C
// B else
// C for (...)
// A; C
//
// This can increase the size of the code exponentially (doubling it every time
// a loop is unswitched) so we only unswitch if the resultant code will be
// smaller than a threshold.
//
// This pass expects LICM to be run before it to hoist invariant conditions out
// of the loop, to make the unswitching opportunity obvious.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "loop-unswitch"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
Chris Lattner
committed
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include <set>
using namespace llvm;
Chris Lattner
committed
STATISTIC(NumBranches, "Number of branches unswitched");
STATISTIC(NumSwitches, "Number of switches unswitched");
STATISTIC(NumSelects , "Number of selects unswitched");
STATISTIC(NumTrivial , "Number of unswitches that are trivial");
STATISTIC(NumSimplify, "Number of simplifications of unswitched code");
namespace {
cl::opt<unsigned>
Threshold("loop-unswitch-threshold", cl::desc("Max loop size to unswitch"),
cl::init(10), cl::Hidden);
class VISIBILITY_HIDDEN LoopUnswitch : public LoopPass {
LoopInfo *LI; // Loop information
// LoopProcessWorklist - Used to check if second loop needs processing
// after RewriteLoopBodyWithConditionConstant rewrites first loop.
std::vector<Loop*> LoopProcessWorklist;
SmallPtrSet<Value *,8> UnswitchedVals;
bool OptimizeForSize;
public:
LoopUnswitch(bool Os = false) :
LoopPass((intptr_t)&ID), OptimizeForSize(Os), redoLoop(false) {}
bool runOnLoop(Loop *L, LPPassManager &LPM);
bool processLoop(Loop *L);
/// This transformation requires natural loop information & requires that
/// loop preheaders be inserted into the CFG...
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredID(LoopSimplifyID);
Chris Lattner
committed
AU.addPreservedID(LoopSimplifyID);
AU.addRequired<LoopInfo>();
AU.addPreserved<LoopInfo>();
AU.addRequiredID(LCSSAID);
AU.addPreservedID(LCSSAID);
AU.addPreserved<DominatorTree>();
AU.addPreserved<DominanceFrontier>();
}
private:
/// RemoveLoopFromWorklist - If the specified loop is on the loop worklist,
/// remove it.
void RemoveLoopFromWorklist(Loop *L) {
std::vector<Loop*>::iterator I = std::find(LoopProcessWorklist.begin(),
LoopProcessWorklist.end(), L);
if (I != LoopProcessWorklist.end())
LoopProcessWorklist.erase(I);
}
bool UnswitchIfProfitable(Value *LoopCond, Constant *Val,Loop *L);
Chris Lattner
committed
unsigned getLoopUnswitchCost(Loop *L, Value *LIC);
Chris Lattner
committed
void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val,
BasicBlock *ExitBlock);
void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L);
void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
Constant *Val, bool isEqual);
void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
BasicBlock *TrueDest,
BasicBlock *FalseDest,
Instruction *InsertPt);
void SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L);
void RemoveBlockIfDead(BasicBlock *BB,
std::vector<Instruction*> &Worklist, Loop *l);
void RemoveLoopFromHierarchy(Loop *L);
};
RegisterPass<LoopUnswitch> X("loop-unswitch", "Unswitch loops");
}
LoopPass *llvm::createLoopUnswitchPass(bool Os) {
return new LoopUnswitch(Os);
}
/// FindLIVLoopCondition - Cond is a condition that occurs in L. If it is
/// invariant in the loop, or has an invariant piece, return the invariant.
/// 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;
// TODO: Handle: br (VARIANT|INVARIANT).
// TODO: Hoist simple expressions out of loops.
if (L->isLoopInvariant(Cond)) return Cond;
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Cond))
if (BO->getOpcode() == Instruction::And ||
BO->getOpcode() == Instruction::Or) {
// If either the left or right side is invariant, we can unswitch on this,
// which will cause the branch to go away in one loop and the condition to
// simplify in the other one.
if (Value *LHS = FindLIVLoopCondition(BO->getOperand(0), L, Changed))
return LHS;
if (Value *RHS = FindLIVLoopCondition(BO->getOperand(1), L, Changed))
return RHS;
}
return 0;
}
bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) {
LI = &getAnalysis<LoopInfo>();
LPM = &LPM_Ref;
bool Changed = false;
do {
redoLoop = false;
Changed |= processLoop(L);
} while(redoLoop);
return Changed;
}
/// processLoop - Do actual work and unswitch loop if possible and profitable.
bool LoopUnswitch::processLoop(Loop *L) {
assert(L->isLCSSAForm());
bool Changed = false;
// Loop over all of the basic blocks in the loop. If we find an interior
// block that is branching on a loop-invariant condition, we can unswitch this
// loop.
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
I != E; ++I) {
TerminatorInst *TI = (*I)->getTerminator();
if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
// If this isn't branching on an invariant condition, we can't unswitch
// it.
if (BI->isConditional()) {
// See if this, or some part of it, is loop invariant. If so, we can
// unswitch on it if we desire.
Value *LoopCond = FindLIVLoopCondition(BI->getCondition(), L, Changed);
if (LoopCond && UnswitchIfProfitable(LoopCond, ConstantInt::getTrue(),
++NumBranches;
return true;
}
}
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
Value *LoopCond = FindLIVLoopCondition(SI->getCondition(), L, Changed);
if (LoopCond && SI->getNumCases() > 1) {
// Find a value to unswitch on:
Loading
Loading full blame...