diff options
-rw-r--r-- | llvm/include/llvm/IR/Constant.h | 7 | ||||
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 18 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/div.ll | 9 |
4 files changed, 43 insertions, 15 deletions
diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h index b91100a0e89..3f3fa4c272c 100644 --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -53,6 +53,10 @@ public: /// Returns true if the value is one. bool isOneValue() const; + /// Return true if the value is not the one value, or, + /// for vectors, does not contain one value elements. + bool isNotOneValue() const; + /// Return true if this is the value that would be returned by /// getAllOnesValue. bool isAllOnesValue() const; @@ -64,7 +68,8 @@ public: /// Return true if the value is negative zero or null value. bool isZeroValue() const; - /// Return true if the value is not the smallest signed value. + /// Return true if the value is not the smallest signed value, or, + /// for vectors, does not contain smallest signed value elements. bool isNotMinSignedValue() const; /// Return true if the value is the smallest signed value. diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index b5df4ea8af6..7ea5cb8b167 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -150,6 +150,30 @@ bool Constant::isOneValue() const { return false; } +bool Constant::isNotOneValue() const { + // Check for 1 integers + if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) + return !CI->isOneValue(); + + // Check for FP which are bitcasted from 1 integers + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) + return !CFP->getValueAPF().bitcastToAPInt().isOneValue(); + + // Check that vectors don't contain 1 + if (this->getType()->isVectorTy()) { + unsigned NumElts = this->getType()->getVectorNumElements(); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = this->getAggregateElement(i); + if (!Elt || !Elt->isNotOneValue()) + return false; + } + return true; + } + + // It *may* contain 1, we can't tell. + return false; +} + bool Constant::isMinSignedValue() const { // Check for INT_MIN integers if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 8bc34825f8a..5b71f9d9c2e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1896,14 +1896,16 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { Builder.CreateNot(Y, Y->getName() + ".not")); // 0 - (X sdiv C) -> (X sdiv -C) provided the negation doesn't overflow. - // TODO: This could be extended to match arbitrary vector constants. - const APInt *DivC; - if (match(Op0, m_Zero()) && match(Op1, m_SDiv(m_Value(X), m_APInt(DivC))) && - !DivC->isMinSignedValue() && *DivC != 1) { - Constant *NegDivC = ConstantInt::get(I.getType(), -(*DivC)); - Instruction *BO = BinaryOperator::CreateSDiv(X, NegDivC); - BO->setIsExact(cast<BinaryOperator>(Op1)->isExact()); - return BO; + if (match(Op0, m_Zero())) { + Constant *Op11C; + if (match(Op1, m_SDiv(m_Value(X), m_Constant(Op11C))) && + !Op11C->containsUndefElement() && Op11C->isNotMinSignedValue() && + Op11C->isNotOneValue()) { + Instruction *BO = + BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(Op11C)); + BO->setIsExact(cast<BinaryOperator>(Op1)->isExact()); + return BO; + } } // 0 - (X << Y) -> (-X << Y) when X is freely negatable. diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll index 4c4308151e7..a4c6139e210 100644 --- a/llvm/test/Transforms/InstCombine/div.ll +++ b/llvm/test/Transforms/InstCombine/div.ll @@ -522,8 +522,7 @@ define <2 x i8> @sdiv_negated_dividend_constant_divisor_vec_undef(<2 x i8> %x) { define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) { ; CHECK-LABEL: @sdiv_negated_dividend_constant_divisor_vec( -; CHECK-NEXT: [[DIV1:%.*]] = sdiv <2 x i64> [[X:%.*]], <i64 3, i64 4> -; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV1]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i64> [[X:%.*]], <i64 -3, i64 -4> ; CHECK-NEXT: ret <2 x i64> [[DIV]] ; %neg = sub nsw <2 x i64> zeroinitializer, %x @@ -533,8 +532,7 @@ define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) { define <2 x i64> @sdiv_exact_negated_dividend_constant_divisor_vec(<2 x i64> %x) { ; CHECK-LABEL: @sdiv_exact_negated_dividend_constant_divisor_vec( -; CHECK-NEXT: [[DIV1:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 3, i64 4> -; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV1]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4> ; CHECK-NEXT: ret <2 x i64> [[DIV]] ; %neg = sub nsw <2 x i64> zeroinitializer, %x @@ -860,8 +858,7 @@ define i32 @test_exact_nsw_exact(i32 %x) { define <2 x i64> @test_exact_vec(<2 x i64> %x) { ; CHECK-LABEL: @test_exact_vec( -; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 3, i64 4> -; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV]] +; CHECK-NEXT: [[NEG:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4> ; CHECK-NEXT: ret <2 x i64> [[NEG]] ; %div = sdiv exact <2 x i64> %x, <i64 3, i64 4> |