diff options
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 45 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/arm64-fmax-safe.ll | 8 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/vminmaxnm.ll | 2 |
3 files changed, 38 insertions, 17 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 12f22f301fc..4d12df87137 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2297,24 +2297,45 @@ void SelectionDAGBuilder::visitSelect(const User &I) { // Min/max matching is only viable if all output VTs are the same. if (std::equal(ValueVTs.begin(), ValueVTs.end(), ValueVTs.begin())) { - Value *LHS, *RHS; - SelectPatternFlavor SPF = - matchSelectPattern(const_cast<User*>(&I), LHS, RHS).Flavor; - ISD::NodeType Opc = ISD::DELETED_NODE; - switch (SPF) { - case SPF_UMAX: Opc = ISD::UMAX; break; - case SPF_UMIN: Opc = ISD::UMIN; break; - case SPF_SMAX: Opc = ISD::SMAX; break; - case SPF_SMIN: Opc = ISD::SMIN; break; - default: break; - } - EVT VT = ValueVTs[0]; LLVMContext &Ctx = *DAG.getContext(); auto &TLI = DAG.getTargetLoweringInfo(); while (TLI.getTypeAction(Ctx, VT) == TargetLoweringBase::TypeSplitVector) VT = TLI.getTypeToTransformTo(Ctx, VT); + Value *LHS, *RHS; + auto SPR = matchSelectPattern(const_cast<User*>(&I), LHS, RHS); + ISD::NodeType Opc = ISD::DELETED_NODE; + switch (SPR.Flavor) { + case SPF_UMAX: Opc = ISD::UMAX; break; + case SPF_UMIN: Opc = ISD::UMIN; break; + case SPF_SMAX: Opc = ISD::SMAX; break; + case SPF_SMIN: Opc = ISD::SMIN; break; + case SPF_FMINNUM: + switch (SPR.NaNBehavior) { + case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?"); + case SPNB_RETURNS_NAN: Opc = ISD::FMINNAN; break; + case SPNB_RETURNS_OTHER: Opc = ISD::FMINNUM; break; + case SPNB_RETURNS_ANY: + Opc = TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT) ? ISD::FMINNUM + : ISD::FMINNAN; + break; + } + break; + case SPF_FMAXNUM: + switch (SPR.NaNBehavior) { + case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?"); + case SPNB_RETURNS_NAN: Opc = ISD::FMAXNAN; break; + case SPNB_RETURNS_OTHER: Opc = ISD::FMAXNUM; break; + case SPNB_RETURNS_ANY: + Opc = TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT) ? ISD::FMAXNUM + : ISD::FMAXNAN; + break; + } + break; + default: break; + } + if (Opc != ISD::DELETED_NODE && TLI.isOperationLegalOrCustom(Opc, VT) && // If the underlying comparison instruction is used by any other instruction, // the consumed instructions won't be destroyed, so it is not profitable diff --git a/llvm/test/CodeGen/AArch64/arm64-fmax-safe.ll b/llvm/test/CodeGen/AArch64/arm64-fmax-safe.ll index e83f0251f3a..8b7d66986e7 100644 --- a/llvm/test/CodeGen/AArch64/arm64-fmax-safe.ll +++ b/llvm/test/CodeGen/AArch64/arm64-fmax-safe.ll @@ -7,7 +7,7 @@ define double @test_direct(float %in) { %longer = fpext float %val to double ret double %longer -; CHECK: fmax +; CHECK: fmax s } define double @test_cross(float %in) { @@ -17,11 +17,11 @@ define double @test_cross(float %in) { %longer = fpext float %val to double ret double %longer -; CHECK: fmin +; CHECK: fmin s } ; Same as previous, but with ordered comparison; -; can't be converted in safe-math mode. +; must become fminnm, not fmin. define double @test_cross_fail_nan(float %in) { ; CHECK-LABEL: test_cross_fail_nan: %cmp = fcmp olt float %in, 0.000000e+00 @@ -29,7 +29,7 @@ define double @test_cross_fail_nan(float %in) { %longer = fpext float %val to double ret double %longer -; CHECK: fcsel s0, s0, s1, mi +; CHECK: fminnm s } ; This isn't a min or a max, but passes the first condition for swapping the diff --git a/llvm/test/CodeGen/ARM/vminmaxnm.ll b/llvm/test/CodeGen/ARM/vminmaxnm.ll index 2c74d9d078e..a6803fc78d8 100644 --- a/llvm/test/CodeGen/ARM/vminmaxnm.ll +++ b/llvm/test/CodeGen/ARM/vminmaxnm.ll @@ -343,7 +343,7 @@ define float @fp-armv8_vminmaxnm_neg0(float %a) { ; CHECK: vmaxnm.f32 %cmp1 = fcmp fast olt float %a, -0. %cond1 = select i1 %cmp1, float %a, float -0. - %cmp2 = fcmp fast ogt float %cond1, -0. + %cmp2 = fcmp fast ugt float %cond1, -0. %cond2 = select i1 %cmp2, float %cond1, float -0. ret float %cond2 } |