From 52b8adef731b02f76f042e0b21aa08fa40a878a7 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 3 Feb 2017 00:51:50 +0000 Subject: [PATCH] AMDGPU: Fold fneg into fmin/fmax_legacy git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293972 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 26 +++++++++- .../CodeGen/AMDGPU/fmin_fmax_legacy.amdgcn.ll | 47 +++++++++++++++++++ test/CodeGen/AMDGPU/fneg-combines.ll | 32 +++++++++++++ 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/AMDGPU/fmin_fmax_legacy.amdgcn.ll diff --git a/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index b8d41008ee9..d9b0b500945 100644 --- a/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -504,6 +504,8 @@ static bool fnegFoldsIntoOp(unsigned Opc) { case AMDGPUISD::RCP_LEGACY: case AMDGPUISD::SIN_HW: case AMDGPUISD::FMUL_LEGACY: + case AMDGPUISD::FMIN_LEGACY: + case AMDGPUISD::FMAX_LEGACY: return true; default: return false; @@ -2904,6 +2906,21 @@ static bool isConstantFPZero(SDValue N) { return false; } +static unsigned inverseMinMax(unsigned Opc) { + switch (Opc) { + case ISD::FMAXNUM: + return ISD::FMINNUM; + case ISD::FMINNUM: + return ISD::FMAXNUM; + case AMDGPUISD::FMAX_LEGACY: + return AMDGPUISD::FMIN_LEGACY; + case AMDGPUISD::FMIN_LEGACY: + return AMDGPUISD::FMAX_LEGACY; + default: + llvm_unreachable("invalid min/max opcode"); + } +} + SDValue AMDGPUTargetLowering::performFNegCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -2999,9 +3016,14 @@ SDValue AMDGPUTargetLowering::performFNegCombine(SDNode *N, return Res; } case ISD::FMAXNUM: - case ISD::FMINNUM: { + case ISD::FMINNUM: + case AMDGPUISD::FMAX_LEGACY: + case AMDGPUISD::FMIN_LEGACY: { // fneg (fmaxnum x, y) -> fminnum (fneg x), (fneg y) // fneg (fminnum x, y) -> fmaxnum (fneg x), (fneg y) + // fneg (fmax_legacy x, y) -> fmin_legacy (fneg x), (fneg y) + // fneg (fmin_legacy x, y) -> fmax_legacy (fneg x), (fneg y) + SDValue LHS = N0.getOperand(0); SDValue RHS = N0.getOperand(1); @@ -3013,7 +3035,7 @@ SDValue AMDGPUTargetLowering::performFNegCombine(SDNode *N, SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, VT, LHS); SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS); - unsigned Opposite = (Opc == ISD::FMAXNUM) ? ISD::FMINNUM : ISD::FMAXNUM; + unsigned Opposite = inverseMinMax(Opc); SDValue Res = DAG.getNode(Opposite, SL, VT, NegLHS, NegRHS, N0->getFlags()); if (!N0.hasOneUse()) diff --git a/test/CodeGen/AMDGPU/fmin_fmax_legacy.amdgcn.ll b/test/CodeGen/AMDGPU/fmin_fmax_legacy.amdgcn.ll new file mode 100644 index 00000000000..fdfe533b3d0 --- /dev/null +++ b/test/CodeGen/AMDGPU/fmin_fmax_legacy.amdgcn.ll @@ -0,0 +1,47 @@ +; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN-SAFE -check-prefix=GCN %s +; RUN: llc -enable-no-nans-fp-math -enable-unsafe-fp-math -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN-NONAN -check-prefix=GCN %s + +; FIXME: Should replace unsafe-fp-math with no signed zeros. + +; GCN-LABEL: {{^}}min_fneg_select_regression_0: +; GCN-SAFE: v_max_legacy_f32_e64 [[MIN:v[0-9]+]], -1.0, -v0 +; GCN-NONAN: v_max_f32_e64 v{{[0-9]+}}, -v0, -1.0 +define amdgpu_ps float @min_fneg_select_regression_0(float %a, float %b) #0 { + %fneg.a = fsub float -0.0, %a + %cmp.a = fcmp ult float %a, 1.0 + %min.a = select i1 %cmp.a, float %fneg.a, float -1.0 + ret float %min.a +} + +; GCN-LABEL: {{^}}min_fneg_select_regression_posk_0: +; GCN-SAFE: v_max_legacy_f32_e64 [[MIN:v[0-9]+]], 1.0, -v0 +; GCN-NONAN: v_max_f32_e64 v{{[0-9]+}}, -v0, 1.0 +define amdgpu_ps float @min_fneg_select_regression_posk_0(float %a, float %b) #0 { + %fneg.a = fsub float -0.0, %a + %cmp.a = fcmp ult float %a, -1.0 + %min.a = select i1 %cmp.a, float %fneg.a, float 1.0 + ret float %min.a +} + +; GCN-LABEL: {{^}}max_fneg_select_regression_0: +; GCN-SAFE: v_min_legacy_f32_e64 [[MIN:v[0-9]+]], -1.0, -v0 +; GCN-NONAN: v_min_f32_e64 [[MIN:v[0-9]+]], -v0, -1.0 +define amdgpu_ps float @max_fneg_select_regression_0(float %a, float %b) #0 { + %fneg.a = fsub float -0.0, %a + %cmp.a = fcmp ugt float %a, 1.0 + %min.a = select i1 %cmp.a, float %fneg.a, float -1.0 + ret float %min.a +} + +; GCN-LABEL: {{^}}max_fneg_select_regression_posk_0: +; GCN-SAFE: v_min_legacy_f32_e64 [[MIN:v[0-9]+]], 1.0, -v0 +; GCN-NONAN: v_min_f32_e64 [[MIN:v[0-9]+]], -v0, 1.0 +define amdgpu_ps float @max_fneg_select_regression_posk_0(float %a, float %b) #0 { + %fneg.a = fsub float -0.0, %a + %cmp.a = fcmp ugt float %a, -1.0 + %min.a = select i1 %cmp.a, float %fneg.a, float 1.0 + ret float %min.a +} + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } diff --git a/test/CodeGen/AMDGPU/fneg-combines.ll b/test/CodeGen/AMDGPU/fneg-combines.ll index 33068100a2d..41f31de18e6 100644 --- a/test/CodeGen/AMDGPU/fneg-combines.ll +++ b/test/CodeGen/AMDGPU/fneg-combines.ll @@ -472,6 +472,22 @@ define void @v_fneg_0_minnum_f32(float addrspace(1)* %out, float addrspace(1)* % ret void } +; GCN-LABEL: {{^}}v_fneg_neg0_minnum_f32: +; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] +; GCN: v_max_f32_e64 [[RESULT:v[0-9]+]], -[[A]], 0 +; GCN: buffer_store_dword [[RESULT]] +define void @v_fneg_neg0_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 { + %tid = call i32 @llvm.amdgcn.workitem.id.x() + %tid.ext = sext i32 %tid to i64 + %a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext + %out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext + %a = load volatile float, float addrspace(1)* %a.gep + %min = call float @llvm.minnum.f32(float -0.0, float %a) + %fneg = fsub float -0.000000e+00, %min + store float %fneg, float addrspace(1)* %out.gep + ret void +} + ; GCN-LABEL: {{^}}v_fneg_0_minnum_foldable_use_f32: ; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] ; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]] @@ -603,6 +619,22 @@ define void @v_fneg_0_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* % ret void } +; GCN-LABEL: {{^}}v_fneg_neg0_maxnum_f32: +; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] +; GCN: v_min_f32_e64 [[RESULT:v[0-9]+]], -[[A]], 0 +; GCN: buffer_store_dword [[RESULT]] +define void @v_fneg_neg0_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 { + %tid = call i32 @llvm.amdgcn.workitem.id.x() + %tid.ext = sext i32 %tid to i64 + %a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext + %out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext + %a = load volatile float, float addrspace(1)* %a.gep + %max = call float @llvm.maxnum.f32(float -0.0, float %a) + %fneg = fsub float -0.000000e+00, %max + store float %fneg, float addrspace(1)* %out.gep + ret void +} + ; GCN-LABEL: {{^}}v_fneg_0_maxnum_foldable_use_f32: ; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] ; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]] -- 2.50.1