From a628c38932ed84839abc1ae870512295012c3ed3 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 10 Jul 2019 16:31:15 +0000 Subject: [PATCH] GlobalISel: Define the full family of FP min/max instructions git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365657 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/TargetOpcodes.def | 12 +++ include/llvm/Target/GenericOpcodes.td | 56 ++++++++++++ lib/CodeGen/GlobalISel/IRTranslator.cpp | 8 ++ .../irtranslator-fp-min-max-intrinsics.ll | 88 +++++++++++++++++++ .../GlobalISel/legalizer-info-validation.mir | 18 ++++ 5 files changed, 182 insertions(+) create mode 100644 test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll diff --git a/include/llvm/Support/TargetOpcodes.def b/include/llvm/Support/TargetOpcodes.def index fa024638561..598c1064efd 100644 --- a/include/llvm/Support/TargetOpcodes.def +++ b/include/llvm/Support/TargetOpcodes.def @@ -493,6 +493,18 @@ HANDLE_TARGET_OPCODE(G_FCOPYSIGN) /// Generic FP canonicalize value. HANDLE_TARGET_OPCODE(G_FCANONICALIZE) +/// FP min/max matching libm's fmin/fmax +HANDLE_TARGET_OPCODE(G_FMINNUM) +HANDLE_TARGET_OPCODE(G_FMAXNUM) + +/// FP min/max matching IEEE-754 2008's minnum/maxnum semantics. +HANDLE_TARGET_OPCODE(G_FMINNUM_IEEE) +HANDLE_TARGET_OPCODE(G_FMAXNUM_IEEE) + +/// FP min/max matching IEEE-754 2018 draft semantics. +HANDLE_TARGET_OPCODE(G_FMINIMUM) +HANDLE_TARGET_OPCODE(G_FMAXIMUM) + /// Generic pointer offset HANDLE_TARGET_OPCODE(G_GEP) diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index 11fbf621154..45718327b4a 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -505,6 +505,62 @@ def G_FCANONICALIZE : GenericInstruction { let hasSideEffects = 0; } +// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two +// values. +// +// In the case where a single input is a NaN (either signaling or quiet), +// the non-NaN input is returned. +// +// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. +def G_FMINNUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +def G_FMAXNUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on +// two values, following the IEEE-754 2008 definition. This differs from +// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a +// signaling NaN, returns a quiet NaN. +def G_FMINNUM_IEEE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +def G_FMAXNUM_IEEE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 +// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 +// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. +def G_FMINIMUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +def G_FMAXIMUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + //------------------------------------------------------------------------------ // Floating Point Binary ops. //------------------------------------------------------------------------------ diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index 96efcf7a373..6e99bdbd826 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1222,6 +1222,14 @@ unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) { return TargetOpcode::G_FABS; case Intrinsic::copysign: return TargetOpcode::G_FCOPYSIGN; + case Intrinsic::minnum: + return TargetOpcode::G_FMINNUM; + case Intrinsic::maxnum: + return TargetOpcode::G_FMAXNUM; + case Intrinsic::minimum: + return TargetOpcode::G_FMINIMUM; + case Intrinsic::maximum: + return TargetOpcode::G_FMAXIMUM; case Intrinsic::canonicalize: return TargetOpcode::G_FCANONICALIZE; case Intrinsic::floor: diff --git a/test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll b/test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll new file mode 100644 index 00000000000..ff92d4c43fa --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll @@ -0,0 +1,88 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -mtriple=aarch64-- -verify-machineinstrs -global-isel -stop-after=irtranslator -o - %s | FileCheck %s + +define float @test_minnum(float %x, float %y) { + ; CHECK-LABEL: name: test_minnum + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $s0, $s1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $s0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $s1 + ; CHECK: [[FMINNUM:%[0-9]+]]:_(s32) = G_FMINNUM [[COPY]], [[COPY1]] + ; CHECK: $s0 = COPY [[FMINNUM]](s32) + ; CHECK: RET_ReallyLR implicit $s0 + %val = call float @llvm.minnum.f32(float %x, float %y) + ret float %val +} + +define float @test_minnum_nnan(float %x, float %y) { + ; CHECK-LABEL: name: test_minnum_nnan + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $s0, $s1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $s0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $s1 + ; CHECK: %2:_(s32) = nnan G_FMINNUM [[COPY]], [[COPY1]] + ; CHECK: $s0 = COPY %2(s32) + ; CHECK: RET_ReallyLR implicit $s0 + %val = call nnan float @llvm.minnum.f32(float %x, float %y) + ret float %val +} + +define float @test_maxnum(float %x, float %y) { + ; CHECK-LABEL: name: test_maxnum + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $s0, $s1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $s0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $s1 + ; CHECK: [[FMAXNUM:%[0-9]+]]:_(s32) = G_FMAXNUM [[COPY]], [[COPY1]] + ; CHECK: $s0 = COPY [[FMAXNUM]](s32) + ; CHECK: RET_ReallyLR implicit $s0 + %val = call float @llvm.maxnum.f32(float %x, float %y) + ret float %val +} + +define float @test_minimum(float %x, float %y) { + ; CHECK-LABEL: name: test_minimum + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $s0, $s1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $s0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $s1 + ; CHECK: [[FMINIMUM:%[0-9]+]]:_(s32) = G_FMINIMUM [[COPY]], [[COPY1]] + ; CHECK: $s0 = COPY [[FMINIMUM]](s32) + ; CHECK: RET_ReallyLR implicit $s0 + %val = call float @llvm.minimum.f32(float %x, float %y) + ret float %val +} + +define float @test_minimum_nnan(float %x, float %y) { + ; CHECK-LABEL: name: test_minimum_nnan + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $s0, $s1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $s0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $s1 + ; CHECK: %2:_(s32) = nnan G_FMINIMUM [[COPY]], [[COPY1]] + ; CHECK: $s0 = COPY %2(s32) + ; CHECK: RET_ReallyLR implicit $s0 + %val = call nnan float @llvm.minimum.f32(float %x, float %y) + ret float %val +} + +define float @test_maximum(float %x, float %y) { + ; CHECK-LABEL: name: test_maximum + ; CHECK: bb.1 (%ir-block.0): + ; CHECK: liveins: $s0, $s1 + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $s0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY $s1 + ; CHECK: [[FMAXIMUM:%[0-9]+]]:_(s32) = G_FMAXIMUM [[COPY]], [[COPY1]] + ; CHECK: $s0 = COPY [[FMAXIMUM]](s32) + ; CHECK: RET_ReallyLR implicit $s0 + %val = call float @llvm.maximum.f32(float %x, float %y) + ret float %val +} + +declare float @llvm.minnum.f32(float, float) #0 +declare float @llvm.maxnum.f32(float, float) #0 + +declare float @llvm.minimum.f32(float, float) #0 +declare float @llvm.maximum.f32(float, float) #0 + +attributes #0 = { nounwind readnone speculatable } diff --git a/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index 37bd3c8193b..6b27848c017 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -303,6 +303,24 @@ # DEBUG-NEXT: G_FCANONICALIZE (opcode {{[0-9]+}}): 1 type index # DEBUG: .. type index coverage check SKIPPED: no rules defined # +# DEBUG-NEXT: G_FMINNUM (opcode 131): 1 type index +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG-NEXT: G_FMAXNUM (opcode 132): 1 type index +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG-NEXT: G_FMINNUM_IEEE (opcode 133): 1 type index +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG-NEXT: G_FMAXNUM_IEEE (opcode 134): 1 type index +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG-NEXT: G_FMINIMUM (opcode 135): 1 type index +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG-NEXT: G_FMAXIMUM (opcode 136): 1 type index +# DEBUG: .. type index coverage check SKIPPED: no rules defined +# # DEBUG-NEXT: G_GEP (opcode {{[0-9]+}}): 2 type indices # DEBUG: .. the first uncovered type index: 2, OK # -- 2.50.0