diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 8f9b45b3c87..4d41cb580b8 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -29,6 +29,11 @@ namespace llvm { Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, 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 /// fold the result. If not, this returns null. Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0, diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 75734e87701..2458d204bca 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -242,17 +242,25 @@ Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, std::swap(Op0, Op1); } - if (Constant *Op1C = dyn_cast(Op1)) { - // X + undef -> undef - if (isa(Op1C)) - return Op1C; + // X + undef -> undef + if (isa(Op1)) + return Op1; - // X + 0 --> X - if (Op1C->isNullValue()) - return Op0; - } + // X + 0 -> X + if (match(Op1, m_Zero())) + 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 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; } +/// 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(Op0)) + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Sub, CLHS->getType(), + Ops, 2, TD); + } + + // X - undef -> undef + // undef - X -> undef + if (isa(Op0) || isa(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 /// fold the result. If not, this returns null. static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD, @@ -835,6 +886,12 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD, cast(I)->hasNoUnsignedWrap(), TD, DT); break; + case Instruction::Sub: + Result = SimplifySubInst(I->getOperand(0), I->getOperand(1), + cast(I)->hasNoSignedWrap(), + cast(I)->hasNoUnsignedWrap(), + TD, DT); + break; case Instruction::And: Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT); break; diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 26679a21895..98d65502017 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -154,17 +154,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { // X + X --> X << 1 if (LHS == RHS) return BinaryOperator::CreateShl(LHS, ConstantInt::get(I.getType(), 1)); - - if (Instruction *RHSI = dyn_cast(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(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 @@ -201,11 +190,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (dyn_castFoldableMul(RHS, C2) == LHS) 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. if (const IntegerType *IT = dyn_cast(I.getType())) { APInt Mask = APInt::getAllOnesValue(IT->getBitWidth()); @@ -547,8 +531,9 @@ Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS, Instruction *InstCombiner::visitSub(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - if (Op0 == Op1) // sub X, X -> 0 - return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + if (Value *V = SimplifySubInst(Op0, Op1, I.hasNoSignedWrap(), + I.hasNoUnsignedWrap(), TD)) + return ReplaceInstUsesWith(I, V); if (Instruction *NV = SimplifyByFactorizing(I)) // (A*B)-(A*C) -> A*(B-C) return NV; @@ -561,10 +546,6 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return Res; } - if (isa(Op0)) - return ReplaceInstUsesWith(I, Op0); // undef - X -> undef - if (isa(Op1)) - return ReplaceInstUsesWith(I, Op1); // X - undef -> undef if (I.getType()->isIntegerTy(1)) return BinaryOperator::CreateXor(Op0, Op1); @@ -693,12 +674,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { } if (BinaryOperator *Op0I = dyn_cast(Op0)) { - if (Op0I->getOpcode() == Instruction::Add) { - 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->getOpcode() == Instruction::Sub) { if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y return BinaryOperator::CreateNeg(Op0I->getOperand(1), I.getName()); diff --git a/test/Analysis/BasicAA/modref.ll b/test/Analysis/BasicAA/modref.ll index 54d10e7b72d..ec0c8a73444 100644 --- a/test/Analysis/BasicAA/modref.ll +++ b/test/Analysis/BasicAA/modref.ll @@ -105,7 +105,7 @@ define i32 @test4(i8* %P) { ; CHECK: load i32* @G ; CHECK: memset.p0i8.i32 ; CHECK-NOT: load -; CHECK: sub i32 %tmp, %tmp +; CHECK: ret i32 0 } ; 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: memcpy.p0i8.p0i8.i32 ; CHECK-NOT: load -; CHECK: sub i32 %tmp, %tmp +; CHECK: ret i32 0 } define i8 @test6(i8* %p, i8* noalias %a) {