mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[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
This commit is contained in:
parent
9ea3b6fb1d
commit
b840189aad
@ -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 <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))
|
||||
@ -250,8 +236,9 @@ template <int64_t Val> inline constantint_match<Val> m_ConstantInt() {
|
||||
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))
|
||||
@ -306,6 +293,38 @@ template <typename Predicate> 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 <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.
|
||||
@ -395,6 +414,14 @@ inline cst_pred_ty<is_sign_mask> m_SignMask() {
|
||||
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 {
|
||||
|
@ -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:%.*]], <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
|
||||
@ -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> <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
|
||||
@ -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:%.*]], <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
|
||||
|
Loading…
Reference in New Issue
Block a user