Skip to content

Commit 31a749f

Browse files
inbelicDanielCChen
authored andcommitted
[HLSL][DXIL] Implement WaveGetLaneIndex Intrinsic (llvm#111576)
- add additional lowering for directx backend in CGBuiltin.cpp - add directx intrinsic to IntrinsicsDirectX.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 Resolves llvm#70105
1 parent 6af36e6 commit 31a749f

File tree

7 files changed

+60
-9
lines changed

7 files changed

+60
-9
lines changed

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18867,9 +18867,21 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
1886718867
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
1886818868
}
1886918869
case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
18870-
return EmitRuntimeCall(CGM.CreateRuntimeFunction(
18871-
llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index",
18872-
{}, false, true));
18870+
// We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
18871+
// defined in SPIRVBuiltins.td. So instead we manually get the matching name
18872+
// for the DirectX intrinsic and the demangled builtin name
18873+
switch (CGM.getTarget().getTriple().getArch()) {
18874+
case llvm::Triple::dxil:
18875+
return EmitRuntimeCall(Intrinsic::getDeclaration(
18876+
&CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
18877+
case llvm::Triple::spirv:
18878+
return EmitRuntimeCall(CGM.CreateRuntimeFunction(
18879+
llvm::FunctionType::get(IntTy, {}, false),
18880+
"__hlsl_wave_get_lane_index", {}, false, true));
18881+
default:
18882+
llvm_unreachable(
18883+
"Intrinsic WaveGetLaneIndex not supported by target architecture");
18884+
}
1887318885
}
1887418886
case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
1887518887
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
19921992
return true;
19931993
break;
19941994
}
1995+
case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
1996+
if (SemaRef.checkArgCount(TheCall, 0))
1997+
return true;
1998+
break;
1999+
}
19952000
case Builtin::BI__builtin_elementwise_acos:
19962001
case Builtin::BI__builtin_elementwise_asin:
19972002
case Builtin::BI__builtin_elementwise_atan:
Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
2-
// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
2+
// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
3+
// RUN: --check-prefixes=CHECK,CHECK-SPIRV
4+
// RUN: %clang_cc1 -finclude-default-header \
5+
// RUN: -triple dxil-pc-shadermodel6.3-library %s \
6+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
7+
// RUN: --check-prefixes=CHECK,CHECK-DXIL
38

4-
// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] {
5-
// CHECK: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry()
6-
// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ]
7-
uint test_1() {
9+
// CHECK-SPIRV: define spir_func noundef i32 @{{.*test_1.*}}() [[A0:#[0-9]+]] {
10+
// CHECK-DXIL: define noundef i32 @{{.*test_1.*}}() [[A0:#[0-9]+]] {
11+
// CHECK-SPIRV: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry()
12+
// CHECK-SPIRV: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ]
13+
// CHECK-DXIL: call i32 @llvm.dx.wave.getlaneindex()
14+
int test_1() {
815
return WaveGetLaneIndex();
916
}
1017

11-
// CHECK: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]]
18+
// CHECK-SPIRV: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]]
19+
// CHECK-DXIL: declare i32 @llvm.dx.wave.getlaneindex() [[A1:#[0-9]+]]
1220

1321
// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} }
1422
// CHECK-DAG: attributes [[A1]] = { {{.*}}convergent{{.*}} }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify
2+
3+
int test_too_many_arg(int x) {
4+
return __builtin_hlsl_wave_get_lane_index(x);
5+
// expected-error@-1 {{too many arguments to function call, expected 0, have 1}}
6+
}

llvm/include/llvm/IR/IntrinsicsDirectX.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLV
8383
def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
8484
def int_dx_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
8585
def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
86+
def int_dx_wave_getlaneindex : DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrConvergent, IntrNoMem]>;
8687
def int_dx_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>;
8788
def int_dx_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
8889
def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,3 +801,12 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> {
801801
let stages = [Stages<DXIL1_0, [all_stages]>];
802802
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
803803
}
804+
805+
def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> {
806+
let Doc = "returns the index of the current lane in the wave";
807+
let LLVMIntrinsic = int_dx_wave_getlaneindex;
808+
let arguments = [];
809+
let result = Int32Ty;
810+
let stages = [Stages<DXIL1_0, [all_stages]>];
811+
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
812+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-compute %s | FileCheck %s
2+
3+
define void @main() {
4+
entry:
5+
; CHECK: call i32 @dx.op.waveGetLaneIndex(i32 111)
6+
%0 = call i32 @llvm.dx.wave.getlaneindex()
7+
ret void
8+
}
9+
10+
declare i32 @llvm.dx.wave.getlaneindex()

0 commit comments

Comments
 (0)