summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp45
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-fmax-safe.ll8
-rw-r--r--llvm/test/CodeGen/ARM/vminmaxnm.ll2
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
}
OpenPOWER on IntegriCloud