https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/236932
>From 0ce9b93b7ea0d23ed200ac932013286c7c9152e2 Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Thu, 29 Oct 2026 13:39:25 -0700 Subject: [PATCH 1/3] first attempt --- clang/include/clang/Basic/Builtins.td | 6 ++++ clang/include/clang/Basic/HLSLIntrinsics.td | 11 ++++++ clang/lib/CodeGen/CGHLSLBuiltins.cpp | 5 +++ clang/lib/CodeGen/CGHLSLRuntime.h | 1 + clang/test/CodeGenHLSL/builtins/QuadAll.hlsl | 24 +++++++++++++ .../BuiltIns/QuadAll-availability.hlsl | 13 +++++++ .../SemaHLSL/BuiltIns/QuadAll-errors.hlsl | 28 +++++++++++++++ llvm/docs/SPIRVUsage.md | 3 ++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 4 +++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 4 +++ llvm/lib/Target/DirectX/DXIL.td | 16 +++++++++ llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 2 +- llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 4 ++- llvm/lib/Target/SPIRV/SPIRVInstrInfo.td | 5 +++ .../Target/SPIRV/SPIRVInstructionSelector.cpp | 7 ++++ llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 16 +++++++++ .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 3 ++ llvm/test/CodeGen/DirectX/QuadAll-errors.ll | 22 ++++++++++++ llvm/test/CodeGen/DirectX/QuadAll.ll | 20 +++++++++++ .../CodeGen/DirectX/ShaderFlags/wave-ops.ll | 7 ++++ .../CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll | 36 +++++++++++++++++++ 21 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGenHLSL/builtins/QuadAll.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/QuadAll-availability.hlsl create mode 100644 clang/test/SemaHLSL/BuiltIns/QuadAll-errors.hlsl create mode 100644 llvm/test/CodeGen/DirectX/QuadAll-errors.ll create mode 100644 llvm/test/CodeGen/DirectX/QuadAll.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index d04fd899eb63a6..519bdbc9899def 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5795,6 +5795,12 @@ def HLSLWavePrefixProduct : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLQuadAll : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_quad_all"]; + let Attributes = [NoThrow, Const]; + let Prototype = "bool(bool)"; +} + def HLSLQuadReadAcrossX : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_quad_read_across_x"]; let Attributes = [NoThrow, Const]; diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td index fd59e3477b8c79..05e7f63f4e2130 100644 --- a/clang/include/clang/Basic/HLSLIntrinsics.td +++ b/clang/include/clang/Basic/HLSLIntrinsics.td @@ -1368,6 +1368,17 @@ def hlsl_pow : HLSLTwoArgBuiltin<"pow", "__builtin_elementwise_pow"> { let VaryingLongVector = 1; } +def hlsl_quad_all : HLSLBuiltin<"QuadAll", "__builtin_hlsl_quad_all"> { + let Doc = [{ +\brief Returns true if the condition is true in all active lanes in the quad. +\param Cond The condition to evaluate. +}]; + let Args = [BoolTy]; + let ReturnType = BoolTy; + let IsConvergent = 1; + let Availability = SM6_7; +} + // Reads the value from the lane across the X axis of the quad. def hlsl_quad_read_across_x : HLSLOneArgBuiltin<"QuadReadAcrossX", diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index fc422918499ed2..a2737287b01a88 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -1728,6 +1728,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return EmitIntrinsicCall(IID, {OpExpr->getType()}, ArrayRef{OpExpr}, "hlsl.wave.prefix.product"); } + case Builtin::BI__builtin_hlsl_quad_all: { + Value *Op = EmitScalarExpr(E->getArg(0)); + Intrinsic::ID ID = CGM.getHLSLRuntime().getQuadAllIntrinsic(); + return EmitIntrinsicCall(ID, {Op}); + } case Builtin::BI__builtin_hlsl_quad_read_across_x: { Value *OpExpr = EmitScalarExpr(E->getArg(0)); Intrinsic::ID ID = CGM.getHLSLRuntime().getQuadReadAcrossXIntrinsic(); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 1957b946826d37..af2cda88318efd 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -159,6 +159,7 @@ class CGHLSLRuntime { subgroup_size) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneFirst, wave_readlane_first) + GENERATE_HLSL_INTRINSIC_FUNCTION(QuadAll, quad_all) GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossX, quad_read_across_x) GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossY, quad_read_across_y) GENERATE_HLSL_INTRINSIC_FUNCTION(QuadReadAcrossDiagonal, diff --git a/clang/test/CodeGenHLSL/builtins/QuadAll.hlsl b/clang/test/CodeGenHLSL/builtins/QuadAll.hlsl new file mode 100644 index 00000000000000..986178e8d9ab1f --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/QuadAll.hlsl @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.7-library %s -emit-llvm \ +// RUN: -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,DXIL +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,SPIRV + +// CHECK-LABEL: define {{.*}}test_quad_all{{.*}}( +// SPIRV: %[[TOKEN:.*]] = call token @llvm.experimental.convergence.entry() +// DXIL: %[[RET:.*]] = call i1 @llvm.dx.quad.all(i1 %{{.*}}) +// SPIRV: %[[RET:.*]] = call i1 @llvm.spv.quad.all(i1 %{{.*}}) [ "convergencectrl"(token %[[TOKEN]]) ] +// CHECK: ret i1 %[[RET]] +bool test_quad_all(bool cond) { + return QuadAll(cond); +} + +// CHECK-LABEL: define {{.*}}test_builtin{{.*}}( +// SPIRV: %[[TOKEN:.*]] = call token @llvm.experimental.convergence.entry() +// DXIL: %[[RET:.*]] = call i1 @llvm.dx.quad.all(i1 %{{.*}}) +// SPIRV: %[[RET:.*]] = call i1 @llvm.spv.quad.all(i1 %{{.*}}) [ "convergencectrl"(token %[[TOKEN]]) ] +// CHECK: ret i1 %[[RET]] +bool test_builtin(bool cond) { + return __builtin_hlsl_quad_all(cond); +} diff --git a/clang/test/SemaHLSL/BuiltIns/QuadAll-availability.hlsl b/clang/test/SemaHLSL/BuiltIns/QuadAll-availability.hlsl new file mode 100644 index 00000000000000..c6b3bea64e760a --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/QuadAll-availability.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.6-library %s -fhlsl-strict-availability \ +// RUN: -fsyntax-only -verify -verify-ignore-unexpected=note +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.7-library %s -fhlsl-strict-availability \ +// RUN: -fsyntax-only -verify=sm67 + +// sm67-no-diagnostics + +bool test_availability(bool cond) { + // expected-error@+1 {{'QuadAll' is only available on Shader Model 6.7}} + return QuadAll(cond); +} diff --git a/clang/test/SemaHLSL/BuiltIns/QuadAll-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/QuadAll-errors.hlsl new file mode 100644 index 00000000000000..b12ca49e1e432f --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/QuadAll-errors.hlsl @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.7-library %s -fsyntax-only -verify +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-pc-vulkan-library %s -fsyntax-only -verify + +bool test_too_few_args() { + return __builtin_hlsl_quad_all(); + // expected-error@-1 {{too few arguments to function call, expected 1}} +} + +bool test_too_many_args(bool cond) { + return __builtin_hlsl_quad_all(cond, cond); + // expected-error@-1 {{too many arguments to function call, expected 1}} +} + +struct Foo { + int value; +}; + +bool test_type(Foo value) { + return __builtin_hlsl_quad_all(value); + // expected-error@-1 {{cannot initialize a parameter of type 'bool'}} +} + +bool test_vector(bool2 value) { + return __builtin_hlsl_quad_all(value); + // expected-warning@-1 {{implicit conversion turns vector to scalar}} +} diff --git a/llvm/docs/SPIRVUsage.md b/llvm/docs/SPIRVUsage.md index 6f958b3ddffe7d..db41d8ce27a5c7 100644 --- a/llvm/docs/SPIRVUsage.md +++ b/llvm/docs/SPIRVUsage.md @@ -231,6 +231,9 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e - Adds predicated load and store instructions that conditionally read from or write to memory based on a boolean predicate. * - ``SPV_KHR_maximal_reconvergence`` - Adds execution mode and capability to enable maximal reconvergence. + * - ``SPV_KHR_quad_control`` + - Adds the quad vote instruction for HLSL `QuadAll`. + This instruction also requires `SPV_KHR_maximal_reconvergence`. * - ``SPV_ALTERA_blocking_pipes`` - Adds new pipe read and write functions that have blocking semantics instead of the non-blocking semantics of the existing pipe read/write functions. * - ``SPV_ALTERA_arbitrary_precision_fixed_point`` diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index b9b02aeb081916..20a73dda1d1d0b 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -488,6 +488,10 @@ let TargetPrefix = "dx" in { [IntrConvergent, IntrNoMem, IntrTriviallyScalarizable]>; + def int_dx_quad_all + : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], + [IntrConvergent, IntrNoMem]>; + def int_dx_quad_read_across_x : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrConvergent, IntrNoMem, diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index f9319918694d7d..4213dfaf80dc28 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -388,6 +388,10 @@ let TargetPrefix = "spv" in { [IntrConvergent, IntrNoMem, IntrTriviallyScalarizable]>; + def int_spv_quad_all + : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i1_ty], + [IntrConvergent, IntrNoMem]>; + def int_spv_quad_read_across_x : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrConvergent, IntrNoMem, diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 3f81e83b01ecba..9b2ed8b9a39012 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -329,6 +329,8 @@ defvar QuadOpKind_ReadAcrossX = 0; defvar QuadOpKind_ReadAcrossY = 1; defvar QuadOpKind_ReadAcrossDiagonal = 2; +defvar QuadVoteOpKind_All = 1; + // Intrinsic arg selection class IntrinArgSelectType; def IntrinArgSelect_Index : IntrinArgSelectType; @@ -1562,6 +1564,20 @@ def CreateHandleFromHeap : DXILOp<218, createHandleFromHeap> { let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } +def QuadVote : DXILOp<222, quadVote> { + let Doc = "compares a boolean condition across a quad"; + let intrinsics = [ + IntrinSelect<int_dx_quad_all, + [IntrinArgIndex<0>, IntrinArgI8<QuadVoteOpKind_All>]> + ]; + let arguments = [Int1Ty, Int8Ty]; + let result = OverloadTy; + let overloads = [Overloads<DXIL1_7, [Int1Ty]>]; + let stages = [ + Stages<DXIL1_7, [library, compute, amplification, mesh, pixel, node]> + ]; +} + def BarrierByMemoryType : DXILOp<244, barrierByMemoryType> { let Doc = "inserts a memory barrier for the specified memory types"; let intrinsics = [IntrinSelect<int_dx_barrier_by_memory_type>]; diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp index 59953c191497be..946c03f19fa043 100644 --- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp @@ -79,7 +79,6 @@ static bool checkWaveOps(Intrinsic::ID IID) { // case Intrinsic::dx_wave_match: // case Intrinsic::dx_wavemulti.*: // case Intrinsic::dx_wavemulti.ballot: - // case Intrinsic::dx_quad.vote: switch (IID) { default: return false; @@ -112,6 +111,7 @@ static bool checkWaveOps(Intrinsic::ID IID) { case Intrinsic::dx_wave_prefix_product: case Intrinsic::dx_wave_prefix_uproduct: // Quad Op Variants + case Intrinsic::dx_quad_all: case Intrinsic::dx_quad_read_across_x: case Intrinsic::dx_quad_read_across_y: case Intrinsic::dx_quad_read_across_diagonal: diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 15f1f2b1b05b36..a430ad49fefb13 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -180,7 +180,9 @@ static const StringMap<SPIRV::Extension::Extension> SPIRVExtensionMap = { SPIRV::Extension::Extension::SPV_KHR_poison_freeze}, {"SPV_KHR_untyped_pointers", SPIRV::Extension::Extension::SPV_KHR_untyped_pointers}, - {"SPV_EXT_long_vector", SPIRV::Extension::Extension::SPV_EXT_long_vector}}; + {"SPV_EXT_long_vector", SPIRV::Extension::Extension::SPV_EXT_long_vector}, + {"SPV_KHR_quad_control", + SPIRV::Extension::Extension::SPV_KHR_quad_control}}; bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, ExtensionSet &Vals) { diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index df9ff2c941c85b..56fddff7cfa0d5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -901,6 +901,11 @@ def OpGroupNonUniformLogicalOr: OpGroupNUGroup<"LogicalOr", 363>; def OpGroupNonUniformLogicalXor: OpGroupNUGroup<"LogicalXor", 364>; def OpGroupNonUniformQuadSwap: OpGroupNU4<"QuadSwap", 366>; +// SPV_KHR_quad_control +def OpGroupNonUniformQuadAllKHR + : Op<5110, (outs ID:$res), (ins TYPE:$ty, ID:$pred), + "$res = OpGroupNonUniformQuadAllKHR $ty $pred">; + // SPV_KHR_subgroup_rotate def OpGroupNonUniformRotateKHR: Op<4431, (outs ID:$res), (ins TYPE:$type, ID:$scope, ID:$value, ID:$delta, variable_ops), diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index b0f1445f6a10be..f07a8f7cea1f89 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -5788,6 +5788,13 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectWaveExclusiveScanSum(ResVReg, ResType, I); case Intrinsic::spv_wave_prefix_product: return selectWaveExclusiveScanProduct(ResVReg, ResType, I); + case Intrinsic::spv_quad_all: + BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpGroupNonUniformQuadAllKHR)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)) + .addUse(I.getOperand(2).getReg()) + .constrainAllUses(TII, TRI, RBI); + return true; case Intrinsic::spv_quad_read_across_x: { return selectQuadSwap(ResVReg, ResType, I, /*Direction*/ 0); } diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 8f847c17e9d74b..4ae3708ac8e950 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -2138,6 +2138,22 @@ void addInstrRequirements(const MachineInstr &MI, Reqs.addCapability(SPIRV::Capability::FunctionPointersINTEL); } break; + case SPIRV::OpGroupNonUniformQuadAllKHR: + if (!ST.isAtLeastSPIRVVer(VersionTuple(1, 3))) + report_fatal_error("OpGroupNonUniformQuadAllKHR requires SPIR-V 1.3", + false); + if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_quad_control)) + report_fatal_error("OpGroupNonUniformQuadAllKHR instruction requires the " + "following SPIR-V extension: SPV_KHR_quad_control", + false); + if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence)) + report_fatal_error("SPV_KHR_quad_control requires the following SPIR-V " + "extension: SPV_KHR_maximal_reconvergence", + false); + Reqs.addExtension(SPIRV::Extension::SPV_KHR_quad_control); + Reqs.addExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence); + Reqs.addCapability(SPIRV::Capability::QuadControlKHR); + break; case SPIRV::OpGroupNonUniformRotateKHR: if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate)) report_fatal_error("OpGroupNonUniformRotateKHR instruction requires the " diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 00bee6c9518453..8792431da11510 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -410,6 +410,7 @@ defm SPV_KHR_poison_freeze : ExtensionOperand<139, [EnvOpenCL]>; defm SPV_KHR_untyped_pointers : ExtensionOperand<140, [EnvOpenCL]>; defm SPV_EXT_long_vector : ExtensionOperand<141, [EnvOpenCL, EnvVulkan]>; defm SPV_KHR_relaxed_extended_instruction : ExtensionOperand<142, [EnvVulkan, EnvOpenCL]>; +defm SPV_KHR_quad_control : ExtensionOperand<143, [EnvVulkan]>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -576,6 +577,8 @@ defm ArbitraryPrecisionIntegersALTERA : CapabilityOperand<5844, 0, 0, [SPV_ALTER defm OptNoneINTEL : CapabilityOperand<6094, 0, 0, [SPV_INTEL_optnone], []>; defm OptNoneEXT : CapabilityOperand<6094, 0, 0, [SPV_EXT_optnone], []>; defm BitInstructions : CapabilityOperand<6025, 0, 0, [SPV_KHR_bit_instructions], []>; +defm QuadControlKHR + : CapabilityOperand<5087, 0, 0, [SPV_KHR_quad_control], []>; defm ExpectAssumeKHR : CapabilityOperand<5629, 0, 0, [SPV_KHR_expect_assume], []>; defm FunctionPointersINTEL : CapabilityOperand<5603, 0, 0, [SPV_INTEL_function_pointers], []>; defm IndirectReferencesINTEL : CapabilityOperand<5604, 0, 0, [SPV_INTEL_function_pointers], []>; diff --git a/llvm/test/CodeGen/DirectX/QuadAll-errors.ll b/llvm/test/CodeGen/DirectX/QuadAll-errors.ll new file mode 100644 index 00000000000000..47d649ab352134 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/QuadAll-errors.ll @@ -0,0 +1,22 @@ +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-compute \ +; RUN: %s 2>&1 | FileCheck %s --check-prefix=VERSION +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-vertex \ +; RUN: %s 2>&1 | FileCheck %s --check-prefix=STAGE +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-geometry \ +; RUN: %s 2>&1 | FileCheck %s --check-prefix=STAGE +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-hull \ +; RUN: %s 2>&1 | FileCheck %s --check-prefix=STAGE +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-domain \ +; RUN: %s 2>&1 | FileCheck %s --check-prefix=STAGE +; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-raygeneration \ +; RUN: %s 2>&1 | FileCheck %s --check-prefix=STAGE + +; VERSION: Cannot create QuadVote operation: No valid overloads for DXIL version 1.6 +; STAGE: Cannot create QuadVote operation: Invalid stage + +define i1 @quad_all(i1 %cond) { + %ret = call i1 @llvm.dx.quad.all(i1 %cond) + ret i1 %ret +} + +declare i1 @llvm.dx.quad.all(i1) diff --git a/llvm/test/CodeGen/DirectX/QuadAll.ll b/llvm/test/CodeGen/DirectX/QuadAll.ll new file mode 100644 index 00000000000000..383de1135adab9 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/QuadAll.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-library %s \ +; RUN: | FileCheck %s +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-compute %s \ +; RUN: | FileCheck %s +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-pixel %s \ +; RUN: | FileCheck %s +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-amplification %s \ +; RUN: | FileCheck %s +; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.7-mesh %s \ +; RUN: | FileCheck %s + +; CHECK-LABEL: define i1 @quad_all( +; CHECK: %[[RET:.*]] = call i1 @dx.op.quadVote.i1(i32 222, i1 %cond, i8 1) +; CHECK-NEXT: ret i1 %[[RET]] +define i1 @quad_all(i1 %cond) { + %ret = call i1 @llvm.dx.quad.all(i1 %cond) + ret i1 %ret +} + +declare i1 @llvm.dx.quad.all(i1) diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll index 37a991e1c1fa8e..19591defcdb317 100644 --- a/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/wave-ops.ll @@ -49,6 +49,13 @@ entry: ret i1 %ret } +define noundef i1 @quad_all(i1 %x) { +entry: + ; CHECK: Function quad_all : [[WAVE_FLAG]] + %ret = call i1 @llvm.dx.quad.all(i1 %x) + ret i1 %ret +} + define noundef i32 @wave_bit_or(i32 %x) { entry: ; CHECK: Function wave_bit_or : [[WAVE_FLAG]] diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll new file mode 100644 index 00000000000000..cd94b87181a6aa --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll @@ -0,0 +1,36 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.5-unknown-vulkan-library \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - | FileCheck %s +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-library \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-EXT +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-library \ +; RUN: --spirv-ext=+SPV_KHR_quad_control %s -o - 2>&1 \ +; RUN: | FileCheck %s --check-prefix=NO-RECONVERGENCE +; RUN: not llc -O0 -mtriple=spirv32v1.2-unknown-vulkan-library \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=VERSION +; RUN: %if spirv-tools %{ llc -O0 \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-library \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - -filetype=obj | spirv-val %} + +; NO-EXT: OpGroupNonUniformQuadAllKHR instruction requires the following SPIR-V extension: SPV_KHR_quad_control +; NO-RECONVERGENCE: SPV_KHR_quad_control requires the following SPIR-V extension: SPV_KHR_maximal_reconvergence +; VERSION: OpGroupNonUniformQuadAllKHR requires SPIR-V 1.3 + +; CHECK-DAG: OpCapability QuadControlKHR +; CHECK-DAG: OpExtension "SPV_KHR_quad_control" +; CHECK-DAG: OpExtension "SPV_KHR_maximal_reconvergence" +; CHECK-DAG: %[[#BOOL:]] = OpTypeBool + +; CHECK-LABEL: Begin function quad_all +; CHECK: %[[#COND:]] = OpFunctionParameter %[[#BOOL]] +; CHECK: %[[#RET:]] = OpGroupNonUniformQuadAllKHR %[[#BOOL]] %[[#COND]] +; CHECK-NEXT: OpReturnValue %[[#RET]] +define i1 @quad_all(i1 %cond) convergent { + %tok = call token @llvm.experimental.convergence.entry() + %ret = call i1 @llvm.spv.quad.all(i1 %cond) [ "convergencectrl"(token %tok) ] + ret i1 %ret +} + +declare i1 @llvm.spv.quad.all(i1) convergent >From 8c23445e2d73757abe82f14345e8ee946a029406 Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Thu, 29 Oct 2026 13:55:13 -0700 Subject: [PATCH 2/3] self review --- llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll index cd94b87181a6aa..512f98e0940517 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll @@ -4,8 +4,8 @@ ; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-library \ ; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-EXT ; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-library \ -; RUN: --spirv-ext=+SPV_KHR_quad_control %s -o - 2>&1 \ -; RUN: | FileCheck %s --check-prefix=NO-RECONVERGENCE +; RUN: --spirv-ext=+SPV_KHR_quad_control,-SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-RECONVERGENCE ; RUN: not llc -O0 -mtriple=spirv32v1.2-unknown-vulkan-library \ ; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ ; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=VERSION >From 9ec100dffab07d772e7d394ba0d2dd09c1ea1dfb Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Fri, 30 Oct 2026 15:45:41 -0700 Subject: [PATCH 3/3] address feedback --- llvm/docs/SPIRVUsage.md | 8 +++- llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 5 ++- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 43 ++++++++++++------ .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 13 +++++- .../derivative-group-quads.ll | 30 +++++++++++++ .../quad-all.ll | 44 +++++++++++++++++++ .../quad-all-with-modes.ll | 37 ++++++++++++++++ .../SPV_KHR_quad_control/quad-derivatives.ll | 35 +++++++++++++++ .../require-full-quads.ll | 35 +++++++++++++++ .../CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll | 3 +- 10 files changed, 233 insertions(+), 20 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/derivative-group-quads.ll create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/quad-all.ll create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-all-with-modes.ll create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-derivatives.ll create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/require-full-quads.ll diff --git a/llvm/docs/SPIRVUsage.md b/llvm/docs/SPIRVUsage.md index db41d8ce27a5c7..df750bdcf23072 100644 --- a/llvm/docs/SPIRVUsage.md +++ b/llvm/docs/SPIRVUsage.md @@ -197,6 +197,9 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e - Adds a function-termination instruction that signals an abnormal error to the client API. Currently supported in OpenCL environments only. * - ``SPV_KHR_bit_instructions`` - Enables bit instructions to be used by SPIR-V modules without requiring the Shader capability. + * - ``SPV_KHR_compute_shader_derivatives`` + - Adds the `DerivativeGroupQuadsKHR` execution mode and the + `ComputeDerivativeGroupQuadsKHR` capability. * - ``SPV_KHR_expect_assume`` - Provides additional information to a compiler, similar to the llvm.assume and llvm.expect intrinsics. * - ``SPV_KHR_float_controls`` @@ -232,8 +235,9 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e * - ``SPV_KHR_maximal_reconvergence`` - Adds execution mode and capability to enable maximal reconvergence. * - ``SPV_KHR_quad_control`` - - Adds the quad vote instruction for HLSL `QuadAll`. - This instruction also requires `SPV_KHR_maximal_reconvergence`. + - Adds the quad vote instruction for HLSL `QuadAll` and the + `QuadDerivativesKHR` and `RequireFullQuadsKHR` execution modes. + These features also require `SPV_KHR_maximal_reconvergence`. * - ``SPV_ALTERA_blocking_pipes`` - Adds new pipe read and write functions that have blocking semantics instead of the non-blocking semantics of the existing pipe read/write functions. * - ``SPV_ALTERA_arbitrary_precision_fixed_point`` diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index a430ad49fefb13..14c9e8fecf0e47 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -181,8 +181,9 @@ static const StringMap<SPIRV::Extension::Extension> SPIRVExtensionMap = { {"SPV_KHR_untyped_pointers", SPIRV::Extension::Extension::SPV_KHR_untyped_pointers}, {"SPV_EXT_long_vector", SPIRV::Extension::Extension::SPV_EXT_long_vector}, - {"SPV_KHR_quad_control", - SPIRV::Extension::Extension::SPV_KHR_quad_control}}; + {"SPV_KHR_quad_control", SPIRV::Extension::Extension::SPV_KHR_quad_control}, + {"SPV_KHR_compute_shader_derivatives", + SPIRV::Extension::Extension::SPV_KHR_compute_shader_derivatives}}; bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, ExtensionSet &Vals) { diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 4ae3708ac8e950..cb3fdc1aa21fc5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -855,10 +855,39 @@ void SPIRVModuleAnalysisImpl::numberRegistersGlobally(const Module &M) { } } +static void addQuadControlRequirements(SPIRV::RequirementHandler &Reqs, + const SPIRVSubtarget &ST, + StringRef Feature) { + if (!ST.isAtLeastSPIRVVer(VersionTuple(1, 3))) + report_fatal_error(Twine(Feature) + " requires SPIR-V 1.3", false); + if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_quad_control)) + report_fatal_error(Twine(Feature) + " requires the following SPIR-V " + "extension: SPV_KHR_quad_control", + false); + if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence)) + report_fatal_error("SPV_KHR_quad_control requires the following SPIR-V " + "extension: SPV_KHR_maximal_reconvergence", + false); + Reqs.addExtension(SPIRV::Extension::SPV_KHR_quad_control); + Reqs.addExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence); +} + // RequirementHandler implementations. void SPIRV::RequirementHandler::getAndAddRequirements( SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST) { + if (Category == SPIRV::OperandCategory::ExecutionModeOperand && + (i == SPIRV::ExecutionMode::QuadDerivativesKHR || + i == SPIRV::ExecutionMode::RequireFullQuadsKHR)) + addQuadControlRequirements(*this, ST, + getSymbolicOperandMnemonic(Category, i)); + if (Category == SPIRV::OperandCategory::ExecutionModeOperand && + i == SPIRV::ExecutionMode::DerivativeGroupQuadsKHR && + !ST.canUseExtension(SPIRV::Extension::SPV_KHR_compute_shader_derivatives)) + report_fatal_error( + "DerivativeGroupQuadsKHR requires the following SPIR-V extension: " + "SPV_KHR_compute_shader_derivatives", + false); addRequirements(getSymbolicOperandRequirements(Category, i, ST, *this)); } @@ -2139,19 +2168,7 @@ void addInstrRequirements(const MachineInstr &MI, } break; case SPIRV::OpGroupNonUniformQuadAllKHR: - if (!ST.isAtLeastSPIRVVer(VersionTuple(1, 3))) - report_fatal_error("OpGroupNonUniformQuadAllKHR requires SPIR-V 1.3", - false); - if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_quad_control)) - report_fatal_error("OpGroupNonUniformQuadAllKHR instruction requires the " - "following SPIR-V extension: SPV_KHR_quad_control", - false); - if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence)) - report_fatal_error("SPV_KHR_quad_control requires the following SPIR-V " - "extension: SPV_KHR_maximal_reconvergence", - false); - Reqs.addExtension(SPIRV::Extension::SPV_KHR_quad_control); - Reqs.addExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence); + addQuadControlRequirements(Reqs, ST, "OpGroupNonUniformQuadAllKHR"); Reqs.addCapability(SPIRV::Capability::QuadControlKHR); break; case SPIRV::OpGroupNonUniformRotateKHR: diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 8792431da11510..8e65710703ee2f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -411,6 +411,7 @@ defm SPV_KHR_untyped_pointers : ExtensionOperand<140, [EnvOpenCL]>; defm SPV_EXT_long_vector : ExtensionOperand<141, [EnvOpenCL, EnvVulkan]>; defm SPV_KHR_relaxed_extended_instruction : ExtensionOperand<142, [EnvVulkan, EnvOpenCL]>; defm SPV_KHR_quad_control : ExtensionOperand<143, [EnvVulkan]>; +defm SPV_KHR_compute_shader_derivatives : ExtensionOperand<144, [EnvVulkan]>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -567,7 +568,11 @@ defm VulkanMemoryModelKHR : CapabilityOperand<5345, 0, 0, [], []>; defm VulkanMemoryModelDeviceScopeKHR : CapabilityOperand<5346, 0, 0, [], []>; defm ImageFootprintNV : CapabilityOperand<5282, 0, 0, [], []>; defm FragmentBarycentricKHR : CapabilityOperand<5284, 0, 0, [SPV_KHR_fragment_shader_barycentric], [Shader]>; -defm ComputeDerivativeGroupQuadsNV : CapabilityOperand<5288, 0, 0, [], []>; +defm ComputeDerivativeGroupQuadsKHR + : CapabilityOperand<5288, 0, 0, [SPV_KHR_compute_shader_derivatives], + [Shader]>; +def ComputeDerivativeGroupQuadsNV + : Capability<"ComputeDerivativeGroupQuadsNV", 5288>; defm DemoteToHelperInvocation : CapabilityOperand<5379, 0x10600, 0, [SPV_EXT_demote_to_helper_invocation], []>; defm ComputeDerivativeGroupLinearNV : CapabilityOperand<5350, 0, 0, [], []>; defm FragmentDensityEXT : CapabilityOperand<5291, 0, 0, [], [Shader]>; @@ -850,8 +855,12 @@ defm SignedZeroInfNanPreserve : ExecutionModeOperand<4461, [SignedZeroInfNanPres defm RoundingModeRTE : ExecutionModeOperand<4462, [RoundingModeRTE]>; defm RoundingModeRTZ : ExecutionModeOperand<4463, [RoundingModeRTZ]>; defm StencilRefReplacingEXT : ExecutionModeOperand<5027, [StencilExportEXT]>; +defm QuadDerivativesKHR : ExecutionModeOperand<5088, [QuadControlKHR]>; +defm RequireFullQuadsKHR : ExecutionModeOperand<5089, [QuadControlKHR]>; defm OutputLinesNV : ExecutionModeOperand<5269, [MeshShadingNV]>; -defm DerivativeGroupQuadsNV : ExecutionModeOperand<5289, [ComputeDerivativeGroupQuadsNV]>; +defm DerivativeGroupQuadsKHR + : ExecutionModeOperand<5289, [ComputeDerivativeGroupQuadsKHR]>; +def DerivativeGroupQuadsNV : ExecutionMode<"DerivativeGroupQuadsNV", 5289>; defm DerivativeGroupLinearNV : ExecutionModeOperand<5290, [ComputeDerivativeGroupLinearNV]>; defm OutputTrianglesNV : ExecutionModeOperand<5298, [MeshShadingNV]>; defm RoundingModeRTPINTEL : ExecutionModeOperand<5620, [RoundToInfinityINTEL]>; diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/derivative-group-quads.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/derivative-group-quads.ll new file mode 100644 index 00000000000000..824c47924090a7 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/derivative-group-quads.ll @@ -0,0 +1,30 @@ +; RUN: llc -O0 -verify-machineinstrs \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-compute \ +; RUN: --spirv-ext=+SPV_KHR_compute_shader_derivatives \ +; RUN: %s -o - | FileCheck %s +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-compute \ +; RUN: --spirv-ext=-SPV_KHR_compute_shader_derivatives \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-EXT +; RUN: %if spirv-tools %{ llc -O0 \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-compute \ +; RUN: --spirv-ext=+SPV_KHR_compute_shader_derivatives \ +; RUN: %s -o - -filetype=obj | spirv-val --target-env vulkan1.2 %} + +; NO-EXT: DerivativeGroupQuadsKHR requires the following SPIR-V extension: SPV_KHR_compute_shader_derivatives + +; CHECK-DAG: OpCapability Shader +; CHECK-DAG: OpCapability ComputeDerivativeGroupQuadsKHR +; CHECK: OpExtension "SPV_KHR_compute_shader_derivatives" +; CHECK-NOT: OpExtension +; CHECK: OpEntryPoint GLCompute %[[#MAIN:]] "main" +; CHECK: OpExecutionMode %[[#MAIN]] DerivativeGroupQuadsKHR +; CHECK: OpExecutionMode %[[#MAIN]] LocalSize 2 2 1 + +define void @main() #0 { + ret void +} + +attributes #0 = { "hlsl.numthreads"="2,2,1" "hlsl.shader"="compute" } + +!spirv.ExecutionMode = !{!0} +!0 = !{ptr @main, i32 5289} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/quad-all.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/quad-all.ll new file mode 100644 index 00000000000000..e62c3d2af07552 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_compute_shader_derivatives/quad-all.ll @@ -0,0 +1,44 @@ +; DEFINE: %{quad-exts} = +SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence +; DEFINE: %{deriv-ext} = +SPV_KHR_compute_shader_derivatives + +; RUN: llc -O0 -verify-machineinstrs \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-compute \ +; RUN: --spirv-ext=%{deriv-ext},%{quad-exts} \ +; RUN: %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-compute \ +; RUN: --spirv-ext=%{deriv-ext},%{quad-exts} \ +; RUN: %s -o - -filetype=obj | spirv-val --target-env vulkan1.2 %} + +; CHECK-DAG: OpCapability ComputeDerivativeGroupQuadsKHR +; CHECK-DAG: OpCapability QuadControlKHR +; CHECK-DAG: OpExtension "SPV_KHR_compute_shader_derivatives" +; CHECK-DAG: OpExtension "SPV_KHR_quad_control" +; CHECK-DAG: OpExtension "SPV_KHR_maximal_reconvergence" +; CHECK: OpEntryPoint GLCompute %[[#MAIN:]] "main" +; CHECK-DAG: OpExecutionMode %[[#MAIN]] DerivativeGroupQuadsKHR +; CHECK-DAG: OpExecutionMode %[[#MAIN]] LocalSize 2 2 1 +; CHECK-DAG: %[[#BOOL:]] = OpTypeBool +; CHECK-DAG: %[[#TRUE:]] = OpConstantTrue %[[#BOOL]] + +; CHECK: %[[#MAIN]] = OpFunction +; CHECK: %[[#ALL:]] = OpGroupNonUniformQuadAllKHR %[[#BOOL]] %[[#TRUE]] +; CHECK: %[[#VALUE:]] = OpSelect %{{[0-9]+}} %[[#ALL]] +; CHECK: OpStore %{{[0-9]+}} %[[#VALUE]] Volatile +define void @main() #0 { + %result = alloca i32 + %tok = call token @llvm.experimental.convergence.entry() + %all = call i1 @llvm.spv.quad.all(i1 true) [ "convergencectrl"(token %tok) ] + %value = zext i1 %all to i32 + store volatile i32 %value, ptr %result + ret void +} + +declare i1 @llvm.spv.quad.all(i1) convergent + +attributes #0 = { + convergent "hlsl.numthreads"="2,2,1" "hlsl.shader"="compute" +} + +!spirv.ExecutionMode = !{!0} +!0 = !{ptr @main, i32 5289} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-all-with-modes.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-all-with-modes.ll new file mode 100644 index 00000000000000..c12426daf3fe8b --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-all-with-modes.ll @@ -0,0 +1,37 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpCapability QuadControlKHR +; CHECK-DAG: OpExtension "SPV_KHR_quad_control" +; CHECK-DAG: OpExtension "SPV_KHR_maximal_reconvergence" +; CHECK: OpEntryPoint Fragment %[[#MAIN:]] "main" +; CHECK-DAG: OpExecutionMode %[[#MAIN]] QuadDerivativesKHR +; CHECK-DAG: OpExecutionMode %[[#MAIN]] RequireFullQuadsKHR +; CHECK-DAG: %[[#BOOL:]] = OpTypeBool +; CHECK-DAG: %[[#TRUE:]] = OpConstantTrue %[[#BOOL]] + +; CHECK: %[[#MAIN]] = OpFunction +; CHECK: %[[#ALL:]] = OpGroupNonUniformQuadAllKHR %[[#BOOL]] %[[#TRUE]] +; CHECK: %[[#VALUE:]] = OpSelect %{{[0-9]+}} %[[#ALL]] +; CHECK: OpStore %{{[0-9]+}} %[[#VALUE]] Volatile +define void @main() #0 { + %result = alloca i32 + %tok = call token @llvm.experimental.convergence.entry() + %all = call i1 @llvm.spv.quad.all(i1 true) [ "convergencectrl"(token %tok) ] + %value = zext i1 %all to i32 + store volatile i32 %value, ptr %result + ret void +} + +declare i1 @llvm.spv.quad.all(i1) convergent + +attributes #0 = { convergent "hlsl.shader"="pixel" } + +!spirv.ExecutionMode = !{!0, !1} +!0 = !{ptr @main, i32 5088} +!1 = !{ptr @main, i32 5089} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-derivatives.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-derivatives.ll new file mode 100644 index 00000000000000..1eeaeaadaeb486 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/quad-derivatives.ll @@ -0,0 +1,35 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - | FileCheck %s +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=-SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-EXT +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,-SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-RECONVERGENCE +; RUN: not llc -O0 -mtriple=spirv32v1.2-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=VERSION +; RUN: %if spirv-tools %{ llc -O0 \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - -filetype=obj | spirv-val %} + +; NO-EXT: QuadDerivativesKHR requires the following SPIR-V extension: SPV_KHR_quad_control +; NO-RECONVERGENCE: SPV_KHR_quad_control requires the following SPIR-V extension: SPV_KHR_maximal_reconvergence +; VERSION: QuadDerivativesKHR requires SPIR-V 1.3 + +; CHECK-DAG: OpCapability QuadControlKHR +; CHECK-DAG: OpExtension "SPV_KHR_quad_control" +; CHECK-DAG: OpExtension "SPV_KHR_maximal_reconvergence" +; CHECK: OpEntryPoint Fragment %[[#MAIN:]] "main" +; CHECK: OpExecutionMode %[[#MAIN]] QuadDerivativesKHR + +define void @main() #0 { + ret void +} + +attributes #0 = { "hlsl.shader"="pixel" } + +!spirv.ExecutionMode = !{!0} +!0 = !{ptr @main, i32 5088} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/require-full-quads.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/require-full-quads.ll new file mode 100644 index 00000000000000..b942c5d62015ed --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_quad_control/require-full-quads.ll @@ -0,0 +1,35 @@ +; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - | FileCheck %s +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=-SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-EXT +; RUN: not llc -O0 -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,-SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=NO-RECONVERGENCE +; RUN: not llc -O0 -mtriple=spirv32v1.2-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - 2>&1 | FileCheck %s --check-prefix=VERSION +; RUN: %if spirv-tools %{ llc -O0 \ +; RUN: -mtriple=spirv1.5-unknown-vulkan-pixel \ +; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ +; RUN: %s -o - -filetype=obj | spirv-val %} + +; NO-EXT: RequireFullQuadsKHR requires the following SPIR-V extension: SPV_KHR_quad_control +; NO-RECONVERGENCE: SPV_KHR_quad_control requires the following SPIR-V extension: SPV_KHR_maximal_reconvergence +; VERSION: RequireFullQuadsKHR requires SPIR-V 1.3 + +; CHECK-DAG: OpCapability QuadControlKHR +; CHECK-DAG: OpExtension "SPV_KHR_quad_control" +; CHECK-DAG: OpExtension "SPV_KHR_maximal_reconvergence" +; CHECK: OpEntryPoint Fragment %[[#MAIN:]] "main" +; CHECK: OpExecutionMode %[[#MAIN]] RequireFullQuadsKHR + +define void @main() #0 { + ret void +} + +attributes #0 = { "hlsl.shader"="pixel" } + +!spirv.ExecutionMode = !{!0} +!0 = !{ptr @main, i32 5089} diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll index 512f98e0940517..10e8faad8cb0f3 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/QuadAll.ll @@ -14,13 +14,14 @@ ; RUN: --spirv-ext=+SPV_KHR_quad_control,+SPV_KHR_maximal_reconvergence \ ; RUN: %s -o - -filetype=obj | spirv-val %} -; NO-EXT: OpGroupNonUniformQuadAllKHR instruction requires the following SPIR-V extension: SPV_KHR_quad_control +; NO-EXT: OpGroupNonUniformQuadAllKHR requires the following SPIR-V extension: SPV_KHR_quad_control ; NO-RECONVERGENCE: SPV_KHR_quad_control requires the following SPIR-V extension: SPV_KHR_maximal_reconvergence ; VERSION: OpGroupNonUniformQuadAllKHR requires SPIR-V 1.3 ; CHECK-DAG: OpCapability QuadControlKHR ; CHECK-DAG: OpExtension "SPV_KHR_quad_control" ; CHECK-DAG: OpExtension "SPV_KHR_maximal_reconvergence" +; CHECK-NOT: OpExecutionMode ; CHECK-DAG: %[[#BOOL:]] = OpTypeBool ; CHECK-LABEL: Begin function quad_all _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
