From e742bb53a3e68b88eac172782fd99cd98f89f4b3 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Wed, 24 Feb 2010 22:15:53 +0000 Subject: [PATCH] Check for comparisons of +/- zero when optimizing less-than-or-equal and greater-than-or-equal SELECT_CCs to NEON vmin/vmax instructions. This is only allowed when UnsafeFPMath is set or when at least one of the operands is known to be nonzero. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97065 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 53 +++++++++++++++++------------- test/CodeGen/ARM/neon_minmax.ll | 16 +++++++++ 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index e5333edd508..525edd21cd9 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -3879,50 +3879,59 @@ static SDValue PerformSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, unsigned Opcode = 0; bool IsReversed; - if (LHS == CondLHS && RHS == CondRHS) { + if (DAG.isEqualTo(LHS, CondLHS) && DAG.isEqualTo(RHS, CondRHS)) { IsReversed = false; // x CC y ? x : y - } else if (LHS == CondRHS && RHS == CondLHS) { + } else if (DAG.isEqualTo(LHS, CondRHS) && DAG.isEqualTo(RHS, CondLHS)) { IsReversed = true ; // x CC y ? y : x } else { return SDValue(); } + bool IsUnordered; switch (CC) { default: break; case ISD::SETOLT: case ISD::SETOLE: case ISD::SETLT: case ISD::SETLE: - // This can be vmin if we can prove that the LHS is not a NaN. - // (If either operand is NaN, the comparison will be false and the result - // will be the RHS, which matches vmin if RHS is the NaN.) - if (DAG.isKnownNeverNaN(LHS)) - Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN; - break; - case ISD::SETULT: case ISD::SETULE: - // Likewise, for ULT/ULE we need to know that RHS is not a NaN. - if (DAG.isKnownNeverNaN(RHS)) - Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN; + // If LHS is NaN, an ordered comparison will be false and the result will + // be the RHS, but vmin(NaN, RHS) = NaN. Avoid this by checking that LHS + // != NaN. Likewise, for unordered comparisons, check for RHS != NaN. + IsUnordered = (CC == ISD::SETULT || CC == ISD::SETULE); + if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS)) + break; + // For less-than-or-equal comparisons, "+0 <= -0" will be true but vmin + // will return -0, so vmin can only be used for unsafe math or if one of + // the operands is known to be nonzero. + if ((CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE) && + !UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) + break; + Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN; break; case ISD::SETOGT: case ISD::SETOGE: case ISD::SETGT: case ISD::SETGE: - // This can be vmax if we can prove that the LHS is not a NaN. - // (If either operand is NaN, the comparison will be false and the result - // will be the RHS, which matches vmax if RHS is the NaN.) - if (DAG.isKnownNeverNaN(LHS)) - Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX; - break; - case ISD::SETUGT: case ISD::SETUGE: - // Likewise, for UGT/UGE we need to know that RHS is not a NaN. - if (DAG.isKnownNeverNaN(RHS)) - Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX; + // If LHS is NaN, an ordered comparison will be false and the result will + // be the RHS, but vmax(NaN, RHS) = NaN. Avoid this by checking that LHS + // != NaN. Likewise, for unordered comparisons, check for RHS != NaN. + IsUnordered = (CC == ISD::SETUGT || CC == ISD::SETUGE); + if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS)) + break; + // For greater-than-or-equal comparisons, "-0 >= +0" will be true but vmax + // will return +0, so vmax can only be used for unsafe math or if one of + // the operands is known to be nonzero. + if ((CC == ISD::SETGE || CC == ISD::SETOGE || CC == ISD::SETUGE) && + !UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) + break; + Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX; break; } diff --git a/test/CodeGen/ARM/neon_minmax.ll b/test/CodeGen/ARM/neon_minmax.ll index 64349d650e9..d301c6a4ca9 100644 --- a/test/CodeGen/ARM/neon_minmax.ll +++ b/test/CodeGen/ARM/neon_minmax.ll @@ -8,6 +8,14 @@ define float @fmin_ole(float %x) nounwind { ret float %min1 } +define float @fmin_ole_zero(float %x) nounwind { +;CHECK: fmin_ole_zero: +;CHECK-NOT: vmin.f32 + %cond = fcmp ole float 0.0, %x + %min1 = select i1 %cond, float 0.0, float %x + ret float %min1 +} + define float @fmin_ult(float %x) nounwind { ;CHECK: fmin_ult: ;CHECK: vmin.f32 @@ -32,6 +40,14 @@ define float @fmax_uge(float %x) nounwind { ret float %max1 } +define float @fmax_uge_zero(float %x) nounwind { +;CHECK: fmax_uge_zero: +;CHECK-NOT: vmax.f32 + %cond = fcmp uge float %x, 0.0 + %max1 = select i1 %cond, float %x, float 0.0 + ret float %max1 +} + define float @fmax_olt_reverse(float %x) nounwind { ;CHECK: fmax_olt_reverse: ;CHECK: vmax.f32