Skip to content

Commit 50a114f

Browse files
committed
[HLSL] Raise Diag for Invalid CounterDirection
1 parent 9f2bcc7 commit 50a114f

File tree

9 files changed

+187
-1
lines changed

9 files changed

+187
-1
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,10 @@ ModulePass *createDXILResourceTypeWrapperPassPass();
451451
//===----------------------------------------------------------------------===//
452452

453453
class DXILResourceMap {
454+
using CallMapTy = DenseMap<CallInst *, unsigned>;
455+
454456
SmallVector<dxil::ResourceInfo> Infos;
455-
DenseMap<CallInst *, unsigned> CallMap;
457+
CallMapTy CallMap;
456458
unsigned FirstUAV = 0;
457459
unsigned FirstCBuffer = 0;
458460
unsigned FirstSampler = 0;
@@ -532,6 +534,21 @@ class DXILResourceMap {
532534
return make_range(sampler_begin(), sampler_end());
533535
}
534536

537+
struct call_iterator
538+
: iterator_adaptor_base<call_iterator, CallMapTy::iterator> {
539+
call_iterator() = default;
540+
call_iterator(CallMapTy::iterator Iter)
541+
: call_iterator::iterator_adaptor_base(std::move(Iter)) {}
542+
543+
CallInst *operator*() const { return I->first; }
544+
};
545+
546+
call_iterator call_begin() { return call_iterator(CallMap.begin()); }
547+
call_iterator call_end() { return call_iterator(CallMap.end()); }
548+
iterator_range<call_iterator> calls() {
549+
return make_range(call_begin(), call_end());
550+
}
551+
535552
void print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
536553
const DataLayout &DL) const;
537554

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: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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 "DXILConstants.h"
11+
#include "DXILIntrinsicExpansion.h"
12+
#include "DXILOpBuilder.h"
13+
#include "DXILShaderFlags.h"
14+
#include "DirectX.h"
15+
#include "llvm/ADT/SmallVector.h"
16+
#include "llvm/Analysis/DXILMetadataAnalysis.h"
17+
#include "llvm/Analysis/DXILResource.h"
18+
#include "llvm/CodeGen/Passes.h"
19+
#include "llvm/IR/DiagnosticInfo.h"
20+
#include "llvm/IR/Function.h"
21+
#include "llvm/IR/IRBuilder.h"
22+
#include "llvm/IR/Instruction.h"
23+
#include "llvm/IR/Instructions.h"
24+
#include "llvm/IR/Intrinsics.h"
25+
#include "llvm/IR/IntrinsicsDirectX.h"
26+
#include "llvm/IR/Module.h"
27+
#include "llvm/IR/PassManager.h"
28+
#include "llvm/InitializePasses.h"
29+
#include "llvm/Pass.h"
30+
#include "llvm/Support/ErrorHandling.h"
31+
#include <cstdio>
32+
33+
#define DEBUG_TYPE "dxil-post-optimization-validation"
34+
35+
using namespace llvm;
36+
using namespace llvm::dxil;
37+
38+
namespace {
39+
class DXILValidator {
40+
Module &M;
41+
DXILResourceMap &DRM;
42+
43+
public:
44+
DXILValidator(Module &M, DXILResourceMap &DRM) : M(M), DRM(DRM) {}
45+
46+
void validate() {
47+
for (const auto &UAV : DRM.uavs()) {
48+
if (UAV.CounterDirection != ResourceCounterDirection::Invalid)
49+
continue;
50+
51+
CallInst *ResourceHandle = nullptr;
52+
for (CallInst *MaybeHandle : DRM.calls()) {
53+
if (*DRM.find(MaybeHandle) == UAV) {
54+
ResourceHandle = MaybeHandle;
55+
break;
56+
}
57+
}
58+
59+
StringRef Message =
60+
"RWStructuredBuffers may increment or decrement their "
61+
"counters, but not both.";
62+
for (const auto &U : ResourceHandle->users()) {
63+
const CallInst *CI = dyn_cast<CallInst>(U);
64+
if (!CI && CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
65+
continue;
66+
67+
M.getContext().diagnose(DiagnosticInfoGenericWithLoc(
68+
Message, *CI->getFunction(), CI->getDebugLoc()));
69+
}
70+
}
71+
}
72+
};
73+
} // namespace
74+
75+
PreservedAnalyses
76+
DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
77+
DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
78+
79+
DXILValidator(M, DRM).validate();
80+
return PreservedAnalyses::all();
81+
}
82+
83+
namespace {
84+
class DXILPostOptimizationValidationLegacy : public ModulePass {
85+
public:
86+
bool runOnModule(Module &M) override {
87+
DXILResourceMap &DRM =
88+
getAnalysis<DXILResourceWrapperPass>().getResourceMap();
89+
90+
DXILValidator(M, DRM).validate();
91+
92+
return false;
93+
}
94+
StringRef getPassName() const override {
95+
return "DXIL Post Optimization Validation";
96+
}
97+
DXILPostOptimizationValidationLegacy() : ModulePass(ID) {}
98+
99+
static char ID; // Pass identification.
100+
void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
101+
AU.addRequired<DXILResourceWrapperPass>();
102+
AU.addPreserved<DXILResourceWrapperPass>();
103+
AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
104+
AU.addPreserved<ShaderFlagsAnalysisWrapper>();
105+
}
106+
};
107+
char DXILPostOptimizationValidationLegacy::ID = 0;
108+
} // end anonymous namespace
109+
110+
INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
111+
"DXIL Post Optimization Validation", false, false)
112+
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
113+
INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
114+
INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
115+
"DXIL Post Optimization Validation", false, false)
116+
117+
ModulePass *llvm::createDXILPostOptimizationValidationLegacyPass() {
118+
return new DXILPostOptimizationValidationLegacy();
119+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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 DXIL after lowering and optimizations are applied.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
14+
#define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
15+
16+
#include "llvm/IR/PassManager.h"
17+
18+
namespace llvm {
19+
20+
class DXILPostOptimizationValidation
21+
: public PassInfoMixin<DXILPostOptimizationValidation> {
22+
public:
23+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
24+
};
25+
26+
} // namespace llvm
27+
28+
#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)