xref: /freebsd/contrib/llvm-project/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/ADT/SmallString.h"
13 #include "llvm/Analysis/DXILMetadataAnalysis.h"
14 #include "llvm/Analysis/DXILResource.h"
15 #include "llvm/IR/DiagnosticInfo.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/IntrinsicsDirectX.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/InitializePasses.h"
20 
21 #define DEBUG_TYPE "dxil-post-optimization-validation"
22 
23 using namespace llvm;
24 using namespace llvm::dxil;
25 
26 namespace {
27 
reportInvalidDirection(Module & M,DXILResourceMap & DRM)28 static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) {
29   for (const auto &UAV : DRM.uavs()) {
30     if (UAV.CounterDirection != ResourceCounterDirection::Invalid)
31       continue;
32 
33     CallInst *ResourceHandle = nullptr;
34     for (CallInst *MaybeHandle : DRM.calls()) {
35       if (*DRM.find(MaybeHandle) == UAV) {
36         ResourceHandle = MaybeHandle;
37         break;
38       }
39     }
40 
41     StringRef Message = "RWStructuredBuffers may increment or decrement their "
42                         "counters, but not both.";
43     for (const auto &U : ResourceHandle->users()) {
44       const CallInst *CI = dyn_cast<CallInst>(U);
45       if (!CI && CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
46         continue;
47 
48       M.getContext().diagnose(DiagnosticInfoGenericWithLoc(
49           Message, *CI->getFunction(), CI->getDebugLoc()));
50     }
51   }
52 }
53 
reportOverlappingError(Module & M,ResourceInfo R1,ResourceInfo R2)54 static void reportOverlappingError(Module &M, ResourceInfo R1,
55                                    ResourceInfo R2) {
56   SmallString<128> Message;
57   raw_svector_ostream OS(Message);
58   OS << "resource " << R1.getName() << " at register "
59      << R1.getBinding().LowerBound << " overlaps with resource " << R2.getName()
60      << " at register " << R2.getBinding().LowerBound << " in space "
61      << R2.getBinding().Space;
62   M.getContext().diagnose(DiagnosticInfoGeneric(Message));
63 }
64 
reportOverlappingBinding(Module & M,DXILResourceMap & DRM)65 static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
66   if (DRM.empty())
67     return;
68 
69   for (const auto &ResList :
70        {DRM.srvs(), DRM.uavs(), DRM.cbuffers(), DRM.samplers()}) {
71     if (ResList.empty())
72       continue;
73     const ResourceInfo *PrevRI = &*ResList.begin();
74     for (auto *I = ResList.begin() + 1; I != ResList.end(); ++I) {
75       const ResourceInfo *CurrentRI = &*I;
76       const ResourceInfo *RI = CurrentRI;
77       while (RI != ResList.end() &&
78              PrevRI->getBinding().overlapsWith(RI->getBinding())) {
79         reportOverlappingError(M, *PrevRI, *RI);
80         RI++;
81       }
82       PrevRI = CurrentRI;
83     }
84   }
85 }
86 
reportErrors(Module & M,DXILResourceMap & DRM,DXILResourceBindingInfo & DRBI)87 static void reportErrors(Module &M, DXILResourceMap &DRM,
88                          DXILResourceBindingInfo &DRBI) {
89   if (DRM.hasInvalidCounterDirection())
90     reportInvalidDirection(M, DRM);
91 
92   if (DRBI.hasOverlappingBinding())
93     reportOverlappingBinding(M, DRM);
94 
95   assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
96                                        "DXILResourceImplicitBinding pass");
97 }
98 } // namespace
99 
100 PreservedAnalyses
run(Module & M,ModuleAnalysisManager & MAM)101 DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
102   DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
103   DXILResourceBindingInfo &DRBI = MAM.getResult<DXILResourceBindingAnalysis>(M);
104   reportErrors(M, DRM, DRBI);
105   return PreservedAnalyses::all();
106 }
107 
108 namespace {
109 class DXILPostOptimizationValidationLegacy : public ModulePass {
110 public:
runOnModule(Module & M)111   bool runOnModule(Module &M) override {
112     DXILResourceMap &DRM =
113         getAnalysis<DXILResourceWrapperPass>().getResourceMap();
114     DXILResourceBindingInfo &DRBI =
115         getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
116     reportErrors(M, DRM, DRBI);
117     return false;
118   }
getPassName() const119   StringRef getPassName() const override {
120     return "DXIL Post Optimization Validation";
121   }
DXILPostOptimizationValidationLegacy()122   DXILPostOptimizationValidationLegacy() : ModulePass(ID) {}
123 
124   static char ID; // Pass identification.
getAnalysisUsage(llvm::AnalysisUsage & AU) const125   void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
126     AU.addRequired<DXILResourceWrapperPass>();
127     AU.addRequired<DXILResourceBindingWrapperPass>();
128     AU.addPreserved<DXILResourceWrapperPass>();
129     AU.addPreserved<DXILResourceBindingWrapperPass>();
130     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
131     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
132   }
133 };
134 char DXILPostOptimizationValidationLegacy::ID = 0;
135 } // end anonymous namespace
136 
137 INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
138                       "DXIL Post Optimization Validation", false, false)
INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)139 INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
140 INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
141 INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
142 INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
143                     "DXIL Post Optimization Validation", false, false)
144 
145 ModulePass *llvm::createDXILPostOptimizationValidationLegacyPass() {
146   return new DXILPostOptimizationValidationLegacy();
147 }
148