mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
Move Sub simplifications and additional Add simplifications out of
instcombine and into InstructionSimplify. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121861 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f8b1a5ea96
commit
fea3b218d6
@ -29,6 +29,11 @@ namespace llvm {
|
|||||||
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||||
|
|
||||||
|
/// SimplifySubInst - Given operands for a Sub, see if we can
|
||||||
|
/// fold the result. If not, this returns null.
|
||||||
|
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||||
|
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||||
|
|
||||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||||
/// fold the result. If not, this returns null.
|
/// fold the result. If not, this returns null.
|
||||||
Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||||
|
@ -242,17 +242,25 @@ Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
|||||||
std::swap(Op0, Op1);
|
std::swap(Op0, Op1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
|
// X + undef -> undef
|
||||||
// X + undef -> undef
|
if (isa<UndefValue>(Op1))
|
||||||
if (isa<UndefValue>(Op1C))
|
return Op1;
|
||||||
return Op1C;
|
|
||||||
|
|
||||||
// X + 0 --> X
|
// X + 0 -> X
|
||||||
if (Op1C->isNullValue())
|
if (match(Op1, m_Zero()))
|
||||||
return Op0;
|
return Op0;
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Could pull several more out of instcombine.
|
// X + (Y - X) -> Y
|
||||||
|
// (Y - X) + X -> Y
|
||||||
|
Value *Y = 0;
|
||||||
|
if (match(Op1, m_Sub(m_Value(Y), m_Specific(Op0))) ||
|
||||||
|
match(Op0, m_Sub(m_Value(Y), m_Specific(Op1))))
|
||||||
|
return Y;
|
||||||
|
|
||||||
|
// X + ~X -> -1 since ~X = -X-1
|
||||||
|
if (match(Op0, m_Not(m_Specific(Op1))) ||
|
||||||
|
match(Op1, m_Not(m_Specific(Op0))))
|
||||||
|
return Constant::getAllOnesValue(Op0->getType());
|
||||||
|
|
||||||
// Threading Add over selects and phi nodes is pointless, so don't bother.
|
// Threading Add over selects and phi nodes is pointless, so don't bother.
|
||||||
// Threading over the select in "A + select(cond, B, C)" means evaluating
|
// Threading over the select in "A + select(cond, B, C)" means evaluating
|
||||||
@ -266,6 +274,49 @@ Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SimplifySubInst - Given operands for a Sub, see if we can
|
||||||
|
/// fold the result. If not, this returns null.
|
||||||
|
Value *llvm::SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||||
|
const TargetData *TD, const DominatorTree *) {
|
||||||
|
if (Constant *CLHS = dyn_cast<Constant>(Op0))
|
||||||
|
if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
|
||||||
|
Constant *Ops[] = { CLHS, CRHS };
|
||||||
|
return ConstantFoldInstOperands(Instruction::Sub, CLHS->getType(),
|
||||||
|
Ops, 2, TD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// X - undef -> undef
|
||||||
|
// undef - X -> undef
|
||||||
|
if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1))
|
||||||
|
return UndefValue::get(Op0->getType());
|
||||||
|
|
||||||
|
// X - 0 -> X
|
||||||
|
if (match(Op1, m_Zero()))
|
||||||
|
return Op0;
|
||||||
|
|
||||||
|
// X - X -> 0
|
||||||
|
if (Op0 == Op1)
|
||||||
|
return Constant::getNullValue(Op0->getType());
|
||||||
|
|
||||||
|
// (X + Y) - Y -> X
|
||||||
|
// (Y + X) - Y -> X
|
||||||
|
Value *X = 0;
|
||||||
|
if (match(Op0, m_Add(m_Value(X), m_Specific(Op1))) ||
|
||||||
|
match(Op0, m_Add(m_Specific(Op1), m_Value(X))))
|
||||||
|
return X;
|
||||||
|
|
||||||
|
// Threading Sub over selects and phi nodes is pointless, so don't bother.
|
||||||
|
// Threading over the select in "A - select(cond, B, C)" means evaluating
|
||||||
|
// "A-B" and "A-C" and seeing if they are equal; but they are equal if and
|
||||||
|
// only if B and C are equal. If B and C are equal then (since we assume
|
||||||
|
// that operands have already been simplified) "select(cond, B, C)" should
|
||||||
|
// have been simplified to the common value of B and C already. Analysing
|
||||||
|
// "A-B" and "A-C" thus gains nothing, but costs compile time. Similarly
|
||||||
|
// for threading over phi nodes.
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||||
/// fold the result. If not, this returns null.
|
/// fold the result. If not, this returns null.
|
||||||
static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD,
|
static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||||
@ -835,6 +886,12 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
|||||||
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
|
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
|
||||||
TD, DT);
|
TD, DT);
|
||||||
break;
|
break;
|
||||||
|
case Instruction::Sub:
|
||||||
|
Result = SimplifySubInst(I->getOperand(0), I->getOperand(1),
|
||||||
|
cast<BinaryOperator>(I)->hasNoSignedWrap(),
|
||||||
|
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
|
||||||
|
TD, DT);
|
||||||
|
break;
|
||||||
case Instruction::And:
|
case Instruction::And:
|
||||||
Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||||
break;
|
break;
|
||||||
|
@ -154,17 +154,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
|||||||
// X + X --> X << 1
|
// X + X --> X << 1
|
||||||
if (LHS == RHS)
|
if (LHS == RHS)
|
||||||
return BinaryOperator::CreateShl(LHS, ConstantInt::get(I.getType(), 1));
|
return BinaryOperator::CreateShl(LHS, ConstantInt::get(I.getType(), 1));
|
||||||
|
|
||||||
if (Instruction *RHSI = dyn_cast<Instruction>(RHS)) {
|
|
||||||
if (RHSI->getOpcode() == Instruction::Sub)
|
|
||||||
if (LHS == RHSI->getOperand(1)) // A + (B - A) --> B
|
|
||||||
return ReplaceInstUsesWith(I, RHSI->getOperand(0));
|
|
||||||
}
|
|
||||||
if (Instruction *LHSI = dyn_cast<Instruction>(LHS)) {
|
|
||||||
if (LHSI->getOpcode() == Instruction::Sub)
|
|
||||||
if (RHS == LHSI->getOperand(1)) // (B - A) + A --> B
|
|
||||||
return ReplaceInstUsesWith(I, LHSI->getOperand(0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -A + B --> B - A
|
// -A + B --> B - A
|
||||||
@ -201,11 +190,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
|||||||
if (dyn_castFoldableMul(RHS, C2) == LHS)
|
if (dyn_castFoldableMul(RHS, C2) == LHS)
|
||||||
return BinaryOperator::CreateMul(LHS, AddOne(C2));
|
return BinaryOperator::CreateMul(LHS, AddOne(C2));
|
||||||
|
|
||||||
// X + ~X --> -1 since ~X = -X-1
|
|
||||||
if (match(LHS, m_Not(m_Specific(RHS))) ||
|
|
||||||
match(RHS, m_Not(m_Specific(LHS))))
|
|
||||||
return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
|
|
||||||
|
|
||||||
// A+B --> A|B iff A and B have no bits set in common.
|
// A+B --> A|B iff A and B have no bits set in common.
|
||||||
if (const IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
|
if (const IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
|
||||||
APInt Mask = APInt::getAllOnesValue(IT->getBitWidth());
|
APInt Mask = APInt::getAllOnesValue(IT->getBitWidth());
|
||||||
@ -547,8 +531,9 @@ Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS,
|
|||||||
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||||
|
|
||||||
if (Op0 == Op1) // sub X, X -> 0
|
if (Value *V = SimplifySubInst(Op0, Op1, I.hasNoSignedWrap(),
|
||||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
I.hasNoUnsignedWrap(), TD))
|
||||||
|
return ReplaceInstUsesWith(I, V);
|
||||||
|
|
||||||
if (Instruction *NV = SimplifyByFactorizing(I)) // (A*B)-(A*C) -> A*(B-C)
|
if (Instruction *NV = SimplifyByFactorizing(I)) // (A*B)-(A*C) -> A*(B-C)
|
||||||
return NV;
|
return NV;
|
||||||
@ -561,10 +546,6 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
|||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isa<UndefValue>(Op0))
|
|
||||||
return ReplaceInstUsesWith(I, Op0); // undef - X -> undef
|
|
||||||
if (isa<UndefValue>(Op1))
|
|
||||||
return ReplaceInstUsesWith(I, Op1); // X - undef -> undef
|
|
||||||
if (I.getType()->isIntegerTy(1))
|
if (I.getType()->isIntegerTy(1))
|
||||||
return BinaryOperator::CreateXor(Op0, Op1);
|
return BinaryOperator::CreateXor(Op0, Op1);
|
||||||
|
|
||||||
@ -693,12 +674,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
|
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
|
||||||
if (Op0I->getOpcode() == Instruction::Add) {
|
if (Op0I->getOpcode() == Instruction::Sub) {
|
||||||
if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
|
|
||||||
return ReplaceInstUsesWith(I, Op0I->getOperand(1));
|
|
||||||
else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
|
|
||||||
return ReplaceInstUsesWith(I, Op0I->getOperand(0));
|
|
||||||
} else if (Op0I->getOpcode() == Instruction::Sub) {
|
|
||||||
if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
|
if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
|
||||||
return BinaryOperator::CreateNeg(Op0I->getOperand(1),
|
return BinaryOperator::CreateNeg(Op0I->getOperand(1),
|
||||||
I.getName());
|
I.getName());
|
||||||
|
@ -105,7 +105,7 @@ define i32 @test4(i8* %P) {
|
|||||||
; CHECK: load i32* @G
|
; CHECK: load i32* @G
|
||||||
; CHECK: memset.p0i8.i32
|
; CHECK: memset.p0i8.i32
|
||||||
; CHECK-NOT: load
|
; CHECK-NOT: load
|
||||||
; CHECK: sub i32 %tmp, %tmp
|
; CHECK: ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
; Verify that basicaa is handling variable length memcpy, knowing it doesn't
|
; Verify that basicaa is handling variable length memcpy, knowing it doesn't
|
||||||
@ -120,7 +120,7 @@ define i32 @test5(i8* %P, i32 %Len) {
|
|||||||
; CHECK: load i32* @G
|
; CHECK: load i32* @G
|
||||||
; CHECK: memcpy.p0i8.p0i8.i32
|
; CHECK: memcpy.p0i8.p0i8.i32
|
||||||
; CHECK-NOT: load
|
; CHECK-NOT: load
|
||||||
; CHECK: sub i32 %tmp, %tmp
|
; CHECK: ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
define i8 @test6(i8* %p, i8* noalias %a) {
|
define i8 @test6(i8* %p, i8* noalias %a) {
|
||||||
|
Loading…
Reference in New Issue
Block a user