From 919564baf2e10e5499430e87a993a5defdf0befd Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Mon, 1 Jul 2019 11:00:23 +0000 Subject: [PATCH] [SelectionDAG] Do minnum->minimum at legalization time instead of building time The SDAGBuilder behavior stems from the days when we didn't have fast math flags available in SDAG. We do now and doing the transformation in the legalizer has the advantage that it also works for vector types. llvm-svn: 364743 --- .../SelectionDAG/SelectionDAGBuilder.cpp | 22 +++++-------------- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 11 ++++++++++ test/CodeGen/WebAssembly/f32.ll | 18 +++++++++++++++ test/CodeGen/WebAssembly/simd-arith.ll | 22 +++++++++++++++++++ 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 8a04d6244bd..cdea8488ccb 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6016,28 +6016,18 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, getValue(I.getArgOperand(0)))); return; } - case Intrinsic::minnum: { - auto VT = getValue(I.getArgOperand(0)).getValueType(); - unsigned Opc = - I.hasNoNaNs() && TLI.isOperationLegalOrCustom(ISD::FMINIMUM, VT) - ? ISD::FMINIMUM - : ISD::FMINNUM; - setValue(&I, DAG.getNode(Opc, sdl, VT, + case Intrinsic::minnum: + setValue(&I, DAG.getNode(ISD::FMINNUM, sdl, + getValue(I.getArgOperand(0)).getValueType(), getValue(I.getArgOperand(0)), getValue(I.getArgOperand(1)))); return; - } - case Intrinsic::maxnum: { - auto VT = getValue(I.getArgOperand(0)).getValueType(); - unsigned Opc = - I.hasNoNaNs() && TLI.isOperationLegalOrCustom(ISD::FMAXIMUM, VT) - ? ISD::FMAXIMUM - : ISD::FMAXNUM; - setValue(&I, DAG.getNode(Opc, sdl, VT, + case Intrinsic::maxnum: + setValue(&I, DAG.getNode(ISD::FMAXNUM, sdl, + getValue(I.getArgOperand(0)).getValueType(), getValue(I.getArgOperand(0)), getValue(I.getArgOperand(1)))); return; - } case Intrinsic::minimum: setValue(&I, DAG.getNode(ISD::FMINIMUM, sdl, getValue(I.getArgOperand(0)).getValueType(), diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 33050621348..772ffca1e50 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5098,6 +5098,17 @@ SDValue TargetLowering::expandFMINNUM_FMAXNUM(SDNode *Node, return DAG.getNode(NewOp, dl, VT, Quiet0, Quiet1, Node->getFlags()); } + // If the target has FMINIMUM/FMAXIMUM but not FMINNUM/FMAXNUM use that + // instead if there are no NaNs. + if (Node->getFlags().hasNoNaNs()) { + unsigned IEEE2018Op = + Node->getOpcode() == ISD::FMINNUM ? ISD::FMINIMUM : ISD::FMAXIMUM; + if (isOperationLegalOrCustom(IEEE2018Op, VT)) { + return DAG.getNode(IEEE2018Op, dl, VT, Node->getOperand(0), + Node->getOperand(1), Node->getFlags()); + } + } + return SDValue(); } diff --git a/test/CodeGen/WebAssembly/f32.ll b/test/CodeGen/WebAssembly/f32.ll index 5208335b278..7f74ddde82e 100644 --- a/test/CodeGen/WebAssembly/f32.ll +++ b/test/CodeGen/WebAssembly/f32.ll @@ -149,6 +149,15 @@ define float @fmin32_intrinsic(float %x, float %y) { ret float %a } +; CHECK-LABEL: fminnum32_intrinsic: +; CHECK: f32.min $push0=, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}} +; CHECK-NEXT: return $pop0{{$}} +declare float @llvm.minnum.f32(float, float) +define float @fminnum32_intrinsic(float %x, float %y) { + %a = call nnan float @llvm.minnum.f32(float %x, float %y) + ret float %a +} + ; CHECK-LABEL: fmax32_intrinsic: ; CHECK: f32.max $push0=, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}} ; CHECK-NEXT: return $pop0{{$}} @@ -158,6 +167,15 @@ define float @fmax32_intrinsic(float %x, float %y) { ret float %a } +; CHECK-LABEL: fmaxnum32_intrinsic: +; CHECK: f32.max $push0=, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}} +; CHECK-NEXT: return $pop0{{$}} +declare float @llvm.maxnum.f32(float, float) +define float @fmaxnum32_intrinsic(float %x, float %y) { + %a = call nnan float @llvm.maxnum.f32(float %x, float %y) + ret float %a +} + ; CHECK-LABEL: fma32: ; CHECK: {{^}} f32.call $push[[LR:[0-9]+]]=, fmaf, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}} ; CHECK-NEXT: return $pop[[LR]]{{$}} diff --git a/test/CodeGen/WebAssembly/simd-arith.ll b/test/CodeGen/WebAssembly/simd-arith.ll index bd5479a0f35..410b2e6f5ab 100644 --- a/test/CodeGen/WebAssembly/simd-arith.ll +++ b/test/CodeGen/WebAssembly/simd-arith.ll @@ -1073,6 +1073,17 @@ define <4 x float> @min_intrinsic_v4f32(<4 x float> %x, <4 x float> %y) { ret <4 x float> %a } +; CHECK-LABEL: minnum_intrinsic_v4f32: +; NO-SIMD128-NOT: f32x4 +; SIMD128-NEXT: .functype minnum_intrinsic_v4f32 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: f32x4.min $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>) +define <4 x float> @minnum_intrinsic_v4f32(<4 x float> %x, <4 x float> %y) { + %a = call nnan <4 x float> @llvm.minnum.v4f32(<4 x float> %x, <4 x float> %y) + ret <4 x float> %a +} + ; CHECK-LABEL: max_intrinsic_v4f32: ; NO-SIMD128-NOT: f32x4 ; SIMD128-NEXT: .functype max_intrinsic_v4f32 (v128, v128) -> (v128){{$}} @@ -1084,6 +1095,17 @@ define <4 x float> @max_intrinsic_v4f32(<4 x float> %x, <4 x float> %y) { ret <4 x float> %a } +; CHECK-LABEL: maxnum_intrinsic_v4f32: +; NO-SIMD128-NOT: f32x4 +; SIMD128-NEXT: .functype maxnum_intrinsic_v4f32 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: f32x4.max $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) +define <4 x float> @maxnum_intrinsic_v4f32(<4 x float> %x, <4 x float> %y) { + %a = call nnan <4 x float> @llvm.maxnum.v4f32(<4 x float> %x, <4 x float> %y) + ret <4 x float> %a +} + ; CHECK-LABEL: min_const_intrinsic_v4f32: ; NO-SIMD128-NOT: f32x4 ; SIMD128-NEXT: .functype min_const_intrinsic_v4f32 () -> (v128){{$}}