summaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/InstructionCombining.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2002-05-06 16:14:14 +0000
committerChris Lattner <sabre@nondot.org>2002-05-06 16:14:14 +0000
commit3f5b877dd4e1bd19915bf0de041dd5e199ef4062 (patch)
treec1f4a2a111836ebb209f231fc50805bff8260791 /lib/Transforms/Scalar/InstructionCombining.cpp
parent4dedcb267039c3a8b0d611583a2d77321159f512 (diff)
downloadllvm-3f5b877dd4e1bd19915bf0de041dd5e199ef4062.tar.gz
llvm-3f5b877dd4e1bd19915bf0de041dd5e199ef4062.tar.bz2
llvm-3f5b877dd4e1bd19915bf0de041dd5e199ef4062.tar.xz
Add many more instruction combination simplifications
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2484 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/InstructionCombining.cpp')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp198
1 files changed, 188 insertions, 10 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 59172b5d01..c56436048b 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2,7 +2,8 @@
//
// InstructionCombining - Combine instructions to form fewer, simple
// instructions. This pass does not modify the CFG, and has a tendancy to
-// make instructions dead, so a subsequent DIE pass is useful.
+// make instructions dead, so a subsequent DIE pass is useful. This pass is
+// where algebraic simplification happens.
//
// This pass combines things like:
// %Y = add int 1, %X
@@ -60,6 +61,13 @@ namespace {
Instruction *visitAdd(BinaryOperator *I);
Instruction *visitSub(BinaryOperator *I);
Instruction *visitMul(BinaryOperator *I);
+ Instruction *visitDiv(BinaryOperator *I);
+ Instruction *visitRem(BinaryOperator *I);
+ Instruction *visitAnd(BinaryOperator *I);
+ Instruction *visitOr (BinaryOperator *I);
+ Instruction *visitXor(BinaryOperator *I);
+ Instruction *visitSetCondInst(BinaryOperator *I);
+ Instruction *visitShiftInst(Instruction *I);
Instruction *visitCastInst(CastInst *CI);
Instruction *visitGetElementPtrInst(GetElementPtrInst *GEP);
Instruction *visitMemAccessInst(MemAccessInst *MAI);
@@ -119,23 +127,26 @@ Instruction *InstCombiner::visitAdd(BinaryOperator *I) {
Instruction *InstCombiner::visitSub(BinaryOperator *I) {
if (I->use_empty()) return 0; // Don't fix dead add instructions...
- bool Changed = SimplifyBinOp(I);
+ Value *Op0 = I->getOperand(0), *Op1 = I->getOperand(1);
+
+ if (Op0 == Op1) { // sub X, X -> 0
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Constant::getNullValue(I->getType()));
+ return I;
+ }
// If this is a subtract instruction with a constant RHS, convert it to an add
// instruction of a negative constant
//
- if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(1)))
- // Calculate 0 - RHS
- if (Constant *RHS = *Constant::getNullValue(I->getType()) - *Op2) {
- return BinaryOperator::create(Instruction::Add, I->getOperand(0), RHS,
- I->getName());
- }
+ if (Constant *Op2 = dyn_cast<Constant>(Op1))
+ if (Constant *RHS = *Constant::getNullValue(I->getType()) - *Op2) // 0 - RHS
+ return BinaryOperator::create(Instruction::Add, Op0, RHS, I->getName());
- return Changed ? I : 0;
+ return 0;
}
Instruction *InstCombiner::visitMul(BinaryOperator *I) {
- if (I->use_empty()) return 0; // Don't fix dead add instructions...
+ if (I->use_empty()) return 0; // Don't fix dead instructions...
bool Changed = SimplifyBinOp(I);
Value *Op1 = I->getOperand(0);
@@ -164,6 +175,173 @@ Instruction *InstCombiner::visitMul(BinaryOperator *I) {
}
+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)) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(I->getOperand(0));
+ return I;
+ }
+ return 0;
+}
+
+
+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)) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Constant::getNullValue(I->getType()));
+ return I;
+ }
+ return 0;
+}
+
+static Constant *getMaxValue(const Type *Ty) {
+ assert(Ty == Type::BoolTy || Ty->isIntegral());
+ 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 ConstantUInt::get(Ty, Val);
+
+ return 0;
+}
+
+
+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);
+
+ // and X, X = X and X, 0 == 0
+ if (Op0 == Op1 || Op1 == Constant::getNullValue(I->getType())) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op1);
+ return I;
+ }
+
+ // and X, -1 == X
+ if (Constant *RHS = dyn_cast<Constant>(Op1))
+ if (RHS == getMaxValue(I->getType())) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op0);
+ return I;
+ }
+
+ return Changed ? I : 0;
+}
+
+
+
+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);
+
+ // or X, X = X or X, 0 == X
+ if (Op0 == Op1 || Op1 == Constant::getNullValue(I->getType())) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op0);
+ return I;
+ }
+
+ // or X, -1 == -1
+ if (Constant *RHS = dyn_cast<Constant>(Op1))
+ if (RHS == getMaxValue(I->getType())) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op1);
+ return I;
+ }
+
+ return Changed ? I : 0;
+}
+
+
+
+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);
+
+ // xor X, X = 0
+ if (Op0 == Op1) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Constant::getNullValue(I->getType()));
+ return I;
+ }
+
+ // xor X, 0 == X
+ if (Op1 == Constant::getNullValue(I->getType())) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op0);
+ return I;
+ }
+
+ return Changed ? I : 0;
+}
+
+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));
+ return I;
+ }
+
+ return Changed ? I : 0;
+}
+
+
+
+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);
+
+ // shl X, 0 == X and shr X, 0 == X
+ // shl 0, X == 0 and shr 0, X == 0
+ if (Op1 == Constant::getNullValue(Type::UByteTy) ||
+ Op0 == Constant::getNullValue(Op0->getType())) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Op0);
+ return I;
+ }
+
+ // shl int X, 32 = 0 and shr sbyte Y, 9 = 0, ... just don't eliminate shr of
+ // a signed value.
+ //
+ if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
+ unsigned TypeBits = Op0->getType()->getPrimitiveSize()*8;
+ if (CUI->getValue() >= TypeBits &&
+ !(Op0->getType()->isSigned() && I->getOpcode() == Instruction::Shr)) {
+ AddUsesToWorkList(I); // Add all modified instrs to worklist
+ I->replaceAllUsesWith(Constant::getNullValue(Op0->getType()));
+ return I;
+ }
+ }
+ return 0;
+}
+
+
// isEliminableCastOfCast - Return true if it is valid to eliminate the CI
// instruction.
//