[clang] [llvm] [HLSL][DXIL][SPIRV] Implementation of an abstraction for intrinsic selection of HLSL backends (PR #87171)

Farzon Lotfi via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 4 14:26:55 PDT 2024


https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/87171

>From 6e088142af4196f11bc006e0024d4ca0ac4e08f0 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Thu, 28 Mar 2024 21:05:36 -0400
Subject: [PATCH 01/11] [HLSL][DXIL][SPIRV] Intrinsic unification PR

---
 clang/include/clang/Basic/Builtins.td         |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp               |  19 ++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h      | 112 +++++++
 clang/lib/Sema/SemaChecking.cpp               |   1 +
 clang/test/CodeGenHLSL/builtins/all.hlsl      | 277 ++++++++++++++++++
 llvm/include/llvm/IR/Intrinsics.td            |  12 +
 llvm/include/llvm/IR/IntrinsicsDirectX.td     |   4 +-
 llvm/include/llvm/IR/IntrinsicsSPIRV.td       |   3 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  19 ++
 .../test/CodeGen/SPIRV/hlsl-intrinsics/all.ll |  95 ++++++
 10 files changed, 545 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/all.hlsl
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index f421223ff087de..d6ceb450bd106b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4587,6 +4587,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
 }
 
 // HLSL
+def HLSLAll : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_all"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(...)";
+}
+
 def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_any"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2537e715b63ee4..2acf799f168785 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -51,6 +51,7 @@
 #include "llvm/IR/IntrinsicsR600.h"
 #include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/IntrinsicsS390.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/IR/IntrinsicsVE.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/IntrinsicsX86.h"
@@ -18166,12 +18167,30 @@ Intrinsic::ID getDotProductIntrinsic(QualType QT, int elementCount) {
   return Intrinsic::dx_udot;
 }
 
+Intrinsic::ID getAllIntrinsic(const llvm::Triple::ArchType Arch) {
+  switch (Arch) {
+  case llvm::Triple::dxil:
+    return Intrinsic::dx_all;
+  case llvm::Triple::spirv:
+    return Intrinsic::spv_all;
+  default:
+    llvm_unreachable("Input semantic not supported by target");
+  }
+}
+
 Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
                                             const CallExpr *E) {
   if (!getLangOpts().HLSL)
     return nullptr;
 
   switch (BuiltinID) {
+  case Builtin::BI__builtin_hlsl_elementwise_all: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    return Builder.CreateIntrinsic(
+        /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
+        getAllIntrinsic(CGM.getTarget().getTriple().getArch()),
+        ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 9fb6204f90c9a8..06409c6fc77417 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -100,6 +100,118 @@ double3 abs(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_abs)
 double4 abs(double4);
 
+//===----------------------------------------------------------------------===//
+// all builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn bool all(T x)
+/// \brief Returns True if all components of the \a x parameter are non-zero;
+/// otherwise, false. \param x The input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t4);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t4);
+#endif
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(bool);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(bool2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(bool3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(bool4);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(double4);
+
 //===----------------------------------------------------------------------===//
 // any builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3dcd18b3afc8b4..4c30cc3160ded5 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5563,6 +5563,7 @@ void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall,
 // returning an ExprError
 bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   switch (BuiltinID) {
+  case Builtin::BI__builtin_hlsl_elementwise_all:
   case Builtin::BI__builtin_hlsl_elementwise_any: {
     if (checkArgCount(*this, TheCall, 1))
       return true;
diff --git a/clang/test/CodeGenHLSL/builtins/all.hlsl b/clang/test/CodeGenHLSL/builtins/all.hlsl
new file mode 100644
index 00000000000000..b48daa287480ff
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/all.hlsl
@@ -0,0 +1,277 @@
+// 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,NATIVE_HALF,SPIR_NATIVE_HALF,SPIR_CHECK
+// 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,SPIR_NO_HALF,SPIR_CHECK
+// 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,DXIL_NATIVE_HALF,DXIL_CHECK
+// 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,DXIL_NO_HALF,DXIL_CHECK
+
+#ifdef __HLSL_ENABLE_16_BIT
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_int16_t(int16_t p0) { return all(p0); }
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v2i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v2i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_int16_t2(int16_t2 p0) { return all(p0); }
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v3i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v3i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_int16_t3(int16_t3 p0) { return all(p0); }
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v4i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v4i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_int16_t4(int16_t4 p0) { return all(p0); }
+
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_uint16_t(uint16_t p0) { return all(p0); }
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v2i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v2i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_uint16_t2(uint16_t2 p0) { return all(p0); }
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v3i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v3i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_uint16_t3(uint16_t3 p0) { return all(p0); }
+// DXIL_NATIVE_HALF: define noundef i1 @
+// SPIR_NATIVE_HALF: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v4i16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v4i16
+// NATIVE_HALF: ret i1 %hlsl.all
+bool test_all_uint16_t4(uint16_t4 p0) { return all(p0); }
+#endif // __HLSL_ENABLE_16_BIT
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.f16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.f16
+// DXIL_NO_HALF: %hlsl.all = call i1 @llvm.dx.all.f32
+// SPIR_NO_HALF: %hlsl.all = call i1 @llvm.spv.all.f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_half(half p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v2f16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v2f16
+// DXIL_NO_HALF: %hlsl.all = call i1 @llvm.dx.all.v2f32
+// SPIR_NO_HALF: %hlsl.all = call i1 @llvm.spv.all.v2f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_half2(half2 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v3f16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v3f16
+// DXIL_NO_HALF: %hlsl.all = call i1 @llvm.dx.all.v3f32
+// SPIR_NO_HALF: %hlsl.all = call i1 @llvm.spv.all.v3f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_half3(half3 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_NATIVE_HALF: %hlsl.all = call i1 @llvm.dx.all.v4f16
+// SPIR_NATIVE_HALF: %hlsl.all = call i1 @llvm.spv.all.v4f16
+// DXIL_NO_HALF: %hlsl.all = call i1 @llvm.dx.all.v4f32
+// SPIR_NO_HALF: %hlsl.all = call i1 @llvm.spv.all.v4f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_half4(half4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.f32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_float(float p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2f32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_float2(float2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3f32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_float3(float3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4f32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4f32
+// CHECK: ret i1 %hlsl.all
+bool test_all_float4(float4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.f64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.f64
+// CHECK: ret i1 %hlsl.all
+bool test_all_double(double p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2f64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2f64
+// CHECK: ret i1 %hlsl.all
+bool test_all_double2(double2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3f64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3f64
+// CHECK: ret i1 %hlsl.all
+bool test_all_double3(double3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4f64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4f64
+// CHECK: ret i1 %hlsl.all
+bool test_all_double4(double4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_int(int p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_int2(int2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_int3(int3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_int4(int4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint(uint p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint2(uint2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint3(uint3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4i32
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4i32
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint4(uint4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_int64_t(int64_t p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_int64_t2(int64_t2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_int64_t3(int64_t3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_int64_t4(int64_t4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint64_t(uint64_t p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint64_t2(uint64_t2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint64_t3(uint64_t3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4i64
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4i64
+// CHECK: ret i1 %hlsl.all
+bool test_all_uint64_t4(uint64_t4 p0) { return all(p0); }
+
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.i1
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.i1
+// CHECK: ret i1 %hlsl.all
+bool test_all_bool(bool p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v2i1
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v2i1
+// CHECK: ret i1 %hlsl.all
+bool test_all_bool2(bool2 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v3i1
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v3i1
+// CHECK: ret i1 %hlsl.all
+bool test_all_bool3(bool3 p0) { return all(p0); }
+// DXIL_CHECK: define noundef i1 @
+// SPIR_CHECK: define spir_func noundef i1 @
+// DXIL_CHECK: %hlsl.all = call i1 @llvm.dx.all.v4i1
+// SPIR_CHECK: %hlsl.all = call i1 @llvm.spv.all.v4i1
+// CHECK: ret i1 %hlsl.all
+bool test_all_bool4(bool4 p0) { return all(p0); }
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index c04f4c52692158..1163bd6c8fbaba 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -684,6 +684,18 @@ class DefaultAttrsIntrinsic<list<LLVMType> ret_types,
                             intr_properties, name,
                             sd_properties, /*disable_default_attributes*/ 0> {}
 
+// HLSL Intrinsic Classes
+class HLSLThreadId
+                : Intrinsic</*ret_types*/ [llvm_i32_ty], 
+                            /*param_types*/[llvm_i32_ty],
+                            /*intr_properties*/ [IntrNoMem, IntrWillReturn], 
+                            /*name*/ ""> {}
+class HLSLAll : Intrinsic</*ret_types*/ [llvm_i1_ty], 
+                            /*param_types*/[llvm_any_ty],
+                            /*intr_properties*/ [IntrNoMem, IntrWillReturn], 
+                            /*name*/ ""> {}
+
+
 /// ClangBuiltin - If this intrinsic exactly corresponds to a Clang builtin, this
 /// specifies the name of the builtin.  This provides automatic CBE and CFE
 /// support.
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index a871fac46b9fd5..c67102a14387f4 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -11,8 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 let TargetPrefix = "dx" in {
-
-def int_dx_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
+def int_dx_thread_id : HLSLThreadId;
 def int_dx_group_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
 def int_dx_thread_id_in_group : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
 def int_dx_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrWillReturn]>;
@@ -20,6 +19,7 @@ def int_dx_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMe
 def int_dx_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">,
     Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>;
 
+def int_dx_all  : HLSLAll;
 def int_dx_any  : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
 def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
 def int_dx_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; 
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 0eb09b1699aff4..f987d7928ab23f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -53,7 +53,8 @@ let TargetPrefix = "spv" in {
                                 ImmArg<ArgIndex<0>>]>;
 
   // The following intrinsic(s) are mirrored from IntrinsicsDirectX.td for HLSL support.
-  def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
+  def int_spv_thread_id : HLSLThreadId;
+  def int_spv_all  : HLSLAll;
   def int_spv_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">,
       Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>;
 }
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 49749b56345306..0a8383c3df4c76 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -144,6 +144,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
   bool selectAddrSpaceCast(Register ResVReg, const SPIRVType *ResType,
                            MachineInstr &I) const;
 
+  bool selectAll(Register ResVReg, const SPIRVType *ResType,
+                 MachineInstr &I) const;
+
   bool selectBitreverse(Register ResVReg, const SPIRVType *ResType,
                         MachineInstr &I) const;
 
@@ -1155,6 +1158,20 @@ static unsigned getBoolCmpOpcode(unsigned PredNum) {
   }
 }
 
+bool SPIRVInstructionSelector::selectAll(Register ResVReg,
+                                         const SPIRVType *ResType,
+                                         MachineInstr &I) const {
+  assert(I.getNumOperands() == 3);
+  assert(I.getOperand(2).isReg());
+
+  MachineBasicBlock &BB = *I.getParent();
+  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpAll))
+      .addDef(ResVReg)
+      .addUse(GR.getSPIRVTypeID(ResType))
+      .addUse(I.getOperand(2).getReg())
+      .constrainAllUses(TII, TRI, RBI);
+}
+
 bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
@@ -1785,6 +1802,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
     break;
   case Intrinsic::spv_thread_id:
     return selectSpvThreadId(ResVReg, ResType, I);
+  case Intrinsic::spv_all:
+    return selectAll(ResVReg, ResType, I);
   case Intrinsic::spv_lifetime_start:
   case Intrinsic::spv_lifetime_end: {
     unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll
new file mode 100644
index 00000000000000..c904ac08699355
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll
@@ -0,0 +1,95 @@
+; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; Note: The validator is wrong it wants the return to be a bool vector when it is bool scalar return
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Make sure spirv operation function calls for all are generated.
+
+; CHECK: OpMemoryModel Logical GLSL450
+
+define noundef i1 @all_bool(i1 noundef %a) {
+entry:
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.i1(i1 %a)
+  ret i1 %hlsl.all
+}
+
+define noundef i1 @all_int64_t(i64 noundef %p0) {
+entry:
+  %p0.addr = alloca i64, align 8
+  store i64 %p0, ptr %p0.addr, align 8
+  %0 = load i64, ptr %p0.addr, align 8
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.i64(i64 %0)
+  ret i1 %hlsl.all
+}
+
+
+define noundef i1 @all_int(i32 noundef %p0) {
+entry:
+  %p0.addr = alloca i32, align 4
+  store i32 %p0, ptr %p0.addr, align 4
+  %0 = load i32, ptr %p0.addr, align 4
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.i32(i32 %0)
+  ret i1 %hlsl.all
+}
+
+
+define noundef i1 @all_int16_t(i16 noundef %p0) {
+entry:
+  %p0.addr = alloca i16, align 2
+  store i16 %p0, ptr %p0.addr, align 2
+  %0 = load i16, ptr %p0.addr, align 2
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.i16(i16 %0)
+  ret i1 %hlsl.all
+}
+
+define noundef i1 @all_double(double noundef %p0) {
+entry:
+  %p0.addr = alloca double, align 8
+  store double %p0, ptr %p0.addr, align 8
+  %0 = load double, ptr %p0.addr, align 8
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.f64(double %0)
+  ret i1 %hlsl.all
+}
+
+
+define noundef i1 @all_float(float noundef %p0) {
+entry:
+  %p0.addr = alloca float, align 4
+  store float %p0, ptr %p0.addr, align 4
+  %0 = load float, ptr %p0.addr, align 4
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.f32(float %0)
+  ret i1 %hlsl.all
+}
+
+
+define noundef i1 @all_half(half noundef %p0) {
+entry:
+  %p0.addr = alloca half, align 2
+  store half %p0, ptr %p0.addr, align 2
+  %0 = load half, ptr %p0.addr, align 2
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.f16(half %0)
+  ret i1 %hlsl.all
+}
+
+
+define noundef i1 @all_bool4(<4 x i1> noundef %p0) {
+entry:
+  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
+  %hlsl.all = call i1 @llvm.spv.all.v4i1(<4 x i1> %p0)
+  ret i1 %hlsl.all
+}
+
+declare i1 @llvm.spv.all.v4i1(<4 x i1>)
+declare i1 @llvm.spv.all.i1(i1)
+declare i1 @llvm.spv.all.i16(i16)
+declare i1 @llvm.spv.all.i32(i32)
+declare i1 @llvm.spv.all.i64(i64)
+declare i1 @llvm.spv.all.f16(half)
+declare i1 @llvm.spv.all.f32(float)
+declare i1 @llvm.spv.all.f64(double)

>From c9f74a036cabb369603aa7c652c0a54fd17df6ce Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Mon, 1 Apr 2024 19:57:34 -0400
Subject: [PATCH 02/11] add a macro for switch statement, remove type classes

---
 clang/lib/CodeGen/CGBuiltin.cpp           | 16 ++-------
 clang/lib/CodeGen/CGHLSLRuntime.cpp       | 18 +++-------
 clang/lib/CodeGen/CGHLSLUtils.h           | 44 +++++++++++++++++++++++
 llvm/include/llvm/IR/Intrinsics.td        | 12 -------
 llvm/include/llvm/IR/IntrinsicsDirectX.td |  7 ++--
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |  4 +--
 6 files changed, 57 insertions(+), 44 deletions(-)
 create mode 100644 clang/lib/CodeGen/CGHLSLUtils.h

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2acf799f168785..92e9089cbe7bb7 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -13,6 +13,7 @@
 #include "ABIInfo.h"
 #include "CGCUDARuntime.h"
 #include "CGCXXABI.h"
+#include "CGHLSLUtils.h"
 #include "CGObjCRuntime.h"
 #include "CGOpenCLRuntime.h"
 #include "CGRecordLayout.h"
@@ -51,7 +52,6 @@
 #include "llvm/IR/IntrinsicsR600.h"
 #include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/IntrinsicsS390.h"
-#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/IR/IntrinsicsVE.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/IntrinsicsX86.h"
@@ -18167,17 +18167,6 @@ Intrinsic::ID getDotProductIntrinsic(QualType QT, int elementCount) {
   return Intrinsic::dx_udot;
 }
 
-Intrinsic::ID getAllIntrinsic(const llvm::Triple::ArchType Arch) {
-  switch (Arch) {
-  case llvm::Triple::dxil:
-    return Intrinsic::dx_all;
-  case llvm::Triple::spirv:
-    return Intrinsic::spv_all;
-  default:
-    llvm_unreachable("Input semantic not supported by target");
-  }
-}
-
 Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
                                             const CallExpr *E) {
   if (!getLangOpts().HLSL)
@@ -18188,7 +18177,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
         /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
-        getAllIntrinsic(CGM.getTarget().getTriple().getArch()),
+        CGHLSLUtils::get_hlsl_all_intrinsic(
+            CGM.getTarget().getTriple().getArch()),
         ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
   }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 794d93358b0a4c..c772049dbe3acc 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -14,11 +14,10 @@
 
 #include "CGHLSLRuntime.h"
 #include "CGDebugInfo.h"
+#include "CGHLSLUtils.h"
 #include "CodeGenModule.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetOptions.h"
-#include "llvm/IR/IntrinsicsDirectX.h"
-#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -343,18 +342,9 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
     return B.CreateCall(FunctionCallee(DxGroupIndex));
   }
   if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
-    llvm::Function *ThreadIDIntrinsic;
-    switch (CGM.getTarget().getTriple().getArch()) {
-    case llvm::Triple::dxil:
-      ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::dx_thread_id);
-      break;
-    case llvm::Triple::spirv:
-      ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::spv_thread_id);
-      break;
-    default:
-      llvm_unreachable("Input semantic not supported by target");
-      break;
-    }
+    llvm::Function *ThreadIDIntrinsic =
+        CGM.getIntrinsic(CGHLSLUtils::get_hlsl_thread_id_intrinsic(
+            CGM.getTarget().getTriple().getArch()));
     return buildVectorInput(B, ThreadIDIntrinsic, Ty);
   }
   assert(false && "Unhandled parameter attribute");
diff --git a/clang/lib/CodeGen/CGHLSLUtils.h b/clang/lib/CodeGen/CGHLSLUtils.h
new file mode 100644
index 00000000000000..ca29835105aa87
--- /dev/null
+++ b/clang/lib/CodeGen/CGHLSLUtils.h
@@ -0,0 +1,44 @@
+
+//===----- CGHLSLUtils.h - Utility functions for HLSL CodeGen ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This File Provides utility function for HLSL code generation.
+// It is used to abstract away implementation details of backends.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H
+#define LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H
+
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsDirectX.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+
+// Define the function generator macro
+#define GENERATE_HLSL_INTRINSIC_FUNCTION(name)                                 \
+  static llvm::Intrinsic::ID get_hlsl_##name##_intrinsic(                      \
+      const llvm::Triple::ArchType Arch) {                                     \
+    switch (Arch) {                                                            \
+    case llvm::Triple::dxil:                                                   \
+      return llvm::Intrinsic::dx_##name;                                       \
+    case llvm::Triple::spirv:                                                  \
+      return llvm::Intrinsic::spv_##name;                                      \
+    default:                                                                   \
+      llvm_unreachable("Input semantic not supported by target");              \
+    }                                                                          \
+  }
+
+class CGHLSLUtils {
+public:
+  GENERATE_HLSL_INTRINSIC_FUNCTION(all)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
+private:
+  CGHLSLUtils() = delete;
+};
+
+#endif
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 1163bd6c8fbaba..c04f4c52692158 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -684,18 +684,6 @@ class DefaultAttrsIntrinsic<list<LLVMType> ret_types,
                             intr_properties, name,
                             sd_properties, /*disable_default_attributes*/ 0> {}
 
-// HLSL Intrinsic Classes
-class HLSLThreadId
-                : Intrinsic</*ret_types*/ [llvm_i32_ty], 
-                            /*param_types*/[llvm_i32_ty],
-                            /*intr_properties*/ [IntrNoMem, IntrWillReturn], 
-                            /*name*/ ""> {}
-class HLSLAll : Intrinsic</*ret_types*/ [llvm_i1_ty], 
-                            /*param_types*/[llvm_any_ty],
-                            /*intr_properties*/ [IntrNoMem, IntrWillReturn], 
-                            /*name*/ ""> {}
-
-
 /// ClangBuiltin - If this intrinsic exactly corresponds to a Clang builtin, this
 /// specifies the name of the builtin.  This provides automatic CBE and CFE
 /// support.
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index c67102a14387f4..a7f212da2f5b63 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -11,7 +11,8 @@
 //===----------------------------------------------------------------------===//
 
 let TargetPrefix = "dx" in {
-def int_dx_thread_id : HLSLThreadId;
+
+def int_dx_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
 def int_dx_group_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
 def int_dx_thread_id_in_group : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
 def int_dx_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrWillReturn]>;
@@ -19,8 +20,8 @@ def int_dx_flattened_thread_id_in_group : Intrinsic<[llvm_i32_ty], [], [IntrNoMe
 def int_dx_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">,
     Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>;
 
-def int_dx_all  : HLSLAll;
-def int_dx_any  : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
+def int_dx_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
+def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
 def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
 def int_dx_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; 
 
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index f987d7928ab23f..f843383f0b00ed 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -53,8 +53,8 @@ let TargetPrefix = "spv" in {
                                 ImmArg<ArgIndex<0>>]>;
 
   // The following intrinsic(s) are mirrored from IntrinsicsDirectX.td for HLSL support.
-  def int_spv_thread_id : HLSLThreadId;
-  def int_spv_all  : HLSLAll;
+  def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
   def int_spv_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">,
       Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>;
+  def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
 }

>From 4fb0e4dab3bf79c6cbd210b1217cfb2eef6da83a Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 2 Apr 2024 20:38:15 -0400
Subject: [PATCH 03/11] address pr comments

---
 clang/lib/CodeGen/CGBuiltin.cpp     |  2 +-
 clang/lib/CodeGen/CGHLSLRuntime.cpp |  2 +-
 clang/lib/CodeGen/CGHLSLUtils.h     | 20 +++++++++++---------
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 92e9089cbe7bb7..c31576afcfc28b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18177,7 +18177,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
         /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
-        CGHLSLUtils::get_hlsl_all_intrinsic(
+        HLSLUtils::get_hlsl_all_intrinsic(
             CGM.getTarget().getTriple().getArch()),
         ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
   }
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index c772049dbe3acc..78c98ed4e13788 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -343,7 +343,7 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
   }
   if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
     llvm::Function *ThreadIDIntrinsic =
-        CGM.getIntrinsic(CGHLSLUtils::get_hlsl_thread_id_intrinsic(
+        CGM.getIntrinsic(HLSLUtils::get_hlsl_thread_id_intrinsic(
             CGM.getTarget().getTriple().getArch()));
     return buildVectorInput(B, ThreadIDIntrinsic, Ty);
   }
diff --git a/clang/lib/CodeGen/CGHLSLUtils.h b/clang/lib/CodeGen/CGHLSLUtils.h
index ca29835105aa87..deb2ca4f2d0ed8 100644
--- a/clang/lib/CodeGen/CGHLSLUtils.h
+++ b/clang/lib/CodeGen/CGHLSLUtils.h
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This File Provides utility function for HLSL code generation.
+// This file provides utility functions for HLSL code generation.
 // It is used to abstract away implementation details of backends.
 //
 //===----------------------------------------------------------------------===//
@@ -33,12 +33,14 @@
     }                                                                          \
   }
 
-class CGHLSLUtils {
-public:
-  GENERATE_HLSL_INTRINSIC_FUNCTION(all)
-  GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
-private:
-  CGHLSLUtils() = delete;
-};
+namespace clang::CodeGen {
+  class HLSLUtils {
+  public:
+    GENERATE_HLSL_INTRINSIC_FUNCTION(all)
+    GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
+  private:
+    HLSLUtils() = delete;
+  };
+} // namespace clang::CodeGen
 
-#endif
+#endif // LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H

>From 4236523ae52b0e8d44c2dd31a687bc64cda5e237 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 2 Apr 2024 20:44:48 -0400
Subject: [PATCH 04/11] remove spirv lowering for all intrinsic

---
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 19 ----
 .../test/CodeGen/SPIRV/hlsl-intrinsics/all.ll | 95 -------------------
 2 files changed, 114 deletions(-)
 delete mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 0a8383c3df4c76..49749b56345306 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -144,9 +144,6 @@ class SPIRVInstructionSelector : public InstructionSelector {
   bool selectAddrSpaceCast(Register ResVReg, const SPIRVType *ResType,
                            MachineInstr &I) const;
 
-  bool selectAll(Register ResVReg, const SPIRVType *ResType,
-                 MachineInstr &I) const;
-
   bool selectBitreverse(Register ResVReg, const SPIRVType *ResType,
                         MachineInstr &I) const;
 
@@ -1158,20 +1155,6 @@ static unsigned getBoolCmpOpcode(unsigned PredNum) {
   }
 }
 
-bool SPIRVInstructionSelector::selectAll(Register ResVReg,
-                                         const SPIRVType *ResType,
-                                         MachineInstr &I) const {
-  assert(I.getNumOperands() == 3);
-  assert(I.getOperand(2).isReg());
-
-  MachineBasicBlock &BB = *I.getParent();
-  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpAll))
-      .addDef(ResVReg)
-      .addUse(GR.getSPIRVTypeID(ResType))
-      .addUse(I.getOperand(2).getReg())
-      .constrainAllUses(TII, TRI, RBI);
-}
-
 bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
@@ -1802,8 +1785,6 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
     break;
   case Intrinsic::spv_thread_id:
     return selectSpvThreadId(ResVReg, ResType, I);
-  case Intrinsic::spv_all:
-    return selectAll(ResVReg, ResType, I);
   case Intrinsic::spv_lifetime_start:
   case Intrinsic::spv_lifetime_end: {
     unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll
deleted file mode 100644
index c904ac08699355..00000000000000
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll
+++ /dev/null
@@ -1,95 +0,0 @@
-; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
-; Note: The validator is wrong it wants the return to be a bool vector when it is bool scalar return
-; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
-
-; Make sure spirv operation function calls for all are generated.
-
-; CHECK: OpMemoryModel Logical GLSL450
-
-define noundef i1 @all_bool(i1 noundef %a) {
-entry:
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.i1(i1 %a)
-  ret i1 %hlsl.all
-}
-
-define noundef i1 @all_int64_t(i64 noundef %p0) {
-entry:
-  %p0.addr = alloca i64, align 8
-  store i64 %p0, ptr %p0.addr, align 8
-  %0 = load i64, ptr %p0.addr, align 8
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.i64(i64 %0)
-  ret i1 %hlsl.all
-}
-
-
-define noundef i1 @all_int(i32 noundef %p0) {
-entry:
-  %p0.addr = alloca i32, align 4
-  store i32 %p0, ptr %p0.addr, align 4
-  %0 = load i32, ptr %p0.addr, align 4
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.i32(i32 %0)
-  ret i1 %hlsl.all
-}
-
-
-define noundef i1 @all_int16_t(i16 noundef %p0) {
-entry:
-  %p0.addr = alloca i16, align 2
-  store i16 %p0, ptr %p0.addr, align 2
-  %0 = load i16, ptr %p0.addr, align 2
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.i16(i16 %0)
-  ret i1 %hlsl.all
-}
-
-define noundef i1 @all_double(double noundef %p0) {
-entry:
-  %p0.addr = alloca double, align 8
-  store double %p0, ptr %p0.addr, align 8
-  %0 = load double, ptr %p0.addr, align 8
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.f64(double %0)
-  ret i1 %hlsl.all
-}
-
-
-define noundef i1 @all_float(float noundef %p0) {
-entry:
-  %p0.addr = alloca float, align 4
-  store float %p0, ptr %p0.addr, align 4
-  %0 = load float, ptr %p0.addr, align 4
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.f32(float %0)
-  ret i1 %hlsl.all
-}
-
-
-define noundef i1 @all_half(half noundef %p0) {
-entry:
-  %p0.addr = alloca half, align 2
-  store half %p0, ptr %p0.addr, align 2
-  %0 = load half, ptr %p0.addr, align 2
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.f16(half %0)
-  ret i1 %hlsl.all
-}
-
-
-define noundef i1 @all_bool4(<4 x i1> noundef %p0) {
-entry:
-  ; CHECK: %[[#]] = OpAll %[[#]] %[[#]]
-  %hlsl.all = call i1 @llvm.spv.all.v4i1(<4 x i1> %p0)
-  ret i1 %hlsl.all
-}
-
-declare i1 @llvm.spv.all.v4i1(<4 x i1>)
-declare i1 @llvm.spv.all.i1(i1)
-declare i1 @llvm.spv.all.i16(i16)
-declare i1 @llvm.spv.all.i32(i32)
-declare i1 @llvm.spv.all.i64(i64)
-declare i1 @llvm.spv.all.f16(half)
-declare i1 @llvm.spv.all.f32(float)
-declare i1 @llvm.spv.all.f64(double)

>From 176b025b2f57f5c34497c8ae8ae0450a1c70ac36 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Tue, 2 Apr 2024 20:55:44 -0400
Subject: [PATCH 05/11] fix format

---
 clang/lib/CodeGen/CGHLSLUtils.h | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLUtils.h b/clang/lib/CodeGen/CGHLSLUtils.h
index deb2ca4f2d0ed8..189a37cc6d98b4 100644
--- a/clang/lib/CodeGen/CGHLSLUtils.h
+++ b/clang/lib/CodeGen/CGHLSLUtils.h
@@ -29,18 +29,19 @@
     case llvm::Triple::spirv:                                                  \
       return llvm::Intrinsic::spv_##name;                                      \
     default:                                                                   \
-      llvm_unreachable("Input semantic not supported by target");              \
+      llvm_unreachable("Intrinsic " #name                                      \
+                       " not supported by target architecture");               \
     }                                                                          \
   }
 
 namespace clang::CodeGen {
-  class HLSLUtils {
-  public:
-    GENERATE_HLSL_INTRINSIC_FUNCTION(all)
-    GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
-  private:
-    HLSLUtils() = delete;
-  };
+class HLSLUtils {
+public:
+  GENERATE_HLSL_INTRINSIC_FUNCTION(all)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
+private:
+  HLSLUtils() = delete;
+};
 } // namespace clang::CodeGen
 
 #endif // LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H

>From 23e15ced6bd47996056a17a7fa33a1b22726bed0 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 3 Apr 2024 13:07:12 -0400
Subject: [PATCH 06/11] move HLSLUtils functions to CGHLSLRuntime

---
 clang/lib/CodeGen/CGBuiltin.cpp     |  4 +--
 clang/lib/CodeGen/CGHLSLRuntime.cpp |  3 +-
 clang/lib/CodeGen/CGHLSLRuntime.h   | 29 ++++++++++++++++++
 clang/lib/CodeGen/CGHLSLUtils.h     | 47 -----------------------------
 4 files changed, 32 insertions(+), 51 deletions(-)
 delete mode 100644 clang/lib/CodeGen/CGHLSLUtils.h

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c31576afcfc28b..11748444f12743 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -13,7 +13,7 @@
 #include "ABIInfo.h"
 #include "CGCUDARuntime.h"
 #include "CGCXXABI.h"
-#include "CGHLSLUtils.h"
+#include "CGHLSLRuntime.h"
 #include "CGObjCRuntime.h"
 #include "CGOpenCLRuntime.h"
 #include "CGRecordLayout.h"
@@ -18177,7 +18177,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
         /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
-        HLSLUtils::get_hlsl_all_intrinsic(
+        CGHLSLRuntime::get_hlsl_all_intrinsic(
             CGM.getTarget().getTriple().getArch()),
         ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
   }
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 78c98ed4e13788..13143998e9dd0a 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -14,7 +14,6 @@
 
 #include "CGHLSLRuntime.h"
 #include "CGDebugInfo.h"
-#include "CGHLSLUtils.h"
 #include "CodeGenModule.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetOptions.h"
@@ -343,7 +342,7 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
   }
   if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
     llvm::Function *ThreadIDIntrinsic =
-        CGM.getIntrinsic(HLSLUtils::get_hlsl_thread_id_intrinsic(
+        CGM.getIntrinsic(CGHLSLRuntime::get_hlsl_thread_id_intrinsic(
             CGM.getTarget().getTriple().getArch()));
     return buildVectorInput(B, ThreadIDIntrinsic, Ty);
   }
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index bffefb66740a00..26bdb6ab38f0ba 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -16,6 +16,9 @@
 #define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
 
 #include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsDirectX.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
 
 #include "clang/Basic/HLSLRuntime.h"
 
@@ -26,6 +29,21 @@
 #include <optional>
 #include <vector>
 
+// Define the function generator macro
+#define GENERATE_HLSL_INTRINSIC_FUNCTION(name)                                 \
+  static llvm::Intrinsic::ID get_hlsl_##name##_intrinsic(                      \
+      const llvm::Triple::ArchType Arch) {                                     \
+    switch (Arch) {                                                            \
+    case llvm::Triple::dxil:                                                   \
+      return llvm::Intrinsic::dx_##name;                                       \
+    case llvm::Triple::spirv:                                                  \
+      return llvm::Intrinsic::spv_##name;                                      \
+    default:                                                                   \
+      llvm_unreachable("Intrinsic " #name                                      \
+                       " not supported by target architecture");               \
+    }                                                                          \
+  }
+
 namespace llvm {
 class GlobalVariable;
 class Function;
@@ -48,6 +66,17 @@ class CodeGenModule;
 
 class CGHLSLRuntime {
 public:
+  //===----------------------------------------------------------------------===//
+  // Start of reserved area for HLSL intrinsic getters.
+  //===----------------------------------------------------------------------===//
+
+  GENERATE_HLSL_INTRINSIC_FUNCTION(all)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
+
+  //===----------------------------------------------------------------------===//
+  // End of reserved area for HLSL intrinsic getters.
+  //===----------------------------------------------------------------------===//
+
   struct BufferResBinding {
     // The ID like 2 in register(b2, space1).
     std::optional<unsigned> Reg;
diff --git a/clang/lib/CodeGen/CGHLSLUtils.h b/clang/lib/CodeGen/CGHLSLUtils.h
deleted file mode 100644
index 189a37cc6d98b4..00000000000000
--- a/clang/lib/CodeGen/CGHLSLUtils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-//===----- CGHLSLUtils.h - Utility functions for HLSL CodeGen ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides utility functions for HLSL code generation.
-// It is used to abstract away implementation details of backends.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H
-#define LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H
-
-#include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/IntrinsicsDirectX.h"
-#include "llvm/IR/IntrinsicsSPIRV.h"
-
-// Define the function generator macro
-#define GENERATE_HLSL_INTRINSIC_FUNCTION(name)                                 \
-  static llvm::Intrinsic::ID get_hlsl_##name##_intrinsic(                      \
-      const llvm::Triple::ArchType Arch) {                                     \
-    switch (Arch) {                                                            \
-    case llvm::Triple::dxil:                                                   \
-      return llvm::Intrinsic::dx_##name;                                       \
-    case llvm::Triple::spirv:                                                  \
-      return llvm::Intrinsic::spv_##name;                                      \
-    default:                                                                   \
-      llvm_unreachable("Intrinsic " #name                                      \
-                       " not supported by target architecture");               \
-    }                                                                          \
-  }
-
-namespace clang::CodeGen {
-class HLSLUtils {
-public:
-  GENERATE_HLSL_INTRINSIC_FUNCTION(all)
-  GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
-private:
-  HLSLUtils() = delete;
-};
-} // namespace clang::CodeGen
-
-#endif // LLVM_CLANG_LIB_CODEGEN_CGHLSLUTILS_H

>From 2d839242e3da501ed80440c3497dc747ebb71299 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 3 Apr 2024 14:03:55 -0400
Subject: [PATCH 07/11] make intrinsic getters member functions. Add a getArch
 abstraction b\c CodeGenModule is incomplete in the header\CGHLSLRuntime.h

---
 clang/lib/CodeGen/CGBuiltin.cpp     | 5 ++---
 clang/lib/CodeGen/CGHLSLRuntime.cpp | 7 +++++--
 clang/lib/CodeGen/CGHLSLRuntime.h   | 5 +++--
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 11748444f12743..effa76429decef 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18177,9 +18177,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
         /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
-        CGHLSLRuntime::get_hlsl_all_intrinsic(
-            CGM.getTarget().getTriple().getArch()),
-        ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
+        CGM.getHLSLRuntime().get_hlsl_all_intrinsic(), ArrayRef<Value *>{Op0},
+        nullptr, "hlsl.all");
   }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 13143998e9dd0a..c42fb4e140d56b 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -115,6 +115,10 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
 
 } // namespace
 
+llvm::Triple::ArchType CGHLSLRuntime::getArch() {
+  return CGM.getTarget().getTriple().getArch();
+}
+
 void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) {
   if (D->getStorageClass() == SC_Static) {
     // For static inside cbuffer, take as global static.
@@ -342,8 +346,7 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
   }
   if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
     llvm::Function *ThreadIDIntrinsic =
-        CGM.getIntrinsic(CGHLSLRuntime::get_hlsl_thread_id_intrinsic(
-            CGM.getTarget().getTriple().getArch()));
+        CGM.getIntrinsic(get_hlsl_thread_id_intrinsic());
     return buildVectorInput(B, ThreadIDIntrinsic, Ty);
   }
   assert(false && "Unhandled parameter attribute");
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 26bdb6ab38f0ba..ffc0de0450452b 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -31,8 +31,8 @@
 
 // Define the function generator macro
 #define GENERATE_HLSL_INTRINSIC_FUNCTION(name)                                 \
-  static llvm::Intrinsic::ID get_hlsl_##name##_intrinsic(                      \
-      const llvm::Triple::ArchType Arch) {                                     \
+  llvm::Intrinsic::ID get_hlsl_##name##_intrinsic() {                          \
+    llvm::Triple::ArchType Arch = getArch();                                   \
     switch (Arch) {                                                            \
     case llvm::Triple::dxil:                                                   \
       return llvm::Intrinsic::dx_##name;                                       \
@@ -125,6 +125,7 @@ class CGHLSLRuntime {
                                    BufferResBinding &Binding);
   void addConstant(VarDecl *D, Buffer &CB);
   void addBufferDecls(const DeclContext *DC, Buffer &CB);
+  llvm::Triple::ArchType getArch();
   llvm::SmallVector<Buffer> Buffers;
 };
 

>From a950dc6b3592a08ccac18da88626a987394fd252 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 3 Apr 2024 18:55:15 -0400
Subject: [PATCH 08/11] add a templated macro for when we have builtins and
 make GENERATE_HLSL_INTRINSIC_FUNCTION take a function name

---
 clang/lib/CodeGen/CGBuiltin.cpp     |  5 ++--
 clang/lib/CodeGen/CGHLSLRuntime.cpp |  2 +-
 clang/lib/CodeGen/CGHLSLRuntime.h   | 43 ++++++++++++++++++-----------
 3 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index effa76429decef..f12312be83422f 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18177,8 +18177,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
         /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
-        CGM.getHLSLRuntime().get_hlsl_all_intrinsic(), ArrayRef<Value *>{Op0},
-        nullptr, "hlsl.all");
+        CGM.getHLSLRuntime()
+            .getIntrinsic<Builtin::BI__builtin_hlsl_elementwise_all>(),
+        ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
   }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index c42fb4e140d56b..5e6a3dd4878f46 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -346,7 +346,7 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
   }
   if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
     llvm::Function *ThreadIDIntrinsic =
-        CGM.getIntrinsic(get_hlsl_thread_id_intrinsic());
+        CGM.getIntrinsic(getThreadIdIntrinsic());
     return buildVectorInput(B, ThreadIDIntrinsic, Ty);
   }
   assert(false && "Unhandled parameter attribute");
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index ffc0de0450452b..17f6516fb276dd 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -20,6 +20,7 @@
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/IntrinsicsSPIRV.h"
 
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/HLSLRuntime.h"
 
 #include "llvm/ADT/SmallVector.h"
@@ -29,19 +30,29 @@
 #include <optional>
 #include <vector>
 
-// Define the function generator macro
-#define GENERATE_HLSL_INTRINSIC_FUNCTION(name)                                 \
-  llvm::Intrinsic::ID get_hlsl_##name##_intrinsic() {                          \
-    llvm::Triple::ArchType Arch = getArch();                                   \
-    switch (Arch) {                                                            \
-    case llvm::Triple::dxil:                                                   \
-      return llvm::Intrinsic::dx_##name;                                       \
-    case llvm::Triple::spirv:                                                  \
-      return llvm::Intrinsic::spv_##name;                                      \
-    default:                                                                   \
-      llvm_unreachable("Intrinsic " #name                                      \
-                       " not supported by target architecture");               \
-    }                                                                          \
+#define GENERATE_HLSL_INTRINSIC_BASE(IntrinsicPostfix)                         \
+  llvm::Triple::ArchType Arch = getArch();                                     \
+  switch (Arch) {                                                              \
+  case llvm::Triple::dxil:                                                     \
+    return llvm::Intrinsic::dx_##IntrinsicPostfix;                             \
+  case llvm::Triple::spirv:                                                    \
+    return llvm::Intrinsic::spv_##IntrinsicPostfix;                            \
+  default:                                                                     \
+    llvm_unreachable("Intrinsic " #IntrinsicPostfix                            \
+                     " not supported by target architecture");                 \
+  }
+
+// A function generator macro for when there is no builtins or
+// when builtins are mapped to a set of intrinsics for different types.
+#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix)       \
+  llvm::Intrinsic::ID get##FunctionName##Intrinsic() {                         \
+    GENERATE_HLSL_INTRINSIC_BASE(IntrinsicPostfix)                             \
+  }
+
+// A template function generator macro for when we have builtins.
+#define GENERATE_HLSL_INTRINSIC_TEMPLATE(BuiltinName, IntrinsicPostfix)        \
+  template <> llvm::Intrinsic::ID getIntrinsic<Builtin::BI__##BuiltinName>() { \
+    GENERATE_HLSL_INTRINSIC_BASE(IntrinsicPostfix)                             \
   }
 
 namespace llvm {
@@ -69,9 +80,9 @@ class CGHLSLRuntime {
   //===----------------------------------------------------------------------===//
   // Start of reserved area for HLSL intrinsic getters.
   //===----------------------------------------------------------------------===//
-
-  GENERATE_HLSL_INTRINSIC_FUNCTION(all)
-  GENERATE_HLSL_INTRINSIC_FUNCTION(thread_id)
+  template <unsigned BI> llvm::Intrinsic::ID getIntrinsic();
+  GENERATE_HLSL_INTRINSIC_TEMPLATE(builtin_hlsl_elementwise_all, all)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
 
   //===----------------------------------------------------------------------===//
   // End of reserved area for HLSL intrinsic getters.

>From 998f8cada38e7708ad0454bb6a685e5801e5b676 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 3 Apr 2024 19:37:58 -0400
Subject: [PATCH 09/11] prevent linker error gore when getIntrinsic is used but
 specialized type isn't defined yet.

---
 clang/lib/CodeGen/CGHLSLRuntime.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 17f6516fb276dd..10fa5f860df50f 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -80,6 +80,7 @@ class CGHLSLRuntime {
   //===----------------------------------------------------------------------===//
   // Start of reserved area for HLSL intrinsic getters.
   //===----------------------------------------------------------------------===//
+
   template <unsigned BI> llvm::Intrinsic::ID getIntrinsic();
   GENERATE_HLSL_INTRINSIC_TEMPLATE(builtin_hlsl_elementwise_all, all)
   GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
@@ -140,6 +141,11 @@ class CGHLSLRuntime {
   llvm::SmallVector<Buffer> Buffers;
 };
 
+// Default implementation
+template <unsigned BI> llvm::Intrinsic::ID CGHLSLRuntime::getIntrinsic() {
+  static_assert(false, "getIntrinsic is only allowed on specialized templates");
+}
+
 } // namespace CodeGen
 } // namespace clang
 

>From 3978c8c0d329db5e0dfb20013025fe148b74346c Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Thu, 4 Apr 2024 16:51:02 -0400
Subject: [PATCH 10/11] remove default template

---
 clang/lib/CodeGen/CGHLSLRuntime.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 10fa5f860df50f..54310b68aad8f6 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -141,11 +141,6 @@ class CGHLSLRuntime {
   llvm::SmallVector<Buffer> Buffers;
 };
 
-// Default implementation
-template <unsigned BI> llvm::Intrinsic::ID CGHLSLRuntime::getIntrinsic() {
-  static_assert(false, "getIntrinsic is only allowed on specialized templates");
-}
-
 } // namespace CodeGen
 } // namespace clang
 

>From 4d0ebe8dc88ba8e6ee1bb9290bc407f22af9ff70 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Thu, 4 Apr 2024 16:54:27 -0400
Subject: [PATCH 11/11] remove template

---
 clang/lib/CodeGen/CGBuiltin.cpp   |  5 ++---
 clang/lib/CodeGen/CGHLSLRuntime.h | 36 +++++++++++--------------------
 2 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f12312be83422f..df7502b8def531 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18177,9 +18177,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
         /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
-        CGM.getHLSLRuntime()
-            .getIntrinsic<Builtin::BI__builtin_hlsl_elementwise_all>(),
-        ArrayRef<Value *>{Op0}, nullptr, "hlsl.all");
+        CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
+        "hlsl.all");
   }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 54310b68aad8f6..2b8073aef973f8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -30,29 +30,20 @@
 #include <optional>
 #include <vector>
 
-#define GENERATE_HLSL_INTRINSIC_BASE(IntrinsicPostfix)                         \
-  llvm::Triple::ArchType Arch = getArch();                                     \
-  switch (Arch) {                                                              \
-  case llvm::Triple::dxil:                                                     \
-    return llvm::Intrinsic::dx_##IntrinsicPostfix;                             \
-  case llvm::Triple::spirv:                                                    \
-    return llvm::Intrinsic::spv_##IntrinsicPostfix;                            \
-  default:                                                                     \
-    llvm_unreachable("Intrinsic " #IntrinsicPostfix                            \
-                     " not supported by target architecture");                 \
-  }
-
-// A function generator macro for when there is no builtins or
-// when builtins are mapped to a set of intrinsics for different types.
+// A function generator macro for picking the right intrinsic
+// for the target backend
 #define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix)       \
   llvm::Intrinsic::ID get##FunctionName##Intrinsic() {                         \
-    GENERATE_HLSL_INTRINSIC_BASE(IntrinsicPostfix)                             \
-  }
-
-// A template function generator macro for when we have builtins.
-#define GENERATE_HLSL_INTRINSIC_TEMPLATE(BuiltinName, IntrinsicPostfix)        \
-  template <> llvm::Intrinsic::ID getIntrinsic<Builtin::BI__##BuiltinName>() { \
-    GENERATE_HLSL_INTRINSIC_BASE(IntrinsicPostfix)                             \
+    llvm::Triple::ArchType Arch = getArch();                                   \
+    switch (Arch) {                                                            \
+    case llvm::Triple::dxil:                                                   \
+      return llvm::Intrinsic::dx_##IntrinsicPostfix;                           \
+    case llvm::Triple::spirv:                                                  \
+      return llvm::Intrinsic::spv_##IntrinsicPostfix;                          \
+    default:                                                                   \
+      llvm_unreachable("Intrinsic " #IntrinsicPostfix                          \
+                       " not supported by target architecture");               \
+    }                                                                          \
   }
 
 namespace llvm {
@@ -81,8 +72,7 @@ class CGHLSLRuntime {
   // Start of reserved area for HLSL intrinsic getters.
   //===----------------------------------------------------------------------===//
 
-  template <unsigned BI> llvm::Intrinsic::ID getIntrinsic();
-  GENERATE_HLSL_INTRINSIC_TEMPLATE(builtin_hlsl_elementwise_all, all)
+  GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
   GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
 
   //===----------------------------------------------------------------------===//



More information about the cfe-commits mailing list