//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/Scalar/InstructionCombining.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/ConstantHandling.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
+#include "llvm/iPHINode.h"
#include "llvm/iOperators.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/InstVisitor.h"
-#include "../TransformInternals.h"
+#include "Support/StatisticReporter.h"
+#include <algorithm>
+static Statistic<> NumCombined("instcombine\t- Number of insts combined");
namespace {
class InstCombiner : public FunctionPass,
// I - Change was made, I is still valid
// otherwise - Change was made, replace I with returned instruction
//
-
+ Instruction *visitNot(UnaryOperator *I);
Instruction *visitAdd(BinaryOperator *I);
Instruction *visitSub(BinaryOperator *I);
Instruction *visitMul(BinaryOperator *I);
Instruction *visitSetCondInst(BinaryOperator *I);
Instruction *visitShiftInst(Instruction *I);
Instruction *visitCastInst(CastInst *CI);
+ Instruction *visitPHINode(PHINode *PN);
Instruction *visitGetElementPtrInst(GetElementPtrInst *GEP);
Instruction *visitMemAccessInst(MemAccessInst *MAI);
}
+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) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op->getOperand(0));
+ return I;
+ }
+ return 0;
+}
+
// Make sure that this instruction has a constant on the right hand side if it
// has any constant arguments. If not, fix it an return true.
Value *LHS = I->getOperand(0), *RHS = I->getOperand(1);
// Eliminate 'add int %X, 0'
- if (I->getType()->isIntegral() &&
- RHS == Constant::getNullValue(I->getType())) {
+ if (RHS == Constant::getNullValue(I->getType())) {
AddUsesToWorkList(I); // Add all modified instrs to worklist
I->replaceAllUsesWith(LHS);
return I;
}
- // -B + A --> A - B
+ // -A + B --> B - A
if (Value *V = dyn_castNegInst(LHS))
- return BinaryOperator::create(Instruction::Sub, RHS, LHS);
+ return BinaryOperator::create(Instruction::Sub, RHS, V);
// A + -B --> A - B
if (Value *V = dyn_castNegInst(RHS))
- return BinaryOperator::create(Instruction::Sub, LHS, RHS);
+ return BinaryOperator::create(Instruction::Sub, LHS, V);
// Simplify add instructions with a constant RHS...
if (Constant *Op2 = dyn_cast<Constant>(RHS)) {
if (Constant *RHS = *Constant::getNullValue(I->getType()) - *Op2) // 0 - RHS
return BinaryOperator::create(Instruction::Add, Op0, RHS, I->getName());
- // If this is a 'C = -B', check to see if 'B = -A', so that C = A...
- if (Op0 == Constant::getNullValue(I->getType()))
- if (Value *V = dyn_castNegInst(Op1)) {
- AddUsesToWorkList(I); // Add all modified instrs to worklist
- I->replaceAllUsesWith(V);
- return I;
- }
+ // If this is a 'C = x-B', check to see if 'B = -A', so that C = x+A...
+ if (Value *V = dyn_castNegInst(Op1))
+ return BinaryOperator::create(Instruction::Add, Op0, V);
+ // Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression is
+ // not used by anyone else...
+ //
+ if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1))
+ if (Op1I->use_size() == 1 && Op1I->getOpcode() == Instruction::Sub) {
+ // Swap the two operands of the subexpr...
+ Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
+ Op1I->setOperand(0, IIOp1);
+ Op1I->setOperand(1, IIOp0);
+
+ // Create the new top level add instruction...
+ return BinaryOperator::create(Instruction::Add, Op0, Op1);
+ }
return 0;
}
if (Ty == Type::BoolTy)
return ConstantBool::True;
- // Calculate -1 casted to the right type...
- unsigned TypeBits = Ty->getPrimitiveSize()*8;
- uint64_t Val = (uint64_t)-1LL; // All ones
- Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
-
if (Ty->isSigned())
- return ConstantSInt::get(Ty, (int64_t)Val);
- else if (Ty->isUnsigned())
+ return ConstantSInt::get(Ty, -1);
+ else if (Ty->isUnsigned()) {
+ // Calculate -1 casted to the right type...
+ unsigned TypeBits = Ty->getPrimitiveSize()*8;
+ uint64_t Val = (uint64_t)-1LL; // All ones
+ Val >>= 64-TypeBits; // Shift out unwanted 1 bits...
return ConstantUInt::get(Ty, Val);
-
+ }
return 0;
}
return Changed ? I : 0;
}
+// isTrueWhenEqual - Return true if the specified setcondinst instruction is
+// true when both operands are equal...
+//
+static bool isTrueWhenEqual(Instruction *I) {
+ return I->getOpcode() == Instruction::SetEQ ||
+ I->getOpcode() == Instruction::SetGE ||
+ I->getOpcode() == Instruction::SetLE;
+}
+
Instruction *InstCombiner::visitSetCondInst(BinaryOperator *I) {
if (I->use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
// setcc X, X
if (I->getOperand(0) == I->getOperand(1)) {
- bool NewVal = I->getOpcode() == Instruction::SetEQ ||
- I->getOpcode() == Instruction::SetGE ||
- I->getOpcode() == Instruction::SetLE;
AddUsesToWorkList(I); // Add all modified instrs to worklist
- I->replaceAllUsesWith(ConstantBool::get(NewVal));
+ I->replaceAllUsesWith(ConstantBool::get(isTrueWhenEqual(I)));
+ return I;
+ }
+
+ // setcc <global*>, 0 - Global value addresses are never null!
+ if (isa<GlobalValue>(I->getOperand(0)) &&
+ isa<ConstantPointerNull>(I->getOperand(1))) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(ConstantBool::get(!isTrueWhenEqual(I)));
return I;
}
// 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()) {
}
+// 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
+ PN->replaceAllUsesWith(PN->getIncomingValue(0));
+ return PN;
+ }
+
+ return 0;
+}
+
Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst *GEP) {
// Is it getelementptr %P, uint 0
// Now that we have an instruction, try combining it to simplify it...
Instruction *Result = visit(I);
if (Result) {
+ ++NumCombined;
// Should we replace the old instruction with a new one?
- if (Result != I)
+ 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);
+ }
+
ReplaceInstWithInst(I, Result);
+ }
WorkList.push_back(Result);
AddUsesToWorkList(Result);