Generalize (A+c1)+c2 optimization to work with all associative operators

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2003-03-10 21:43:22 +00:00
parent 2bd37807d0
commit 4f98c56936

View File

@ -109,14 +109,49 @@ namespace {
RegisterOpt<InstCombiner> X("instcombine", "Combine redundant instructions"); RegisterOpt<InstCombiner> X("instcombine", "Combine redundant instructions");
} }
// getComplexity: Assign a complexity or rank value to LLVM Values...
// 0 -> Constant, 1 -> Other, 2 -> Argument, 2 -> Unary, 3 -> OtherInst
static unsigned getComplexity(Value *V) {
if (isa<Instruction>(V)) {
if (BinaryOperator::isNeg(V) || BinaryOperator::isNot(V))
return 2;
return 3;
}
if (isa<Argument>(V)) return 2;
return isa<Constant>(V) ? 0 : 1;
}
// Make sure that this instruction has a constant on the right hand side if it // SimplifyCommutative - This performs a few simplifications for commutative
// has any constant arguments. If not, fix it an return true. // operators:
// //
static bool SimplifyBinOp(BinaryOperator &I) { // 1. Order operands such that they are listed from right (least complex) to
if (isa<Constant>(I.getOperand(0)) && !isa<Constant>(I.getOperand(1))) // left (most complex). This puts constants before unary operators before
return !I.swapOperands(); // binary operators.
return false; //
// 2. Handle the case of (op (op V, C1), C2), changing it to:
// (op V, (op C1, C2))
//
static bool SimplifyCommutative(BinaryOperator &I) {
bool Changed = false;
if (getComplexity(I.getOperand(0)) < getComplexity(I.getOperand(1)))
Changed = !I.swapOperands();
if (!I.isAssociative()) return Changed;
Instruction::BinaryOps Opcode = I.getOpcode();
if (BinaryOperator *Op = dyn_cast<BinaryOperator>(I.getOperand(0))) {
if (Op->getOpcode() == Opcode && isa<Constant>(I.getOperand(1)) &&
isa<Constant>(Op->getOperand(1))) {
Instruction *New = BinaryOperator::create(I.getOpcode(), I.getOperand(1),
Op->getOperand(1));
Constant *Folded = ConstantFoldInstruction(New);
delete New;
assert(Folded && "Couldn't constant fold commutative operand?");
I.setOperand(0, Op->getOperand(0));
I.setOperand(1, Folded);
return true;
}
}
return Changed;
} }
// dyn_castNegInst - Given a 'sub' instruction, return the RHS of the // dyn_castNegInst - Given a 'sub' instruction, return the RHS of the
@ -157,7 +192,7 @@ static inline Value *dyn_castFoldableMul(Value *V) {
Instruction *InstCombiner::visitAdd(BinaryOperator &I) { Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
bool Changed = SimplifyBinOp(I); bool Changed = SimplifyCommutative(I);
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
// Eliminate 'add int %X, 0' // Eliminate 'add int %X, 0'
@ -172,26 +207,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (Value *V = dyn_castNegInst(RHS)) if (Value *V = dyn_castNegInst(RHS))
return BinaryOperator::create(Instruction::Sub, LHS, V); return BinaryOperator::create(Instruction::Sub, LHS, V);
// Simplify add instructions with a constant RHS...
if (Constant *Op2 = dyn_cast<Constant>(RHS)) {
if (BinaryOperator *ILHS = dyn_cast<BinaryOperator>(LHS)) {
if (ILHS->getOpcode() == Instruction::Add &&
isa<Constant>(ILHS->getOperand(1))) {
// Fold:
// %Y = add int %X, 1
// %Z = add int %Y, 1
// into:
// %Z = add int %X, 2
//
if (Constant *Val = *Op2 + *cast<Constant>(ILHS->getOperand(1))) {
I.setOperand(0, ILHS->getOperand(0));
I.setOperand(1, Val);
return &I;
}
}
}
}
// X*C + X --> X * (C+1) // X*C + X --> X * (C+1)
if (dyn_castFoldableMul(LHS) == RHS) { if (dyn_castFoldableMul(LHS) == RHS) {
Constant *CP1 = *cast<Constant>(cast<Instruction>(LHS)->getOperand(1)) + Constant *CP1 = *cast<Constant>(cast<Instruction>(LHS)->getOperand(1)) +
@ -279,7 +294,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
} }
Instruction *InstCombiner::visitMul(BinaryOperator &I) { Instruction *InstCombiner::visitMul(BinaryOperator &I) {
bool Changed = SimplifyBinOp(I); bool Changed = SimplifyCommutative(I);
Value *Op0 = I.getOperand(0); Value *Op0 = I.getOperand(0);
// Simplify mul instructions with a constant RHS... // Simplify mul instructions with a constant RHS...
@ -397,7 +412,7 @@ static bool isMinValuePlusOne(const ConstantInt *C) {
Instruction *InstCombiner::visitAnd(BinaryOperator &I) { Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
bool Changed = SimplifyBinOp(I); bool Changed = SimplifyCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// and X, X = X and X, 0 == 0 // and X, X = X and X, 0 == 0
@ -429,7 +444,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
Instruction *InstCombiner::visitOr(BinaryOperator &I) { Instruction *InstCombiner::visitOr(BinaryOperator &I) {
bool Changed = SimplifyBinOp(I); bool Changed = SimplifyCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// or X, X = X or X, 0 == X // or X, X = X or X, 0 == X
@ -457,7 +472,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
Instruction *InstCombiner::visitXor(BinaryOperator &I) { Instruction *InstCombiner::visitXor(BinaryOperator &I) {
bool Changed = SimplifyBinOp(I); bool Changed = SimplifyCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// xor X, X = 0 // xor X, X = 0
@ -510,11 +525,11 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if (Op0I->getOpcode() == Instruction::Or && Op0I->use_size() == 1) { if (Op0I->getOpcode() == Instruction::Or && Op0I->use_size() == 1) {
if (Op0I->getOperand(0) == Op1) // (B|A)^B == (A|B)^B if (Op0I->getOperand(0) == Op1) // (B|A)^B == (A|B)^B
cast<BinaryOperator>(Op0I)->swapOperands(); cast<BinaryOperator>(Op0I)->swapOperands();
if (Op0I->getOperand(1) == Op1) { // (A|B)^B == ~B & A if (Op0I->getOperand(1) == Op1) { // (A|B)^B == A & ~B
Value *NotB = BinaryOperator::createNot(Op1, Op1->getName()+".not", &I); Value *NotB = BinaryOperator::createNot(Op1, Op1->getName()+".not", &I);
WorkList.push_back(cast<Instruction>(NotB)); WorkList.push_back(cast<Instruction>(NotB));
return BinaryOperator::create(Instruction::And, NotB, return BinaryOperator::create(Instruction::And, Op0I->getOperand(0),
Op0I->getOperand(0)); NotB);
} }
} }
@ -543,7 +558,7 @@ static bool isTrueWhenEqual(Instruction &I) {
} }
Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
bool Changed = SimplifyBinOp(I); bool Changed = SimplifyCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
const Type *Ty = Op0->getType(); const Type *Ty = Op0->getType();