[clang] [llvm] [HLSL] Implement isfinite() intrinsic (PR #225947)

Dan Brown via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 8 18:51:08 PDT 2026


https://github.com/danbrown-amd updated https://github.com/llvm/llvm-project/pull/225947

>From cc184d58e6489fdffa41ad540fc96c3fe1f538ff Mon Sep 17 00:00:00 2001
From: Dan Brown <danbrown at amd.com>
Date: Thu, 21 May 2026 16:04:07 -0600
Subject: [PATCH 1/5] [HLSL] Implement isfinite() intrinsic

Resolves #99131

Assisted-by: Claude Sonnet 4
---
 clang/include/clang/Basic/Builtins.td         |  6 ++
 clang/include/clang/Basic/HLSLIntrinsics.td   | 15 +++++
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          | 19 ++++++
 clang/lib/CodeGen/CGHLSLRuntime.h             |  1 +
 .../lib/Headers/hlsl/hlsl_compat_overloads.h  | 13 ++++
 clang/lib/Sema/SemaHLSL.cpp                   |  1 +
 .../builtins/isfinite-overloads.hlsl          | 37 +++++++++++
 clang/test/CodeGenHLSL/builtins/isfinite.hlsl | 62 +++++++++++++++++++
 .../SemaHLSL/BuiltIns/isfinite-errors.hlsl    | 27 ++++++++
 llvm/include/llvm/IR/IntrinsicsDirectX.td     |  2 +
 llvm/lib/Target/DirectX/DXIL.td               |  1 +
 .../Target/DirectX/DXILIntrinsicExpansion.cpp |  4 ++
 .../DirectX/DirectXTargetTransformInfo.cpp    |  1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 33 +++++++++-
 .../CodeGen/DirectX/LongVector/isfinite.ll    | 11 ++++
 llvm/test/CodeGen/DirectX/isfinite.ll         | 62 +++++++++++++++++++
 llvm/test/CodeGen/DirectX/isfinite_error.ll   | 14 +++++
 .../SPIRV/hlsl-intrinsics/OpIsFinite.ll       | 20 ++++--
 18 files changed, 322 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/isfinite-overloads.hlsl
 create mode 100644 clang/test/CodeGenHLSL/builtins/isfinite.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/LongVector/isfinite.ll
 create mode 100644 llvm/test/CodeGen/DirectX/isfinite.ll
 create mode 100644 llvm/test/CodeGen/DirectX/isfinite_error.ll

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index cd92a36049e32d..be7f4e718dd92b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5810,6 +5810,12 @@ def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLIsfinite : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_isfinite"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_isinf"];
   let Attributes = [NoThrow, Const, CustomTypeChecking];
diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td
index 7e0d51bf3795f4..4481cf7dde33a9 100644
--- a/clang/include/clang/Basic/HLSLIntrinsics.td
+++ b/clang/include/clang/Basic/HLSLIntrinsics.td
@@ -1098,6 +1098,21 @@ def hlsl_barrier : HLSLBuiltin<"Barrier", "__builtin_hlsl_barrier"> {
   let Availability = SM6_8;
 }
 
+// Determines if the specified value x is finite.
+def hlsl_isfinite : HLSLOneArgBuiltin<"isfinite", "__builtin_hlsl_elementwise_isfinite"> {
+  let Doc = [{
+\fn T isinf(T x)
+\brief Determines if the specified value \a x  is finite.
+\param x The specified input value.
+
+Returns a value of the same size as the input, with a value set
+to False if the x parameter is +INF, -INF, NaN, or QNaN. Otherwise, True.
+}];
+  let ReturnType = VaryingShape<BoolTy>;
+  let VaryingTypes = [HalfTy, FloatTy];
+  let VaryingLongVector = 1;
+}
+
 // Determines if the specified value x is infinite.
 def hlsl_isinf : HLSLOneArgBuiltin<"isinf", "__builtin_hlsl_elementwise_isinf"> {
   let Doc = [{
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 2ed2b189f2c2e0..efc9e1405afa85 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -1344,6 +1344,25 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
         /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getFracIntrinsic(),
         ArrayRef<Value *>{Op0}, nullptr, "hlsl.frac");
   }
+  case Builtin::BI__builtin_hlsl_elementwise_isfinite: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    llvm::Type *Xty = Op0->getType();
+    llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
+    if (Xty->isVectorTy()) {
+      unsigned NumElts;
+      if (auto *MatTy = E->getArg(0)->getType()->getAs<ConstantMatrixType>())
+        NumElts = MatTy->getNumRows() * MatTy->getNumColumns();
+      else
+        NumElts =
+            E->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
+      retType = llvm::VectorType::get(retType, ElementCount::getFixed(NumElts));
+    }
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+      llvm_unreachable("isfinite operand must have a float representation");
+    return Builder.CreateIntrinsic(
+        retType, CGM.getHLSLRuntime().getIsFiniteIntrinsic(),
+        ArrayRef<Value *>{Op0}, nullptr, "hlsl.isfinite");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_isinf: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     if (!E->getArg(0)->getType()->hasFloatingRepresentation())
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index e2f3f743e1fbc4..f845aff5f5b763 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -130,6 +130,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,
                                    flattened_thread_id_in_group)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(IsFinite, isfinite)
   GENERATE_HLSL_INTRINSIC_FUNCTION(IsInf, isinf)
   GENERATE_HLSL_INTRINSIC_FUNCTION(IsNaN, isnan)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
diff --git a/clang/lib/Headers/hlsl/hlsl_compat_overloads.h b/clang/lib/Headers/hlsl/hlsl_compat_overloads.h
index 53ea7e28ef41da..7959e1abb540a8 100644
--- a/clang/lib/Headers/hlsl/hlsl_compat_overloads.h
+++ b/clang/lib/Headers/hlsl/hlsl_compat_overloads.h
@@ -382,6 +382,19 @@ _DXC_COMPAT_UNARY_INTEGER_OVERLOADS(floor)
 _DXC_COMPAT_UNARY_DOUBLE_OVERLOADS(frac)
 _DXC_COMPAT_UNARY_INTEGER_OVERLOADS(frac)
 
+//===----------------------------------------------------------------------===//
+// isfinite builtins overloads
+//===----------------------------------------------------------------------===//
+
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool isfinite(double V) { return isfinite((float)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool2 isfinite(double2 V) { return isfinite((float2)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool3 isfinite(double3 V) { return isfinite((float3)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool4 isfinite(double4 V) { return isfinite((float4)V); }
+
 //===----------------------------------------------------------------------===//
 // isinf builtins overloads
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 2888fa3ac6aec6..13a139faa96806 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4894,6 +4894,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       return true;
     break;
   }
+  case Builtin::BI__builtin_hlsl_elementwise_isfinite:
   case Builtin::BI__builtin_hlsl_elementwise_isinf:
   case Builtin::BI__builtin_hlsl_elementwise_isnan: {
     if (SemaRef.checkArgCount(TheCall, 1))
diff --git a/clang/test/CodeGenHLSL/builtins/isfinite-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/isfinite-overloads.hlsl
new file mode 100644
index 00000000000000..d84c94d8c739c0
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/isfinite-overloads.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm \
+// RUN:   -Wdeprecated-declarations -o - | FileCheck %s --check-prefixes=CHECK \
+// RUN:   -DFNATTRS="hidden noundef" -DTARGET=dx
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-library %s -emit-llvm \
+// RUN:   -Wdeprecated-declarations -o - | FileCheck %s --check-prefixes=CHECK \
+// RUN:   -DFNATTRS="hidden spir_func noundef" -DTARGET=spv
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s  \
+// RUN:   -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-library %s  \
+// RUN:   -verify -verify-ignore-unexpected=note
+
+// CHECK: define [[FNATTRS]] i1 @_Z20test_isfinite_doubled(
+// CHECK:    [[CONVI:%.*]] = fptrunc {{.*}} double %{{.*}} to float
+// CHECK:    [[HLSLISFINITEI:%.*]] = call noundef i1 @llvm.[[TARGET]].isfinite.f32(float [[CONVI]])
+// CHECK:    ret i1 [[HLSLISFINITEI]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool test_isfinite_double(double p0) { return isfinite(p0); }
+// CHECK: define [[FNATTRS]] <2 x i1> @_Z21test_isfinite_double2Dv2_d(
+// CHECK:    [[CONVI:%.*]] = fptrunc {{.*}} <2 x double> %{{.*}} to <2 x float>
+// CHECK:    [[HLSLISFINITEI:%.*]] = call noundef <2 x i1> @llvm.[[TARGET]].isfinite.v2f32(<2 x float> [[CONVI]])
+// CHECK:    ret <2 x i1> [[HLSLISFINITEI]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool2 test_isfinite_double2(double2 p0) { return isfinite(p0); }
+// CHECK: define [[FNATTRS]] <3 x i1> @_Z21test_isfinite_double3Dv3_d(
+// CHECK:    [[CONVI:%.*]] = fptrunc {{.*}} <3 x double> %{{.*}} to <3 x float>
+// CHECK:    [[HLSLISFINITEI:%.*]] = call noundef <3 x i1> @llvm.[[TARGET]].isfinite.v3f32(<3 x float> [[CONVI]])
+// CHECK:    ret <3 x i1> [[HLSLISFINITEI]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool3 test_isfinite_double3(double3 p0) { return isfinite(p0); }
+// CHECK: define [[FNATTRS]] <4 x i1> @_Z21test_isfinite_double4Dv4_d(
+// CHECK:    [[CONVI:%.*]] = fptrunc {{.*}} <4 x double> %{{.*}} to <4 x float>
+// CHECK:    [[HLSLISFINITEI:%.*]] = call noundef <4 x i1> @llvm.[[TARGET]].isfinite.v4f32(<4 x float> [[CONVI]])
+// CHECK:    ret <4 x i1> [[HLSLISFINITEI]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool4 test_isfinite_double4(double4 p0) { return isfinite(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/isfinite.hlsl b/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
new file mode 100644
index 00000000000000..d05534a5df7bb6
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-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-library %s -fnative-half-type -fnative-int16-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-library %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.isfinite = call i1 @llvm.[[ICF:dx]].isfinite.f32(
+// SPVCHECK: %hlsl.isfinite = call i1 @llvm.[[ICF:spv]].isfinite.f32(
+// CHECK: ret i1 %hlsl.isfinite
+bool test_isfinite_float(float p0) { return isfinite(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef i1 @
+// NATIVE_HALF: %hlsl.isfinite = call i1 @llvm.[[ICF]].isfinite.f16(
+// NO_HALF: %hlsl.isfinite = call i1 @llvm.[[ICF]].isfinite.f32(
+// CHECK: ret i1 %hlsl.isfinite
+bool test_isfinite_half(half p0) { return isfinite(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
+// NATIVE_HALF: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f16
+// NO_HALF: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32(
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool2 test_isfinite_half2(half2 p0) { return isfinite(p0); }
+
+// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <3 x i1> @
+// NATIVE_HALF: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f16
+// NO_HALF: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32(
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool3 test_isfinite_half3(half3 p0) { return isfinite(p0); }
+
+// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <4 x i1> @
+// NATIVE_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f16
+// NO_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32(
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool4 test_isfinite_half4(half4 p0) { return isfinite(p0); }
+
+
+// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
+// CHECK: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool2 test_isfinite_float2(float2 p0) { return isfinite(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef <3 x i1> @
+// CHECK: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool3 test_isfinite_float3(float3 p0) { return isfinite(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef <4 x i1> @
+// CHECK: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool4 test_isfinite_float4(float4 p0) { return isfinite(p0); }
diff --git a/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl
new file mode 100644
index 00000000000000..03892c50fa65d1
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl
@@ -0,0 +1,27 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
+
+bool test_too_few_arg() {
+  return __builtin_hlsl_elementwise_isfinite();
+  // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_isfinite(p0, p0);
+  // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+bool builtin_bool_to_float_type_promotion(bool p1) {
+  return __builtin_hlsl_elementwise_isfinite(p1);
+  // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'bool')}}
+}
+
+bool builtin_isfinite_int_to_float_promotion(int p1) {
+  return __builtin_hlsl_elementwise_isfinite(p1);
+  // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+bool2 builtin_isfinite_int2_to_float2_promotion(int2 p1) {
+  return __builtin_hlsl_elementwise_isfinite(p1);
+  // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int2' (aka 'vector<int, 2>'))}}
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index e3c131850d1f41..5963c444c9bd70 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -268,6 +268,8 @@ def int_dx_dot4add_u8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty,
 
 def int_dx_frac  : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrTriviallyScalarizable]>;
 
+def int_dx_isfinite : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
+    [llvm_anyfloat_ty], [IntrNoMem, IntrTriviallyScalarizable]>;
 def int_dx_isinf : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
     [llvm_anyfloat_ty], [IntrNoMem, IntrTriviallyScalarizable]>;
 def int_dx_isnan : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index cfb2c30fecc225..a36f460ac30cc4 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -476,6 +476,7 @@ def IsInf : DXILOp<9, isSpecialFloat> {
 
 def IsFinite : DXILOp<10, isSpecialFloat> {
   let Doc = "Determines if the specified value is finite.";
+  let intrinsics = [IntrinSelect<int_dx_isfinite>];
   let arguments = [OverloadTy];
   let result = Int1Ty;
   let overloads = [Overloads<DXIL1_0, [HalfTy, FloatTy]>];
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index dce8a1ec9f92a0..e7aac17b47cb79 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -225,6 +225,7 @@ static bool isIntrinsicExpansion(Function &F) {
   case Intrinsic::dx_uclamp:
   case Intrinsic::dx_sclamp:
   case Intrinsic::dx_nclamp:
+  case Intrinsic::dx_isfinite:
   case Intrinsic::dx_isinf:
   case Intrinsic::dx_isnan:
   case Intrinsic::dx_sdot:
@@ -1331,6 +1332,9 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
   case Intrinsic::dx_nclamp:
     Result = expandClampIntrinsic(Orig, IntrinsicId);
     break;
+  case Intrinsic::dx_isfinite:
+    Result = expand16BitIsFinite(Orig);
+    break;
   case Intrinsic::dx_isinf:
     Result = expand16BitIsInf(Orig);
     break;
diff --git a/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp b/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
index af1d7bc4521263..6c65fb7b9e0fc7 100644
--- a/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
+++ b/llvm/lib/Target/DirectX/DirectXTargetTransformInfo.cpp
@@ -32,6 +32,7 @@ bool DirectXTTIImpl::isTargetIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID,
   case Intrinsic::dx_firstbitlow:
   case Intrinsic::dx_firstbitshigh:
   case Intrinsic::dx_firstbituhigh:
+  case Intrinsic::dx_isfinite:
   case Intrinsic::dx_isinf:
   case Intrinsic::dx_isnan:
   case Intrinsic::dx_legacyf16tof32:
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 8788707d8fff96..3f90b3992208cf 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3429,11 +3429,38 @@ bool SPIRVInstructionSelector::selectOpIsNan(Register ResVReg,
 bool SPIRVInstructionSelector::selectOpIsFinite(Register ResVReg,
                                                 SPIRVTypeInst ResType,
                                                 MachineInstr &I) const {
+  // OpIsFinite requires Kernel capability; emulate with OpIsInf & OpIsNan
   MachineBasicBlock &BB = *I.getParent();
-  BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsFinite))
+  Register Src = I.getOperand(2).getReg();
+  Register TypeID = GR.getSPIRVTypeID(ResType);
+  const DebugLoc &DL = I.getDebugLoc();
+
+  Register IsInfReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+  BuildMI(BB, I, DL, TII.get(SPIRV::OpIsInf))
+      .addDef(IsInfReg)
+      .addUse(TypeID)
+      .addUse(Src)
+      .constrainAllUses(TII, TRI, RBI);
+
+  Register IsNanReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+  BuildMI(BB, I, DL, TII.get(SPIRV::OpIsNan))
+      .addDef(IsNanReg)
+      .addUse(TypeID)
+      .addUse(Src)
+      .constrainAllUses(TII, TRI, RBI);
+
+  Register OrReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
+  BuildMI(BB, I, DL, TII.get(SPIRV::OpLogicalOr))
+      .addDef(OrReg)
+      .addUse(TypeID)
+      .addUse(IsInfReg)
+      .addUse(IsNanReg)
+      .constrainAllUses(TII, TRI, RBI);
+
+  BuildMI(BB, I, DL, TII.get(SPIRV::OpLogicalNot))
       .addDef(ResVReg)
-      .addUse(GR.getSPIRVTypeID(ResType))
-      .addUse(I.getOperand(2).getReg())
+      .addUse(TypeID)
+      .addUse(OrReg)
       .constrainAllUses(TII, TRI, RBI);
   return true;
 }
diff --git a/llvm/test/CodeGen/DirectX/LongVector/isfinite.ll b/llvm/test/CodeGen/DirectX/LongVector/isfinite.ll
new file mode 100644
index 00000000000000..1b1fa71a0e8c32
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/LongVector/isfinite.ll
@@ -0,0 +1,11 @@
+; RUN: llc -mtriple=dxil-pc-shadermodel6.8-library -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SCALAR
+; RUN: llc -mtriple=dxil-pc-shadermodel6.9-library -stop-before=dxil-op-lower -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-VECTOR
+
+; CHECK-LABEL: define <17 x i1> @test_isfinite(
+; CHECK-SCALAR-COUNT-17: call i1 @dx.op.isSpecialFloat.f32(i32 10, float {{.*}})
+; CHECK-VECTOR: call <17 x i1> @llvm.dx.isfinite.v17f32
+define <17 x i1> @test_isfinite(<17 x float> %a) {
+  %result = call <17 x i1> @llvm.dx.isfinite.v17f32(<17 x float> %a)
+  ret <17 x i1> %result
+}
+declare <17 x i1> @llvm.dx.isfinite.v17f32(<17 x float>)
diff --git a/llvm/test/CodeGen/DirectX/isfinite.ll b/llvm/test/CodeGen/DirectX/isfinite.ll
new file mode 100644
index 00000000000000..46c04d22f9f80c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/isfinite.ll
@@ -0,0 +1,62 @@
+; 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 -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.8-library %s | FileCheck %s --check-prefixes=CHECK,SMOLDCHECK
+
+; Make sure dxil operation function calls for isfinite are generated for float and half.
+
+define noundef i1 @isfinite_float(float noundef %a) {
+entry:
+  ; CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 10, float %{{.*}})
+  %dx.isfinite = call i1 @llvm.dx.isfinite.f32(float %a)
+  ret i1 %dx.isfinite
+}
+
+define noundef i1 @isfinite_half(half noundef %a) {
+entry:
+  ; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 10, half %{{.*}})
+  ; SMOLDCHECK: [[BITCAST:%.*]] = bitcast half %a to i16
+  ; SMOLDCHECK: [[AND:%.*]] = and i16 [[BITCAST]], 31744
+  ; SMOLDCHECK: [[CMP:%.*]] = icmp ne i16 [[AND]], 31744
+  %dx.isfinite = call i1 @llvm.dx.isfinite.f16(half %a)
+  ret i1 %dx.isfinite
+}
+
+define noundef <4 x i1> @isfinite_half4(<4 x half> noundef %p0) {
+entry:
+  ; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 10, half
+  ; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 10, half
+  ; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 10, half
+  ; SM69CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 10, half
+
+  ; SMOLDCHECK: [[ee0:%.*]] = extractelement <4 x half> %p0, i64 0
+  ; SMOLDCHECK: [[BITCAST0:%.*]] = bitcast half [[ee0]] to i16
+  ; SMOLDCHECK: [[ee1:%.*]] = extractelement <4 x half> %p0, i64 1
+  ; SMOLDCHECK: [[BITCAST1:%.*]] = bitcast half [[ee1]] to i16
+  ; SMOLDCHECK: [[ee2:%.*]] = extractelement <4 x half> %p0, i64 2
+  ; SMOLDCHECK: [[BITCAST2:%.*]] = bitcast half [[ee2]] to i16
+  ; SMOLDCHECK: [[ee3:%.*]] = extractelement <4 x half> %p0, i64 3
+  ; SMOLDCHECK: [[BITCAST3:%.*]] = bitcast half [[ee3]] to i16
+  ; SMOLDCHECK: [[AND0:%.*]] = and i16 [[BITCAST0]], 31744
+  ; SMOLDCHECK: [[AND1:%.*]] = and i16 [[BITCAST1]], 31744
+  ; SMOLDCHECK: [[AND2:%.*]] = and i16 [[BITCAST2]], 31744
+  ; SMOLDCHECK: [[AND3:%.*]] = and i16 [[BITCAST3]], 31744
+  ; SMOLDCHECK: [[CMP0:%.*]] = icmp ne i16 [[AND0]], 31744
+  ; SMOLDCHECK: [[CMP1:%.*]] = icmp ne i16 [[AND1]], 31744
+  ; SMOLDCHECK: [[CMP2:%.*]] = icmp ne i16 [[AND2]], 31744
+  ; SMOLDCHECK: [[CMP3:%.*]] = icmp ne i16 [[AND3]], 31744
+
+  %hlsl.isfinite = call <4 x i1> @llvm.dx.isfinite.v4f16(<4 x half> %p0)
+  ret <4 x i1> %hlsl.isfinite
+}
+
+define noundef <3 x i1> @isfinite_float3(<3 x float> noundef %p0) {
+entry:
+  ; CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 10, float
+  ; CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 10, float
+  ; CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 10, float
+  %hlsl.isfinite = call <3 x i1> @llvm.dx.isfinite.v3f32(<3 x float> %p0)
+  ret <3 x i1> %hlsl.isfinite
+}
+
+; CHECK-DAG: declare i1 @dx.op.isSpecialFloat.f32(i32, float) #[[#ATTR0:]]
+; SM69CHECK-DAG: declare i1 @dx.op.isSpecialFloat.f16(i32, half) #[[#ATTR0]]
+; CHECK: attributes #[[#ATTR0]] = { nounwind memory(none) }
diff --git a/llvm/test/CodeGen/DirectX/isfinite_error.ll b/llvm/test/CodeGen/DirectX/isfinite_error.ll
new file mode 100644
index 00000000000000..03dd513f99ac0e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/isfinite_error.ll
@@ -0,0 +1,14 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+
+; DXIL operation isfinite does not support double overload type
+; CHECK: in function isfinite_double
+; CHECK-SAME: Cannot create IsFinite operation: Invalid overload type
+
+define noundef i1 @isfinite_double(double noundef %a) #0 {
+entry:
+  %a.addr = alloca double, align 8
+  store double %a, ptr %a.addr, align 8
+  %0 = load double, ptr %a.addr, align 8
+  %dx.isfinite = call i1 @llvm.dx.isfinite.f64(double %0)
+  ret i1 %dx.isfinite
+}
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
index 0455e715a349d2..4829558aa3e3bd 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
@@ -12,7 +12,10 @@ define noundef i1 @isfinite_half(half noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#bool]] %[[#or]]
   %hlsl.isfinite = call i1 @llvm.spv.isfinite.f16(half %a)
   ret i1 %hlsl.isfinite
 }
@@ -21,7 +24,10 @@ define noundef i1 @isfinite_float(float noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#bool]] %[[#or]]
   %hlsl.isfinite = call i1 @llvm.spv.isfinite.f32(float %a)
   ret i1 %hlsl.isfinite
 }
@@ -30,7 +36,10 @@ define noundef <4 x i1> @isfinite_half4(<4 x half> noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#vec4_bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#vec4_bool]] %[[#or]]
   %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f16(<4 x half> %a)
   ret <4 x i1> %hlsl.isfinite
 }
@@ -39,7 +48,10 @@ define noundef <4 x i1> @isfinite_float4(<4 x float> noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#vec4_bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#vec4_bool]] %[[#or]]
   %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f32(<4 x float> %a)
   ret <4 x i1> %hlsl.isfinite
 }

>From fd331c70a02405bae62a941bb85a4b5f8c32ee72 Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Mon, 28 Sep 2026 19:22:14 -0600
Subject: [PATCH 2/5] Address review comments and bugs

---
 clang/include/clang/Basic/Builtins.td         |   2 +-
 clang/include/clang/Basic/HLSLIntrinsics.td   |   2 +-
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |  13 +-
 .../lib/Headers/hlsl/hlsl_compat_overloads.h  |  30 +++
 clang/test/CodeGenHLSL/builtins/isfinite.hlsl |  30 +--
 .../builtins/isfinite_mat-overloads.hlsl      | 115 +++++++++++
 .../CodeGenHLSL/builtins/isfinite_mat.hlsl    | 182 ++++++++++++++++++
 .../SemaHLSL/BuiltIns/isfinite-errors.hlsl    |   1 -
 .../BuiltIns/isfinite_mat-errors.hlsl         |  21 ++
 9 files changed, 367 insertions(+), 29 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/isfinite_mat-overloads.hlsl
 create mode 100644 clang/test/CodeGenHLSL/builtins/isfinite_mat.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/isfinite_mat-errors.hlsl

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index be7f4e718dd92b..ad9a58bb2ad2d3 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5812,7 +5812,7 @@ def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
 
 def HLSLIsfinite : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_isfinite"];
-  let Attributes = [NoThrow, Const];
+  let Attributes = [NoThrow, Const, CustomTypeChecking];
   let Prototype = "void(...)";
 }
 
diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td
index 4481cf7dde33a9..fd59e3477b8c79 100644
--- a/clang/include/clang/Basic/HLSLIntrinsics.td
+++ b/clang/include/clang/Basic/HLSLIntrinsics.td
@@ -1101,7 +1101,7 @@ def hlsl_barrier : HLSLBuiltin<"Barrier", "__builtin_hlsl_barrier"> {
 // Determines if the specified value x is finite.
 def hlsl_isfinite : HLSLOneArgBuiltin<"isfinite", "__builtin_hlsl_elementwise_isfinite"> {
   let Doc = [{
-\fn T isinf(T x)
+\fn T isfinite(T x)
 \brief Determines if the specified value \a x  is finite.
 \param x The specified input value.
 
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index efc9e1405afa85..acd5dca81f0136 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -1346,19 +1346,10 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
   }
   case Builtin::BI__builtin_hlsl_elementwise_isfinite: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
-    llvm::Type *Xty = Op0->getType();
-    llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
-    if (Xty->isVectorTy()) {
-      unsigned NumElts;
-      if (auto *MatTy = E->getArg(0)->getType()->getAs<ConstantMatrixType>())
-        NumElts = MatTy->getNumRows() * MatTy->getNumColumns();
-      else
-        NumElts =
-            E->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
-      retType = llvm::VectorType::get(retType, ElementCount::getFixed(NumElts));
-    }
     if (!E->getArg(0)->getType()->hasFloatingRepresentation())
       llvm_unreachable("isfinite operand must have a float representation");
+    llvm::Type *retType = getAggregateType(
+        llvm::Type::getInt1Ty(getLLVMContext()), E->getArg(0)->getType());
     return Builder.CreateIntrinsic(
         retType, CGM.getHLSLRuntime().getIsFiniteIntrinsic(),
         ArrayRef<Value *>{Op0}, nullptr, "hlsl.isfinite");
diff --git a/clang/lib/Headers/hlsl/hlsl_compat_overloads.h b/clang/lib/Headers/hlsl/hlsl_compat_overloads.h
index 7959e1abb540a8..15af384ec15076 100644
--- a/clang/lib/Headers/hlsl/hlsl_compat_overloads.h
+++ b/clang/lib/Headers/hlsl/hlsl_compat_overloads.h
@@ -394,6 +394,36 @@ _DXC_DEPRECATED_64BIT_FN(isfinite)
 constexpr bool3 isfinite(double3 V) { return isfinite((float3)V); }
 _DXC_DEPRECATED_64BIT_FN(isfinite)
 constexpr bool4 isfinite(double4 V) { return isfinite((float4)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool1x2 isfinite(double1x2 V) { return isfinite((float1x2)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool1x3 isfinite(double1x3 V) { return isfinite((float1x3)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool1x4 isfinite(double1x4 V) { return isfinite((float1x4)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool2x1 isfinite(double2x1 V) { return isfinite((float2x1)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool2x2 isfinite(double2x2 V) { return isfinite((float2x2)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool2x3 isfinite(double2x3 V) { return isfinite((float2x3)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool2x4 isfinite(double2x4 V) { return isfinite((float2x4)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool3x1 isfinite(double3x1 V) { return isfinite((float3x1)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool3x2 isfinite(double3x2 V) { return isfinite((float3x2)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool3x3 isfinite(double3x3 V) { return isfinite((float3x3)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool3x4 isfinite(double3x4 V) { return isfinite((float3x4)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool4x1 isfinite(double4x1 V) { return isfinite((float4x1)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool4x2 isfinite(double4x2 V) { return isfinite((float4x2)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool4x3 isfinite(double4x3 V) { return isfinite((float4x3)V); }
+_DXC_DEPRECATED_64BIT_FN(isfinite)
+constexpr bool4x4 isfinite(double4x4 V) { return isfinite((float4x4)V); }
 
 //===----------------------------------------------------------------------===//
 // isinf builtins overloads
diff --git a/clang/test/CodeGenHLSL/builtins/isfinite.hlsl b/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
index d05534a5df7bb6..d549a255a765f8 100644
--- a/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
@@ -21,6 +21,21 @@
 // CHECK: ret i1 %hlsl.isfinite
 bool test_isfinite_float(float p0) { return isfinite(p0); }
 
+// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
+// CHECK: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool2 test_isfinite_float2(float2 p0) { return isfinite(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef <3 x i1> @
+// CHECK: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool3 test_isfinite_float3(float3 p0) { return isfinite(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef <4 x i1> @
+// CHECK: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool4 test_isfinite_float4(float4 p0) { return isfinite(p0); }
+
 // CHECK: define hidden [[FN_TYPE]]noundef i1 @
 // NATIVE_HALF: %hlsl.isfinite = call i1 @llvm.[[ICF]].isfinite.f16(
 // NO_HALF: %hlsl.isfinite = call i1 @llvm.[[ICF]].isfinite.f32(
@@ -45,18 +60,3 @@ bool3 test_isfinite_half3(half3 p0) { return isfinite(p0); }
 // CHECK: ret <4 x i1> %hlsl.isfinite
 bool4 test_isfinite_half4(half4 p0) { return isfinite(p0); }
 
-
-// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
-// CHECK: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32
-// CHECK: ret <2 x i1> %hlsl.isfinite
-bool2 test_isfinite_float2(float2 p0) { return isfinite(p0); }
-
-// CHECK: define hidden [[FN_TYPE]]noundef <3 x i1> @
-// CHECK: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
-// CHECK: ret <3 x i1> %hlsl.isfinite
-bool3 test_isfinite_float3(float3 p0) { return isfinite(p0); }
-
-// CHECK: define hidden [[FN_TYPE]]noundef <4 x i1> @
-// CHECK: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
-// CHECK: ret <4 x i1> %hlsl.isfinite
-bool4 test_isfinite_float4(float4 p0) { return isfinite(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/isfinite_mat-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/isfinite_mat-overloads.hlsl
new file mode 100644
index 00000000000000..da7dbf9e4b5d6d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/isfinite_mat-overloads.hlsl
@@ -0,0 +1,115 @@
+// 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 -DTARGET=dx
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
+// RUN:   spirv-unknown-vulkan-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s -DTARGET=spv
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN:   -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple spirv-unknown-vulkan-library %s \
+// RUN:   -verify -verify-ignore-unexpected=note
+
+// CHECK-LABEL: define {{.*}} <2 x i1> @_{{.*}}test_isfinite_double1x2{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <2 x double> %{{.*}} to <2 x float>
+// CHECK:    [[RET:%.*]] = call <2 x i1> @llvm.[[TARGET]].isfinite.v2f32(<2 x float> [[CONV]])
+// CHECK:    ret <2 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool1x2 test_isfinite_double1x2(double1x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <3 x i1> @_{{.*}}test_isfinite_double1x3{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <3 x double> %{{.*}} to <3 x float>
+// CHECK:    [[RET:%.*]] = call <3 x i1> @llvm.[[TARGET]].isfinite.v3f32(<3 x float> [[CONV]])
+// CHECK:    ret <3 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool1x3 test_isfinite_double1x3(double1x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <4 x i1> @_{{.*}}test_isfinite_double1x4{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <4 x double> %{{.*}} to <4 x float>
+// CHECK:    [[RET:%.*]] = call <4 x i1> @llvm.[[TARGET]].isfinite.v4f32(<4 x float> [[CONV]])
+// CHECK:    ret <4 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool1x4 test_isfinite_double1x4(double1x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <2 x i1> @_{{.*}}test_isfinite_double2x1{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <2 x double> %{{.*}} to <2 x float>
+// CHECK:    [[RET:%.*]] = call <2 x i1> @llvm.[[TARGET]].isfinite.v2f32(<2 x float> [[CONV]])
+// CHECK:    ret <2 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool2x1 test_isfinite_double2x1(double2x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <4 x i1> @_{{.*}}test_isfinite_double2x2{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <4 x double> %{{.*}} to <4 x float>
+// CHECK:    [[RET:%.*]] = call <4 x i1> @llvm.[[TARGET]].isfinite.v4f32(<4 x float> [[CONV]])
+// CHECK:    ret <4 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool2x2 test_isfinite_double2x2(double2x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <6 x i1> @_{{.*}}test_isfinite_double2x3{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <6 x double> %{{.*}} to <6 x float>
+// CHECK:    [[RET:%.*]] = call <6 x i1> @llvm.[[TARGET]].isfinite.v6f32(<6 x float> [[CONV]])
+// CHECK:    ret <6 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool2x3 test_isfinite_double2x3(double2x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <8 x i1> @_{{.*}}test_isfinite_double2x4{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <8 x double> %{{.*}} to <8 x float>
+// CHECK:    [[RET:%.*]] = call <8 x i1> @llvm.[[TARGET]].isfinite.v8f32(<8 x float> [[CONV]])
+// CHECK:    ret <8 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool2x4 test_isfinite_double2x4(double2x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <3 x i1> @_{{.*}}test_isfinite_double3x1{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <3 x double> %{{.*}} to <3 x float>
+// CHECK:    [[RET:%.*]] = call <3 x i1> @llvm.[[TARGET]].isfinite.v3f32(<3 x float> [[CONV]])
+// CHECK:    ret <3 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool3x1 test_isfinite_double3x1(double3x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <6 x i1> @_{{.*}}test_isfinite_double3x2{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <6 x double> %{{.*}} to <6 x float>
+// CHECK:    [[RET:%.*]] = call <6 x i1> @llvm.[[TARGET]].isfinite.v6f32(<6 x float> [[CONV]])
+// CHECK:    ret <6 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool3x2 test_isfinite_double3x2(double3x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <9 x i1> @_{{.*}}test_isfinite_double3x3{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <9 x double> %{{.*}} to <9 x float>
+// CHECK:    [[RET:%.*]] = call <9 x i1> @llvm.[[TARGET]].isfinite.v9f32(<9 x float> [[CONV]])
+// CHECK:    ret <9 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool3x3 test_isfinite_double3x3(double3x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <12 x i1> @_{{.*}}test_isfinite_double3x4{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <12 x double> %{{.*}} to <12 x float>
+// CHECK:    [[RET:%.*]] = call <12 x i1> @llvm.[[TARGET]].isfinite.v12f32(<12 x float> [[CONV]])
+// CHECK:    ret <12 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool3x4 test_isfinite_double3x4(double3x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <4 x i1> @_{{.*}}test_isfinite_double4x1{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <4 x double> %{{.*}} to <4 x float>
+// CHECK:    [[RET:%.*]] = call <4 x i1> @llvm.[[TARGET]].isfinite.v4f32(<4 x float> [[CONV]])
+// CHECK:    ret <4 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool4x1 test_isfinite_double4x1(double4x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <8 x i1> @_{{.*}}test_isfinite_double4x2{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <8 x double> %{{.*}} to <8 x float>
+// CHECK:    [[RET:%.*]] = call <8 x i1> @llvm.[[TARGET]].isfinite.v8f32(<8 x float> [[CONV]])
+// CHECK:    ret <8 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool4x2 test_isfinite_double4x2(double4x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <12 x i1> @_{{.*}}test_isfinite_double4x3{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <12 x double> %{{.*}} to <12 x float>
+// CHECK:    [[RET:%.*]] = call <12 x i1> @llvm.[[TARGET]].isfinite.v12f32(<12 x float> [[CONV]])
+// CHECK:    ret <12 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool4x3 test_isfinite_double4x3(double4x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define {{.*}} <16 x i1> @_{{.*}}test_isfinite_double4x4{{.*}}(
+// CHECK:    [[CONV:%.*]] = fptrunc {{.*}} <16 x double> %{{.*}} to <16 x float>
+// CHECK:    [[RET:%.*]] = call <16 x i1> @llvm.[[TARGET]].isfinite.v16f32(<16 x float> [[CONV]])
+// CHECK:    ret <16 x i1> [[RET]]
+// expected-warning at +1 {{'isfinite' is deprecated: In 202x 64 bit API lowering for isfinite is deprecated. Explicitly cast parameters to 32 or 16 bit types.}}
+bool4x4 test_isfinite_double4x4(double4x4 p0) { return isfinite(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/isfinite_mat.hlsl b/clang/test/CodeGenHLSL/builtins/isfinite_mat.hlsl
new file mode 100644
index 00000000000000..886f4ef2d071d9
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/isfinite_mat.hlsl
@@ -0,0 +1,182 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-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-library %s -fnative-half-type -fnative-int16-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-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK,NO_HALF
+
+// CHECK-LABEL: define hidden {{.*}}noundef <2 x i1> @_{{.*}}test_isfinite_float1x2{{.*}}(
+// DXCHECK: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF:dx]].isfinite.v2f32(
+// SPVCHECK: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF:spv]].isfinite.v2f32(
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool1x2 test_isfinite_float1x2(float1x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <3 x i1> @_{{.*}}test_isfinite_float1x3{{.*}}(
+// CHECK: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool1x3 test_isfinite_float1x3(float1x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <4 x i1> @_{{.*}}test_isfinite_float1x4{{.*}}(
+// CHECK: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool1x4 test_isfinite_float1x4(float1x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <2 x i1> @_{{.*}}test_isfinite_float2x1{{.*}}(
+// CHECK: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool2x1 test_isfinite_float2x1(float2x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <4 x i1> @_{{.*}}test_isfinite_float2x2{{.*}}(
+// CHECK: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool2x2 test_isfinite_float2x2(float2x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <6 x i1> @_{{.*}}test_isfinite_float2x3{{.*}}(
+// CHECK: %hlsl.isfinite = call <6 x i1> @llvm.[[ICF]].isfinite.v6f32
+// CHECK: ret <6 x i1> %hlsl.isfinite
+bool2x3 test_isfinite_float2x3(float2x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <8 x i1> @_{{.*}}test_isfinite_float2x4{{.*}}(
+// CHECK: %hlsl.isfinite = call <8 x i1> @llvm.[[ICF]].isfinite.v8f32
+// CHECK: ret <8 x i1> %hlsl.isfinite
+bool2x4 test_isfinite_float2x4(float2x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <3 x i1> @_{{.*}}test_isfinite_float3x1{{.*}}(
+// CHECK: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool3x1 test_isfinite_float3x1(float3x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <6 x i1> @_{{.*}}test_isfinite_float3x2{{.*}}(
+// CHECK: %hlsl.isfinite = call <6 x i1> @llvm.[[ICF]].isfinite.v6f32
+// CHECK: ret <6 x i1> %hlsl.isfinite
+bool3x2 test_isfinite_float3x2(float3x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <9 x i1> @_{{.*}}test_isfinite_float3x3{{.*}}(
+// CHECK: %hlsl.isfinite = call <9 x i1> @llvm.[[ICF]].isfinite.v9f32
+// CHECK: ret <9 x i1> %hlsl.isfinite
+bool3x3 test_isfinite_float3x3(float3x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <12 x i1> @_{{.*}}test_isfinite_float3x4{{.*}}(
+// CHECK: %hlsl.isfinite = call <12 x i1> @llvm.[[ICF]].isfinite.v12f32
+// CHECK: ret <12 x i1> %hlsl.isfinite
+bool3x4 test_isfinite_float3x4(float3x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <4 x i1> @_{{.*}}test_isfinite_float4x1{{.*}}(
+// CHECK: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool4x1 test_isfinite_float4x1(float4x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <8 x i1> @_{{.*}}test_isfinite_float4x2{{.*}}(
+// CHECK: %hlsl.isfinite = call <8 x i1> @llvm.[[ICF]].isfinite.v8f32
+// CHECK: ret <8 x i1> %hlsl.isfinite
+bool4x2 test_isfinite_float4x2(float4x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <12 x i1> @_{{.*}}test_isfinite_float4x3{{.*}}(
+// CHECK: %hlsl.isfinite = call <12 x i1> @llvm.[[ICF]].isfinite.v12f32
+// CHECK: ret <12 x i1> %hlsl.isfinite
+bool4x3 test_isfinite_float4x3(float4x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <16 x i1> @_{{.*}}test_isfinite_float4x4{{.*}}(
+// CHECK: %hlsl.isfinite = call <16 x i1> @llvm.[[ICF]].isfinite.v16f32
+// CHECK: ret <16 x i1> %hlsl.isfinite
+bool4x4 test_isfinite_float4x4(float4x4 p0) { return isfinite(p0); }
+
+
+// CHECK-LABEL: define hidden {{.*}}noundef <2 x i1> @_{{.*}}test_isfinite_half1x2{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f16
+// NO_HALF: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool1x2 test_isfinite_half1x2(half1x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <3 x i1> @_{{.*}}test_isfinite_half1x3{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f16
+// NO_HALF: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool1x3 test_isfinite_half1x3(half1x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <4 x i1> @_{{.*}}test_isfinite_half1x4{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f16
+// NO_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool1x4 test_isfinite_half1x4(half1x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <2 x i1> @_{{.*}}test_isfinite_half2x1{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f16
+// NO_HALF: %hlsl.isfinite = call <2 x i1> @llvm.[[ICF]].isfinite.v2f32
+// CHECK: ret <2 x i1> %hlsl.isfinite
+bool2x1 test_isfinite_half2x1(half2x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <4 x i1> @_{{.*}}test_isfinite_half2x2{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f16
+// NO_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool2x2 test_isfinite_half2x2(half2x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <6 x i1> @_{{.*}}test_isfinite_half2x3{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <6 x i1> @llvm.[[ICF]].isfinite.v6f16
+// NO_HALF: %hlsl.isfinite = call <6 x i1> @llvm.[[ICF]].isfinite.v6f32
+// CHECK: ret <6 x i1> %hlsl.isfinite
+bool2x3 test_isfinite_half2x3(half2x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <8 x i1> @_{{.*}}test_isfinite_half2x4{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <8 x i1> @llvm.[[ICF]].isfinite.v8f16
+// NO_HALF: %hlsl.isfinite = call <8 x i1> @llvm.[[ICF]].isfinite.v8f32
+// CHECK: ret <8 x i1> %hlsl.isfinite
+bool2x4 test_isfinite_half2x4(half2x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <3 x i1> @_{{.*}}test_isfinite_half3x1{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f16
+// NO_HALF: %hlsl.isfinite = call <3 x i1> @llvm.[[ICF]].isfinite.v3f32
+// CHECK: ret <3 x i1> %hlsl.isfinite
+bool3x1 test_isfinite_half3x1(half3x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <6 x i1> @_{{.*}}test_isfinite_half3x2{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <6 x i1> @llvm.[[ICF]].isfinite.v6f16
+// NO_HALF: %hlsl.isfinite = call <6 x i1> @llvm.[[ICF]].isfinite.v6f32
+// CHECK: ret <6 x i1> %hlsl.isfinite
+bool3x2 test_isfinite_half3x2(half3x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <9 x i1> @_{{.*}}test_isfinite_half3x3{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <9 x i1> @llvm.[[ICF]].isfinite.v9f16
+// NO_HALF: %hlsl.isfinite = call <9 x i1> @llvm.[[ICF]].isfinite.v9f32
+// CHECK: ret <9 x i1> %hlsl.isfinite
+bool3x3 test_isfinite_half3x3(half3x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <12 x i1> @_{{.*}}test_isfinite_half3x4{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <12 x i1> @llvm.[[ICF]].isfinite.v12f16
+// NO_HALF: %hlsl.isfinite = call <12 x i1> @llvm.[[ICF]].isfinite.v12f32
+// CHECK: ret <12 x i1> %hlsl.isfinite
+bool3x4 test_isfinite_half3x4(half3x4 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <4 x i1> @_{{.*}}test_isfinite_half4x1{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f16
+// NO_HALF: %hlsl.isfinite = call <4 x i1> @llvm.[[ICF]].isfinite.v4f32
+// CHECK: ret <4 x i1> %hlsl.isfinite
+bool4x1 test_isfinite_half4x1(half4x1 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <8 x i1> @_{{.*}}test_isfinite_half4x2{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <8 x i1> @llvm.[[ICF]].isfinite.v8f16
+// NO_HALF: %hlsl.isfinite = call <8 x i1> @llvm.[[ICF]].isfinite.v8f32
+// CHECK: ret <8 x i1> %hlsl.isfinite
+bool4x2 test_isfinite_half4x2(half4x2 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <12 x i1> @_{{.*}}test_isfinite_half4x3{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <12 x i1> @llvm.[[ICF]].isfinite.v12f16
+// NO_HALF: %hlsl.isfinite = call <12 x i1> @llvm.[[ICF]].isfinite.v12f32
+// CHECK: ret <12 x i1> %hlsl.isfinite
+bool4x3 test_isfinite_half4x3(half4x3 p0) { return isfinite(p0); }
+
+// CHECK-LABEL: define hidden {{.*}}noundef <16 x i1> @_{{.*}}test_isfinite_half4x4{{.*}}(
+// NATIVE_HALF: %hlsl.isfinite = call <16 x i1> @llvm.[[ICF]].isfinite.v16f16
+// NO_HALF: %hlsl.isfinite = call <16 x i1> @llvm.[[ICF]].isfinite.v16f32
+// CHECK: ret <16 x i1> %hlsl.isfinite
+bool4x4 test_isfinite_half4x4(half4x4 p0) { return isfinite(p0); }
diff --git a/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl
index 03892c50fa65d1..29bc17e4fc10c9 100644
--- a/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/isfinite-errors.hlsl
@@ -1,4 +1,3 @@
-
 // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
 
 bool test_too_few_arg() {
diff --git a/clang/test/SemaHLSL/BuiltIns/isfinite_mat-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isfinite_mat-errors.hlsl
new file mode 100644
index 00000000000000..b95281459bf1c5
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/isfinite_mat-errors.hlsl
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
+
+bool2x2 test_too_few_arg() {
+  return __builtin_hlsl_elementwise_isfinite();
+  // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool2x2 test_too_many_arg(float2x2 p0) {
+  return __builtin_hlsl_elementwise_isfinite(p0, p0);
+  // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+bool2x2 test_builtin_isfinite_int_matrix(int2x2 p0) {
+  return __builtin_hlsl_elementwise_isfinite(p0);
+  // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int2x2' (aka 'matrix<int, 2, 2>'))}}
+}
+
+bool2x2 test_builtin_isfinite_double_matrix(double2x2 p0) {
+  return __builtin_hlsl_elementwise_isfinite(p0);
+  // expected-error at -1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double2x2' (aka 'matrix<double, 2, 2>'))}}
+}

>From 85b475da08bc84925d773de4bb3453e4599ffc23 Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Tue, 29 Sep 2026 14:08:07 -0600
Subject: [PATCH 3/5] Add long vector tests

---
 clang/test/CodeGenHLSL/builtins/isfinite.hlsl | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/clang/test/CodeGenHLSL/builtins/isfinite.hlsl b/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
index d549a255a765f8..aa6158167926a4 100644
--- a/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/isfinite.hlsl
@@ -36,6 +36,13 @@ bool3 test_isfinite_float3(float3 p0) { return isfinite(p0); }
 // CHECK: ret <4 x i1> %hlsl.isfinite
 bool4 test_isfinite_float4(float4 p0) { return isfinite(p0); }
 
+// CHECK: define hidden [[FN_TYPE]]noundef <5 x i1> @
+// CHECK: %hlsl.isfinite = call <5 x i1> @llvm.[[ICF]].isfinite.v5f32
+// CHECK: ret <5 x i1> %hlsl.isfinite
+vector<bool, 5> test_isfinite_float5(vector<float, 5> p0) {
+  return isfinite(p0);
+}
+
 // CHECK: define hidden [[FN_TYPE]]noundef i1 @
 // NATIVE_HALF: %hlsl.isfinite = call i1 @llvm.[[ICF]].isfinite.f16(
 // NO_HALF: %hlsl.isfinite = call i1 @llvm.[[ICF]].isfinite.f32(
@@ -60,3 +67,11 @@ bool3 test_isfinite_half3(half3 p0) { return isfinite(p0); }
 // CHECK: ret <4 x i1> %hlsl.isfinite
 bool4 test_isfinite_half4(half4 p0) { return isfinite(p0); }
 
+// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <5 x i1> @
+// NATIVE_HALF: %hlsl.isfinite = call <5 x i1> @llvm.[[ICF]].isfinite.v5f16
+// NO_HALF: %hlsl.isfinite = call <5 x i1> @llvm.[[ICF]].isfinite.v5f32(
+// CHECK: ret <5 x i1> %hlsl.isfinite
+vector<bool, 5> test_isfinite_half5(vector<half, 5> p0) {
+  return isfinite(p0);
+}
+

>From 85f68cbfd03c445669dbced116356f35853a15b2 Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Mon, 5 Oct 2026 17:40:26 -0600
Subject: [PATCH 4/5] [SPIR-V] Emulate OpIsFinite only for shaders

---
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  9 +++++++++
 .../SPIRV/hlsl-intrinsics/OpIsFinite.ll       | 20 ++++---------------
 2 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 3f90b3992208cf..d6d1e58a252a90 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3435,6 +3435,15 @@ bool SPIRVInstructionSelector::selectOpIsFinite(Register ResVReg,
   Register TypeID = GR.getSPIRVTypeID(ResType);
   const DebugLoc &DL = I.getDebugLoc();
 
+  if (!STI.isShader()) {
+    BuildMI(BB, I, DL, TII.get(SPIRV::OpIsFinite))
+        .addDef(ResVReg)
+        .addUse(TypeID)
+        .addUse(Src)
+        .constrainAllUses(TII, TRI, RBI);
+    return true;
+  }
+
   Register IsInfReg = MRI->createVirtualRegister(&SPIRV::IDRegClass);
   BuildMI(BB, I, DL, TII.get(SPIRV::OpIsInf))
       .addDef(IsInfReg)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
index 4829558aa3e3bd..0455e715a349d2 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
@@ -12,10 +12,7 @@ define noundef i1 @isfinite_half(half noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]]
-  ; CHECK: %[[#isinf:]] = OpIsInf %[[#bool]] %[[#arg0]]
-  ; CHECK: %[[#isnan:]] = OpIsNan %[[#bool]] %[[#arg0]]
-  ; CHECK: %[[#or:]] = OpLogicalOr %[[#bool]] %[[#isinf]] %[[#isnan]]
-  ; CHECK: %[[#]] = OpLogicalNot %[[#bool]] %[[#or]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
   %hlsl.isfinite = call i1 @llvm.spv.isfinite.f16(half %a)
   ret i1 %hlsl.isfinite
 }
@@ -24,10 +21,7 @@ define noundef i1 @isfinite_float(float noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]]
-  ; CHECK: %[[#isinf:]] = OpIsInf %[[#bool]] %[[#arg0]]
-  ; CHECK: %[[#isnan:]] = OpIsNan %[[#bool]] %[[#arg0]]
-  ; CHECK: %[[#or:]] = OpLogicalOr %[[#bool]] %[[#isinf]] %[[#isnan]]
-  ; CHECK: %[[#]] = OpLogicalNot %[[#bool]] %[[#or]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
   %hlsl.isfinite = call i1 @llvm.spv.isfinite.f32(float %a)
   ret i1 %hlsl.isfinite
 }
@@ -36,10 +30,7 @@ define noundef <4 x i1> @isfinite_half4(<4 x half> noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
-  ; CHECK: %[[#isinf:]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
-  ; CHECK: %[[#isnan:]] = OpIsNan %[[#vec4_bool]] %[[#arg0]]
-  ; CHECK: %[[#or:]] = OpLogicalOr %[[#vec4_bool]] %[[#isinf]] %[[#isnan]]
-  ; CHECK: %[[#]] = OpLogicalNot %[[#vec4_bool]] %[[#or]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
   %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f16(<4 x half> %a)
   ret <4 x i1> %hlsl.isfinite
 }
@@ -48,10 +39,7 @@ define noundef <4 x i1> @isfinite_float4(<4 x float> noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
-  ; CHECK: %[[#isinf:]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
-  ; CHECK: %[[#isnan:]] = OpIsNan %[[#vec4_bool]] %[[#arg0]]
-  ; CHECK: %[[#or:]] = OpLogicalOr %[[#vec4_bool]] %[[#isinf]] %[[#isnan]]
-  ; CHECK: %[[#]] = OpLogicalNot %[[#vec4_bool]] %[[#or]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
   %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f32(<4 x float> %a)
   ret <4 x i1> %hlsl.isfinite
 }

>From 89532d8d2a3f1af86319b371564c6a99688fabe6 Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Tue, 6 Oct 2026 14:42:40 -0600
Subject: [PATCH 5/5] Update tests

Original test preserved as llvm/test/CodeGen/SPIRV/opencl/isfinite.ll.
Though OpIsFinite.ll is really misnamed now, the name is retained for the sake of continuity.
---
 .../SPIRV/hlsl-intrinsics/OpIsFinite.ll       | 23 +++++++---
 llvm/test/CodeGen/SPIRV/opencl/isfinite.ll    | 45 +++++++++++++++++++
 2 files changed, 62 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/opencl/isfinite.ll

diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
index 0455e715a349d2..d32ac97ab19953 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsFinite.ll
@@ -1,5 +1,4 @@
-; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val --target-env spv1.4 %}
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan-library %s -o - | FileCheck %s
 
 ; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
 ; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
@@ -12,7 +11,10 @@ define noundef i1 @isfinite_half(half noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#bool]] %[[#or]]
   %hlsl.isfinite = call i1 @llvm.spv.isfinite.f16(half %a)
   ret i1 %hlsl.isfinite
 }
@@ -21,7 +23,10 @@ define noundef i1 @isfinite_float(float noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#bool]] %[[#or]]
   %hlsl.isfinite = call i1 @llvm.spv.isfinite.f32(float %a)
   ret i1 %hlsl.isfinite
 }
@@ -30,7 +35,10 @@ define noundef <4 x i1> @isfinite_half4(<4 x half> noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#vec4_bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#vec4_bool]] %[[#or]]
   %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f16(<4 x half> %a)
   ret <4 x i1> %hlsl.isfinite
 }
@@ -39,7 +47,10 @@ define noundef <4 x i1> @isfinite_float4(<4 x float> noundef %a) {
 entry:
   ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
   ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
-  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isinf:]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#isnan:]] = OpIsNan %[[#vec4_bool]] %[[#arg0]]
+  ; CHECK: %[[#or:]] = OpLogicalOr %[[#vec4_bool]] %[[#isinf]] %[[#isnan]]
+  ; CHECK: %[[#]] = OpLogicalNot %[[#vec4_bool]] %[[#or]]
   %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f32(<4 x float> %a)
   ret <4 x i1> %hlsl.isfinite
 }
diff --git a/llvm/test/CodeGen/SPIRV/opencl/isfinite.ll b/llvm/test/CodeGen/SPIRV/opencl/isfinite.ll
new file mode 100644
index 00000000000000..0455e715a349d2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl/isfinite.ll
@@ -0,0 +1,45 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val --target-env spv1.4 %}
+
+; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
+; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
+; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
+; CHECK-DAG: %[[#bool:]] = OpTypeBool
+; CHECK-DAG: %[[#vec4_bool:]] = OpTypeVector %[[#bool]] 4
+
+define noundef i1 @isfinite_half(half noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
+  %hlsl.isfinite = call i1 @llvm.spv.isfinite.f16(half %a)
+  ret i1 %hlsl.isfinite
+}
+
+define noundef i1 @isfinite_float(float noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#bool]] %[[#arg0]]
+  %hlsl.isfinite = call i1 @llvm.spv.isfinite.f32(float %a)
+  ret i1 %hlsl.isfinite
+}
+
+define noundef <4 x i1> @isfinite_half4(<4 x half> noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
+  %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f16(<4 x half> %a)
+  ret <4 x i1> %hlsl.isfinite
+}
+
+define noundef <4 x i1> @isfinite_float4(<4 x float> noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+  ; CHECK: %[[#]] = OpIsFinite %[[#vec4_bool]] %[[#arg0]]
+  %hlsl.isfinite = call <4 x i1> @llvm.spv.isfinite.v4f32(<4 x float> %a)
+  ret <4 x i1> %hlsl.isfinite
+}



More information about the cfe-commits mailing list