From: Sanjay Patel Date: Sun, 25 Mar 2018 21:16:33 +0000 (+0000) Subject: [PatternMatch] allow undef elements when matching vector FP +0.0 X-Git-Tag: android-x86-7.1-r4~3236 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=10176786777936911f1c29fbd65215164760c16e;p=android-x86%2Fexternal-llvm.git [PatternMatch] allow undef elements when matching vector FP +0.0 This continues the FP constant pattern matching improvements from: https://reviews.llvm.org/rL327627 https://reviews.llvm.org/rL327339 https://reviews.llvm.org/rL327307 Several integer constant matchers also have this ability. I'm separating matching of integer/pointer null from FP positive zero and renaming/commenting to make the functionality clearer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328461 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index fec89dc8e01..5ac5aab4a0b 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -314,6 +314,7 @@ struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; /// Match an integer or vector with all bits set. +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_AllOnes() { return cst_pred_ty(); } @@ -323,6 +324,7 @@ struct is_maxsignedvalue { }; /// Match an integer or vector with values having all bits except for the high /// bit set (0x7f...). +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_MaxSignedValue() { return cst_pred_ty(); } @@ -334,6 +336,7 @@ struct is_negative { bool isValue(const APInt &C) { return C.isNegative(); } }; /// Match an integer or vector of negative values. +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_Negative() { return cst_pred_ty(); } @@ -345,6 +348,7 @@ struct is_nonnegative { bool isValue(const APInt &C) { return C.isNonNegative(); } }; /// Match an integer or vector of nonnegative values. +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_NonNegative() { return cst_pred_ty(); } @@ -356,6 +360,7 @@ struct is_one { bool isValue(const APInt &C) { return C.isOneValue(); } }; /// Match an integer 1 or a vector with all elements equal to 1. +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_One() { return cst_pred_ty(); } @@ -364,6 +369,7 @@ struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; /// Match an integer or vector power-of-2. +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_Power2() { return cst_pred_ty(); } @@ -375,6 +381,7 @@ struct is_power2_or_zero { bool isValue(const APInt &C) { return !C || C.isPowerOf2(); } }; /// Match an integer or vector of 0 or power-of-2 values. +/// For vectors, this includes constants with undefined elements. inline cst_pred_ty m_Power2OrZero() { return cst_pred_ty(); } @@ -386,22 +393,16 @@ struct is_sign_mask { bool isValue(const APInt &C) { return C.isSignMask(); } }; /// Match an integer or vector with only the sign bit(s) set. +/// For vectors, this includes constants with undefined elements. 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(); -} - struct is_nan { bool isValue(const APFloat &C) { return C.isNaN(); } }; -// Match an arbitrary NaN constant. This includes quiet and signalling nans. +/// Match an arbitrary NaN constant. This includes quiet and signalling nans. +/// For vectors, this includes constants with undefined elements. inline cstfp_pred_ty m_NaN() { return cstfp_pred_ty(); } @@ -409,12 +410,30 @@ inline cstfp_pred_ty m_NaN() { struct is_any_zero_fp { bool isValue(const APFloat &C) { return C.isZero(); } }; - -/// Match a floating-point negative zero or positive zero +/// Match a floating-point negative zero or positive zero. +/// For vectors, this includes constants with undefined elements. inline cstfp_pred_ty m_AnyZeroFP() { return cstfp_pred_ty(); } +struct is_pos_zero_fp { + bool isValue(const APFloat &C) { return C.isPosZero(); } +}; +/// Match a floating-point positive zero. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty m_PosZeroFP() { + return cstfp_pred_ty(); +} + +struct is_neg_zero_fp { + bool isValue(const APFloat &C) { return C.isNegZero(); } +}; +/// Match a floating-point negative zero. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty m_NegZeroFP() { + return cstfp_pred_ty(); +} + /////////////////////////////////////////////////////////////////////////////// template struct bind_ty { diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 149a1967164..fb0650a5cba 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -4196,11 +4196,11 @@ static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, return C; // fadd X, -0 ==> X - if (match(Op1, m_NegZero())) + if (match(Op1, m_NegZeroFP())) return Op0; // fadd X, 0 ==> X, when we know X is not -0 - if (match(Op1, m_Zero()) && + if (match(Op1, m_PosZeroFP()) && (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) return Op0; @@ -4228,18 +4228,19 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, if (Constant *C = simplifyFPBinop(Op0, Op1)) return C; - // fsub X, 0 ==> X - if (match(Op1, m_Zero())) + // fsub X, +0 ==> X + if (match(Op1, m_PosZeroFP())) return Op0; // fsub X, -0 ==> X, when we know X is not -0 - if (match(Op1, m_NegZero()) && + if (match(Op1, m_NegZeroFP()) && (FMF.noSignedZeros() || CannotBeNegativeZero(Op0, Q.TLI))) return Op0; // fsub -0.0, (fsub -0.0, X) ==> X Value *X; - if (match(Op0, m_NegZero()) && match(Op1, m_FSub(m_NegZero(), m_Value(X)))) + if (match(Op0, m_NegZeroFP()) && + match(Op1, m_FSub(m_NegZeroFP(), m_Value(X)))) return X; // fsub 0.0, (fsub 0.0, X) ==> X if signed zeros are ignored. @@ -4358,11 +4359,11 @@ static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF, // The constant match may include undef elements in a vector, so return a full // zero constant as the result. if (FMF.noNaNs()) { - // 0 % X -> 0 - if (match(Op0, m_Zero())) + // +0 % X -> 0 + if (match(Op0, m_PosZeroFP())) return ConstantFP::getNullValue(Op0->getType()); // -0 % X -> -0 - if (match(Op0, m_NegZero())) + if (match(Op0, m_NegZeroFP())) return ConstantFP::getNegativeZero(Op0->getType()); } diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 2ec9cc11493..1a41d0cb657 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -2687,7 +2687,7 @@ bool llvm::CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI, return true; // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0. - if (match(Op, m_FAdd(m_Value(), m_Zero()))) + if (match(Op, m_FAdd(m_Value(), m_PosZeroFP()))) return true; // sitofp and uitofp turn into +0.0 for zero. diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index b37b201ff25..1f04a8b3a3a 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1700,7 +1700,7 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { // Subtraction from -0.0 is the canonical form of fneg. // fsub nsz 0, X ==> fsub nsz -0.0, X - if (I.getFastMathFlags().noSignedZeros() && match(Op0, m_Zero())) + if (I.getFastMathFlags().noSignedZeros() && match(Op0, m_PosZeroFP())) return BinaryOperator::CreateFNegFMF(Op1, &I); if (isa(Op0)) diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 16e8c4ff92c..04a85c7a3e7 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1121,8 +1121,8 @@ Value *InstCombiner::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd) return nullptr; // FCmp canonicalization ensures that (fcmp ord/uno X, X) and - // (fcmp ord/uno X, C) will be transformed to (fcmp X, 0.0). - if (match(LHS1, m_Zero()) && LHS1 == RHS1) + // (fcmp ord/uno X, C) will be transformed to (fcmp X, +0.0). + if (match(LHS1, m_PosZeroFP()) && match(RHS1, m_PosZeroFP())) // Ignore the constants because they are obviously not NANs: // (fcmp ord x, 0.0) & (fcmp ord y, 0.0) -> (fcmp ord x, y) // (fcmp uno x, 0.0) | (fcmp uno y, 0.0) -> (fcmp uno x, y) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index bdd1a58171e..f5400f978a4 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2362,7 +2362,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // Folding cmp(sub(a,b),0) -> cmp(a,b) and cmp(0,sub(a,b)) -> cmp(b,a) Value *Arg0 = II->getArgOperand(0); Value *Arg1 = II->getArgOperand(1); - bool Arg0IsZero = match(Arg0, m_Zero()); + bool Arg0IsZero = match(Arg0, m_PosZeroFP()); if (Arg0IsZero) std::swap(Arg0, Arg1); Value *A, *B; @@ -2374,7 +2374,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // The compare intrinsic uses the above assumptions and therefore // doesn't require additional flags. if ((match(Arg0, m_OneUse(m_FSub(m_Value(A), m_Value(B)))) && - match(Arg1, m_Zero()) && isa(Arg0) && + match(Arg1, m_PosZeroFP()) && isa(Arg0) && cast(Arg0)->getFastMathFlags().noInfs())) { if (Arg0IsZero) std::swap(A, B); diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 46448aa7f8d..c0876a27594 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4942,11 +4942,11 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { // If we're just checking for a NaN (ORD/UNO) and have a non-NaN operand, // then canonicalize the operand to 0.0. if (Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) { - if (!match(Op0, m_Zero()) && isKnownNeverNaN(Op0)) { + if (!match(Op0, m_PosZeroFP()) && isKnownNeverNaN(Op0)) { I.setOperand(0, ConstantFP::getNullValue(Op0->getType())); return &I; } - if (!match(Op1, m_Zero()) && isKnownNeverNaN(Op1)) { + if (!match(Op1, m_PosZeroFP()) && isKnownNeverNaN(Op1)) { I.setOperand(1, ConstantFP::getNullValue(Op0->getType())); return &I; } diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index ff682acd3fd..d6d046f0185 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1579,10 +1579,10 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { if (match(FCI->getOperand(1), m_AnyZeroFP()) && FCI->hasNoNaNs()) { // (X <= +/-0.0) ? (0.0 - X) : X --> fabs(X) // (X > +/-0.0) ? X : (0.0 - X) --> fabs(X) - if ((X == FalseVal && match(TrueVal, m_FSub(m_Zero(), m_Specific(X))) && - Pred == FCmpInst::FCMP_OLE) || - (X == TrueVal && match(FalseVal, m_FSub(m_Zero(), m_Specific(X))) && - Pred == FCmpInst::FCMP_OGT)) { + if ((X == FalseVal && Pred == FCmpInst::FCMP_OLE && + match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X)))) || + (X == TrueVal && Pred == FCmpInst::FCMP_OGT && + match(FalseVal, m_FSub(m_PosZeroFP(), m_Specific(X))))) { Value *Fabs = Builder.CreateIntrinsic(Intrinsic::fabs, { X }, FCI); return replaceInstUsesWith(SI, Fabs); } diff --git a/test/Transforms/InstCombine/X86/X86FsubCmpCombine.ll b/test/Transforms/InstCombine/X86/X86FsubCmpCombine.ll index abb2d840b7c..cd2482485ae 100644 --- a/test/Transforms/InstCombine/X86/X86FsubCmpCombine.ll +++ b/test/Transforms/InstCombine/X86/X86FsubCmpCombine.ll @@ -34,8 +34,7 @@ define i8 @sub_compare_foldingPD128(<2 x double> %a, <2 x double> %b){ define i8 @sub_compare_foldingPD128_undef_elt(<2 x double> %a, <2 x double> %b){ ; CHECK-LABEL: @sub_compare_foldingPD128_undef_elt( -; CHECK-NEXT: [[SUB_I:%.*]] = fsub ninf <2 x double> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[T0:%.*]] = call <2 x i1> @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> [[SUB_I]], <2 x double> , i32 5) +; CHECK-NEXT: [[T0:%.*]] = call <2 x i1> @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], i32 5) ; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x i1> [[T0]], <2 x i1> zeroinitializer, <8 x i32> ; CHECK-NEXT: [[T2:%.*]] = bitcast <8 x i1> [[T1]] to i8 ; CHECK-NEXT: ret i8 [[T2]] diff --git a/test/Transforms/InstCombine/fabs.ll b/test/Transforms/InstCombine/fabs.ll index cc08e561a1d..2dcdc52210a 100644 --- a/test/Transforms/InstCombine/fabs.ll +++ b/test/Transforms/InstCombine/fabs.ll @@ -279,10 +279,8 @@ define double @select_fcmp_nnan_ole_zero(double %x) { define <2 x float> @select_fcmp_nnan_ole_negzero(<2 x float> %x) { ; CHECK-LABEL: @select_fcmp_nnan_ole_negzero( -; CHECK-NEXT: [[LEZERO:%.*]] = fcmp nnan ole <2 x float> [[X:%.*]], -; CHECK-NEXT: [[NEGX:%.*]] = fsub <2 x float> , [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[LEZERO]], <2 x float> [[NEGX]], <2 x float> [[X]] -; CHECK-NEXT: ret <2 x float> [[FABS]] +; CHECK-NEXT: [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) +; CHECK-NEXT: ret <2 x float> [[TMP1]] ; %lezero = fcmp nnan ole <2 x float> %x, %negx = fsub <2 x float> , %x diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index 868208f0b1c..cd9cd29670c 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -235,7 +235,7 @@ define float @fneg2(float %x) { define <2 x float> @fneg2_vec_undef(<2 x float> %x) { ; CHECK-LABEL: @fneg2_vec_undef( -; CHECK-NEXT: [[SUB:%.*]] = fsub nsz <2 x float> , [[X:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = fsub nsz <2 x float> , [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[SUB]] ; %sub = fsub nsz <2 x float> , %x diff --git a/test/Transforms/InstCombine/fcmp-special.ll b/test/Transforms/InstCombine/fcmp-special.ll index 1966ee0339e..8d131b3c2a6 100644 --- a/test/Transforms/InstCombine/fcmp-special.ll +++ b/test/Transforms/InstCombine/fcmp-special.ll @@ -155,7 +155,7 @@ define <2 x i1> @uno_vec_with_undef(<2 x double> %x) { define <2 x i1> @ord_vec_with_undef(<2 x double> %x) { ; CHECK-LABEL: @ord_vec_with_undef( -; CHECK-NEXT: [[F:%.*]] = fcmp ord <2 x double> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[F:%.*]] = fcmp ord <2 x double> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[F]] ; %f = fcmp ord <2 x double> %x, diff --git a/test/Transforms/InstSimplify/fast-math.ll b/test/Transforms/InstSimplify/fast-math.ll index 491658a1ce7..67419048669 100644 --- a/test/Transforms/InstSimplify/fast-math.ll +++ b/test/Transforms/InstSimplify/fast-math.ll @@ -206,8 +206,7 @@ define <2 x float> @fadd_zero_nsz_vec(<2 x float> %x) { define <2 x float> @fadd_zero_nsz_vec_undef(<2 x float> %x) { ; CHECK-LABEL: @fadd_zero_nsz_vec_undef( -; CHECK-NEXT: [[R:%.*]] = fadd nsz <2 x float> [[X:%.*]], -; CHECK-NEXT: ret <2 x float> [[R]] +; CHECK-NEXT: ret <2 x float> [[X:%.*]] ; %r = fadd nsz <2 x float> %x, ret <2 x float> %r @@ -259,8 +258,7 @@ define double @frem_zero_by_x(double %x) { define <2 x double> @frem_poszero_by_x_vec_undef(<2 x double> %x) { ; CHECK-LABEL: @frem_poszero_by_x_vec_undef( -; CHECK-NEXT: [[R:%.*]] = frem nnan <2 x double> , [[X:%.*]] -; CHECK-NEXT: ret <2 x double> [[R]] +; CHECK-NEXT: ret <2 x double> zeroinitializer ; %r = frem nnan <2 x double> , %x ret <2 x double> %r diff --git a/test/Transforms/InstSimplify/floating-point-arithmetic.ll b/test/Transforms/InstSimplify/floating-point-arithmetic.ll index 4c5b5f08d2e..04e6ce1bf83 100644 --- a/test/Transforms/InstSimplify/floating-point-arithmetic.ll +++ b/test/Transforms/InstSimplify/floating-point-arithmetic.ll @@ -72,8 +72,7 @@ define float @fsub_x_0(float %x) { define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) { ; CHECK-LABEL: @fsub_x_0_vec_undef( -; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[X:%.*]], -; CHECK-NEXT: ret <2 x float> [[R]] +; CHECK-NEXT: ret <2 x float> [[X:%.*]] ; %r = fsub <2 x float> %x, ret <2 x float> %r