[GlobalISel] Add G_ISNAN

Add a generic opcode equivalent to the `llvm.isnan` intrinsic +
MachineVerifier support for it.

We need an opcode here because we may want target-specific lowering later on.

Differential Revision: https://reviews.llvm.org/D108222
This commit is contained in:
Jessica Paquette 2021-08-17 09:45:23 -07:00
parent e8c8407aca
commit 0a2b1ba33a
5 changed files with 73 additions and 1 deletions

View File

@ -629,6 +629,17 @@ G_VECREDUCE_FMAX, G_VECREDUCE_FMIN
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
G_ISNAN
^^^^^^^
GlobalISel-equivalent of the '``llvm.isnan``' intrinsic.
Returns a 1-bit scalar or vector of 1-bit scalar values. The result's contents
represent whether or not the source value is NaN.
.. code-block:: none
%is_nan:_(s1) = G_ISNAN %check_me_for_nan
Integer/bitwise reductions
^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -769,10 +769,12 @@ HANDLE_TARGET_OPCODE(G_VECREDUCE_UMIN)
HANDLE_TARGET_OPCODE(G_SBFX)
HANDLE_TARGET_OPCODE(G_UBFX)
HANDLE_TARGET_OPCODE(G_ISNAN)
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_UBFX)
HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_ISNAN)
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here.

View File

@ -225,6 +225,13 @@ def G_FREEZE : GenericInstruction {
let hasSideEffects = false;
}
// Generic opcode equivalent to the llvm.isnan intrinsic.
def G_ISNAN: GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src);
let hasSideEffects = false;
}
//------------------------------------------------------------------------------
// Binary ops.
//------------------------------------------------------------------------------

View File

@ -947,6 +947,25 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
// Verify properties of various specific instruction types
unsigned Opc = MI->getOpcode();
switch (Opc) {
case TargetOpcode::G_ISNAN: {
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
LLT SrcTy = MRI->getType(MI->getOperand(1).getReg());
LLT S1 = DstTy.isVector() ? DstTy.getElementType() : DstTy;
if (S1 != LLT::scalar(1)) {
report("Destination must be a 1-bit scalar or vector of 1-bit elements",
MI);
break;
}
// Disallow pointers.
LLT SrcOrElt = SrcTy.isVector() ? SrcTy.getElementType() : SrcTy;
if (!SrcOrElt.isScalar()) {
report("Source must be a scalar or vector of scalars", MI);
break;
}
verifyVectorElementMatch(DstTy, SrcTy, MI);
break;
}
case TargetOpcode::G_ASSERT_SEXT:
case TargetOpcode::G_ASSERT_ZEXT: {
std::string OpcName =

View File

@ -0,0 +1,33 @@
# REQUIRES: aarch64-registered-target
# RUN: not --crash llc -verify-machineinstrs -mtriple aarch64 -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
name: test
body: |
bb.0:
liveins: $x0
%s64:_(s64) = COPY $x0
%v4s16:_(<4 x s16>) = COPY $x0
; CHECK: *** Bad machine code: Destination must be a 1-bit scalar or vector of 1-bit elements ***
; CHECK: instruction: %isnan1:_(s64) = G_ISNAN %s64:_(s64)
%isnan1:_(s64) = G_ISNAN %s64
; CHECK: *** Bad machine code: operand types must be all-vector or all-scalar ***
; CHECK: instruction: %isnan2:_(<2 x s1>) = G_ISNAN %s64:_(s64)
%isnan2:_(<2 x s1>) = G_ISNAN %s64
; CHECK: *** Bad machine code: operand types must preserve number of vector elements ***
; CHECK: instruction: %isnan3:_(<2 x s1>) = G_ISNAN %v4s16:_(<4 x s16>)
%isnan3:_(<2 x s1>) = G_ISNAN %v4s16
; CHECK: *** Bad machine code: operand types must be all-vector or all-scalar ***
; CHECK: instruction: %isnan4:_(s1) = G_ISNAN %v4s16:_(<4 x s16>)
%isnan4:_(s1) = G_ISNAN %v4s16
; CHECK: *** Bad machine code: Destination must be a 1-bit scalar or vector of 1-bit elements ***
; CHECK: instruction: %isnan5:_(p0) = G_ISNAN %s64:_(s64)
%isnan5:_(p0) = G_ISNAN %s64
; CHECK: *** Bad machine code: Destination must be a 1-bit scalar or vector of 1-bit elements ***
; CHECK: instruction: %isnan6:_(<4 x p0>) = G_ISNAN %v4s16:_(<4 x s16>)
%isnan6:_(<4 x p0>) = G_ISNAN %v4s16