Skip to content

[DirectX] Set Shader Flag DisableOptimizations. #123136

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

Conversation

bharadwajy
Copy link
Contributor

Disabling optimizations using the option -Od to clang-dxc results in generation of named metadata "dx.disable_optimizations" - as tested here.

  • Following changes facilitate setting of Shader Flag DisableOptimizations.

    • Detect metadata "dx.disable_optimizations" as part of Metadata Analysis pass and set a new bool field
      ModuleMetadatainfo::DisableOptimization accordingly.
    • Add DXILMetadataAnalysis as required pass for the pass DXILShaderFlags that sets shader flags mask.
    • Set shader flag DisableOptimizations based on the value of ModuleMetadatainfo::DisableOptimizations.
  • Added test to verify setting of shader flag DisableOptimizations.

  • Updated llc-pipeline.ll to reflect changes in output resulting from addition of Metadata Analysis pass as required by DXILShaderFlags pass.

NOTE: An alternative implementation that

  1. does not detect presence of metadata "dx.disable_optimizations" in Metadata Analysis pass and thus does not add the pass as a pre-requisite pass for DXILShaderFlags but
  2. detects presence of metadata "dx.disable_optimizations" directly in DXILShaderFlags pass

has been considered. However, Metadata Analysis pass seemed appropriate for detection of metadata relevant to setting the shader flag DisableOptimizations. Hence this PR.

Closes #112263

@llvmbot llvmbot added backend:DirectX llvm:analysis Includes value tracking, cost tables and constant folding labels Jan 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 15, 2025

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-backend-directx

Author: S. Bharadwaj Yadavalli (bharadwajy)

Changes

Disabling optimizations using the option -Od to clang-dxc results in generation of named metadata "dx.disable_optimizations" - as tested here.

  • Following changes facilitate setting of Shader Flag DisableOptimizations.

    • Detect metadata "dx.disable_optimizations" as part of Metadata Analysis pass and set a new bool field
      ModuleMetadatainfo::DisableOptimization accordingly.
    • Add DXILMetadataAnalysis as required pass for the pass DXILShaderFlags that sets shader flags mask.
    • Set shader flag DisableOptimizations based on the value of ModuleMetadatainfo::DisableOptimizations.
  • Added test to verify setting of shader flag DisableOptimizations.

  • Updated llc-pipeline.ll to reflect changes in output resulting from addition of Metadata Analysis pass as required by DXILShaderFlags pass.

NOTE: An alternative implementation that

  1. does not detect presence of metadata "dx.disable_optimizations" in Metadata Analysis pass and thus does not add the pass as a pre-requisite pass for DXILShaderFlags but
  2. detects presence of metadata "dx.disable_optimizations" directly in DXILShaderFlags pass

has been considered. However, Metadata Analysis pass seemed appropriate for detection of metadata relevant to setting the shader flag DisableOptimizations. Hence this PR.

Closes #112263


Full diff: https://github.com/llvm/llvm-project/pull/123136.diff

6 Files Affected:

  • (modified) llvm/include/llvm/Analysis/DXILMetadataAnalysis.h (+1)
  • (modified) llvm/lib/Analysis/DXILMetadataAnalysis.cpp (+16)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+12-3)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.h (+3-1)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt.ll (+25)
  • (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+1-1)
diff --git a/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h b/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
index cb535ac14f1c61..93a926c8991a8c 100644
--- a/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
+++ b/llvm/include/llvm/Analysis/DXILMetadataAnalysis.h
@@ -37,6 +37,7 @@ struct ModuleMetadataInfo {
   Triple::EnvironmentType ShaderProfile{Triple::UnknownEnvironment};
   VersionTuple ValidatorVersion{};
   SmallVector<EntryProperties> EntryPropertyVec{};
+  bool DisableOptimizations{false};
   void print(raw_ostream &OS) const;
 };
 
diff --git a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
index a7f666a3f8b48f..426559c64f8762 100644
--- a/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
+++ b/llvm/lib/Analysis/DXILMetadataAnalysis.cpp
@@ -68,6 +68,22 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
     }
     MMDAI.EntryPropertyVec.push_back(EFP);
   }
+
+  // Set shader flags based on Module properties
+  SmallVector<llvm::Module::ModuleFlagEntry> FlagEntries;
+  M.getModuleFlagsMetadata(FlagEntries);
+  for (const auto &Flag : FlagEntries) {
+    if (Flag.Behavior != Module::ModFlagBehavior::Override)
+      continue;
+    if (Flag.Key->getString().compare("dx.disable_optimizations") == 0) {
+      const auto *V = mdconst::extract<llvm::ConstantInt>(Flag.Val);
+      if (V->isOne()) {
+        MMDAI.DisableOptimizations = true;
+        break;
+      }
+    }
+  }
+
   return MMDAI;
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index b1ff975d4dae96..3684411c63bc56 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -85,7 +85,8 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
 }
 
 /// Construct ModuleShaderFlags for module Module M
-void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM) {
+void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
+                                   const ModuleMetadataInfo &MMDI) {
   CallGraph CG(M);
 
   // Compute Shader Flags Mask for all functions using post-order visit of SCC
@@ -131,6 +132,9 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM) {
       // Merge SCCSF with that of F
       FunctionFlags[F].merge(SCCSF);
   }
+
+  // Set shader flags based on Module properties based on module metadata
+  CombinedSFMask.DisableOptimizations = MMDI.DisableOptimizations;
 }
 
 void ComputedShaderFlags::print(raw_ostream &OS) const {
@@ -169,9 +173,10 @@ AnalysisKey ShaderFlagsAnalysis::Key;
 ModuleShaderFlags ShaderFlagsAnalysis::run(Module &M,
                                            ModuleAnalysisManager &AM) {
   DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);
+  const ModuleMetadataInfo MMDI = AM.getResult<DXILMetadataAnalysis>(M);
 
   ModuleShaderFlags MSFI;
-  MSFI.initialize(M, DRTM);
+  MSFI.initialize(M, DRTM, MMDI);
 
   return MSFI;
 }
@@ -201,14 +206,17 @@ PreservedAnalyses ShaderFlagsAnalysisPrinter::run(Module &M,
 bool ShaderFlagsAnalysisWrapper::runOnModule(Module &M) {
   DXILResourceTypeMap &DRTM =
       getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
+  const ModuleMetadataInfo MMDI =
+      getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
 
-  MSFI.initialize(M, DRTM);
+  MSFI.initialize(M, DRTM, MMDI);
   return false;
 }
 
 void ShaderFlagsAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
   AU.addRequiredTransitive<DXILResourceTypeWrapperPass>();
+  AU.addRequired<DXILMetadataAnalysisWrapperPass>();
 }
 
 char ShaderFlagsAnalysisWrapper::ID = 0;
@@ -216,5 +224,6 @@ char ShaderFlagsAnalysisWrapper::ID = 0;
 INITIALIZE_PASS_BEGIN(ShaderFlagsAnalysisWrapper, "dx-shader-flag-analysis",
                       "DXIL Shader Flag Analysis", true, true)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
 INITIALIZE_PASS_END(ShaderFlagsAnalysisWrapper, "dx-shader-flag-analysis",
                     "DXIL Shader Flag Analysis", true, true)
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h
index e6c6d56402c1a7..abf7cc86259ed8 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 "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Pass.h"
@@ -83,7 +84,8 @@ struct ComputedShaderFlags {
 };
 
 struct ModuleShaderFlags {
-  void initialize(Module &, DXILResourceTypeMap &DRTM);
+  void initialize(Module &, DXILResourceTypeMap &DRTM,
+                  const ModuleMetadataInfo &MMDI);
   const ComputedShaderFlags &getFunctionFlags(const Function *) const;
   const ComputedShaderFlags &getCombinedFlags() const { return CombinedSFMask; }
 
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt.ll
new file mode 100644
index 00000000000000..ee42b5b758ca0c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt.ll
@@ -0,0 +1,25 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+target triple = "dxilv1.6-unknown-shadermodel6.6-library"
+
+; CHECK: ; Combined Shader Flags for Module
+; CHECK-NEXT: ; Shader Flags Value: 0x00000001
+
+; CHECK: ; Note: extra DXIL module flags:
+; CHECK-NEXT: ;       D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION
+
+; CHECK: ; Shader Flags for Module Functions
+
+target triple = "dxilv1.6-unknown-shadermodel6.6-library"
+
+; CHECK: ; Function main : 0x00000000
+define void @main() {
+entry:
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 4, !"dx.disable_optimizations", i32 1}
+
+
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index b0715572494146..03b2150bbc1dc3 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -23,8 +23,8 @@
 ; CHECK-NEXT:     Scalarize vector operations
 ; CHECK-NEXT:   DXIL Resource Binding Analysis
 ; CHECK-NEXT:   DXIL resource Information
-; CHECK-NEXT:   DXIL Shader Flag Analysis
 ; CHECK-NEXT:   DXIL Module Metadata analysis
+; CHECK-NEXT:   DXIL Shader Flag Analysis
 ; CHECK-NEXT:   DXIL Translate Metadata
 ; CHECK-NEXT:   DXIL Op Lowering
 ; CHECK-NEXT:   DXIL Prepare Module

@bogner
Copy link
Contributor

bogner commented Jan 24, 2025

Is the dx.disable_optimizations metadata documented somewhere? This all looks like it will work, but I don't really understand why we have a custom metadata node coming from the frontend here rather than just looking at llvm::Attribute::OptimizeNone on the entry function or something like that.

@bharadwajy
Copy link
Contributor Author

bharadwajy commented Jan 24, 2025

Is the dx.disable_optimizations metadata documented somewhere? This all looks like it will work, but I don't really understand why we have a custom metadata node coming from the frontend here rather than just looking at llvm::Attribute::OptimizeNone on the entry function or something like that.

I am not aware of module-level metadata dx.disable_optimizations being documented anywhere nor of other module-level metadata presently in use - such as dx.valver, dx.shaderModel. Created an issue to add documentation.

Currently, presence of command-line option -Od is denoted by adding a module metadata dx.disable_optimizations. I do not know of the context of the design choice, but it seems to be a reasonable choice to capture the module-wide property of optimizations being disabled. Relying on an attribute of a specific function(s) (such as entry) appears to involve additional bookkeeping or traversals and an awkward way to denote a module-wide property.

@bogner
Copy link
Contributor

bogner commented Jan 27, 2025

I am not aware of module-level metadata dx.disable_optimizations being documented anywhere nor of other module-level metadata presently in use - such as dx.valver, dx.shaderModel. Created an issue to add documentation.

Currently, presence of command-line option -Od is denoted by adding a module metadata dx.disable_optimizations. I do not know of the context of the design choice, but it seems to be a reasonable choice to capture the module-wide property of optimizations being disabled. Relying on an attribute of a specific function(s) (such as entry) appears to involve additional bookkeeping or traversals and an awkward way to denote a module-wide property.

There's a very big difference between dx.disable_optimizations and metadata like dx.valver and dx.shaderModel - the latter are part of DXIL and we're required to generate them to match dxc/fxc output. dx.disable_optimizations is unique to the upstream llvm implementation (it was added in f712c01 without any specific mention of why it was needed). My concern here is mostly that the dx.disable_optimizations metadata is redundant with information that's already available in more standard ways and the story around keeping it consistent within the module isn't clear. It also isn't clear to me how this will interact with linking - what if part of the module is built with optimizations disabled and part with them enabled? Reconciling global metadata in this case sounds like a nightmare, whereas the optnone attribute that is already present on functions will already do the right thing.

Disabling optimizations using the option -Od to clang-dxc
results in generation of named metadata "dx.disable_optimizations".

- Detect metadata "dx.disable_optimizations" as part of Metadata
  Analysis pass and set a new bool field
  ModuleMetadatainfo::DisableOptimization accordingly.
- Add DXILMetadataAnalysis as required pass for the pass ShaderFlags
  that sets shader flags mask.
- Set shader flag DisableOptimization based on the value of
  ModuleMetadatainfo::DisableOptimization.

Updated llc-pipeline.ll to reflect changes in output resulting
from addition of Metadata Analysis pass as required by ShaderFlags pass.
from module after its presence has been noted in
ModuleMetadata Analysis pass. This ensures that this
metadata that is not part of DXIL specification
is not emitted in the final output.

Update disable-opt.ll to verify dx.disable_optimizations
metadata is deleted.
@bharadwajy bharadwajy force-pushed the shader-flags/disable-opt-flag-with-md-analysis branch from 1dbf4f7 to ca014db Compare January 30, 2025 15:07
@bharadwajy
Copy link
Contributor Author

Since optnone function atribute is not set when -O0 (or -Od) is specified, my experiements to set them appear to reveal that such a change interferes adversely with the exisiting DXIL linkage assumptions / rules. To prevent "non-standard" DXIL metadata (i.e., that not specified in DXIL Spec) from being generated in the final DXIL output, I pushed changes to delete the metadata once its intent is captured in Metadata analysis pass. Following the discussion offline, @bogner, please see if this would address the concerns raised. Thanks!

@bharadwajy
Copy link
Contributor Author

bharadwajy commented Jan 30, 2025

[...] It also isn't clear to me how this will interact with linking - what if part of the module is built with optimizations disabled and part with them enabled? Reconciling global metadata in this case sounds like a nightmare, whereas the optnone attribute that is already present on functions will already do the right thing.

With the changes that delete the metadata dx.disable_optimizations, the only thing a DXIL linker would rely on to know if optimizations were disabled during compilation of modules being linked is the documented (and generated) shader flag DisableOptimizations. I believe DXC linking rules have a (some?) solution for this or we may have to revisit them for the ongoing clang support for HLSL, irrespective of the mechanism to set the shader flag DisableOptimizations.

Copy link
Member

@hekota hekota left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, though I also find it strange that there is no module-level flag in Clang which signifies that optimizations are disabled and that we have to rely on dx.disable_optimizations.

// emitted in the final DXIL output, now that its intent is captured in MMDAI,
// if present.

if (NewFlagEntries.size() != FlagEntries.size()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do this here? We have code in DXILPrepare that cleans the module flags.

@bogner, I think the reason the dx.disable_optimizations named metadata wasn't causing issues is because DXIL doesn't use custom module flags at all, so in DXILPrepare we just strip out any non-standard LLVM 3.7 module flags, which will clean this up.

Copy link
Contributor Author

@bharadwajy bharadwajy Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do this here? We have code in DXILPrepare that cleans the module flags.

@bogner, I think the reason the dx.disable_optimizations named metadata wasn't causing issues is because DXIL doesn't use custom module flags at all, so in DXILPrepare we just strip out any non-standard LLVM 3.7 module flags, which will clean this up.

@llvm-beanz I proposed a PR to decorate shader entry functions with the attribute optnone as an alternative to using dx.disable_optimizations named metadata - per feedback above.

The idea is to eliminate creation of dx.disable_optimizations metadata and key off the optnone attribute on shader entry functions to set the shader flag DisableOptimizations as implemented here with an expectation of converting it to a follow-on PR to #125937.

I'd appreciate feedback on #125937 in this context as well as the preferred choice compared to this PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it now needs an update to adjust to #125937 landing.

@bogner
Copy link
Contributor

bogner commented Feb 13, 2025

This is superceded by #126813, right? Please close this if it's no longer relevant.

@bharadwajy
Copy link
Contributor Author

Closing. Superceded by #126813.

@bharadwajy bharadwajy closed this Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:DirectX llvm:analysis Includes value tracking, cost tables and constant folding
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[DirectX] Shader Flags Analysis for DisableOptimizations
5 participants