#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PatternMatch.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
: public FunctionPass,
public InstVisitor<InstCombiner, Instruction*> {
// Worklist of all of the instructions that need to be simplified.
- std::vector<Instruction*> WorkList;
+ std::vector<Instruction*> Worklist;
+ DenseMap<Instruction*, unsigned> WorklistMap;
TargetData *TD;
+ public:
+ /// AddToWorkList - Add the specified instruction to the worklist if it
+ /// isn't already in it.
+ void AddToWorkList(Instruction *I) {
+ if (WorklistMap.insert(std::make_pair(I, Worklist.size())))
+ Worklist.push_back(I);
+ }
+
+ // RemoveFromWorkList - remove I from the worklist if it exists.
+ void RemoveFromWorkList(Instruction *I) {
+ DenseMap<Instruction*, unsigned>::iterator It = WorklistMap.find(I);
+ if (It == WorklistMap.end()) return; // Not in worklist.
+
+ // Don't bother moving everything down, just null out the slot.
+ Worklist[It->second] = 0;
+
+ WorklistMap.erase(It);
+ }
+
+ Instruction *RemoveOneFromWorkList() {
+ Instruction *I = Worklist.back();
+ Worklist.pop_back();
+ WorklistMap.erase(I);
+ return I;
+ }
+
/// AddUsersToWorkList - When an instruction is simplified, add all users of
/// the instruction to the work lists because they might get more simplified
/// now.
void AddUsersToWorkList(Value &I) {
for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
UI != UE; ++UI)
- WorkList.push_back(cast<Instruction>(*UI));
+ AddToWorkList(cast<Instruction>(*UI));
}
/// AddUsesToWorkList - When an instruction is simplified, add operands to
void AddUsesToWorkList(Instruction &I) {
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
if (Instruction *Op = dyn_cast<Instruction>(I.getOperand(i)))
- WorkList.push_back(Op);
+ AddToWorkList(Op);
}
/// AddSoonDeadInstToWorklist - The specified instruction is about to become
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
if (Instruction *Op = dyn_cast<Instruction>(I.getOperand(i))) {
- WorkList.push_back(Op);
+ AddToWorkList(Op);
// Set the operand to undef to drop the use.
I.setOperand(i, UndefValue::get(Op->getType()));
}
return R;
}
- // removeFromWorkList - remove all instances of I from the worklist.
- void removeFromWorkList(Instruction *I);
public:
virtual bool runOnFunction(Function &F);
"New instruction already inserted into a basic block!");
BasicBlock *BB = Old.getParent();
BB->getInstList().insert(&Old, New); // Insert inst
- WorkList.push_back(New); // Add to worklist
+ AddToWorkList(New);
return New;
}
return ConstantExpr::getCast(opc, CV, Ty);
Instruction *C = CastInst::create(opc, V, Ty, V->getName(), &Pos);
- WorkList.push_back(C);
+ AddToWorkList(C);
return C;
}
if (Old != New)
Old->replaceAllUsesWith(New);
if (Instruction *I = dyn_cast<Instruction>(Old))
- WorkList.push_back(I);
+ AddToWorkList(I);
if (Instruction *I = dyn_cast<Instruction>(New))
- WorkList.push_back(I);
+ AddToWorkList(I);
return true;
}
Instruction *EraseInstFromFunction(Instruction &I) {
assert(I.use_empty() && "Cannot erase instruction that is used!");
AddUsesToWorkList(I);
- removeFromWorkList(&I);
+ RemoveFromWorkList(&I);
I.eraseFromParent();
return 0; // Don't do anything with FI
}
Instruction *New = BinaryOperator::create(Opcode, Op->getOperand(0),
Op1->getOperand(0),
Op1->getName(), &I);
- WorkList.push_back(New);
+ AddToWorkList(New);
I.setOperand(0, New);
I.setOperand(1, Folded);
return true;
else
assert(0 && "Unknown binop!");
- WorkList.push_back(cast<Instruction>(InV));
+ AddToWorkList(cast<Instruction>(InV));
}
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
InV = CastInst::create(CI->getOpcode(), PN->getIncomingValue(i),
I.getType(), "phitmp",
NonConstBB->getTerminator());
- WorkList.push_back(cast<Instruction>(InV));
+ AddToWorkList(cast<Instruction>(InV));
}
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHS);
NewRHS = ConstantExpr::getAnd(NewRHS,
ConstantExpr::getNot(CommonBits));
- WorkList.push_back(Op0I);
+ AddToWorkList(Op0I);
I.setOperand(0, Op0I->getOperand(0));
I.setOperand(1, NewRHS);
return &I;
NewAndCST = ConstantExpr::getShl(AndCST, ShAmt);
LHSI->setOperand(1, NewAndCST);
LHSI->setOperand(0, Shift->getOperand(0));
- WorkList.push_back(Shift); // Shift is dead.
+ AddToWorkList(Shift); // Shift is dead.
AddUsesToWorkList(I);
return &I;
}
default: break;
case Intrinsic::bswap_i16:
// icmp eq (bswap(x)), c -> icmp eq (x,bswap(c))
- WorkList.push_back(II); // Dead?
+ AddToWorkList(II); // Dead?
I.setOperand(0, II->getOperand(1));
I.setOperand(1, ConstantInt::get(Type::Int16Ty,
ByteSwap_16(CI->getZExtValue())));
return &I;
case Intrinsic::bswap_i32:
// icmp eq (bswap(x)), c -> icmp eq (x,bswap(c))
- WorkList.push_back(II); // Dead?
+ AddToWorkList(II); // Dead?
I.setOperand(0, II->getOperand(1));
I.setOperand(1, ConstantInt::get(Type::Int32Ty,
ByteSwap_32(CI->getZExtValue())));
return &I;
case Intrinsic::bswap_i64:
// icmp eq (bswap(x)), c -> icmp eq (x,bswap(c))
- WorkList.push_back(II); // Dead?
+ AddToWorkList(II); // Dead?
I.setOperand(0, II->getOperand(1));
I.setOperand(1, ConstantInt::get(Type::Int64Ty,
ByteSwap_64(CI->getZExtValue())));
if (Caller->getType() != Type::VoidTy && !Caller->use_empty())
Caller->replaceAllUsesWith(NV);
Caller->eraseFromParent();
- removeFromWorkList(Caller);
+ RemoveFromWorkList(Caller);
return true;
}
if (!isa<UndefValue>(Val)) {
SI.setOperand(0, UndefValue::get(Val->getType()));
if (Instruction *U = dyn_cast<Instruction>(Val))
- WorkList.push_back(U); // Dropped a use.
+ AddToWorkList(U); // Dropped a use.
++NumCombined;
}
return 0; // Do not modify these!
BI.setCondition(NewSCC);
BI.setSuccessor(0, FalseDest);
BI.setSuccessor(1, TrueDest);
- removeFromWorkList(I);
+ RemoveFromWorkList(I);
I->eraseFromParent();
- WorkList.push_back(NewSCC);
+ AddToWorkList(NewSCC);
return &BI;
}
BI.setCondition(NewSCC);
BI.setSuccessor(0, FalseDest);
BI.setSuccessor(1, TrueDest);
- removeFromWorkList(I);
+ RemoveFromWorkList(I);
I->eraseFromParent();;
- WorkList.push_back(NewSCC);
+ AddToWorkList(NewSCC);
return &BI;
}
SI.setOperand(i,ConstantExpr::getSub(cast<Constant>(SI.getOperand(i)),
AddRHS));
SI.setOperand(0, I->getOperand(0));
- WorkList.push_back(I);
+ AddToWorkList(I);
return &SI;
}
}
-void InstCombiner::removeFromWorkList(Instruction *I) {
- WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), I),
- WorkList.end());
-}
-
/// TryToSinkInstruction - Try to move the specified instruction from its
/// current block into the beginning of DestBlock, which can only happen if it's
///
static void AddReachableCodeToWorklist(BasicBlock *BB,
SmallPtrSet<BasicBlock*, 64> &Visited,
- std::vector<Instruction*> &WorkList,
+ InstCombiner &IC,
const TargetData *TD) {
// We have now visited this block! If we've already been here, bail out.
if (!Visited.insert(BB)) return;
continue;
}
- WorkList.push_back(Inst);
+ IC.AddToWorkList(Inst);
}
// Recursively visit successors. If this is a branch or switch on a constant,
if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
if (BI->isConditional() && isa<ConstantInt>(BI->getCondition())) {
bool CondVal = cast<ConstantInt>(BI->getCondition())->getZExtValue();
- AddReachableCodeToWorklist(BI->getSuccessor(!CondVal), Visited, WorkList,
- TD);
+ AddReachableCodeToWorklist(BI->getSuccessor(!CondVal), Visited, IC, TD);
return;
}
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
// See if this is an explicit destination.
for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i)
if (SI->getCaseValue(i) == Cond) {
- AddReachableCodeToWorklist(SI->getSuccessor(i), Visited, WorkList,TD);
+ AddReachableCodeToWorklist(SI->getSuccessor(i), Visited, IC, TD);
return;
}
// Otherwise it is the default destination.
- AddReachableCodeToWorklist(SI->getSuccessor(0), Visited, WorkList, TD);
+ AddReachableCodeToWorklist(SI->getSuccessor(0), Visited, IC, TD);
return;
}
}
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
- AddReachableCodeToWorklist(TI->getSuccessor(i), Visited, WorkList, TD);
+ AddReachableCodeToWorklist(TI->getSuccessor(i), Visited, IC, TD);
}
bool InstCombiner::runOnFunction(Function &F) {
// the reachable instructions. Ignore blocks that are not reachable. Keep
// track of which blocks we visit.
SmallPtrSet<BasicBlock*, 64> Visited;
- AddReachableCodeToWorklist(F.begin(), Visited, WorkList, TD);
+ AddReachableCodeToWorklist(F.begin(), Visited, *this, TD);
// Do a quick scan over the function. If we find any blocks that are
// unreachable, remove any instructions inside of them. This prevents
}
}
- while (!WorkList.empty()) {
- Instruction *I = WorkList.back(); // Get an instruction from the worklist
- WorkList.pop_back();
+ while (!Worklist.empty()) {
+ Instruction *I = RemoveOneFromWorkList();
+ if (I == 0) continue; // skip null values.
// Check to see if we can DCE the instruction.
if (isInstructionTriviallyDead(I)) {
DOUT << "IC: DCE: " << *I;
I->eraseFromParent();
- removeFromWorkList(I);
+ RemoveFromWorkList(I);
continue;
}
++NumConstProp;
I->eraseFromParent();
- removeFromWorkList(I);
+ RemoveFromWorkList(I);
continue;
}
I->replaceAllUsesWith(Result);
// Push the new instruction and any users onto the worklist.
- WorkList.push_back(Result);
+ AddToWorkList(Result);
AddUsersToWorkList(*Result);
// Move the name to the new instruction first.
// Make sure that we reprocess all operands now that we reduced their
// use counts.
- for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
- if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(i)))
- WorkList.push_back(OpI);
+ AddUsesToWorkList(*I);
// Instructions can end up on the worklist more than once. Make sure
// we do not process an instruction that has been deleted.
- removeFromWorkList(I);
+ RemoveFromWorkList(I);
// Erase the old instruction.
InstParent->getInstList().erase(I);
if (isInstructionTriviallyDead(I)) {
// Make sure we process all operands now that we are reducing their
// use counts.
- for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
- if (Instruction *OpI = dyn_cast<Instruction>(I->getOperand(i)))
- WorkList.push_back(OpI);
+ AddUsesToWorkList(*I);;
// Instructions may end up in the worklist more than once. Erase all
// occurrences of this instruction.
- removeFromWorkList(I);
+ RemoveFromWorkList(I);
I->eraseFromParent();
} else {
- WorkList.push_back(Result);
+ AddToWorkList(Result);
AddUsersToWorkList(*Result);
}
}