Skip to content

[DirectX] Set Shader Flag DisableOptimizations #126813

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

Merged
merged 2 commits into from
Feb 12, 2025

Conversation

bharadwajy
Copy link
Contributor

  • Set the shader flag DisableOptimizations based on optnone attribute of shader entry functions.

  • Add DXIL Metadata Analysis pass as pre-requisite for Shader Flags pass to obtain entry function information collected therein.

  • Named module metadata dx.disable_optimizations is intended to indicate disabling optimizations (-O0) via commandline flag. However, its intent is fulfilled via an optnone attribute of shader entry functions via a recent change - b92bab3 - and thus not needed. Delete generation of named metadata and corresponding test file disable_opt.ll.

  • Add tests to verify correctness of setting shader flag.

Closes #112263

Set the shader flag DisableOptimizations based on the optnone
attribute of shader entry functions.

Add DXIL Metadata Analysis pass as pre-requisite for
Shader Flags pass to obtain entry function information
collected therein.

Delete generation of named metadata dx.disable_optimization
that it is intended to indicate commandline flag specifying
disable opt. However, its intent is fulfilled using optnone
attribute of shader entry functions and not needed.
Delete corresponding test file disable_opt.ll

Named module metadata `dx.disable_optimizations` is intended
to indicate disabling optimizations (`-O0`) via commandline
flag. However, its intent is fulfilled via an `optnone` attribute
of shader entry functions via a recent change and thus not
needed. Delete generation of named metadata and corresponding
test file `disable_opt.ll`.

Add tests to verify correctness of setting shader flag.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. backend:DirectX HLSL HLSL Language Support labels Feb 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-directx

Author: S. Bharadwaj Yadavalli (bharadwajy)

Changes
  • Set the shader flag DisableOptimizations based on optnone attribute of shader entry functions.

  • Add DXIL Metadata Analysis pass as pre-requisite for Shader Flags pass to obtain entry function information collected therein.

  • Named module metadata dx.disable_optimizations is intended to indicate disabling optimizations (-O0) via commandline flag. However, its intent is fulfilled via an optnone attribute of shader entry functions via a recent change - b92bab3 - and thus not needed. Delete generation of named metadata and corresponding test file disable_opt.ll.

  • Add tests to verify correctness of setting shader flag.

Closes #112263


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

8 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (-6)
  • (removed) clang/test/CodeGenHLSL/disable_opt.hlsl (-12)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+25-3)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.h (+3-1)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll (+43)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll (+53)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll (+30)
  • (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+1-1)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 6cccd353cff96..03ddc87d8d3df 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -54,10 +54,6 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
   auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
   DXILValMD->addOperand(Val);
 }
-void addDisableOptimizations(llvm::Module &M) {
-  StringRef Key = "dx.disable_optimizations";
-  M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1);
-}
 // cbuffer will be translated into global variable in special address space.
 // If translate into C,
 // cbuffer A {
@@ -171,8 +167,6 @@ void CGHLSLRuntime::finishCodeGen() {
     addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
 
   generateGlobalCtorDtorCalls();
-  if (CGM.getCodeGenOpts().OptimizationLevel == 0)
-    addDisableOptimizations(M);
 
   const DataLayout &DL = M.getDataLayout();
 
diff --git a/clang/test/CodeGenHLSL/disable_opt.hlsl b/clang/test/CodeGenHLSL/disable_opt.hlsl
deleted file mode 100644
index bfffe76cfa9de..0000000000000
--- a/clang/test/CodeGenHLSL/disable_opt.hlsl
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O0 -emit-llvm -xhlsl -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O3 -emit-llvm -xhlsl -o - %s | FileCheck %s --check-prefix=OPT
-
-// CHECK:!"dx.disable_optimizations", i32 1}
-
-// OPT-NOT:"dx.disable_optimizations"
-
-float bar(float a, float b);
-
-float foo(float a, float b) {
-  return bar(a, b);
-}
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 6a15bac153d85..bb502d8f189f6 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -17,6 +17,8 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/DXILResource.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -96,7 +98,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
@@ -142,6 +145,20 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM) {
       // Merge SCCSF with that of F
       FunctionFlags[F].merge(SCCSF);
   }
+
+  // Set DisableOptimizations flag based on the presence of OptimizeNone
+  // attribute of entry functions.
+  if (MMDI.EntryPropertyVec.size() > 0) {
+    CombinedSFMask.DisableOptimizations =
+        MMDI.EntryPropertyVec[0].Entry->hasFnAttribute(
+            llvm::Attribute::OptimizeNone);
+    // Ensure all entry functions have the same optimization attribute
+    for (auto EF : MMDI.EntryPropertyVec)
+      if (CombinedSFMask.DisableOptimizations !=
+          EF.Entry->hasFnAttribute(llvm::Attribute::OptimizeNone))
+        EF.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
+            *(EF.Entry), "Inconsistent optnone attribute "));
+  }
 }
 
 void ComputedShaderFlags::print(raw_ostream &OS) const {
@@ -180,9 +197,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;
 }
@@ -212,14 +230,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;
@@ -227,5 +248,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 e6c6d56402c1a..abf7cc86259ed 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-cs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll
new file mode 100644
index 0000000000000..4c5c77fabbb9d
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll
@@ -0,0 +1,43 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+
+; 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
+; CHECK: ; Function main : 0x00000000
+; The test source in this file generated from the following command:
+; clang -cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -O0 -o - <<EOF
+; [numthreads(1,1,1)]
+; [shader("compute")]
+; void main() {}
+; EOF
+
+; ModuleID = '-'
+source_filename = "-"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.0-pc-shadermodel6.0-compute"
+
+; Function Attrs: convergent noinline norecurse optnone
+define void @main() #0 {
+entry:
+  ret void
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z3foov() #1 {
+entry:
+  ret i32 0
+}
+
+attributes #0 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { alwaysinline convergent mustprogress norecurse nounwind "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll
new file mode 100644
index 0000000000000..5ad11a2f07881
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll
@@ -0,0 +1,53 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+
+; 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
+; CHECK: ; Function main : 0x00000000
+; The test source in this file generated from the following command:
+; clang -cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -O0 -o - <<EOF
+
+; [numthreads(1,1,1)]
+; [shader("compute")]
+; void main() {}
+
+; int foo() {return 0;}
+; EOF
+
+; ModuleID = '-'
+source_filename = "-"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
+define internal void @_Z4mainv() #0 {
+entry:
+  ret void
+}
+
+; Function Attrs: convergent noinline norecurse optnone
+define void @main() #1 {
+entry:
+  call void @_Z4mainv()
+  ret void
+}
+
+; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
+define noundef i32 @_Z3foov() #0 {
+entry:
+  ret i32 0
+}
+
+attributes #0 = { convergent mustprogress noinline norecurse nounwind optnone "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll
new file mode 100644
index 0000000000000..74d5fd093ded6
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll
@@ -0,0 +1,30 @@
+; RUN: not opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+; All entry functions of a library shader need to either have optnone
+; or not have the attribute
+; CHECK: error:
+; CHECK-SAME: in function entry_two
+; CHECK-SAME:  Inconsistent optnone attribute
+; Function Attrs: convergent noinline norecurse optnone
+define void @entry_one() #0 {
+entry:
+  ret void
+}
+
+; Function Attrs: convergent noinline norecurse
+define void @entry_two() #1 {
+entry:
+  ret void
+}
+
+attributes #0 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { convergent noinline norecurse "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0, !1}
+!dx.valver = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
+!2 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index b071557249414..03b2150bbc1dc 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

@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

@llvm/pr-subscribers-hlsl

Author: S. Bharadwaj Yadavalli (bharadwajy)

Changes
  • Set the shader flag DisableOptimizations based on optnone attribute of shader entry functions.

  • Add DXIL Metadata Analysis pass as pre-requisite for Shader Flags pass to obtain entry function information collected therein.

  • Named module metadata dx.disable_optimizations is intended to indicate disabling optimizations (-O0) via commandline flag. However, its intent is fulfilled via an optnone attribute of shader entry functions via a recent change - b92bab3 - and thus not needed. Delete generation of named metadata and corresponding test file disable_opt.ll.

  • Add tests to verify correctness of setting shader flag.

Closes #112263


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

8 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (-6)
  • (removed) clang/test/CodeGenHLSL/disable_opt.hlsl (-12)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.cpp (+25-3)
  • (modified) llvm/lib/Target/DirectX/DXILShaderFlags.h (+3-1)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll (+43)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll (+53)
  • (added) llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll (+30)
  • (modified) llvm/test/CodeGen/DirectX/llc-pipeline.ll (+1-1)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 6cccd353cff96..03ddc87d8d3df 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -54,10 +54,6 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
   auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
   DXILValMD->addOperand(Val);
 }
-void addDisableOptimizations(llvm::Module &M) {
-  StringRef Key = "dx.disable_optimizations";
-  M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1);
-}
 // cbuffer will be translated into global variable in special address space.
 // If translate into C,
 // cbuffer A {
@@ -171,8 +167,6 @@ void CGHLSLRuntime::finishCodeGen() {
     addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
 
   generateGlobalCtorDtorCalls();
-  if (CGM.getCodeGenOpts().OptimizationLevel == 0)
-    addDisableOptimizations(M);
 
   const DataLayout &DL = M.getDataLayout();
 
diff --git a/clang/test/CodeGenHLSL/disable_opt.hlsl b/clang/test/CodeGenHLSL/disable_opt.hlsl
deleted file mode 100644
index bfffe76cfa9de..0000000000000
--- a/clang/test/CodeGenHLSL/disable_opt.hlsl
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O0 -emit-llvm -xhlsl -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O3 -emit-llvm -xhlsl -o - %s | FileCheck %s --check-prefix=OPT
-
-// CHECK:!"dx.disable_optimizations", i32 1}
-
-// OPT-NOT:"dx.disable_optimizations"
-
-float bar(float a, float b);
-
-float foo(float a, float b) {
-  return bar(a, b);
-}
diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
index 6a15bac153d85..bb502d8f189f6 100644
--- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
+++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp
@@ -17,6 +17,8 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/DXILResource.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -96,7 +98,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
@@ -142,6 +145,20 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM) {
       // Merge SCCSF with that of F
       FunctionFlags[F].merge(SCCSF);
   }
+
+  // Set DisableOptimizations flag based on the presence of OptimizeNone
+  // attribute of entry functions.
+  if (MMDI.EntryPropertyVec.size() > 0) {
+    CombinedSFMask.DisableOptimizations =
+        MMDI.EntryPropertyVec[0].Entry->hasFnAttribute(
+            llvm::Attribute::OptimizeNone);
+    // Ensure all entry functions have the same optimization attribute
+    for (auto EF : MMDI.EntryPropertyVec)
+      if (CombinedSFMask.DisableOptimizations !=
+          EF.Entry->hasFnAttribute(llvm::Attribute::OptimizeNone))
+        EF.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
+            *(EF.Entry), "Inconsistent optnone attribute "));
+  }
 }
 
 void ComputedShaderFlags::print(raw_ostream &OS) const {
@@ -180,9 +197,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;
 }
@@ -212,14 +230,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;
@@ -227,5 +248,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 e6c6d56402c1a..abf7cc86259ed 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-cs.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll
new file mode 100644
index 0000000000000..4c5c77fabbb9d
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll
@@ -0,0 +1,43 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+
+; 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
+; CHECK: ; Function main : 0x00000000
+; The test source in this file generated from the following command:
+; clang -cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -O0 -o - <<EOF
+; [numthreads(1,1,1)]
+; [shader("compute")]
+; void main() {}
+; EOF
+
+; ModuleID = '-'
+source_filename = "-"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.0-pc-shadermodel6.0-compute"
+
+; Function Attrs: convergent noinline norecurse optnone
+define void @main() #0 {
+entry:
+  ret void
+}
+
+; Function Attrs: alwaysinline convergent mustprogress norecurse nounwind
+define noundef i32 @_Z3foov() #1 {
+entry:
+  ret i32 0
+}
+
+attributes #0 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { alwaysinline convergent mustprogress norecurse nounwind "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll
new file mode 100644
index 0000000000000..5ad11a2f07881
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll
@@ -0,0 +1,53 @@
+; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+
+; 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
+; CHECK: ; Function main : 0x00000000
+; The test source in this file generated from the following command:
+; clang -cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -O0 -o - <<EOF
+
+; [numthreads(1,1,1)]
+; [shader("compute")]
+; void main() {}
+
+; int foo() {return 0;}
+; EOF
+
+; ModuleID = '-'
+source_filename = "-"
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
+define internal void @_Z4mainv() #0 {
+entry:
+  ret void
+}
+
+; Function Attrs: convergent noinline norecurse optnone
+define void @main() #1 {
+entry:
+  call void @_Z4mainv()
+  ret void
+}
+
+; Function Attrs: convergent mustprogress noinline norecurse nounwind optnone
+define noundef i32 @_Z3foov() #0 {
+entry:
+  ret i32 0
+}
+
+attributes #0 = { convergent mustprogress noinline norecurse nounwind optnone "approx-func-fp-math"="true" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0}
+!dx.valver = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll
new file mode 100644
index 0000000000000..74d5fd093ded6
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ShaderFlags/lib-entry-attr-error.ll
@@ -0,0 +1,30 @@
+; RUN: not opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
+
+target triple = "dxilv1.3-pc-shadermodel6.3-library"
+
+; All entry functions of a library shader need to either have optnone
+; or not have the attribute
+; CHECK: error:
+; CHECK-SAME: in function entry_two
+; CHECK-SAME:  Inconsistent optnone attribute
+; Function Attrs: convergent noinline norecurse optnone
+define void @entry_one() #0 {
+entry:
+  ret void
+}
+
+; Function Attrs: convergent noinline norecurse
+define void @entry_two() #1 {
+entry:
+  ret void
+}
+
+attributes #0 = { convergent noinline norecurse optnone "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { convergent noinline norecurse "approx-func-fp-math"="true" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+
+!llvm.module.flags = !{!0, !1}
+!dx.valver = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
+!2 = !{i32 1, i32 8}
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index b071557249414..03b2150bbc1dc 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

return false;
}

void ShaderFlagsAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequiredTransitive<DXILResourceTypeWrapperPass>();
AU.addRequired<DXILMetadataAnalysisWrapperPass>();
Copy link
Member

@farzonl farzonl Feb 12, 2025

Choose a reason for hiding this comment

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

This change causes DXIL Module Metadata analysis pass to run before DXIL Shader Flag Analysis because it is now needed MMDI.EntryPropertyVec[0].Entry->hasFnAttribute( llvm::Attribute::OptimizeNone); to initialize ModuleShaderFlags.

I think before we never intended to fetch fn attributes since you were using dx.disable_optimizations.
Does that make optnone a one off here or are there other attributes that could use this pattern?

Copy link
Contributor Author

@bharadwajy bharadwajy Feb 12, 2025

Choose a reason for hiding this comment

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

This change causes DXIL Module Metadata analysis pass to run before DXIL Shader Flag Analysis because it is now needed MMDI.EntryPropertyVec[0].Entry->hasFnAttribute( llvm::Attribute::OptimizeNone); to initialize ModuleShaderFlags.

I think before we never intended to fetch fn attributes since you were using dx.disable_optimizations.

Yes, that was the proposed mechanism in PR #123136. This PR supersedes that following the feedback there.

Does that make optnone a one off here or are there other attributes that could use this pattern?

The list of entry function information collected by Metadata Analysis pass is leveraged in this pass to look at optnone of each of the entry functions. Similarly it can be leveraged by other passes that require access to entry function information - for example, a pass that would want to query for entry function declaration withHLSLWaveSizeAttr.

Entry functions can be collected during the call graph traversal in this pass to query for optnone attribute. I just chose to leverage the same info that would be built in Metadata Analysis pass.

Comment on lines 19 to 22
; ModuleID = '-'
source_filename = "-"
target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
target triple = "dxilv1.0-pc-shadermodel6.0-compute"
Copy link
Contributor

Choose a reason for hiding this comment

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

Best to remove these when they aren't relevant to the test at hand.

Comment on lines 22 to 25
; ModuleID = '-'
source_filename = "-"
target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
target triple = "dxilv1.3-pc-shadermodel6.3-library"
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here

Comment on lines 39 to 43
!llvm.module.flags = !{!0}
!dx.valver = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, i32 8}
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't need the module.flags and valver metadata for these tests

MMDI.EntryPropertyVec[0].Entry->hasFnAttribute(
llvm::Attribute::OptimizeNone);
// Ensure all entry functions have the same optimization attribute
for (auto EF : MMDI.EntryPropertyVec)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be const auto & or const EntryProperties & rather than forcing copies here. Also what is "EF" an abbreviation of? It doesn't seem to have anything to do with what this variable represents. I'd probably call this "Props" or something like that.

@bharadwajy bharadwajy merged commit f2650c5 into llvm:main Feb 12, 2025
7 of 9 checks passed
flovent pushed a commit to flovent/llvm-project that referenced this pull request Feb 13, 2025
- Set the shader flag `DisableOptimizations` based on `optnone`
attribute of shader entry functions.

- Add DXIL Metadata Analysis pass as pre-requisite for Shader Flags pass
to obtain entry function information collected therein.

- Named module metadata `dx.disable_optimizations` is intended to
indicate disabling optimizations (`-O0`) via commandline flag. However,
its intent is fulfilled by `optnone` attribute of shader entry functions as 
implemented in a recent change, and thus not needed. Delete
generation of named metadata and corresponding test file
`disable_opt.ll`.

- Add tests to verify correctness of setting shader flag.

Closes llvm#112263
joaosaffran pushed a commit to joaosaffran/llvm-project that referenced this pull request Feb 14, 2025
- Set the shader flag `DisableOptimizations` based on `optnone`
attribute of shader entry functions.

- Add DXIL Metadata Analysis pass as pre-requisite for Shader Flags pass
to obtain entry function information collected therein.

- Named module metadata `dx.disable_optimizations` is intended to
indicate disabling optimizations (`-O0`) via commandline flag. However,
its intent is fulfilled by `optnone` attribute of shader entry functions as 
implemented in a recent change, and thus not needed. Delete
generation of named metadata and corresponding test file
`disable_opt.ll`.

- Add tests to verify correctness of setting shader flag.

Closes llvm#112263
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Feb 24, 2025
- Set the shader flag `DisableOptimizations` based on `optnone`
attribute of shader entry functions.

- Add DXIL Metadata Analysis pass as pre-requisite for Shader Flags pass
to obtain entry function information collected therein.

- Named module metadata `dx.disable_optimizations` is intended to
indicate disabling optimizations (`-O0`) via commandline flag. However,
its intent is fulfilled by `optnone` attribute of shader entry functions as 
implemented in a recent change, and thus not needed. Delete
generation of named metadata and corresponding test file
`disable_opt.ll`.

- Add tests to verify correctness of setting shader flag.

Closes llvm#112263
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:DirectX clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

[DirectX] Shader Flags Analysis for DisableOptimizations
4 participants