#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ConstantHandling.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
Instruction *visitCastInst(CastInst &CI);
Instruction *visitPHINode(PHINode &PN);
Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
- Instruction *visitMemAccessInst(MemAccessInst &MAI);
// visitInstruction - Specify what to return for unhandled instructions...
Instruction *visitInstruction(Instruction &I) { return 0; }
Instruction *InstCombiner::visitNot(UnaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
-
// not (not X) = X
if (Instruction *Op = dyn_cast<Instruction>(I.getOperand(0)))
if (Op->getOpcode() == Instruction::Not) {
}
Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead add instructions...
bool Changed = SimplifyBinOp(I);
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
}
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead add instructions...
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Op0 == Op1) { // sub X, X -> 0
}
Instruction *InstCombiner::visitMul(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
Value *Op1 = I.getOperand(0);
Instruction *InstCombiner::visitDiv(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
-
// div X, 1 == X
if (ConstantInt *RHS = dyn_cast<ConstantInt>(I.getOperand(1)))
if (RHS->equalsInt(1)) {
Instruction *InstCombiner::visitRem(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
-
// rem X, 1 == 0
if (ConstantInt *RHS = dyn_cast<ConstantInt>(I.getOperand(1)))
if (RHS->equalsInt(1)) {
Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Instruction *InstCombiner::visitOr(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Instruction *InstCombiner::visitXor(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
}
Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
// setcc X, X
Instruction *InstCombiner::visitShiftInst(Instruction &I) {
- if (I.use_empty()) return 0; // Don't fix dead instructions...
assert(I.getOperand(1)->getType() == Type::UByteTy);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// CastInst simplification
//
Instruction *InstCombiner::visitCastInst(CastInst &CI) {
- if (CI.use_empty()) return 0; // Don't fix dead instructions...
-
// If the user is casting a value to the same type, eliminate this cast
// instruction...
- if (CI.getType() == CI.getOperand(0)->getType() && !CI.use_empty()) {
+ if (CI.getType() == CI.getOperand(0)->getType()) {
AddUsesToWorkList(CI); // Add all modified instrs to worklist
CI.replaceAllUsesWith(CI.getOperand(0));
return &CI;
// PHINode simplification
//
Instruction *InstCombiner::visitPHINode(PHINode &PN) {
- if (PN.use_empty()) return 0; // Don't fix dead instructions...
-
// If the PHI node only has one incoming value, eliminate the PHI node...
if (PN.getNumIncomingValues() == 1) {
AddUsesToWorkList(PN); // Add all modified instrs to worklist
Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
- // Is it getelementptr %P, uint 0
+ // Is it 'getelementptr %P, uint 0' or 'getelementptr %P'
// If so, eliminate the noop.
- if (GEP.getNumOperands() == 2 && !GEP.use_empty() &&
- GEP.getOperand(1) == Constant::getNullValue(Type::UIntTy)) {
+ if ((GEP.getNumOperands() == 2 &&
+ GEP.getOperand(1) == Constant::getNullValue(Type::UIntTy)) ||
+ GEP.getNumOperands() == 1) {
AddUsesToWorkList(GEP); // Add all modified instrs to worklist
GEP.replaceAllUsesWith(GEP.getOperand(0));
return &GEP;
}
- return visitMemAccessInst(GEP);
-}
-
-
-// Combine Indices - If the source pointer to this mem access instruction is a
-// getelementptr instruction, combine the indices of the GEP into this
-// instruction
-//
-Instruction *InstCombiner::visitMemAccessInst(MemAccessInst &MAI) {
- return 0; // DISABLE FOLDING. GEP is now the only MAI!
-
- GetElementPtrInst *Src =
- dyn_cast<GetElementPtrInst>(MAI.getPointerOperand());
- if (!Src) return 0;
-
- std::vector<Value *> Indices;
+ // Combine Indices - If the source pointer to this getelementptr instruction
+ // is a getelementptr instruction, combine the indices of the two
+ // getelementptr instructions into a single instruction.
+ //
+ if (GetElementPtrInst *Src =
+ dyn_cast<GetElementPtrInst>(GEP.getPointerOperand())) {
+ std::vector<Value *> Indices;
- // Only special case we have to watch out for is pointer arithmetic on the
- // 0th index of MAI.
- unsigned FirstIdx = MAI.getFirstIndexOperandNumber();
- if (FirstIdx == MAI.getNumOperands() ||
- (FirstIdx == MAI.getNumOperands()-1 &&
- MAI.getOperand(FirstIdx) == ConstantUInt::get(Type::UIntTy, 0))) {
- // Replace the index list on this MAI with the index on the getelementptr
- Indices.insert(Indices.end(), Src->idx_begin(), Src->idx_end());
- } else if (*MAI.idx_begin() == ConstantUInt::get(Type::UIntTy, 0)) {
- // Otherwise we can do the fold if the first index of the GEP is a zero
- Indices.insert(Indices.end(), Src->idx_begin(), Src->idx_end());
- Indices.insert(Indices.end(), MAI.idx_begin()+1, MAI.idx_end());
- }
+ // Can we combine the two pointer arithmetics offsets?
+ if (Src->getNumOperands() == 2 && isa<Constant>(Src->getOperand(1)) &&
+ isa<Constant>(GEP.getOperand(1))) {
+ // Replace the index list on this GEP with the index on the getelementptr
+ Indices.insert(Indices.end(), GEP.idx_begin(), GEP.idx_end());
+ Indices[0] = *cast<Constant>(Src->getOperand(1)) +
+ *cast<Constant>(GEP.getOperand(1));
+ assert(Indices[0] != 0 && "Constant folding of uint's failed!?");
+
+ } else if (*GEP.idx_begin() == ConstantUInt::get(Type::UIntTy, 0)) {
+ // Otherwise we can do the fold if the first index of the GEP is a zero
+ Indices.insert(Indices.end(), Src->idx_begin(), Src->idx_end());
+ Indices.insert(Indices.end(), GEP.idx_begin()+1, GEP.idx_end());
+ }
- if (Indices.empty()) return 0; // Can't do the fold?
-
- switch (MAI.getOpcode()) {
- case Instruction::GetElementPtr:
- return new GetElementPtrInst(Src->getOperand(0), Indices, MAI.getName());
- case Instruction::Load:
- return new LoadInst(Src->getOperand(0), Indices, MAI.getName());
- case Instruction::Store:
- return new StoreInst(MAI.getOperand(0), Src->getOperand(0), Indices);
- default:
- assert(0 && "Unknown memaccessinst!");
- break;
+ if (!Indices.empty())
+ return new GetElementPtrInst(Src->getOperand(0), Indices, GEP.getName());
}
- abort();
+
return 0;
}
WorkList.pop_back();
// Now that we have an instruction, try combining it to simplify it...
- Instruction *Result = visit(*I);
- if (Result) {
+ if (Instruction *Result = visit(*I)) {
++NumCombined;
// Should we replace the old instruction with a new one?
if (Result != I) {
// Instructions can end up on the worklist more than once. Make sure
// we do not process an instruction that has been deleted.
- std::vector<Instruction*>::iterator It = std::find(WorkList.begin(),
- WorkList.end(), I);
- while (It != WorkList.end()) {
- It = WorkList.erase(It);
- It = std::find(It, WorkList.end(), I);
- }
+ WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), I),
+ WorkList.end());
ReplaceInstWithInst(I, Result);
} else {
- // FIXME:
- // FIXME:
- // FIXME: This should DCE the instruction to simplify the cases above.
- // FIXME:
- // FIXME:
+ BasicBlock::iterator II = I;
+
+ // If the instruction was modified, it's possible that it is now dead.
+ // if so, remove it.
+ if (dceInstruction(II)) {
+ // Instructions may end up in the worklist more than once. Erase them
+ // all.
+ WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), I),
+ WorkList.end());
+ Result = 0;
+ }
}
- WorkList.push_back(Result);
- AddUsesToWorkList(*Result);
+ if (Result) {
+ WorkList.push_back(Result);
+ AddUsesToWorkList(*Result);
+ }
Changed = true;
}
}