/// zero_initializer for vectors and ConstantPointerNull for pointers.
inline match_zero m_Zero() { return match_zero(); }
-struct match_neg_zero {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<Constant>(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 <typename ITy> bool match(ITy *V) {
if (const auto *C = dyn_cast<Constant>(V))
return constantint_match<Val>();
}
-/// 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 <typename Predicate> struct cst_pred_ty : public Predicate {
template <typename ITy> bool match(ITy *V) {
if (const auto *CI = dyn_cast<ConstantInt>(V))
}
};
+/// 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 <typename Predicate> struct cstfp_pred_ty : public Predicate {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CF = dyn_cast<ConstantFP>(V))
+ return this->isValue(CF->getValueAPF());
+ if (V->getType()->isVectorTy()) {
+ if (const auto *C = dyn_cast<Constant>(V)) {
+ if (const auto *CF = dyn_cast_or_null<ConstantFP>(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<UndefValue>(Elt))
+ continue;
+ auto *CF = dyn_cast<ConstantFP>(Elt);
+ if (!CF || !this->isValue(CF->getValueAPF()))
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
///////////////////////////////////////////////////////////////////////////////
//
// Encapsulate constant value queries for use in templated predicate matchers.
return cst_pred_ty<is_sign_mask>();
}
+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<is_neg_zero> m_NegZero() {
+ return cstfp_pred_ty<is_neg_zero>();
+}
+
///////////////////////////////////////////////////////////////////////////////
template <typename Class> struct bind_ty {
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:%.*]], <float undef, float -0.000000e+00>
-; CHECK-NEXT: ret <2 x float> [[R]]
+; CHECK-NEXT: ret <2 x float> [[X:%.*]]
;
%r = fsub nsz <2 x float> %x, <float undef, float -0.0>
ret <2 x float> %r
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> <float undef, float -0.000000e+00>, [[A:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = fsub <2 x float> <float -0.000000e+00, float undef>, [[T1]]
-; CHECK-NEXT: ret <2 x float> [[RET]]
+; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> <float undef, float -0.0>, %a
%ret = fsub <2 x float> <float -0.0, float undef>, %t1
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:%.*]], <float -0.000000e+00, float undef>
-; CHECK-NEXT: ret <2 x float> [[RET]]
+; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%ret = fadd <2 x float> %a, <float -0.0, float undef>
ret <2 x float> %ret