/// zero_initializer for vectors and ConstantPointerNull for pointers.
inline match_zero m_Zero() { return match_zero(); }
-struct match_any_zero {
- template <typename ITy> bool match(ITy *V) {
- if (const auto *C = dyn_cast<Constant>(V))
- return C->isZeroValue();
- 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 and positive zero
-inline match_any_zero m_AnyZero() { return match_any_zero(); }
-
struct apint_match {
const APInt *&Res;
return cstfp_pred_ty<is_nan>();
}
+struct is_any_zero_fp {
+ bool isValue(const APFloat &C) { return C.isZero(); }
+};
+
+/// Match a floating-point negative zero or positive zero
+inline cstfp_pred_ty<is_any_zero_fp> m_AnyZeroFP() {
+ return cstfp_pred_ty<is_any_zero_fp>();
+}
+
///////////////////////////////////////////////////////////////////////////////
template <typename Class> struct bind_ty {
// X = -0.0: ( 0.0 - (-0.0)) + (-0.0) == ( 0.0) + (-0.0) == 0.0
// X = 0.0: (-0.0 - ( 0.0)) + ( 0.0) == (-0.0) + ( 0.0) == 0.0
// X = 0.0: ( 0.0 - ( 0.0)) + ( 0.0) == ( 0.0) + ( 0.0) == 0.0
- if (FMF.noNaNs() && (match(Op0, m_FSub(m_AnyZero(), m_Specific(Op1))) ||
- match(Op1, m_FSub(m_AnyZero(), m_Specific(Op0)))))
+ if (FMF.noNaNs() && (match(Op0, m_FSub(m_AnyZeroFP(), m_Specific(Op1))) ||
+ match(Op1, m_FSub(m_AnyZeroFP(), m_Specific(Op0)))))
return ConstantFP::getNullValue(Op0->getType());
return nullptr;
return X;
// fsub 0.0, (fsub 0.0, X) ==> X if signed zeros are ignored.
- if (FMF.noSignedZeros() && match(Op0, m_AnyZero()) &&
- match(Op1, m_FSub(m_AnyZero(), m_Value(X))))
+ if (FMF.noSignedZeros() && match(Op0, m_AnyZeroFP()) &&
+ match(Op1, m_FSub(m_AnyZeroFP(), m_Value(X))))
return X;
// fsub nnan x, x ==> 0.0
return Op0;
// fmul nnan nsz X, 0 ==> 0
- if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op1, m_AnyZero()))
- return Op1;
+ if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op1, m_AnyZeroFP()))
+ return ConstantFP::getNullValue(Op0->getType());
// sqrt(X) * sqrt(X) --> X
Value *X;
// 0 / X -> 0
// Requires that NaNs are off (X could be zero) and signed zeroes are
// ignored (X could be positive or negative, so the output sign is unknown).
- if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op0, m_AnyZero()))
- return Op0;
+ if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op0, m_AnyZeroFP()))
+ return ConstantFP::getNullValue(Op0->getType());
if (FMF.noNaNs()) {
// X / X -> 1.0 is legal when NaNs are ignored.
define <2 x float> @mul_zero_nsz_nnan_vec_undef(<2 x float> %a) {
; CHECK-LABEL: @mul_zero_nsz_nnan_vec_undef(
-; CHECK-NEXT: [[B:%.*]] = fmul nnan nsz <2 x float> [[A:%.*]], <float 0.000000e+00, float undef>
-; CHECK-NEXT: ret <2 x float> [[B]]
+; CHECK-NEXT: ret <2 x float> zeroinitializer
;
%b = fmul nsz nnan <2 x float> %a, <float 0.0, float undef>
ret <2 x float> %b
define <2 x float> @fadd_fnegx_commute_vec_undef(<2 x float> %x) {
; CHECK-LABEL: @fadd_fnegx_commute_vec_undef(
-; CHECK-NEXT: [[NEGX:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = fadd nnan <2 x float> [[X]], [[NEGX]]
-; CHECK-NEXT: ret <2 x float> [[R]]
+; CHECK-NEXT: ret <2 x float> zeroinitializer
;
%negx = fsub <2 x float> <float undef, float -0.0>, %x
%r = fadd nnan <2 x float> %x, %negx
define <2 x float> @fsub_0_0_x_vec_undef1(<2 x float> %a) {
; CHECK-LABEL: @fsub_0_0_x_vec_undef1(
-; CHECK-NEXT: [[T1:%.*]] = fsub <2 x float> <float 0.000000e+00, float undef>, [[A:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = fsub nsz <2 x float> zeroinitializer, [[T1]]
-; CHECK-NEXT: ret <2 x float> [[RET]]
+; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> <float 0.0, float undef>, %a
%ret = fsub nsz <2 x float> zeroinitializer, %t1
define <2 x float> @fsub_0_0_x_vec_undef2(<2 x float> %a) {
; CHECK-LABEL: @fsub_0_0_x_vec_undef2(
-; CHECK-NEXT: [[T1:%.*]] = fsub <2 x float> zeroinitializer, [[A:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = fsub nsz <2 x float> <float undef, float -0.000000e+00>, [[T1]]
-; CHECK-NEXT: ret <2 x float> [[RET]]
+; CHECK-NEXT: ret <2 x float> [[A:%.*]]
;
%t1 = fsub <2 x float> zeroinitializer, %a
%ret = fsub nsz <2 x float> <float undef, float -0.0>, %t1
define <2 x double> @fdiv_zero_by_x_vec_undef(<2 x double> %x) {
; CHECK-LABEL: @fdiv_zero_by_x_vec_undef(
-; CHECK-NEXT: [[R:%.*]] = fdiv nnan nsz <2 x double> <double 0.000000e+00, double undef>, [[X:%.*]]
-; CHECK-NEXT: ret <2 x double> [[R]]
+; CHECK-NEXT: ret <2 x double> zeroinitializer
;
%r = fdiv nnan nsz <2 x double> <double 0.0, double undef>, %x
ret <2 x double> %r