From a0d8d127c6c1756d78c7528699c630427b184d41 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 12 Mar 2018 18:17:01 +0000 Subject: [PATCH] [PatternMatch, InstSimplify] allow undef elements when matching vector -0.0 This is the FP equivalent of D42818. Use it for the few cases in InstSimplify with -0.0 folds (that's the only current use of m_NegZero()). Differential Revision: https://reviews.llvm.org/D43792 llvm-svn: 327307 --- llvm/include/llvm/IR/PatternMatch.h | 59 ++++++++++++++++------ .../InstSimplify/floating-point-arithmetic.ll | 10 ++-- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 0023988..6bfd8cf 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -144,20 +144,6 @@ struct match_zero { /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } -struct match_neg_zero { - template bool match(ITy *V) { - if (const auto *C = dyn_cast(V)) - return C->isNegativeZeroValue(); - return false; - } -}; - -/// Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. For -/// floating point constants, this will match negative zero but not positive -/// zero -inline match_neg_zero m_NegZero() { return match_neg_zero(); } - struct match_any_zero { template bool match(ITy *V) { if (const auto *C = dyn_cast(V)) @@ -250,8 +236,9 @@ template inline constantint_match m_ConstantInt() { return constantint_match(); } -/// This helper class is used to match scalar and vector constants that satisfy -/// a specified predicate. For vector constants, undefined elements are ignored. +/// This helper class is used to match scalar and vector integer constants that +/// satisfy a specified predicate. +/// For vector constants, undefined elements are ignored. template struct cst_pred_ty : public Predicate { template bool match(ITy *V) { if (const auto *CI = dyn_cast(V)) @@ -306,6 +293,38 @@ template struct api_pred_ty : public Predicate { } }; +/// This helper class is used to match scalar and vector floating-point +/// constants that satisfy a specified predicate. +/// For vector constants, undefined elements are ignored. +template struct cstfp_pred_ty : public Predicate { + template bool match(ITy *V) { + if (const auto *CF = dyn_cast(V)) + return this->isValue(CF->getValueAPF()); + if (V->getType()->isVectorTy()) { + if (const auto *C = dyn_cast(V)) { + if (const auto *CF = dyn_cast_or_null(C->getSplatValue())) + return this->isValue(CF->getValueAPF()); + + // Non-splat vector constant: check each element for a match. + unsigned NumElts = V->getType()->getVectorNumElements(); + assert(NumElts != 0 && "Constant vector with no elements?"); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = C->getAggregateElement(i); + if (!Elt) + return false; + if (isa(Elt)) + continue; + auto *CF = dyn_cast(Elt); + if (!CF || !this->isValue(CF->getValueAPF())) + return false; + } + return true; + } + } + return false; + } +}; + /////////////////////////////////////////////////////////////////////////////// // // Encapsulate constant value queries for use in templated predicate matchers. @@ -395,6 +414,14 @@ inline cst_pred_ty m_SignMask() { return cst_pred_ty(); } +struct is_neg_zero { + bool isValue(const APFloat &C) { return C.isNegZero(); } +}; +/// Match an FP or FP vector with all -0.0 values. +inline cstfp_pred_ty m_NegZero() { + return cstfp_pred_ty(); +} + /////////////////////////////////////////////////////////////////////////////// template struct bind_ty { diff --git a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll index fc36493..94179a6 100644 --- a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll +++ b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll @@ -3,8 +3,7 @@ define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) { ; CHECK-LABEL: @fsub_negzero_vec_undef_elts( -; CHECK-NEXT: [[R:%.*]] = fsub nsz <2 x float> [[X:%.*]], -; CHECK-NEXT: ret <2 x float> [[R]] +; CHECK-NEXT: ret <2 x float> [[X:%.*]] ; %r = fsub nsz <2 x float> %x, ret <2 x float> %r @@ -31,9 +30,7 @@ define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) { define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) { ; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts( -; CHECK-NEXT: [[T1:%.*]] = fsub <2 x float> , [[A:%.*]] -; CHECK-NEXT: [[RET:%.*]] = fsub <2 x float> , [[T1]] -; CHECK-NEXT: ret <2 x float> [[RET]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %t1 = fsub <2 x float> , %a %ret = fsub <2 x float> , %t1 @@ -84,8 +81,7 @@ define float @fadd_x_n0(float %a) { define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) { ; CHECK-LABEL: @fadd_x_n0_vec_undef_elt( -; CHECK-NEXT: [[RET:%.*]] = fadd <2 x float> [[A:%.*]], -; CHECK-NEXT: ret <2 x float> [[RET]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %ret = fadd <2 x float> %a, ret <2 x float> %ret -- 2.7.4