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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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 <farzonlo...@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) //===----------------------------------------------------------------------===// _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits