Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -5083,6 +5083,12 @@ def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLIsnan : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_isnan"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_lerp"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGHLSLBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
retType, CGM.getHLSLRuntime().getIsInfIntrinsic(),
ArrayRef<Value *>{Op0}, nullptr, "hlsl.isinf");
}
case Builtin::BI__builtin_hlsl_elementwise_isnan: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
llvm::Type *Xty = Op0->getType();
llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
if (Xty->isVectorTy()) {
auto *XVecTy = E->getArg(0)->getType()->castAs<VectorType>();
retType = llvm::VectorType::get(
retType, ElementCount::getFixed(XVecTy->getNumElements()));
}
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("isnan operand must have a float representation");
return Builder.CreateIntrinsic(
retType, CGM.getHLSLRuntime().getIsNaNIntrinsic(),
ArrayRef<Value *>{Op0}, nullptr, "hlsl.isnan");
}
case Builtin::BI__builtin_hlsl_mad: {
Value *M = EmitScalarExpr(E->getArg(0));
Value *A = EmitScalarExpr(E->getArg(1));
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,
flattened_thread_id_in_group)
GENERATE_HLSL_INTRINSIC_FUNCTION(IsInf, isinf)
GENERATE_HLSL_INTRINSIC_FUNCTION(IsNaN, isnan)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize)
GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,39 @@ bool3 isinf(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf)
bool4 isinf(float4);

//===----------------------------------------------------------------------===//
// isnan builtins
//===----------------------------------------------------------------------===//

/// \fn T isnan(T x)
/// \brief Determines if the specified value \a x is Not a Number.
/// \param x The specified input value.
///
/// Returns a value of the same size as the input, with a value set
/// to True if the x parameter is NaN or QNaN. Otherwise, False.

_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool isnan(half);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool2 isnan(half2);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool3 isnan(half3);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool4 isnan(half4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool isnan(float);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool2 isnan(float2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool3 isnan(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isnan)
bool4 isnan(float4);

//===----------------------------------------------------------------------===//
// lerp builtins
//===----------------------------------------------------------------------===//
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_compat_overloads.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,15 @@ constexpr bool2 isinf(double2 V) { return isinf((float2)V); }
constexpr bool3 isinf(double3 V) { return isinf((float3)V); }
constexpr bool4 isinf(double4 V) { return isinf((float4)V); }

//===----------------------------------------------------------------------===//
// isnan builtins overloads
//===----------------------------------------------------------------------===//

constexpr bool isnan(double V) { return isnan((float)V); }
constexpr bool2 isnan(double2 V) { return isnan((float2)V); }
constexpr bool3 isnan(double3 V) { return isnan((float3)V); }
constexpr bool4 isnan(double4 V) { return isnan((float4)V); }

//===----------------------------------------------------------------------===//
// lerp builtins overloads
//===----------------------------------------------------------------------===//
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2990,7 +2990,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
case Builtin::BI__builtin_hlsl_elementwise_isinf: {
case Builtin::BI__builtin_hlsl_elementwise_isinf:
case Builtin::BI__builtin_hlsl_elementwise_isnan: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CodeGenHLSL/builtins/isnan-overloads.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
// RUN: -o - | FileCheck %s

// CHECK: define hidden noundef i1 @
// CHECK: %hlsl.isnan = call i1 @llvm.dx.isnan.f32(
// CHECK: ret i1 %hlsl.isnan
bool test_isnan_double(double p0) { return isnan(p0); }
// CHECK: define hidden noundef <2 x i1> @
// CHECK: %hlsl.isnan = call <2 x i1> @llvm.dx.isnan.v2f32
// CHECK: ret <2 x i1> %hlsl.isnan
bool2 test_isnan_double2(double2 p0) { return isnan(p0); }
// CHECK: define hidden noundef <3 x i1> @
// CHECK: %hlsl.isnan = call <3 x i1> @llvm.dx.isnan.v3f32
// CHECK: ret <3 x i1> %hlsl.isnan
bool3 test_isnan_double3(double3 p0) { return isnan(p0); }
// CHECK: define hidden noundef <4 x i1> @
// CHECK: %hlsl.isnan = call <4 x i1> @llvm.dx.isnan.v4f32
// CHECK: ret <4 x i1> %hlsl.isnan
bool4 test_isnan_double4(double4 p0) { return isnan(p0); }
62 changes: 62 additions & 0 deletions clang/test/CodeGenHLSL/builtins/isnan.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: --check-prefixes=CHECK,DXCHECK,NATIVE_HALF
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK,NO_HALF

// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: --check-prefixes=CHECK,SPVCHECK,NATIVE_HALF
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK,NO_HALF

// DXCHECK: define hidden [[FN_TYPE:]]noundef i1 @
// SPVCHECK: define hidden [[FN_TYPE:spir_func ]]noundef i1 @
// DXCHECK: %hlsl.isnan = call i1 @llvm.[[ICF:dx]].isnan.f32(
// SPVCHECK: %hlsl.isnan = call i1 @llvm.[[ICF:spv]].isnan.f32(
// CHECK: ret i1 %hlsl.isnan
bool test_isnan_float(float p0) { return isnan(p0); }

// CHECK: define hidden [[FN_TYPE]]noundef i1 @
// NATIVE_HALF: %hlsl.isnan = call i1 @llvm.[[ICF]].isnan.f16(
// NO_HALF: %hlsl.isnan = call i1 @llvm.[[ICF]].isnan.f32(
// CHECK: ret i1 %hlsl.isnan
bool test_isnan_half(half p0) { return isnan(p0); }

// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
// NATIVE_HALF: %hlsl.isnan = call <2 x i1> @llvm.[[ICF]].isnan.v2f16
// NO_HALF: %hlsl.isnan = call <2 x i1> @llvm.[[ICF]].isnan.v2f32(
// CHECK: ret <2 x i1> %hlsl.isnan
bool2 test_isnan_half2(half2 p0) { return isnan(p0); }

// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <3 x i1> @
// NATIVE_HALF: %hlsl.isnan = call <3 x i1> @llvm.[[ICF]].isnan.v3f16
// NO_HALF: %hlsl.isnan = call <3 x i1> @llvm.[[ICF]].isnan.v3f32(
// CHECK: ret <3 x i1> %hlsl.isnan
bool3 test_isnan_half3(half3 p0) { return isnan(p0); }

// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <4 x i1> @
// NATIVE_HALF: %hlsl.isnan = call <4 x i1> @llvm.[[ICF]].isnan.v4f16
// NO_HALF: %hlsl.isnan = call <4 x i1> @llvm.[[ICF]].isnan.v4f32(
// CHECK: ret <4 x i1> %hlsl.isnan
bool4 test_isnan_half4(half4 p0) { return isnan(p0); }


// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
// CHECK: %hlsl.isnan = call <2 x i1> @llvm.[[ICF]].isnan.v2f32
// CHECK: ret <2 x i1> %hlsl.isnan
bool2 test_isnan_float2(float2 p0) { return isnan(p0); }

// CHECK: define hidden [[FN_TYPE]]noundef <3 x i1> @
// CHECK: %hlsl.isnan = call <3 x i1> @llvm.[[ICF]].isnan.v3f32
// CHECK: ret <3 x i1> %hlsl.isnan
bool3 test_isnan_float3(float3 p0) { return isnan(p0); }

// CHECK: define hidden [[FN_TYPE]]noundef <4 x i1> @
// CHECK: %hlsl.isnan = call <4 x i1> @llvm.[[ICF]].isnan.v4f32
// CHECK: ret <4 x i1> %hlsl.isnan
bool4 test_isnan_float4(float4 p0) { return isnan(p0); }
38 changes: 38 additions & 0 deletions clang/test/SemaHLSL/BuiltIns/isnan-errors.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify

bool test_too_few_arg() {
return __builtin_hlsl_elementwise_isnan();
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
}

bool2 test_too_many_arg(float2 p0) {
return __builtin_hlsl_elementwise_isnan(p0, p0);
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
}

bool builtin_bool_to_float_type_promotion(bool p1) {
return __builtin_hlsl_elementwise_isnan(p1);
// expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'bool')}}
}

bool builtin_isnan_int_to_float_promotion(int p1) {
return __builtin_hlsl_elementwise_isnan(p1);
// expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
}

bool2 builtin_isnan_int2_to_float2_promotion(int2 p1) {
return __builtin_hlsl_elementwise_isnan(p1);
// expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int2' (aka 'vector<int, 2>'))}}
}

// builtins are variadic functions and so are subject to DefaultVariadicArgumentPromotion
half builtin_isnan_half_scalar (half p0) {
return __builtin_hlsl_elementwise_isnan (p0);
// expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
}

float builtin_isnan_float_scalar ( float p0) {
return __builtin_hlsl_elementwise_isnan (p0);
// expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
}
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsDirectX.td
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ def int_dx_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty

def int_dx_isinf : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_dx_isnan : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
[llvm_anyfloat_ty], [IntrNoMem]>;

def int_dx_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem]>;
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsSPIRV.td
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ let TargetPrefix = "spv" in {
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_isinf : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_isnan : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
def int_spv_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/DirectX/DXIL.td
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ def Saturate : DXILOp<7, unary> {

def IsNaN : DXILOp<8, isSpecialFloat> {
let Doc = "Determines if the specified value is NaN.";
let intrinsics = [IntrinSelect<int_dx_isnan>];
let arguments = [OverloadTy];
let result = Int1Ty;
let overloads = [Overloads<DXIL1_0, [HalfTy, FloatTy]>];
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ static bool isIntrinsicExpansion(Function &F) {
case Intrinsic::dx_nclamp:
case Intrinsic::dx_degrees:
case Intrinsic::dx_isinf:
case Intrinsic::dx_isnan:
case Intrinsic::dx_lerp:
case Intrinsic::dx_normalize:
case Intrinsic::dx_fdot:
Expand Down Expand Up @@ -1024,6 +1025,9 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
case Intrinsic::dx_isinf:
Result = expand16BitIsInf(Orig);
break;
case Intrinsic::dx_isnan:
Result = expand16BitIsNaN(Orig);
break;
case Intrinsic::dx_lerp:
Result = expandLerpIntrinsic(Orig);
break;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ bool DirectXTTIImpl::isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
switch (ID) {
case Intrinsic::dx_asdouble:
case Intrinsic::dx_isinf:
case Intrinsic::dx_isnan:
case Intrinsic::dx_firstbitlow:
case Intrinsic::dx_firstbituhigh:
case Intrinsic::dx_firstbitshigh:
Expand All @@ -48,6 +49,7 @@ bool DirectXTTIImpl::isTargetIntrinsicTriviallyScalarizable(
case Intrinsic::dx_firstbituhigh:
case Intrinsic::dx_frac:
case Intrinsic::dx_isinf:
case Intrinsic::dx_isnan:
case Intrinsic::dx_rsqrt:
case Intrinsic::dx_saturate:
case Intrinsic::dx_splitdouble:
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectOpIsInf(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;

bool selectOpIsNan(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;

template <bool Signed>
bool selectDot4AddPacked(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
Expand Down Expand Up @@ -2056,6 +2059,17 @@ bool SPIRVInstructionSelector::selectOpIsInf(Register ResVReg,
.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectOpIsNan(Register ResVReg,
const SPIRVType *ResType,
MachineInstr &I) const {
MachineBasicBlock &BB = *I.getParent();
return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsNan))
.addDef(ResVReg)
.addUse(GR.getSPIRVTypeID(ResType))
.addUse(I.getOperand(2).getReg())
.constrainAllUses(TII, TRI, RBI);
}

template <bool Signed>
bool SPIRVInstructionSelector::selectDot4AddPacked(Register ResVReg,
const SPIRVType *ResType,
Expand Down Expand Up @@ -3199,6 +3213,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_isinf:
return selectOpIsInf(ResVReg, ResType, I);
case Intrinsic::spv_isnan:
return selectOpIsNan(ResVReg, ResType, I);
case Intrinsic::spv_normalize:
return selectExtInst(ResVReg, ResType, I, CL::normalize, GL::Normalize);
case Intrinsic::spv_refract:
Expand Down
53 changes: 53 additions & 0 deletions llvm/test/CodeGen/DirectX/isnan.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
; RUN: opt -S -dxil-intrinsic-expansion -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.9-library %s | FileCheck %s --check-prefixes=CHECK,SM69CHECK
; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.8-library %s | FileCheck %s --check-prefixes=CHECK,SMOLDCHECK

; Make sure dxil operation function calls for isnan are generated for float and half.

define noundef i1 @isnan_float(float noundef %a) {
entry:
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 8, float %{{.*}}) #[[#ATTR:]]
; SMOLDCHECK: call i1 @llvm.dx.isnan.f32(float %{{.*}})
%dx.isnan = call i1 @llvm.dx.isnan.f32(float %a)
ret i1 %dx.isnan
}

define noundef i1 @isnan_half(half noundef %a) {
entry:
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 8, half %{{.*}}) #[[#ATTR]]
; SMOLDCHECK: [[BITCAST:%.*]] = bitcast half %{{.*}} to i16
; SMOLDCHECK: [[ANDHIGH:%.*]] = and i16 [[BITCAST]], 31744
; SMOLDCHECK: [[CMPHIGH:%.*]] = icmp eq i16 [[ANDHIGH]], 31744
; SMOLDCHECK: [[ANDLOW:%.*]] = and i16 [[BITCAST]], 1023
; SMOLDCHECK: [[CMPLOW:%.*]] = icmp ne i16 [[ANDLOW]], 0
; SMOLDCHECK: [[AND:%.*]] = and i1 [[CMPHIGH]], [[CMPLOW]]
%dx.isnan = call i1 @llvm.dx.isnan.f16(half %a)
ret i1 %dx.isnan
}

define noundef <4 x i1> @isnan_half4(<4 x half> noundef %p0) {
entry:
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 8, half
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 8, half
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 8, half
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 8, half
; SMOLDCHECK: [[BITCAST:%.*]] = bitcast <4 x half> %{{.*}} to <4 x i16>
; SMOLDCHECK: [[ANDHIGH:%.*]] = and <4 x i16> [[BITCAST]], splat (i16 31744)
; SMOLDCHECK: [[CMPHIGH:%.*]] = icmp eq <4 x i16> [[ANDHIGH]], splat (i16 31744)
; SMOLDCHECK: [[ANDLOW:%.*]] = and <4 x i16> [[BITCAST]], splat (i16 1023)
; SMOLDCHECK: [[CMPLOW:%.*]] = icmp ne <4 x i16> [[ANDLOW]], zeroinitializer
; SMOLDCHECK: [[AND:%.*]] = and <4 x i1> [[CMPHIGH]], [[CMPLOW]]
%hlsl.isnan = call <4 x i1> @llvm.dx.isnan.v4f16(<4 x half> %p0)
ret <4 x i1> %hlsl.isnan
}

define noundef <3 x i1> @isnan_float3(<3 x float> noundef %p0) {
entry:
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 8, float
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 8, float
; SM69CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 8, float
; SMOLDCHECK: = call <3 x i1> @llvm.dx.isnan.v3f32(<3 x float>
%hlsl.isnan = call <3 x i1> @llvm.dx.isnan.v3f32(<3 x float> %p0)
ret <3 x i1> %hlsl.isnan
}

; CHECK: attributes #{{[0-9]*}} = {{{.*}} memory(none) {{.*}}}
Loading
Loading