https://github.com/Icohedron created https://github.com/llvm/llvm-project/pull/131070
Fixes #112270 Completed ACs: - `-res-may-alias` clang-dxc command-line option added - Shader flag set appropriately: - CASE 1: command-line option -res-may-alias is NOT specified AND DXIL Version > 1.7 AND function uses UAVs - Add tests - A test (`res-may-not-alias-shadermodel6.8.ll`) for CASE 1 - A test (`res-may-not-alias-shadermodel6.7.ll`) for CASE 2 - A test (`res-may-alias.ll`) for the case where the command-line option `-res-may-alias` is specified ACs left to complete: - Shader flag set appropriately: - CASE 2: command-line option -res-may-alias is NOT specified AND DXIL Version <= 1.7 AND UAVs present globally - This Draft PR currently uses the now-removed `DXILResourceMD` analysis (#130323) to query for global UAVs - Need to create an alternative implementation for this case >From ad5fbee6d0d58df1884153bb70e59a1434953659 Mon Sep 17 00:00:00 2001 From: Icohedron <cheung.de...@gmail.com> Date: Thu, 13 Mar 2025 03:15:39 +0000 Subject: [PATCH] Initial ResMayNotAlias shader flag implementation --- clang/include/clang/Basic/CodeGenOptions.def | 3 ++ clang/include/clang/Driver/Options.td | 5 +++ clang/lib/CodeGen/CGHLSLRuntime.cpp | 3 ++ clang/lib/Driver/ToolChains/Clang.cpp | 1 + llvm/lib/Target/DirectX/DXILShaderFlags.cpp | 30 +++++++++++++--- llvm/lib/Target/DirectX/DXILShaderFlags.h | 9 +++-- .../DirectX/ShaderFlags/res-may-alias.ll | 34 +++++++++++++++++++ .../res-may-not-alias-shadermodel6.7.ll | 33 ++++++++++++++++++ .../res-may-not-alias-shadermodel6.8.ll | 33 ++++++++++++++++++ 9 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias.ll create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll create mode 100644 llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index a7f5f1abbb825..a436c0ec98d5b 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -476,6 +476,9 @@ CODEGENOPT(ImportCallOptimization, 1, 0) /// (BlocksRuntime) on Windows. CODEGENOPT(StaticClosure, 1, 0) +/// Assume that UAVs/SRVs may alias +CODEGENOPT(ResMayAlias, 1, 0) + /// FIXME: Make DebugOptions its own top-level .def file. #include "DebugOptions.def" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d0414aba35209..9d33994c777d1 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9044,6 +9044,11 @@ def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARA HelpText<"Override validator version for module. Format: <major.minor>;" "Default: DXIL.dll version or current internal version">, MarshallingInfoString<TargetOpts<"DxilValidatorVersion">, "\"1.8\"">; +def res_may_alias : Option<["/", "-"], "res-may-alias", KIND_FLAG>, + Group<dxc_Group>, Flags<[HelpHidden]>, + Visibility<[DXCOption, ClangOption, CC1Option]>, + HelpText<"Assume that UAVs/SRVs may alias">, + MarshallingInfoFlag<CodeGenOpts<"ResMayAlias">>; def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">, HelpText<"Set target profile">, Values<"ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7," diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index dc34653e8f497..b6c2cb0bfefc0 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -252,10 +252,13 @@ void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType, void CGHLSLRuntime::finishCodeGen() { auto &TargetOpts = CGM.getTarget().getTargetOpts(); + auto &CodeGenOpts = CGM.getCodeGenOpts(); llvm::Module &M = CGM.getModule(); Triple T(M.getTargetTriple()); if (T.getArch() == Triple::ArchType::dxil) addDxilValVersion(TargetOpts.DxilValidatorVersion, M); + if (CodeGenOpts.ResMayAlias) + M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1); generateGlobalCtorDtorCalls(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4ebbd241d2f0b..f066e333c6e74 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3960,6 +3960,7 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs, static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs, types::ID InputType) { const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version, + options::OPT_res_may_alias, options::OPT_D, options::OPT_I, options::OPT_O, diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp index 31fbd66dfaa2d..e05ab0cee1102 100644 --- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "DXILShaderFlags.h" +#include "DXILResourceAnalysis.h" #include "DirectX.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/SmallVector.h" @@ -74,6 +75,7 @@ static bool checkWaveOps(Intrinsic::ID IID) { /// \param I Instruction to check. void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF, const Instruction &I, + const ModuleMetadataInfo &MMDI, DXILResourceTypeMap &DRTM) { if (!CSF.Doubles) CSF.Doubles = I.getType()->isDoubleTy(); @@ -117,6 +119,11 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF, default: break; case Intrinsic::dx_resource_handlefrombinding: + if (!ResMayAlias && !CSF.ResMayNotAlias && + MMDI.DXILVersion > VersionTuple(1, 7) && + DRTM[cast<TargetExtType>(II->getType())].isUAV()) { + CSF.ResMayNotAlias = true; + } switch (DRTM[cast<TargetExtType>(II->getType())].getResourceKind()) { case dxil::ResourceKind::StructuredBuffer: case dxil::ResourceKind::RawBuffer: @@ -151,7 +158,14 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF, /// Construct ModuleShaderFlags for module Module M void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM, - const ModuleMetadataInfo &MMDI) { + const ModuleMetadataInfo &MMDI, + const dxil::Resources &MDR) { + + if (mdconst::extract_or_null<ConstantInt>( + M.getModuleFlag("dx.resmayalias"))) { + ResMayAlias = true; + } + CallGraph CG(M); // Compute Shader Flags Mask for all functions using post-order visit of SCC @@ -176,10 +190,15 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM, continue; } + if (!ResMayAlias && !SCCSF.ResMayNotAlias && + MMDI.DXILVersion <= VersionTuple(1, 7)) { + SCCSF.ResMayNotAlias = MDR.hasUAVs(); + } + ComputedShaderFlags CSF; for (const auto &BB : *F) for (const auto &I : BB) - updateFunctionFlags(CSF, I, DRTM); + updateFunctionFlags(CSF, I, MMDI, DRTM); // Update combined shader flags mask for all functions in this SCC SCCSF.merge(CSF); @@ -250,9 +269,10 @@ ModuleShaderFlags ShaderFlagsAnalysis::run(Module &M, ModuleAnalysisManager &AM) { DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M); const ModuleMetadataInfo MMDI = AM.getResult<DXILMetadataAnalysis>(M); + const dxil::Resources &MDR = AM.getResult<DXILResourceMDAnalysis>(M); ModuleShaderFlags MSFI; - MSFI.initialize(M, DRTM, MMDI); + MSFI.initialize(M, DRTM, MMDI, MDR); return MSFI; } @@ -284,14 +304,16 @@ bool ShaderFlagsAnalysisWrapper::runOnModule(Module &M) { getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap(); const ModuleMetadataInfo MMDI = getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata(); + dxil::Resources &MDR = getAnalysis<DXILResourceMDWrapper>().getDXILResource(); - MSFI.initialize(M, DRTM, MMDI); + MSFI.initialize(M, DRTM, MMDI, MDR); return false; } void ShaderFlagsAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequiredTransitive<DXILResourceTypeWrapperPass>(); + AU.addRequired<DXILResourceMDWrapper>(); AU.addRequired<DXILMetadataAnalysisWrapperPass>(); } diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h index abf7cc86259ed..7b395b729e412 100644 --- a/llvm/lib/Target/DirectX/DXILShaderFlags.h +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.h @@ -14,6 +14,7 @@ #ifndef LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H #define LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H +#include "DXILResource.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/IR/Function.h" #include "llvm/IR/PassManager.h" @@ -85,7 +86,7 @@ struct ComputedShaderFlags { struct ModuleShaderFlags { void initialize(Module &, DXILResourceTypeMap &DRTM, - const ModuleMetadataInfo &MMDI); + const ModuleMetadataInfo &MMDI, const dxil::Resources &MDR); const ComputedShaderFlags &getFunctionFlags(const Function *) const; const ComputedShaderFlags &getCombinedFlags() const { return CombinedSFMask; } @@ -97,7 +98,11 @@ struct ModuleShaderFlags { /// Combined Shader Flag Mask of all functions of the module ComputedShaderFlags CombinedSFMask{}; void updateFunctionFlags(ComputedShaderFlags &, const Instruction &, - DXILResourceTypeMap &); + const ModuleMetadataInfo &MMDI, + DXILResourceTypeMap &DRTM); + + // Set to indicate if the -res-may-alias flag was passed to clang-dxc + bool ResMayAlias = false; }; class ShaderFlagsAnalysis : public AnalysisInfoMixin<ShaderFlagsAnalysis> { diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias.ll new file mode 100644 index 0000000000000..e5bdbc7012b55 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-alias.ll @@ -0,0 +1,34 @@ +; TODO: Figure out an appropriate RUN command for this test. Normally, -res-may-alias is only applicable to clang-dxc +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.8-library" + +; CHECK: Combined Shader Flags for Module +; CHECK-NEXT: Shader Flags Value: 0x00000010 + +; CHECK: Note: extra DXIL module flags: +; CHECK: Raw and Structured buffers +; CHECK-NOT: Any UAV may not alias any other UAV +; + +; CHECK: Function loadUAV : 0x00000000 +define float @loadUAV() #0 { + %res = call target("dx.TypedBuffer", float, 1, 0, 0) + @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false) + %load = call {float, i1} @llvm.dx.resource.load.typedbuffer( + target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0) + %val = extractvalue {float, i1} %load, 0 + ret float %val +} + +; CHECK: Function loadSRV : 0x00000010 +define float @loadSRV() #0 { + %res = tail call target("dx.RawBuffer", float, 0, 0) + @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false) + %load = call {float, i1} @llvm.dx.resource.load.rawbuffer( + target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0) + %val = extractvalue { float, i1 } %load, 0 + ret float %val +} + +attributes #0 = { convergent norecurse nounwind "hlsl.export"} diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll new file mode 100644 index 0000000000000..3aed93e593e3b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.7.ll @@ -0,0 +1,33 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.7-library" + +; CHECK: Combined Shader Flags for Module +; CHECK-NEXT: Shader Flags Value: 0x200000010 + +; CHECK: Note: extra DXIL module flags: +; CHECK: Raw and Structured buffers +; CHECK: Any UAV may not alias any other UAV +; + +; CHECK: Function loadUAV : 0x00000000 +define float @loadUAV() #0 { + %res = call target("dx.TypedBuffer", float, 1, 0, 0) + @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false) + %load = call {float, i1} @llvm.dx.resource.load.typedbuffer( + target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0) + %val = extractvalue {float, i1} %load, 0 + ret float %val +} + +; CHECK: Function loadSRV : 0x00000010 +define float @loadSRV() #0 { + %res = tail call target("dx.RawBuffer", float, 0, 0) + @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false) + %load = call {float, i1} @llvm.dx.resource.load.rawbuffer( + target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0) + %val = extractvalue { float, i1 } %load, 0 + ret float %val +} + +attributes #0 = { convergent norecurse nounwind "hlsl.export"} diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll new file mode 100644 index 0000000000000..fb5e234f0bd93 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/res-may-not-alias-shadermodel6.8.ll @@ -0,0 +1,33 @@ +; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.8-library" + +; CHECK: Combined Shader Flags for Module +; CHECK-NEXT: Shader Flags Value: 0x200000010 + +; CHECK: Note: extra DXIL module flags: +; CHECK: Raw and Structured buffers +; CHECK: Any UAV may not alias any other UAV +; + +; CHECK: Function loadUAV : 0x20000000 +define float @loadUAV() #0 { + %res = call target("dx.TypedBuffer", float, 1, 0, 0) + @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false) + %load = call {float, i1} @llvm.dx.resource.load.typedbuffer( + target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0) + %val = extractvalue {float, i1} %load, 0 + ret float %val +} + +; CHECK: Function loadSRV : 0x00000010 +define float @loadSRV() #0 { + %res = tail call target("dx.RawBuffer", float, 0, 0) + @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false) + %load = call {float, i1} @llvm.dx.resource.load.rawbuffer( + target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0) + %val = extractvalue { float, i1 } %load, 0 + ret float %val +} + +attributes #0 = { convergent norecurse nounwind "hlsl.export"} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits