[GlobalISel] Add IRTranslator support for G_ISNAN
authorJessica Paquette <jpaquette@apple.com>
Tue, 17 Aug 2021 16:49:44 +0000 (09:49 -0700)
committerJessica Paquette <jpaquette@apple.com>
Wed, 18 Aug 2021 17:48:10 +0000 (10:48 -0700)
Translate the `@llvm.isnan` intrinsic to G_ISNAN when we see it.

This is pretty much the same as the associated SelectionDAGBuilder code. Main
difference is that we don't expand it here. It makes more sense to do that
during legalization in GlobalISel. GlobalISel will just legalize the generated
illegal types.

Differential Revision: https://reviews.llvm.org/D108226

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-isnan.ll [new file with mode: 0644]

index 9b652d8..4d50533 100644 (file)
@@ -1865,6 +1865,12 @@ public:
     return buildInstr(TargetOpcode::G_BITREVERSE, {Dst}, {Src});
   }
 
+  /// Build and insert \p Dst = G_ISNAN \p Src
+  MachineInstrBuilder buildIsNaN(const DstOp &Dst, const SrcOp &Src,
+                                 Optional<unsigned> Flags = None) {
+    return buildInstr(TargetOpcode::G_ISNAN, {Dst}, {Src}, Flags);
+  }
+
   virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
                                          ArrayRef<SrcOp> SrcOps,
                                          Optional<unsigned> Flags = None);
index d4880f0..8663264 100644 (file)
@@ -2228,6 +2228,14 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
 
     return true;
   }
+  case Intrinsic::isnan: {
+    Register Src = getOrCreateVReg(*CI.getArgOperand(0));
+    unsigned Flags = MachineInstr::copyFlagsFromInstruction(CI);
+    if (!CI.getFunction()->getAttributes().hasFnAttr(llvm::Attribute::StrictFP))
+      Flags |= MachineInstr::NoFPExcept;
+    MIRBuilder.buildIsNaN(getOrCreateVReg(CI), Src, Flags);
+    return true;
+  }
 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)  \
   case Intrinsic::INTRINSIC:
 #include "llvm/IR/ConstrainedOps.def"
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-isnan.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-isnan.ll
new file mode 100644 (file)
index 0000000..2368b6a
--- /dev/null
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -global-isel -mtriple=aarch64-unknown-unknown -stop-after=irtranslator -verify-machineinstrs -o - %s | FileCheck %s
+declare i1 @llvm.isnan.f16(half)
+declare <4 x i1> @llvm.isnan.v4f16(<4 x half>)
+
+define i1 @s16(half %x) {
+  ; CHECK-LABEL: name: s16
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $h0
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s16) = COPY $h0
+  ; CHECK:   %1:_(s1) = nofpexcept G_ISNAN [[COPY]](s16)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s8) = G_ZEXT %1(s1)
+  ; CHECK:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[ZEXT]](s8)
+  ; CHECK:   $w0 = COPY [[ANYEXT]](s32)
+  ; CHECK:   RET_ReallyLR implicit $w0
+  %isnan = tail call i1 @llvm.isnan.f16(half %x)
+  ret i1 %isnan
+}
+
+define <4 x i1> @v4s16(<4 x half> %x) {
+  ; CHECK-LABEL: name: v4s16
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $d0
+  ; CHECK:   [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0
+  ; CHECK:   %1:_(<4 x s1>) = nofpexcept G_ISNAN [[COPY]](<4 x s16>)
+  ; CHECK:   [[ANYEXT:%[0-9]+]]:_(<4 x s16>) = G_ANYEXT %1(<4 x s1>)
+  ; CHECK:   $d0 = COPY [[ANYEXT]](<4 x s16>)
+  ; CHECK:   RET_ReallyLR implicit $d0
+  %isnan = tail call <4 x i1> @llvm.isnan.v4f16(<4 x half> %x)
+  ret <4 x i1> %isnan
+}
+
+define i1 @strictfp(half %x) strictfp {
+  ; CHECK-LABEL: name: strictfp
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   liveins: $h0
+  ; CHECK:   [[COPY:%[0-9]+]]:_(s16) = COPY $h0
+  ; CHECK:   [[ISNAN:%[0-9]+]]:_(s1) = G_ISNAN [[COPY]](s16)
+  ; CHECK:   [[ZEXT:%[0-9]+]]:_(s8) = G_ZEXT [[ISNAN]](s1)
+  ; CHECK:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[ZEXT]](s8)
+  ; CHECK:   $w0 = COPY [[ANYEXT]](s32)
+  ; CHECK:   RET_ReallyLR implicit $w0
+  %isnan = tail call i1 @llvm.isnan.f16(half %x)
+  ret i1 %isnan
+}