https://github.com/farzonl created 
https://github.com/llvm/llvm-project/pull/156570

fixes #148051

- update EmitHLSLBuiltinExpr in CGHLSLBuiltins.cpp to toggle intrinsics by 
target
- Add a GENERATE_HLSL_INTRINSIC_FUNCTION for isinf in CGHLSLRuntime.h
- Update the SPIRVInstructionSelector.cpp to emit the OpSinf instruction
- Updates the isinf.hlsl test to check spirv intrinsic generation
- add OpIsinf.ll  tests

>From b460c91f3867f9fd886db9b5950dbbf881622d5b Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlo...@microsoft.com>
Date: Fri, 29 Aug 2025 14:49:31 -0400
Subject: [PATCH] [SPIRV] Add OpInf support for isinf hlsl intrinsic

fixes #148051

- update EmitHLSLBuiltinExpr in CGHLSLBuiltins.cpp to toggle intrinsics by 
target
- Add a GENERATE_HLSL_INTRINSIC_FUNCTION for isinf in CGHLSLRuntime.h
- Update the SPIRVInstructionSelector.cpp to emit the OpSinf instruction
- Updates the isinf.hlsl test to check spirv intrinsic generation
- add OpIsinf.ll  tests
---
 clang/lib/CodeGen/CGHLSLBuiltins.cpp          |  4 +-
 clang/lib/CodeGen/CGHLSLRuntime.h             |  1 +
 clang/test/CodeGenHLSL/builtins/isinf.hlsl    | 81 +++++++++++--------
 llvm/include/llvm/IR/IntrinsicsSPIRV.td       |  2 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 16 ++++
 .../CodeGen/SPIRV/hlsl-intrinsics/OpIsInf.ll  | 45 +++++++++++
 6 files changed, 115 insertions(+), 34 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsInf.ll

diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp 
b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 32e930b27c4e0..7962dec4d7efe 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -536,8 +536,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
     }
     if (!E->getArg(0)->getType()->hasFloatingRepresentation())
       llvm_unreachable("isinf operand must have a float representation");
-    return Builder.CreateIntrinsic(retType, Intrinsic::dx_isinf,
-                                   ArrayRef<Value *>{Op0}, nullptr, 
"dx.isinf");
+    return Builder.CreateIntrinsic(retType, 
CGM.getHLSLRuntime().getIsInfIntrinsic(),
+                                   ArrayRef<Value *>{Op0}, nullptr, 
"hlsl.isinf");
   }
   case Builtin::BI__builtin_hlsl_mad: {
     Value *M = EmitScalarExpr(E->getArg(0));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h 
b/clang/lib/CodeGen/CGHLSLRuntime.h
index b872f9ef0e9b6..0582be3d99ec4 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -91,6 +91,7 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
   GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,
                                    flattened_thread_id_in_group)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(IsInf, isinf)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize)
   GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
diff --git a/clang/test/CodeGenHLSL/builtins/isinf.hlsl 
b/clang/test/CodeGenHLSL/builtins/isinf.hlsl
index 4d53daaafb692..dc869a64a65b7 100644
--- a/clang/test/CodeGenHLSL/builtins/isinf.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/isinf.hlsl
@@ -1,45 +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,NATIVE_HALF
+// 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,NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK,NO_HALF
 
-// CHECK: define hidden noundef i1 @
-// NATIVE_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f16(
-// NO_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f32(
-// CHECK: ret i1 %dx.isinf
+// 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.isinf = call i1 @llvm.[[ICF:dx]].isinf.f32(
+// SPVCHECK: %hlsl.isinf = call i1 @llvm.[[ICF:spv]].isinf.f32(
+// CHECK: ret i1 %hlsl.isinf
+bool test_isinf_float(float p0) { return isinf(p0); }
+
+// CHECK: define hidden [[FN_TYPE]]noundef i1 @
+// NATIVE_HALF: %hlsl.isinf = call i1 @llvm.[[ICF]].isinf.f16(
+// NO_HALF: %hlsl.isinf = call i1 @llvm.[[ICF]].isinf.f32(
+// CHECK: ret i1 %hlsl.isinf
 bool test_isinf_half(half p0) { return isinf(p0); }
-// CHECK: define hidden noundef <2 x i1> @
-// NATIVE_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f16
-// NO_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32(
-// CHECK: ret <2 x i1> %dx.isinf
+
+// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
+// NATIVE_HALF: %hlsl.isinf = call <2 x i1> @llvm.[[ICF]].isinf.v2f16
+// NO_HALF: %hlsl.isinf = call <2 x i1> @llvm.[[ICF]].isinf.v2f32(
+// CHECK: ret <2 x i1> %hlsl.isinf
 bool2 test_isinf_half2(half2 p0) { return isinf(p0); }
-// NATIVE_HALF: define hidden noundef <3 x i1> @
-// NATIVE_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f16
-// NO_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32(
-// CHECK: ret <3 x i1> %dx.isinf
+
+// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <3 x i1> @
+// NATIVE_HALF: %hlsl.isinf = call <3 x i1> @llvm.[[ICF]].isinf.v3f16
+// NO_HALF: %hlsl.isinf = call <3 x i1> @llvm.[[ICF]].isinf.v3f32(
+// CHECK: ret <3 x i1> %hlsl.isinf
 bool3 test_isinf_half3(half3 p0) { return isinf(p0); }
-// NATIVE_HALF: define hidden noundef <4 x i1> @
-// NATIVE_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f16
-// NO_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32(
-// CHECK: ret <4 x i1> %dx.isinf
+
+// NATIVE_HALF: define hidden [[FN_TYPE]]noundef <4 x i1> @
+// NATIVE_HALF: %hlsl.isinf = call <4 x i1> @llvm.[[ICF]].isinf.v4f16
+// NO_HALF: %hlsl.isinf = call <4 x i1> @llvm.[[ICF]].isinf.v4f32(
+// CHECK: ret <4 x i1> %hlsl.isinf
 bool4 test_isinf_half4(half4 p0) { return isinf(p0); }
 
-// CHECK: define hidden noundef i1 @
-// CHECK: %dx.isinf = call i1 @llvm.dx.isinf.f32(
-// CHECK: ret i1 %dx.isinf
-bool test_isinf_float(float p0) { return isinf(p0); }
-// CHECK: define hidden noundef <2 x i1> @
-// CHECK: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32
-// CHECK: ret <2 x i1> %dx.isinf
+
+// CHECK: define hidden [[FN_TYPE]]noundef <2 x i1> @
+// CHECK: %hlsl.isinf = call <2 x i1> @llvm.[[ICF]].isinf.v2f32
+// CHECK: ret <2 x i1> %hlsl.isinf
 bool2 test_isinf_float2(float2 p0) { return isinf(p0); }
-// CHECK: define hidden noundef <3 x i1> @
-// CHECK: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32
-// CHECK: ret <3 x i1> %dx.isinf
+
+// CHECK: define hidden [[FN_TYPE]]noundef <3 x i1> @
+// CHECK: %hlsl.isinf = call <3 x i1> @llvm.[[ICF]].isinf.v3f32
+// CHECK: ret <3 x i1> %hlsl.isinf
 bool3 test_isinf_float3(float3 p0) { return isinf(p0); }
-// CHECK: define hidden noundef <4 x i1> @
-// CHECK: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32
-// CHECK: ret <4 x i1> %dx.isinf
+
+// CHECK: define hidden [[FN_TYPE]]noundef <4 x i1> @
+// CHECK: %hlsl.isinf = call <4 x i1> @llvm.[[ICF]].isinf.v4f32
+// CHECK: ret <4 x i1> %hlsl.isinf
 bool4 test_isinf_float4(float4 p0) { return isinf(p0); }
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td 
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 05e54bdbd58e5..bc026fa33c769 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -85,6 +85,8 @@ let TargetPrefix = "spv" in {
   def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], 
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
   def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>], 
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
   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_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], 
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
     [IntrNoMem] >;
   def int_spv_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], 
[llvm_anyfloat_ty], [IntrNoMem]>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp 
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 5d2bb8765efbb..f00ac47900ef5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -204,6 +204,9 @@ class SPIRVInstructionSelector : public InstructionSelector 
{
   bool selectIntegerDotExpansion(Register ResVReg, const SPIRVType *ResType,
                                  MachineInstr &I) const;
 
+  bool selectOpIsInf(Register ResVReg, const SPIRVType *ResType,
+                 MachineInstr &I) const;
+
   template <bool Signed>
   bool selectDot4AddPacked(Register ResVReg, const SPIRVType *ResType,
                            MachineInstr &I) const;
@@ -2042,6 +2045,17 @@ bool SPIRVInstructionSelector::selectIntegerDotExpansion(
   return Result;
 }
 
+bool SPIRVInstructionSelector::selectOpIsInf(Register ResVReg,
+                                                   const SPIRVType *ResType,
+                                                   MachineInstr &I) const {
+  MachineBasicBlock &BB = *I.getParent();
+  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsInf))
+      .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,
@@ -3183,6 +3197,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register 
ResVReg,
     return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
   case Intrinsic::spv_frac:
     return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
+  case Intrinsic::spv_isinf:
+    return selectOpIsInf(ResVReg, ResType, I);
   case Intrinsic::spv_normalize:
     return selectExtInst(ResVReg, ResType, I, CL::normalize, GL::Normalize);
   case Intrinsic::spv_refract:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsInf.ll 
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsInf.ll
new file mode 100644
index 0000000000000..e9ac1e1997400
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/OpIsInf.ll
@@ -0,0 +1,45 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | 
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %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 @isinf_half(half noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_16]]
+  ; CHECK: %[[#]] = OpIsInf %[[#bool]] %[[#arg0]]
+  %hlsl.isinf = call i1 @llvm.spv.isinf.f16(half %a)
+  ret i1 %hlsl.isinf
+}
+
+define noundef i1 @isinf_float(float noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#float_32]]
+  ; CHECK: %[[#]] = OpIsInf %[[#bool]] %[[#arg0]]
+  %hlsl.isinf = call i1 @llvm.spv.isinf.f32(float %a)
+  ret i1 %hlsl.isinf
+}
+
+define noundef <4 x i1> @isinf_half4(<4 x half> noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+  ; CHECK: %[[#]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
+  %hlsl.isinf = call <4 x i1> @llvm.spv.isinf.v4f16(<4 x half> %a)
+  ret <4 x i1> %hlsl.isinf
+}
+
+define noundef <4 x i1> @isinf_float4(<4 x float> noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpFunction %[[#vec4_bool]] None %[[#]]
+  ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+  ; CHECK: %[[#]] = OpIsInf %[[#vec4_bool]] %[[#arg0]]
+  %hlsl.isinf = call <4 x i1> @llvm.spv.isinf.v4f32(<4 x float> %a)
+  ret <4 x i1> %hlsl.isinf
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to