Skip to content

Commit 81196e0

Browse files
committed
Implement ResMayNotAlias DXIL shader flag analysis
1 parent 4bcf1e6 commit 81196e0

File tree

12 files changed

+210
-12
lines changed

12 files changed

+210
-12
lines changed

clang/include/clang/Basic/CodeGenOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ CODEGENOPT(ImportCallOptimization, 1, 0)
476476
/// (BlocksRuntime) on Windows.
477477
CODEGENOPT(StaticClosure, 1, 0)
478478

479+
/// Assume that UAVs/SRVs may alias
480+
CODEGENOPT(ResMayAlias, 1, 0)
481+
479482
/// FIXME: Make DebugOptions its own top-level .def file.
480483
#include "DebugOptions.def"
481484

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9043,6 +9043,11 @@ def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARA
90439043
HelpText<"Override validator version for module. Format: <major.minor>;"
90449044
"Default: DXIL.dll version or current internal version">,
90459045
MarshallingInfoString<TargetOpts<"DxilValidatorVersion">, "\"1.8\"">;
9046+
def res_may_alias : Option<["/", "-"], "res-may-alias", KIND_FLAG>,
9047+
Group<dxc_Group>, Flags<[HelpHidden]>,
9048+
Visibility<[DXCOption, ClangOption, CC1Option]>,
9049+
HelpText<"Assume that UAVs/SRVs may alias">,
9050+
MarshallingInfoFlag<CodeGenOpts<"ResMayAlias">>;
90469051
def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">,
90479052
HelpText<"Set target profile">,
90489053
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,"

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,13 @@ void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
283283

284284
void CGHLSLRuntime::finishCodeGen() {
285285
auto &TargetOpts = CGM.getTarget().getTargetOpts();
286+
auto &CodeGenOpts = CGM.getCodeGenOpts();
286287
llvm::Module &M = CGM.getModule();
287288
Triple T(M.getTargetTriple());
288289
if (T.getArch() == Triple::ArchType::dxil)
289290
addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
291+
if (CodeGenOpts.ResMayAlias)
292+
M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
290293

291294
generateGlobalCtorDtorCalls();
292295
}

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3959,6 +3959,7 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
39593959
static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
39603960
types::ID InputType) {
39613961
const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version,
3962+
options::OPT_res_may_alias,
39623963
options::OPT_D,
39633964
options::OPT_I,
39643965
options::OPT_O,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -res-may-alias -finclude-default-header -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=FLAG
2+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=NOFLAG
3+
4+
// FLAG-DAG: ![[RMA:.*]] = !{i32 1, !"dx.resmayalias", i32 1}
5+
// FLAG-DAG: !llvm.module.flags = !{{{.*}}![[RMA]]{{.*}}}
6+
7+
// NOFLAG-NOT: dx.resmayalias

llvm/lib/Target/DirectX/DXILShaderFlags.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ static bool checkWaveOps(Intrinsic::ID IID) {
7474
/// \param I Instruction to check.
7575
void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
7676
const Instruction &I,
77-
DXILResourceTypeMap &DRTM) {
77+
DXILResourceTypeMap &DRTM,
78+
const ModuleMetadataInfo &MMDI) {
7879
if (!CSF.Doubles)
7980
CSF.Doubles = I.getType()->isDoubleTy();
8081

@@ -116,8 +117,17 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
116117
switch (II->getIntrinsicID()) {
117118
default:
118119
break;
119-
case Intrinsic::dx_resource_handlefrombinding:
120-
switch (DRTM[cast<TargetExtType>(II->getType())].getResourceKind()) {
120+
case Intrinsic::dx_resource_handlefrombinding: {
121+
dxil::ResourceTypeInfo &RTI = DRTM[cast<TargetExtType>(II->getType())];
122+
123+
// If -res-may-alias is NOT specified, and DXIL Ver > 1.7.
124+
// Then set ResMayNotAlias if function uses UAVs.
125+
if (!CSF.ResMayNotAlias && !ResMayAlias &&
126+
MMDI.DXILVersion > VersionTuple(1, 7) && RTI.isUAV()) {
127+
CSF.ResMayNotAlias = true;
128+
}
129+
130+
switch (RTI.getResourceKind()) {
121131
case dxil::ResourceKind::StructuredBuffer:
122132
case dxil::ResourceKind::RawBuffer:
123133
CSF.EnableRawAndStructuredBuffers = true;
@@ -126,6 +136,7 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
126136
break;
127137
}
128138
break;
139+
}
129140
case Intrinsic::dx_resource_load_typedbuffer: {
130141
dxil::ResourceTypeInfo &RTI =
131142
DRTM[cast<TargetExtType>(II->getArgOperand(0)->getType())];
@@ -151,7 +162,17 @@ void ModuleShaderFlags::updateFunctionFlags(ComputedShaderFlags &CSF,
151162

152163
/// Construct ModuleShaderFlags for module Module M
153164
void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
165+
DXILBindingMap &DBM,
154166
const ModuleMetadataInfo &MMDI) {
167+
168+
// Check if -res-may-alias was provided on the command line.
169+
// The command line option will set the dx.resmayalias module flag to 1.
170+
if (auto *RMA = mdconst::extract_or_null<ConstantInt>(
171+
M.getModuleFlag("dx.resmayalias"))) {
172+
if (RMA->getValue() != 0)
173+
ResMayAlias = true;
174+
}
175+
155176
CallGraph CG(M);
156177

157178
// Compute Shader Flags Mask for all functions using post-order visit of SCC
@@ -176,10 +197,16 @@ void ModuleShaderFlags::initialize(Module &M, DXILResourceTypeMap &DRTM,
176197
continue;
177198
}
178199

200+
// If -res-may-alias is NOT specified, and DXIL Ver <= 1.7.
201+
// Then set ResMayNotAlias to true if there are UAVs present globally.
202+
if (!ResMayAlias && MMDI.DXILVersion <= VersionTuple(1, 7)) {
203+
SCCSF.ResMayNotAlias = !DBM.uavs().empty();
204+
}
205+
179206
ComputedShaderFlags CSF;
180207
for (const auto &BB : *F)
181208
for (const auto &I : BB)
182-
updateFunctionFlags(CSF, I, DRTM);
209+
updateFunctionFlags(CSF, I, DRTM, MMDI);
183210
// Update combined shader flags mask for all functions in this SCC
184211
SCCSF.merge(CSF);
185212

@@ -249,10 +276,11 @@ AnalysisKey ShaderFlagsAnalysis::Key;
249276
ModuleShaderFlags ShaderFlagsAnalysis::run(Module &M,
250277
ModuleAnalysisManager &AM) {
251278
DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);
279+
DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
252280
const ModuleMetadataInfo MMDI = AM.getResult<DXILMetadataAnalysis>(M);
253281

254282
ModuleShaderFlags MSFI;
255-
MSFI.initialize(M, DRTM, MMDI);
283+
MSFI.initialize(M, DRTM, DBM, MMDI);
256284

257285
return MSFI;
258286
}
@@ -282,16 +310,19 @@ PreservedAnalyses ShaderFlagsAnalysisPrinter::run(Module &M,
282310
bool ShaderFlagsAnalysisWrapper::runOnModule(Module &M) {
283311
DXILResourceTypeMap &DRTM =
284312
getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
313+
DXILBindingMap &DBM =
314+
getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
285315
const ModuleMetadataInfo MMDI =
286316
getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
287317

288-
MSFI.initialize(M, DRTM, MMDI);
318+
MSFI.initialize(M, DRTM, DBM, MMDI);
289319
return false;
290320
}
291321

292322
void ShaderFlagsAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
293323
AU.setPreservesAll();
294324
AU.addRequiredTransitive<DXILResourceTypeWrapperPass>();
325+
AU.addRequiredTransitive<DXILResourceBindingWrapperPass>();
295326
AU.addRequired<DXILMetadataAnalysisWrapperPass>();
296327
}
297328

llvm/lib/Target/DirectX/DXILShaderFlags.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace llvm {
2828
class Module;
2929
class GlobalVariable;
3030
class DXILResourceTypeMap;
31+
class DXILBindingMap;
3132

3233
namespace dxil {
3334

@@ -85,19 +86,23 @@ struct ComputedShaderFlags {
8586

8687
struct ModuleShaderFlags {
8788
void initialize(Module &, DXILResourceTypeMap &DRTM,
88-
const ModuleMetadataInfo &MMDI);
89+
DXILBindingMap &DBM, const ModuleMetadataInfo &MMDI);
8990
const ComputedShaderFlags &getFunctionFlags(const Function *) const;
9091
const ComputedShaderFlags &getCombinedFlags() const { return CombinedSFMask; }
9192

9293
private:
94+
// A bool to indicate if the -res-may-alias flag was passed to clang-dxc.
95+
// A module flag "dx.resmayalias" is set to 1 if true.
96+
// This bool is used in the logic for setting the flag ResMayNotAlias.
97+
bool ResMayAlias = false;
9398
/// Map of Function-Shader Flag Mask pairs representing properties of each of
9499
/// the functions in the module. Shader Flags of each function represent both
95100
/// module-level and function-level flags
96101
DenseMap<const Function *, ComputedShaderFlags> FunctionFlags;
97102
/// Combined Shader Flag Mask of all functions of the module
98103
ComputedShaderFlags CombinedSFMask{};
99104
void updateFunctionFlags(ComputedShaderFlags &, const Instruction &,
100-
DXILResourceTypeMap &);
105+
DXILResourceTypeMap &, const ModuleMetadataInfo &);
101106
};
102107

103108
class ShaderFlagsAnalysis : public AnalysisInfoMixin<ShaderFlagsAnalysis> {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
target triple = "dxil-pc-shadermodel6.8-library"
4+
5+
; CHECK: Combined Shader Flags for Module
6+
; CHECK-NEXT: Shader Flags Value: 0x200000010
7+
8+
; CHECK: Note: extra DXIL module flags:
9+
; CHECK: Raw and Structured buffers
10+
; CHECK: Any UAV may not alias any other UAV
11+
;
12+
13+
; CHECK: Function loadUAV : 0x20000000
14+
define float @loadUAV() #0 {
15+
%res = call target("dx.TypedBuffer", float, 1, 0, 0)
16+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
17+
%load = call {float, i1} @llvm.dx.resource.load.typedbuffer(
18+
target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0)
19+
%val = extractvalue {float, i1} %load, 0
20+
ret float %val
21+
}
22+
23+
; CHECK: Function loadSRV : 0x00000010
24+
define float @loadSRV() #0 {
25+
%res = tail call target("dx.RawBuffer", float, 0, 0)
26+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
27+
%load = call {float, i1} @llvm.dx.resource.load.rawbuffer(
28+
target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0)
29+
%val = extractvalue { float, i1 } %load, 0
30+
ret float %val
31+
}
32+
33+
!llvm.module.flags = !{!0}
34+
35+
; dx.resmayalias should never appear with a value of 0.
36+
; But if it does, ensure that it has no effect.
37+
!0 = !{i32 1, !"dx.resmayalias", i32 0}
38+
39+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
target triple = "dxil-pc-shadermodel6.8-library"
4+
5+
; CHECK: Combined Shader Flags for Module
6+
; CHECK-NEXT: Shader Flags Value: 0x00000010
7+
8+
; CHECK: Note: extra DXIL module flags:
9+
; CHECK: Raw and Structured buffers
10+
; CHECK-NOT: Any UAV may not alias any other UAV
11+
;
12+
13+
; CHECK: Function loadUAV : 0x00000000
14+
define float @loadUAV() #0 {
15+
%res = call target("dx.TypedBuffer", float, 1, 0, 0)
16+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
17+
%load = call {float, i1} @llvm.dx.resource.load.typedbuffer(
18+
target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0)
19+
%val = extractvalue {float, i1} %load, 0
20+
ret float %val
21+
}
22+
23+
; CHECK: Function loadSRV : 0x00000010
24+
define float @loadSRV() #0 {
25+
%res = tail call target("dx.RawBuffer", float, 0, 0)
26+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
27+
%load = call {float, i1} @llvm.dx.resource.load.rawbuffer(
28+
target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0)
29+
%val = extractvalue { float, i1 } %load, 0
30+
ret float %val
31+
}
32+
33+
!llvm.module.flags = !{!0}
34+
35+
!0 = !{i32 1, !"dx.resmayalias", i32 1}
36+
37+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
target triple = "dxil-pc-shadermodel6.7-library"
4+
5+
; CHECK: Combined Shader Flags for Module
6+
; CHECK-NEXT: Shader Flags Value: 0x200000010
7+
8+
; CHECK: Note: extra DXIL module flags:
9+
; CHECK: Raw and Structured buffers
10+
; CHECK: Any UAV may not alias any other UAV
11+
;
12+
13+
; CHECK: Function loadUAV : 0x200000000
14+
define float @loadUAV() #0 {
15+
%res = call target("dx.TypedBuffer", float, 1, 0, 0)
16+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
17+
%load = call {float, i1} @llvm.dx.resource.load.typedbuffer(
18+
target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0)
19+
%val = extractvalue {float, i1} %load, 0
20+
ret float %val
21+
}
22+
23+
; CHECK: Function loadSRV : 0x200000010
24+
define float @loadSRV() #0 {
25+
%res = tail call target("dx.RawBuffer", float, 0, 0)
26+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
27+
%load = call {float, i1} @llvm.dx.resource.load.rawbuffer(
28+
target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0)
29+
%val = extractvalue { float, i1 } %load, 0
30+
ret float %val
31+
}
32+
33+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt -S --passes="print-dx-shader-flags" 2>&1 %s | FileCheck %s
2+
3+
target triple = "dxil-pc-shadermodel6.8-library"
4+
5+
; CHECK: Combined Shader Flags for Module
6+
; CHECK-NEXT: Shader Flags Value: 0x200000010
7+
8+
; CHECK: Note: extra DXIL module flags:
9+
; CHECK: Raw and Structured buffers
10+
; CHECK: Any UAV may not alias any other UAV
11+
;
12+
13+
; CHECK: Function loadUAV : 0x20000000
14+
define float @loadUAV() #0 {
15+
%res = call target("dx.TypedBuffer", float, 1, 0, 0)
16+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
17+
%load = call {float, i1} @llvm.dx.resource.load.typedbuffer(
18+
target("dx.TypedBuffer", float, 1, 0, 0) %res, i32 0)
19+
%val = extractvalue {float, i1} %load, 0
20+
ret float %val
21+
}
22+
23+
; CHECK: Function loadSRV : 0x00000010
24+
define float @loadSRV() #0 {
25+
%res = tail call target("dx.RawBuffer", float, 0, 0)
26+
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
27+
%load = call {float, i1} @llvm.dx.resource.load.rawbuffer(
28+
target("dx.RawBuffer", float, 0, 0) %res, i32 0, i32 0)
29+
%val = extractvalue { float, i1 } %load, 0
30+
ret float %val
31+
}
32+
33+
attributes #0 = { convergent norecurse nounwind "hlsl.export"}

llvm/test/CodeGen/DirectX/ShaderFlags/typed-uav-load-additional-formats.ll

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ target triple = "dxil-pc-shadermodel6.7-library"
88
; CHECK-OBJ: TypedUAVLoadAdditionalFormats: true
99

1010
; CHECK: Combined Shader Flags for Module
11-
; CHECK-NEXT: Shader Flags Value: 0x00002000
11+
; CHECK-NEXT: Shader Flags Value: 0x200002000
1212

1313
; CHECK: Note: shader requires additional functionality:
1414
; CHECK: Typed UAV Load Additional Formats
15+
; CHECK: Any UAV may not alias any other UAV
1516

16-
; CHECK: Function multicomponent : 0x00002000
17+
; CHECK: Function multicomponent : 0x200002000
1718
define <4 x float> @multicomponent() #0 {
1819
%res = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
1920
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
@@ -23,7 +24,7 @@ define <4 x float> @multicomponent() #0 {
2324
ret <4 x float> %val
2425
}
2526

26-
; CHECK: Function onecomponent : 0x00000000
27+
; CHECK: Function onecomponent : 0x200000000
2728
define float @onecomponent() #0 {
2829
%res = call target("dx.TypedBuffer", float, 1, 0, 0)
2930
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)
@@ -33,7 +34,7 @@ define float @onecomponent() #0 {
3334
ret float %val
3435
}
3536

36-
; CHECK: Function noload : 0x00000000
37+
; CHECK: Function noload : 0x200000000
3738
define void @noload(<4 x float> %val) #0 {
3839
%res = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
3940
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false)

0 commit comments

Comments
 (0)