Skip to content

[DirectX] Set whole-module flags prior to evaluating per-function flags #139967

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 4 commits into from
May 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 60 additions & 50 deletions llvm/lib/Target/DirectX/DXILShaderFlags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
using namespace llvm;
using namespace llvm::dxil;

static bool hasUAVsAtEveryStage(DXILResourceMap &DRM,
static bool hasUAVsAtEveryStage(const DXILResourceMap &DRM,
const ModuleMetadataInfo &MMDI) {
if (DRM.uavs().empty())
return false;
Expand Down Expand Up @@ -143,7 +143,7 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
}

if (CSF.LowPrecisionPresent) {
if (CanSetNativeLowPrecisionMode)
if (CSF.NativeLowPrecisionMode)
CSF.NativeLowPrecision = true;
else
CSF.MinimumPrecision = true;
Expand Down Expand Up @@ -207,26 +207,73 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
}
}

/// Set shader flags that apply to all functions within the module
ComputedShaderFlags
ModuleShaderFlags::gatherGlobalModuleFlags(const Module &M,
const DXILResourceMap &DRM,
const ModuleMetadataInfo &MMDI) {

ComputedShaderFlags CSF;

// Set DisableOptimizations flag based on the presence of OptimizeNone
// attribute of entry functions.
if (MMDI.EntryPropertyVec.size() > 0) {
CSF.DisableOptimizations = MMDI.EntryPropertyVec[0].Entry->hasFnAttribute(
llvm::Attribute::OptimizeNone);
// Ensure all entry functions have the same optimization attribute
for (const auto &EntryFunProps : MMDI.EntryPropertyVec)
if (CSF.DisableOptimizations !=
EntryFunProps.Entry->hasFnAttribute(llvm::Attribute::OptimizeNone))
EntryFunProps.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
*(EntryFunProps.Entry), "Inconsistent optnone attribute "));
}

CSF.UAVsAtEveryStage = hasUAVsAtEveryStage(DRM, MMDI);

// Set the Max64UAVs flag if the number of UAVs is > 8
uint32_t NumUAVs = 0;
for (auto &UAV : DRM.uavs())
if (MMDI.ValidatorVersion < VersionTuple(1, 6))
NumUAVs++;
else // MMDI.ValidatorVersion >= VersionTuple(1, 6)
NumUAVs += UAV.getBinding().Size;
if (NumUAVs > 8)
CSF.Max64UAVs = true;

// Set the module flag that enables native low-precision execution mode.
// NativeLowPrecisionMode can only be set when the command line option
// -enable-16bit-types is provided. This is indicated by the dx.nativelowprec
// module flag being set
// This flag is needed even if the module does not use 16-bit types because a
// corresponding debug module may include 16-bit types, and tools that use the
// debug module may expect it to have the same flags as the original
if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
M.getModuleFlag("dx.nativelowprec")))
if (MMDI.ShaderModelVersion >= VersionTuple(6, 2))
CSF.NativeLowPrecisionMode = NativeLowPrec->getValue().getBoolValue();

// Set ResMayNotAlias to true if DXIL validator version < 1.8 and there
// are UAVs present globally.
if (CanSetResMayNotAlias && MMDI.ValidatorVersion < VersionTuple(1, 8))
CSF.ResMayNotAlias = !DRM.uavs().empty();

return CSF;
}

/// Construct ModuleShaderFlags for module Module M
void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
DXILResourceMap &DRM,
const DXILResourceMap &DRM,
const ModuleMetadataInfo &MMDI) {

CanSetResMayNotAlias = MMDI.DXILVersion >= VersionTuple(1, 7);
// The command line option -res-may-alias will set the dx.resmayalias module
// flag to 1, thereby disabling the ability to set the ResMayNotAlias flag
if (auto *ResMayAlias = mdconst::extract_or_null<ConstantInt>(
M.getModuleFlag("dx.resmayalias")))
CanSetResMayNotAlias = !ResMayAlias->getValue().getBoolValue();
if (ResMayAlias->getValue().getBoolValue())
CanSetResMayNotAlias = false;

// NativeLowPrecisionMode can only be set when the command line option
// -enable-16bit-types is provided. This is indicated by the dx.nativelowprec
// module flag being set
CanSetNativeLowPrecisionMode = false;
if (auto *NativeLowPrec = mdconst::extract_or_null<ConstantInt>(
M.getModuleFlag("dx.nativelowprec")))
if (MMDI.ShaderModelVersion >= VersionTuple(6, 2))
CanSetNativeLowPrecisionMode = NativeLowPrec->getValue().getBoolValue();
ComputedShaderFlags GlobalSFMask = gatherGlobalModuleFlags(M, DRM, MMDI);

CallGraph CG(M);

Expand All @@ -252,7 +299,7 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
continue;
}

ComputedShaderFlags CSF;
ComputedShaderFlags CSF = GlobalSFMask;
for (const auto &BB : *F)
for (const auto &I : BB)
updateFunctionFlags(CSF, I, DRTM, MMDI);
Expand All @@ -273,43 +320,6 @@ 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 (const auto &EntryFunProps : MMDI.EntryPropertyVec)
if (CombinedSFMask.DisableOptimizations !=
EntryFunProps.Entry->hasFnAttribute(llvm::Attribute::OptimizeNone))
EntryFunProps.Entry->getContext().diagnose(DiagnosticInfoUnsupported(
*(EntryFunProps.Entry), "Inconsistent optnone attribute "));
}

// Set ResMayNotAlias to true if DXIL validator version < 1.8 and there
// are UAVs present globally.
if (CanSetResMayNotAlias && MMDI.ValidatorVersion < VersionTuple(1, 8))
CombinedSFMask.ResMayNotAlias = !DRM.uavs().empty();

// Set the module flag that enables native low-precision execution mode. This
// is needed even if the module does not use 16-bit types because a
// corresponding debug module may include 16-bit types, and tools that use the
// debug module may expect it to have the same flags as the original
CombinedSFMask.NativeLowPrecisionMode = CanSetNativeLowPrecisionMode;

// Set the Max64UAVs flag if the number of UAVs is > 8
uint32_t NumUAVs = 0;
for (auto &UAV : DRM.uavs())
if (MMDI.ValidatorVersion < VersionTuple(1, 6))
NumUAVs++;
else // MMDI.ValidatorVersion >= VersionTuple(1, 6)
NumUAVs += UAV.getBinding().Size;
if (NumUAVs > 8)
CombinedSFMask.Max64UAVs = true;

CombinedSFMask.UAVsAtEveryStage = hasUAVsAtEveryStage(DRM, MMDI);
}

void ComputedShaderFlags::print(raw_ostream &OS) const {
Expand Down
13 changes: 8 additions & 5 deletions llvm/lib/Target/DirectX/DXILShaderFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,25 @@ struct ComputedShaderFlags {
};

struct ModuleShaderFlags {
void initialize(Module &, DXILResourceTypeMap &DRTM, DXILResourceMap &DRM,
const ModuleMetadataInfo &MMDI);
void initialize(Module &, DXILResourceTypeMap &DRTM,
const DXILResourceMap &DRM, const ModuleMetadataInfo &MMDI);
const ComputedShaderFlags &getFunctionFlags(const Function *) const;
const ComputedShaderFlags &getCombinedFlags() const { return CombinedSFMask; }

private:
// Booleans set by module flags
bool CanSetResMayNotAlias; // dx.resmayalias
bool CanSetNativeLowPrecisionMode; // dx.nativelowprec
// This boolean is inversely set by the LLVM module flag dx.resmayalias to
// determine whether or not the ResMayNotAlias DXIL module flag can be set
bool CanSetResMayNotAlias;

/// Map of Function-Shader Flag Mask pairs representing properties of each of
/// the functions in the module. Shader Flags of each function represent both
/// module-level and function-level flags
DenseMap<const Function *, ComputedShaderFlags> FunctionFlags;
/// Combined Shader Flag Mask of all functions of the module
ComputedShaderFlags CombinedSFMask{};
ComputedShaderFlags gatherGlobalModuleFlags(const Module &M,
const DXILResourceMap &,
const ModuleMetadataInfo &);
void updateFunctionFlags(ComputedShaderFlags &, const Instruction &,
DXILResourceTypeMap &, const ModuleMetadataInfo &);
};
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-cs.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
; CHECK-NEXT: ; Disable shader optimizations

; CHECK: ; Shader Flags for Module Functions
; CHECK: ; Function main : 0x00000000
; CHECK: ; Function main : 0x00000001
; 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)]
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/DirectX/ShaderFlags/disable-opt-lib.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
; CHECK-NEXT: ; Disable shader optimizations

; CHECK: ; Shader Flags for Module Functions
; CHECK: ; Function main : 0x00000000
; CHECK: ; Function main : 0x00000001
; 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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK: UAVs at every shader stage
; CHECK-NOT: 64 UAV slots

; CHECK: Function test : 0x00000000
; CHECK: Function test : 0x00010000
define void @test() "hlsl.export" {
; RWBuffer<float> Buf : register(u0, space0)
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK: UAVs at every shader stage
; CHECK: 64 UAV slots

; CHECK: Function test : 0x00000000
; CHECK: Function test : 0x00018000
define void @test() "hlsl.export" {
; RWBuffer<float> Buf : register(u0, space0)
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/DirectX/ShaderFlags/max-64-uavs.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK: 64 UAV slots

; Note: 64 UAV slots does not get set per-function
; CHECK: Function test : 0x00000000
; CHECK: Function test : 0x00008000
define void @test() "hlsl.export" {
; RWBuffer<float> Buf : register(u0, space0)
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ target triple = "dxil-pc-shadermodel6.7-library"
; CHECK: Any UAV may not alias any other UAV
;

; CHECK: Function loadUAV : 0x00000000
; CHECK: Function loadUAV : 0x200010000
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)
Expand All @@ -29,7 +29,7 @@ define float @loadUAV() #0 {
ret float %val
}

; CHECK: Function loadSRV : 0x00000010
; CHECK: Function loadSRV : 0x200010010
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ target triple = "dxil-pc-shadermodel6.5-library"
; CHECK: Note: shader requires additional functionality:
; CHECK: UAVs at every shader stage

; CHECK: Function test : 0x00000000
; CHECK: Function test : 0x00010000
define void @test() "hlsl.export" {
; RWBuffer<float> Buf : register(u0, space0)
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ target triple = "dxil-pc-shadermodel6.5-vertex"
; CHECK: Note: shader requires additional functionality:
; CHECK: UAVs at every shader stage

; CHECK: Function VSMain : 0x00000000
; CHECK: Function VSMain : 0x00010000
define void @VSMain() {
; RWBuffer<float> Buf : register(u0, space0)
%buf0 = call target("dx.TypedBuffer", float, 1, 0, 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ target triple = "dxil-pc-shadermodel6.7-library"
;CHECK-NEXT: ;
;CHECK-NEXT: ; Shader Flags for Module Functions

;CHECK-LABEL: ; Function add_i16 : 0x00000020
;CHECK-LABEL: ; Function add_i16 : 0x00800020
define i16 @add_i16(i16 %a, i16 %b) "hlsl.export" {
%sum = add i16 %a, %b
ret i16 %sum
}

;CHECK-LABEL: ; Function add_i32 : 0x00000000
;CHECK-LABEL: ; Function add_i32 : 0x00800000
define i32 @add_i32(i32 %a, i32 %b) "hlsl.export" {
%sum = add i32 %a, %b
ret i32 %sum
}

;CHECK-LABEL: ; Function add_half : 0x00000020
;CHECK-LABEL: ; Function add_half : 0x00800020
define half @add_half(half %a, half %b) "hlsl.export" {
%sum = fadd half %a, %b
ret half %sum
Expand Down