[clang] [llvm] [HLSL][DXIL] Implement WaveGetLaneIndex Intrinsic (PR #111576)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 9 10:31:17 PDT 2024
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/111576
>From 167718e352554e167c4690a4962234ba782bceff Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Tue, 8 Oct 2024 09:28:43 -0700
Subject: [PATCH 1/3] [HLSL][DXIL] Implement WaveGetLaneIndex
- add additional lowering for directx backend in CGBuiltin.cpp
- add directx intrinsic to IntrinscsDirectX.td
- add semantic check of arguments in SemaHLSL.cpp
- add mapping to DXIL op in DXIL.td
- add testing of semantics in WaveGetLaneIndex-errors.hlsl
- add testing of dxil lowering in WaveGetLaneIndex.ll
---
clang/lib/CodeGen/CGBuiltin.cpp | 15 +++++++++++---
clang/lib/Sema/SemaHLSL.cpp | 5 +++++
.../builtins/wave_get_lane_index_simple.hlsl | 20 +++++++++++++------
.../BuiltIns/WaveGetLaneIndex-errors.hlsl | 6 ++++++
llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 +
llvm/lib/Target/DirectX/DXIL.td | 9 +++++++++
llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll | 10 ++++++++++
7 files changed, 57 insertions(+), 9 deletions(-)
create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl
create mode 100644 llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da3eca73bfb575..c83b2c5a2ca047 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18827,9 +18827,18 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
}
case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
- return EmitRuntimeCall(CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index",
- {}, false, true));
+ switch (CGM.getTarget().getTriple().getArch()) {
+ case llvm::Triple::dxil:
+ return EmitRuntimeCall(Intrinsic::getDeclaration(
+ &CGM.getModule(), Intrinsic::dx_waveGetLaneIndex));
+ case llvm::Triple::spirv:
+ return EmitRuntimeCall(CGM.CreateRuntimeFunction(
+ llvm::FunctionType::get(IntTy, {}, false),
+ "__hlsl_wave_get_lane_index", {}, false, true));
+ default:
+ llvm_unreachable(
+ "Intrinsic WaveGetLaneIndex not supported by target architecture");
+ }
}
case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 43cc6c81ae5cb0..7d93f41bb2d7a0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1956,6 +1956,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
+ case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
+ if (SemaRef.checkArgCount(TheCall, 0))
+ return true;
+ break;
+ }
case Builtin::BI__builtin_elementwise_acos:
case Builtin::BI__builtin_elementwise_asin:
case Builtin::BI__builtin_elementwise_atan:
diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
index 8f52d81091c180..e76d35a86e512a 100644
--- a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
@@ -1,14 +1,22 @@
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
-// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN: --check-prefixes=CHECK,CHECK-SPIRV
+// RUN: %clang_cc1 -finclude-default-header \
+// RUN: -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN: --check-prefixes=CHECK,CHECK-DXIL
-// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] {
-// CHECK: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry()
-// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ]
-uint test_1() {
+// CHECK-SPIRV: define spir_func noundef i32 @{{.*test_1.*}}() [[A0:#[0-9]+]] {
+// CHECK-DXIL: define noundef i32 @{{.*test_1.*}}() [[A0:#[0-9]+]] {
+// CHECK-SPIRV: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry()
+// CHECK-SPIRV: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ]
+// CHECK-DXIL: call i32 @llvm.dx.waveGetLaneIndex()
+int test_1() {
return WaveGetLaneIndex();
}
-// CHECK: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]]
+// CHECK-SPIRV: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]]
+// CHECK-DXIL: declare i32 @llvm.dx.waveGetLaneIndex() [[A1:#[0-9]+]]
// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} }
// CHECK-DAG: attributes [[A1]] = { {{.*}}convergent{{.*}} }
diff --git a/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl
new file mode 100644
index 00000000000000..94cfd0662b5fc3
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
+
+int test_too_many_arg(int x) {
+ return __builtin_hlsl_wave_get_lane_index(x);
+ // expected-error at -1 {{too many arguments to function call, expected 0, have 1}}
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 555877e7aaf0e5..585cb2b7b300df 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -82,6 +82,7 @@ def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLV
def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_dx_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_dx_waveGetLaneIndex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrConvergent, IntrNoMem]>;
def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>;
def int_dx_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 9aa0af3e3a6b17..f0db3b4c165e41 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -801,3 +801,12 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
let stages = [Stages<DXIL1_0, [all_stages]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
+
+def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
+ let Doc = "returns the index of the current lane in the wave";
+ let LLVMIntrinsic = int_dx_waveGetLaneIndex;
+ let arguments = [];
+ let result = Int32Ty;
+ let stages = [Stages<DXIL1_0, [all_stages]>];
+ let attributes = [Attributes<DXIL1_0, [ReadNone]>];
+}
diff --git a/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll b/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll
new file mode 100644
index 00000000000000..0b1c96976f594a
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll
@@ -0,0 +1,10 @@
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-compute %s | FileCheck %s
+
+define void @main() {
+entry:
+; CHECK: call i32 @dx.op.waveGetLaneIndex(i32 111)
+ %0 = call i32 @llvm.dx.waveGetLaneIndex()
+ ret void
+}
+
+declare i32 @llvm.dx.waveGetLaneIndex()
>From ba1e9f2210afb7a6e25d26c53065c0a14e0145bf Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Tue, 8 Oct 2024 12:37:09 -0700
Subject: [PATCH 2/3] add comment
---
clang/lib/CodeGen/CGBuiltin.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c83b2c5a2ca047..803bdbaa0e7e01 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18827,6 +18827,9 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
}
case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
+ // Since we don't define a SPIR-V intrinsic for the SPIR-V built-in from
+ // SPIRVBuiltins.td, manually get the matching name for the DirectX
+ // intrinsic and the demangled builtin name
switch (CGM.getTarget().getTriple().getArch()) {
case llvm::Triple::dxil:
return EmitRuntimeCall(Intrinsic::getDeclaration(
>From 0ac048c6d68addf3b4f7fc573c9bcdb4412fb715 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Oct 2024 10:20:26 -0700
Subject: [PATCH 3/3] review comments:
- remove flags that are not needed
- update intrinsic naming to wave_getlaneindex to follow llvm conventions
---
clang/lib/CodeGen/CGBuiltin.cpp | 8 ++++----
.../CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl | 4 ++--
clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl | 2 +-
llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 +-
llvm/lib/Target/DirectX/DXIL.td | 2 +-
llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll | 4 ++--
6 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 803bdbaa0e7e01..7eb81cbcdc02ab 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18827,13 +18827,13 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
}
case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
- // Since we don't define a SPIR-V intrinsic for the SPIR-V built-in from
- // SPIRVBuiltins.td, manually get the matching name for the DirectX
- // intrinsic and the demangled builtin name
+ // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
+ // defined in SPIRVBuiltins.td. So instead we manually get the matching name
+ // for the DirectX intrinsic and the demangled builtin name
switch (CGM.getTarget().getTriple().getArch()) {
case llvm::Triple::dxil:
return EmitRuntimeCall(Intrinsic::getDeclaration(
- &CGM.getModule(), Intrinsic::dx_waveGetLaneIndex));
+ &CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
case llvm::Triple::spirv:
return EmitRuntimeCall(CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, {}, false),
diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
index e76d35a86e512a..06a2715b00e969 100644
--- a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
@@ -10,13 +10,13 @@
// CHECK-DXIL: define noundef i32 @{{.*test_1.*}}() [[A0:#[0-9]+]] {
// CHECK-SPIRV: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry()
// CHECK-SPIRV: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ]
-// CHECK-DXIL: call i32 @llvm.dx.waveGetLaneIndex()
+// CHECK-DXIL: call i32 @llvm.dx.wave.getlaneindex()
int test_1() {
return WaveGetLaneIndex();
}
// CHECK-SPIRV: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]]
-// CHECK-DXIL: declare i32 @llvm.dx.waveGetLaneIndex() [[A1:#[0-9]+]]
+// CHECK-DXIL: declare i32 @llvm.dx.wave.getlaneindex() [[A1:#[0-9]+]]
// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} }
// CHECK-DAG: attributes [[A1]] = { {{.*}}convergent{{.*}} }
diff --git a/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl
index 94cfd0662b5fc3..6208442fab6590 100644
--- a/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/WaveGetLaneIndex-errors.hlsl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify
int test_too_many_arg(int x) {
return __builtin_hlsl_wave_get_lane_index(x);
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 585cb2b7b300df..de61e32c3623c9 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -82,7 +82,7 @@ def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLV
def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_dx_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
-def int_dx_waveGetLaneIndex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrConvergent, IntrNoMem]>;
+def int_dx_wave_getlaneindex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrConvergent, IntrNoMem]>;
def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>;
def int_dx_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index f0db3b4c165e41..e8f56b18730d71 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -804,7 +804,7 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
let Doc = "returns the index of the current lane in the wave";
- let LLVMIntrinsic = int_dx_waveGetLaneIndex;
+ let LLVMIntrinsic = int_dx_wave_getlaneindex;
let arguments = [];
let result = Int32Ty;
let stages = [Stages<DXIL1_0, [all_stages]>];
diff --git a/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll b/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll
index 0b1c96976f594a..86b7ea4f962f77 100644
--- a/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll
+++ b/llvm/test/CodeGen/DirectX/WaveGetLaneIndex.ll
@@ -3,8 +3,8 @@
define void @main() {
entry:
; CHECK: call i32 @dx.op.waveGetLaneIndex(i32 111)
- %0 = call i32 @llvm.dx.waveGetLaneIndex()
+ %0 = call i32 @llvm.dx.wave.getlaneindex()
ret void
}
-declare i32 @llvm.dx.waveGetLaneIndex()
+declare i32 @llvm.dx.wave.getlaneindex()
More information about the cfe-commits
mailing list