Skip to content

Commit 793bee4

Browse files
authored
[HLSL] Raise Diag for Invalid CounterDirection (#137697)
Fixes #135672 Raise a diagnostic in the post optimization validation pass as defined in https://github.com/llvm/wg-hlsl/blob/main/proposals/0022-resource-instance-analysis.md
1 parent 9f71664 commit 793bee4

File tree

10 files changed

+177
-2
lines changed

10 files changed

+177
-2
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,14 @@ ModulePass *createDXILResourceTypeWrapperPassPass();
454454
//===----------------------------------------------------------------------===//
455455

456456
class DXILResourceMap {
457+
using CallMapTy = DenseMap<CallInst *, unsigned>;
458+
457459
SmallVector<dxil::ResourceInfo> Infos;
458-
DenseMap<CallInst *, unsigned> CallMap;
460+
CallMapTy CallMap;
459461
unsigned FirstUAV = 0;
460462
unsigned FirstCBuffer = 0;
461463
unsigned FirstSampler = 0;
464+
bool HasInvalidDirection = false;
462465

463466
/// Populate all the resource instance data.
464467
void populate(Module &M, DXILResourceTypeMap &DRTM);
@@ -535,6 +538,23 @@ class DXILResourceMap {
535538
return make_range(sampler_begin(), sampler_end());
536539
}
537540

541+
struct call_iterator
542+
: iterator_adaptor_base<call_iterator, CallMapTy::iterator> {
543+
call_iterator() = default;
544+
call_iterator(CallMapTy::iterator Iter)
545+
: call_iterator::iterator_adaptor_base(std::move(Iter)) {}
546+
547+
CallInst *operator*() const { return I->first; }
548+
};
549+
550+
call_iterator call_begin() { return call_iterator(CallMap.begin()); }
551+
call_iterator call_end() { return call_iterator(CallMap.end()); }
552+
iterator_range<call_iterator> calls() {
553+
return make_range(call_begin(), call_end());
554+
}
555+
556+
bool hasInvalidCounterDirection() const { return HasInvalidDirection; }
557+
538558
void print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
539559
const DataLayout &DL) const;
540560

llvm/lib/Analysis/DXILResource.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,8 +815,10 @@ void DXILResourceMap::populateCounterDirections(Module &M) {
815815
for (ResourceInfo *RBInfo : RBInfos) {
816816
if (RBInfo->CounterDirection == ResourceCounterDirection::Unknown)
817817
RBInfo->CounterDirection = Direction;
818-
else if (RBInfo->CounterDirection != Direction)
818+
else if (RBInfo->CounterDirection != Direction) {
819819
RBInfo->CounterDirection = ResourceCounterDirection::Invalid;
820+
HasInvalidDirection = true;
821+
}
820822
}
821823
}
822824
}

llvm/lib/Target/DirectX/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_llvm_target(DirectXCodeGen
2828
DXILIntrinsicExpansion.cpp
2929
DXILOpBuilder.cpp
3030
DXILOpLowering.cpp
31+
DXILPostOptimizationValidation.cpp
3132
DXILPrepare.cpp
3233
DXILPrettyPrinter.cpp
3334
DXILResourceAccess.cpp
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//===- DXILPostOptimizationValidation.cpp - Opt DXIL validation ----------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "DXILPostOptimizationValidation.h"
10+
#include "DXILShaderFlags.h"
11+
#include "DirectX.h"
12+
#include "llvm/Analysis/DXILMetadataAnalysis.h"
13+
#include "llvm/Analysis/DXILResource.h"
14+
#include "llvm/IR/DiagnosticInfo.h"
15+
#include "llvm/IR/Instructions.h"
16+
#include "llvm/IR/IntrinsicsDirectX.h"
17+
#include "llvm/IR/Module.h"
18+
#include "llvm/InitializePasses.h"
19+
20+
#define DEBUG_TYPE "dxil-post-optimization-validation"
21+
22+
using namespace llvm;
23+
using namespace llvm::dxil;
24+
25+
namespace {
26+
27+
static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) {
28+
for (const auto &UAV : DRM.uavs()) {
29+
if (UAV.CounterDirection != ResourceCounterDirection::Invalid)
30+
continue;
31+
32+
CallInst *ResourceHandle = nullptr;
33+
for (CallInst *MaybeHandle : DRM.calls()) {
34+
if (*DRM.find(MaybeHandle) == UAV) {
35+
ResourceHandle = MaybeHandle;
36+
break;
37+
}
38+
}
39+
40+
StringRef Message = "RWStructuredBuffers may increment or decrement their "
41+
"counters, but not both.";
42+
for (const auto &U : ResourceHandle->users()) {
43+
const CallInst *CI = dyn_cast<CallInst>(U);
44+
if (!CI && CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
45+
continue;
46+
47+
M.getContext().diagnose(DiagnosticInfoGenericWithLoc(
48+
Message, *CI->getFunction(), CI->getDebugLoc()));
49+
}
50+
}
51+
}
52+
53+
} // namespace
54+
55+
PreservedAnalyses
56+
DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
57+
DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
58+
59+
if (DRM.hasInvalidCounterDirection())
60+
reportInvalidDirection(M, DRM);
61+
62+
return PreservedAnalyses::all();
63+
}
64+
65+
namespace {
66+
class DXILPostOptimizationValidationLegacy : public ModulePass {
67+
public:
68+
bool runOnModule(Module &M) override {
69+
DXILResourceMap &DRM =
70+
getAnalysis<DXILResourceWrapperPass>().getResourceMap();
71+
72+
if (DRM.hasInvalidCounterDirection())
73+
reportInvalidDirection(M, DRM);
74+
75+
return false;
76+
}
77+
StringRef getPassName() const override {
78+
return "DXIL Post Optimization Validation";
79+
}
80+
DXILPostOptimizationValidationLegacy() : ModulePass(ID) {}
81+
82+
static char ID; // Pass identification.
83+
void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
84+
AU.addRequired<DXILResourceWrapperPass>();
85+
AU.addPreserved<DXILResourceWrapperPass>();
86+
AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
87+
AU.addPreserved<ShaderFlagsAnalysisWrapper>();
88+
}
89+
};
90+
char DXILPostOptimizationValidationLegacy::ID = 0;
91+
} // end anonymous namespace
92+
93+
INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
94+
"DXIL Post Optimization Validation", false, false)
95+
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
96+
INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
97+
INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
98+
"DXIL Post Optimization Validation", false, false)
99+
100+
ModulePass *llvm::createDXILPostOptimizationValidationLegacyPass() {
101+
return new DXILPostOptimizationValidationLegacy();
102+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===- DXILPostOptimizationValidation.h - Opt DXIL Validations -*- C++ -*--===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// \file Pass for validating IR after optimizations are applied and before
10+
// lowering to DXIL.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
15+
#define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
16+
17+
#include "llvm/IR/PassManager.h"
18+
19+
namespace llvm {
20+
21+
class DXILPostOptimizationValidation
22+
: public PassInfoMixin<DXILPostOptimizationValidation> {
23+
public:
24+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
25+
};
26+
27+
} // namespace llvm
28+
29+
#endif // LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H

llvm/lib/Target/DirectX/DirectX.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ ModulePass *createDXILPrettyPrinterLegacyPass(raw_ostream &OS);
9090
/// Initializer for DXILPrettyPrinter.
9191
void initializeDXILPrettyPrinterLegacyPass(PassRegistry &);
9292

93+
/// Initializer for DXILPostOptimizationValidation.
94+
void initializeDXILPostOptimizationValidationLegacyPass(PassRegistry &);
95+
96+
/// Pass to lowering LLVM intrinsic call to DXIL op function call.
97+
ModulePass *createDXILPostOptimizationValidationLegacyPass();
98+
9399
/// Initializer for dxil::ShaderFlagsAnalysisWrapper pass.
94100
void initializeShaderFlagsAnalysisWrapperPass(PassRegistry &);
95101

llvm/lib/Target/DirectX/DirectXPassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ MODULE_PASS("dxil-intrinsic-expansion", DXILIntrinsicExpansion())
3030
MODULE_PASS("dxil-op-lower", DXILOpLowering())
3131
MODULE_PASS("dxil-pretty-printer", DXILPrettyPrinterPass(dbgs()))
3232
MODULE_PASS("dxil-translate-metadata", DXILTranslateMetadata())
33+
MODULE_PASS("dxil-post-optimization-validation", DXILPostOptimizationValidation())
3334
// TODO: rename to print<foo> after NPM switch
3435
MODULE_PASS("print-dx-shader-flags", dxil::ShaderFlagsAnalysisPrinter(dbgs()))
3536
MODULE_PASS("print<dxil-root-signature>", dxil::RootSignatureAnalysisPrinter(dbgs()))

llvm/lib/Target/DirectX/DirectXTargetMachine.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "DXILIntrinsicExpansion.h"
2020
#include "DXILLegalizePass.h"
2121
#include "DXILOpLowering.h"
22+
#include "DXILPostOptimizationValidation.h"
2223
#include "DXILPrettyPrinter.h"
2324
#include "DXILResourceAccess.h"
2425
#include "DXILRootSignature.h"
@@ -63,6 +64,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
6364
initializeDXILOpLoweringLegacyPass(*PR);
6465
initializeDXILResourceAccessLegacyPass(*PR);
6566
initializeDXILTranslateMetadataLegacyPass(*PR);
67+
initializeDXILPostOptimizationValidationLegacyPass(*PR);
6668
initializeShaderFlagsAnalysisWrapperPass(*PR);
6769
initializeRootSignatureAnalysisWrapperPass(*PR);
6870
initializeDXILFinalizeLinkageLegacyPass(*PR);
@@ -110,6 +112,7 @@ class DirectXPassConfig : public TargetPassConfig {
110112
addPass(createDXILForwardHandleAccessesLegacyPass());
111113
addPass(createDXILLegalizeLegacyPass());
112114
addPass(createDXILTranslateMetadataLegacyPass());
115+
addPass(createDXILPostOptimizationValidationLegacyPass());
113116
addPass(createDXILOpLoweringLegacyPass());
114117
addPass(createDXILPrepareModulePass());
115118
}

llvm/test/CodeGen/DirectX/llc-pipeline.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
; CHECK-NEXT: DXIL Module Metadata analysis
2929
; CHECK-NEXT: DXIL Shader Flag Analysis
3030
; CHECK-NEXT: DXIL Translate Metadata
31+
; CHECK-NEXT: DXIL Post Optimization Validation
3132
; CHECK-NEXT: DXIL Op Lowering
3233
; CHECK-NEXT: DXIL Prepare Module
3334

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
2+
; CHECK: RWStructuredBuffers may increment or decrement their counters, but not both.
3+
4+
define void @inc_and_dec() {
5+
entry:
6+
%handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
7+
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
8+
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
9+
ret void
10+
}

0 commit comments

Comments
 (0)