-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[HLSL] Implement WaveActiveAnyTrue intrinsic #115902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
845256b
3b63a3a
37fbd29
af0c150
fcd1949
dd6eff1
9c43edf
7823ce6
dfeb327
40d13cb
66848d8
883b2a8
4dd242a
e616b31
8ac6052
7d1192d
8733a1b
e61310b
42d24e4
ee78787
781b1b3
74008ff
0b6f9c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2223,6 +2223,15 @@ float4 trunc(float4); | |
// Wave* builtins | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// \brief Returns true if the expression is true in any active lane in the | ||
/// current wave. | ||
/// | ||
/// \param Val The boolean expression to evaluate. | ||
/// \return True if the expression is true in any lane. | ||
_HLSL_AVAILABILITY(shadermodel, 6.0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this is correct. And I can see the other wave intrinsics do this, but our default availability is 6.0. Is the thinking to do this that do the bookkeeping now so that it makes it easier to support pre 6.0 shader models i.e. FXC shaders at some point? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had propagated this for the sake of user documentation as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was just kind of following what others had done. But imo its worth keeping if for nothing else besides the documentation |
||
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_any_true) | ||
__attribute__((convergent)) bool WaveActiveAnyTrue(bool Val); | ||
|
||
/// \brief Counts the number of boolean variables which evaluate to true across | ||
/// all active lanes in the current wave. | ||
/// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \ | ||
// RUN: dxil-pc-shadermodel6.3-compute %s -emit-llvm -disable-llvm-passes -o - | \ | ||
// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-DXIL | ||
// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -triple \ | ||
// RUN: spirv-pc-vulkan-compute %s -emit-llvm -disable-llvm-passes -o - | \ | ||
// RUN: FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV | ||
|
||
// Test basic lowering to runtime function call for int values. | ||
|
||
// CHECK-LABEL: define {{.*}}test | ||
bool test(bool p1) { | ||
// CHECK-SPIRV: %[[#entry_tok0:]] = call token @llvm.experimental.convergence.entry() | ||
// CHECK-SPIRV: %[[RET:.*]] = call spir_func i1 @llvm.spv.wave.any(i1 %{{[a-zA-Z0-9]+}}) [ "convergencectrl"(token %[[#entry_tok0]]) ] | ||
// CHECK-DXIL: %[[RET:.*]] = call i1 @llvm.dx.wave.any(i1 %{{[a-zA-Z0-9]+}}) | ||
// CHECK: ret i1 %[[RET]] | ||
return WaveActiveAnyTrue(p1); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify | ||
|
||
bool test_too_few_arg() { | ||
return __builtin_hlsl_wave_active_any_true(); | ||
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}} | ||
} | ||
|
||
bool test_too_many_arg(bool p0) { | ||
return __builtin_hlsl_wave_active_any_true(p0, p0); | ||
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}} | ||
} | ||
|
||
struct Foo | ||
{ | ||
int a; | ||
}; | ||
|
||
bool test_type_check(Foo p0) { | ||
return __builtin_hlsl_wave_active_any_true(p0); | ||
// expected-error@-1 {{no viable conversion from 'Foo' to 'bool'}} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,7 @@ def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLV | |
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_wave_active_countbits : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; | ||
def int_dx_wave_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think @inbelic is working to remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite, we can keep the I will audit that they are added correctly, in this case I think |
||
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_wave_readlane : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrConvergent, IntrNoMem]>; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,6 +86,7 @@ let TargetPrefix = "spv" in { | |
def int_spv_dot4add_i8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; | ||
def int_spv_dot4add_u8packed : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; | ||
def int_spv_wave_active_countbits : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; | ||
def int_spv_wave_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall IntrNoMem be removed? AFAIK is IntrNoMem is added, compiler can assume there are no other side effect. But since this depends on other lanes, isn't that equivalent to IntrReadMem? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @inbelic says its fine to keep here #115902 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Happy to be corrected. My understanding was that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding was |
||
def int_spv_wave_is_first_lane : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrConvergent]>; | ||
def int_spv_wave_readlane : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrConvergent, IntrNoMem]>; | ||
def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-compute %s | FileCheck %s | ||
|
||
define noundef i1 @wave_any_simple(i1 noundef %p1) { | ||
entry: | ||
; CHECK: call i1 @dx.op.waveAnyTrue(i32 113, i1 %p1) | ||
%ret = call i1 @llvm.dx.wave.any(i1 %p1) | ||
ret i1 %ret | ||
} | ||
|
||
declare i1 @llvm.dx.wave.any(i1) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s | ||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} | ||
|
||
; CHECK-DAG: %[[#bool:]] = OpTypeBool | ||
; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0 | ||
; CHECK-DAG: %[[#scope:]] = OpConstant %[[#uint]] 3 | ||
; CHECK-DAG: OpCapability GroupNonUniformVote | ||
|
||
; CHECK-LABEL: Begin function test_wave_any | ||
define i1 @test_wave_any(i1 %p1) #0 { | ||
entry: | ||
; CHECK: %[[#param:]] = OpFunctionParameter %[[#bool]] | ||
; CHECK: %{{.+}} = OpGroupNonUniformAny %[[#bool]] %[[#scope]] %[[#param]] | ||
V-FEXrt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
%0 = call token @llvm.experimental.convergence.entry() | ||
%ret = call i1 @llvm.spv.wave.any(i1 %p1) [ "convergencectrl"(token %0) ] | ||
ret i1 %ret | ||
} | ||
|
||
declare i1 @llvm.spv.wave.any(i1) #0 | ||
|
||
attributes #0 = { convergent } |
Uh oh!
There was an error while loading. Please reload this page.