https://github.com/V-FEXrt updated https://github.com/llvm/llvm-project/pull/117245
>From 1156d98a0ba25a92b4edbacb7c17e5ad6bb2b522 Mon Sep 17 00:00:00 2001 From: Ashley Coleman <ascole...@microsoft.com> Date: Thu, 21 Nov 2024 08:42:31 -0700 Subject: [PATCH 1/2] [HLSL] Implement WaveActiveAllTrue Intrinsic --- clang/include/clang/Basic/Builtins.td | 6 ++++++ clang/lib/CodeGen/CGBuiltin.cpp | 10 +++++++++ clang/lib/CodeGen/CGHLSLRuntime.h | 1 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 9 ++++++++ .../builtins/WaveActiveAllTrue.hlsl | 17 +++++++++++++++ .../BuiltIns/WaveActiveAllTrue-errors.hlsl | 21 +++++++++++++++++++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + llvm/lib/Target/DirectX/DXIL.td | 8 +++++++ .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++ .../test/CodeGen/DirectX/WaveActiveAllTrue.ll | 10 +++++++++ .../hlsl-intrinsics/WaveActiveAllTrue.ll | 21 +++++++++++++++++++ 12 files changed, 107 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 32a09e2ceb3857..d64a66fc9d9cf7 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4762,6 +4762,12 @@ def HLSLAsDouble : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLWaveActiveAllTrue : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_wave_active_all_true"]; + let Attributes = [NoThrow, Const]; + let Prototype = "bool(bool)"; +} + def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_wave_active_any_true"]; let Attributes = [NoThrow, Const]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c2e983eebebc10..06d7aaf9badc07 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19419,6 +19419,16 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(), ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step"); } + case Builtin::BI__builtin_hlsl_wave_active_all_true: { + Value *Op = EmitScalarExpr(E->getArg(0)); + llvm::Type *Ty = Op->getType(); + assert(Ty->isIntegerTy(1) && + "Intrinsic WaveActiveAllTrue operand must be a bool"); + + Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic(); + return EmitRuntimeCall( + Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op}); + } case Builtin::BI__builtin_hlsl_wave_active_any_true: { Value *Op = EmitScalarExpr(E->getArg(0)); assert(Op->getType()->isIntegerTy(1) && diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index bb120c8b5e9e60..1260bb4bc9001b 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -91,6 +91,7 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot) GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed) GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed) + GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 1126e13600f8af..b745997f1d5a2b 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -2241,6 +2241,15 @@ float4 trunc(float4); // Wave* builtins //===----------------------------------------------------------------------===// +/// \brief Returns true if the expression is true in all active lanes in the +/// current wave. +/// +/// \param Val The boolean expression to evaluate. +/// \return True if the expression is true in all lanes. +_HLSL_AVAILABILITY(shadermodel, 6.0) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_all_true) +__attribute__((convergent)) bool WaveActiveAllTrue(bool Val); + /// \brief Returns true if the expression is true in any active lane in the /// current wave. /// diff --git a/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl b/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl new file mode 100644 index 00000000000000..df530a9cee561a --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl @@ -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.all(i1 %{{[a-zA-Z0-9]+}}) [ "convergencectrl"(token %[[#entry_tok0]]) ] + // CHECK-DXIL: %[[RET:.*]] = call i1 @llvm.dx.wave.all(i1 %{{[a-zA-Z0-9]+}}) + // CHECK: ret i1 %[[RET]] + return WaveActiveAllTrue(p1); +} diff --git a/clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl new file mode 100644 index 00000000000000..b0d0fdfca5e18d --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/WaveActiveAllTrue-errors.hlsl @@ -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_all_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_all_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_all_true(p0); + // expected-error@-1 {{no viable conversion from 'Foo' to 'bool'}} +} diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 5696345a617fe5..d509c17ee36c81 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -98,6 +98,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_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; def int_dx_wave_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_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]>; diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 1ae3129774e507..c8421cd5a4f577 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -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_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; def int_spv_wave_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], [IntrConvergent, IntrNoMem]>; 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]>; diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index cff6cdce813ded..ff76e4ba0990df 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -924,6 +924,14 @@ def CreateHandleFromBinding : DXILOp<217, createHandleFromBinding> { let stages = [Stages<DXIL1_6, [all_stages]>]; } +def WaveActiveAllTrue : DXILOp<334, waveAllTrue> { + let Doc = "returns true if the expression is true in all of the active lanes in the current wave"; + let LLVMIntrinsic = int_dx_wave_all; + let arguments = [Int1Ty]; + let result = Int1Ty; + let stages = [Stages<DXIL1_0, [all_stages]>]; +} + def WaveActiveAnyTrue : DXILOp<113, waveAnyTrue> { let Doc = "returns true if the expression is true in any of the active lanes in the current wave"; let intrinsics = [ IntrinSelect<int_dx_wave_any> ]; diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 3a98b74b3d6757..5039c7a63aa09e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -2935,6 +2935,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectExtInst(ResVReg, ResType, I, CL::s_clamp, GL::SClamp); case Intrinsic::spv_wave_active_countbits: return selectWaveActiveCountBits(ResVReg, ResType, I); + case Intrinsic::spv_wave_all: + return selectWaveOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAll); case Intrinsic::spv_wave_any: return selectWaveOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAny); case Intrinsic::spv_wave_is_first_lane: diff --git a/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll b/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll new file mode 100644 index 00000000000000..73b3e4f7843845 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll @@ -0,0 +1,10 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-compute %s | FileCheck %s + +define noundef i1 @wave_all_simple(i1 noundef %p1) { +entry: +; CHECK: call i1 @dx.op.waveAllTrue(i32 334, i1 %p1) + %ret = call i1 @llvm.dx.wave.all(i1 %p1) + ret i1 %ret +} + +declare i1 @llvm.dx.wave.all(i1) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll new file mode 100644 index 00000000000000..d030353ad93b4f --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveActiveAllTrue.ll @@ -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_all +define i1 @test_wave_all(i1 %p1) #0 { +entry: +; CHECK: %[[#param:]] = OpFunctionParameter %[[#bool]] +; CHECK: %{{.+}} = OpGroupNonUniformAll %[[#bool]] %[[#scope]] %[[#param]] + %0 = call token @llvm.experimental.convergence.entry() + %ret = call i1 @llvm.spv.wave.all(i1 %p1) [ "convergencectrl"(token %0) ] + ret i1 %ret +} + +declare i1 @llvm.spv.wave.all(i1) #0 + +attributes #0 = { convergent } >From 47a582db3c0e58ec73d6bbe738be703e76bd3ef9 Mon Sep 17 00:00:00 2001 From: Ashley Coleman <ascole...@microsoft.com> Date: Mon, 9 Dec 2024 13:06:40 -0700 Subject: [PATCH 2/2] fixup --- llvm/lib/Target/DirectX/DXIL.td | 4 ++-- llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index ff76e4ba0990df..5d865a3c0bbbb7 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -924,9 +924,9 @@ def CreateHandleFromBinding : DXILOp<217, createHandleFromBinding> { let stages = [Stages<DXIL1_6, [all_stages]>]; } -def WaveActiveAllTrue : DXILOp<334, waveAllTrue> { +def WaveActiveAllTrue : DXILOp<114, waveAllTrue> { let Doc = "returns true if the expression is true in all of the active lanes in the current wave"; - let LLVMIntrinsic = int_dx_wave_all; + let intrinsics = [ IntrinSelect<int_dx_wave_all> ]; let arguments = [Int1Ty]; let result = Int1Ty; let stages = [Stages<DXIL1_0, [all_stages]>]; diff --git a/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll b/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll index 73b3e4f7843845..7e84f33579a619 100644 --- a/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll +++ b/llvm/test/CodeGen/DirectX/WaveActiveAllTrue.ll @@ -2,7 +2,7 @@ define noundef i1 @wave_all_simple(i1 noundef %p1) { entry: -; CHECK: call i1 @dx.op.waveAllTrue(i32 334, i1 %p1) +; CHECK: call i1 @dx.op.waveAllTrue(i32 114, i1 %p1) %ret = call i1 @llvm.dx.wave.all(i1 %p1) ret i1 %ret } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits