mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-18 12:29:27 +00:00
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:
parent
2bd37807d0
commit
4f98c56936
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user