diff options
Diffstat (limited to 'llvm')
| -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>  | 

