GlobalISel: Define the full family of FP min/max instructions
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Wed, 10 Jul 2019 16:31:15 +0000 (16:31 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Wed, 10 Jul 2019 16:31:15 +0000 (16:31 +0000)
llvm-svn: 365657

llvm/include/llvm/Support/TargetOpcodes.def
llvm/include/llvm/Target/GenericOpcodes.td
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll [new file with mode: 0644]
llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

index fa02463..598c106 100644 (file)
@@ -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)
 
index 11fbf62..4571832 100644 (file)
@@ -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.
 //------------------------------------------------------------------------------
index 96efcf7..6e99bdb 100644 (file)
@@ -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/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-fp-min-max-intrinsics.ll
new file mode 100644 (file)
index 0000000..ff92d4c
--- /dev/null
@@ -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 }
index 37bd3c8..6b27848 100644 (file)
 # 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
 #