Index: llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1865,6 +1865,12 @@ 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 Flags = None) { + return buildInstr(TargetOpcode::G_ISNAN, {Dst}, {Src}, Flags); + } + virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, ArrayRef SrcOps, Optional Flags = None); Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2228,6 +2228,14 @@ 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" Index: llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-isnan.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-isnan.ll @@ -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 +}