88
99#include " llvm/Analysis/DXILResource.h"
1010#include " llvm/ADT/APInt.h"
11+ #include " llvm/ADT/STLExtras.h"
1112#include " llvm/ADT/SmallString.h"
13+ #include " llvm/ADT/SmallVector.h"
1214#include " llvm/IR/Constants.h"
1315#include " llvm/IR/DerivedTypes.h"
1416#include " llvm/IR/DiagnosticInfo.h"
1921#include " llvm/IR/Module.h"
2022#include " llvm/InitializePasses.h"
2123#include " llvm/Support/FormatVariadic.h"
24+ #include < climits>
25+ #include < cstdint>
2226
2327#define DEBUG_TYPE " dxil-resource"
2428
@@ -879,8 +883,121 @@ SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
879883
880884// ===----------------------------------------------------------------------===//
881885
886+ void DXILResourceBindingsInfo::populate (Module &M, DXILResourceTypeMap &DRTM) {
887+ struct Binding {
888+ ResourceClass ResClass;
889+ uint32_t Space;
890+ uint32_t LowerBound;
891+ uint32_t UpperBound;
892+ Binding (ResourceClass RC, uint32_t Sp, uint32_t LB, uint32_t UB)
893+ : ResClass(RC), Space(Sp), LowerBound(LB), UpperBound(UB) {}
894+ };
895+ SmallVector<Binding> Bindings;
896+
897+ // collect all of the llvm.dx.resource.handlefrombinding calls;
898+ // make a note if there is llvm.dx.resource.handlefromimplicitbinding
899+ for (Function &F : M.functions ()) {
900+ if (!F.isDeclaration ())
901+ continue ;
902+
903+ switch (F.getIntrinsicID ()) {
904+ default :
905+ continue ;
906+ case Intrinsic::dx_resource_handlefrombinding: {
907+ auto *HandleTy = cast<TargetExtType>(F.getReturnType ());
908+ ResourceTypeInfo &RTI = DRTM[HandleTy];
909+
910+ for (User *U : F.users ())
911+ if (CallInst *CI = dyn_cast<CallInst>(U)) {
912+ uint32_t Space =
913+ cast<ConstantInt>(CI->getArgOperand (0 ))->getZExtValue ();
914+ uint32_t LowerBound =
915+ cast<ConstantInt>(CI->getArgOperand (1 ))->getZExtValue ();
916+ int32_t Size =
917+ cast<ConstantInt>(CI->getArgOperand (2 ))->getZExtValue ();
918+
919+ // negative size means unbounded resource array;
920+ // upper bound register overflow should be detected in Sema
921+ assert ((Size < 0 || (unsigned )LowerBound + Size - 1 <= UINT32_MAX) &&
922+ " upper bound register overflow" );
923+ uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1 ;
924+ Bindings.emplace_back (RTI.getResourceClass (), Space, LowerBound,
925+ UpperBound);
926+ }
927+ break ;
928+ }
929+ case Intrinsic::dx_resource_handlefromimplicitbinding: {
930+ if (!F.user_empty ())
931+ ImplicitBinding = true ;
932+ break ;
933+ }
934+ }
935+ }
936+
937+ // sort all the collected bindings
938+ llvm::stable_sort (Bindings, [](auto &LHS, auto &RHS) {
939+ return std::tie (LHS.ResClass , LHS.Space , LHS.LowerBound ) <
940+ std::tie (RHS.ResClass , RHS.Space , RHS.LowerBound );
941+ });
942+
943+ // remove duplicates
944+ llvm::unique (Bindings, [](auto &LHS, auto &RHS) {
945+ return std::tie (LHS.ResClass , LHS.Space , LHS.LowerBound , LHS.UpperBound ) ==
946+ std::tie (RHS.ResClass , RHS.Space , RHS.LowerBound , RHS.UpperBound );
947+ });
948+
949+ // Go over the sorted bindings and build up lists of free register ranges
950+ // for each binding type and used spaces. Bindings are sorted by resource
951+ // class, space, and lower bound register slot.
952+ BindingSpaces *BS = &SRVSpaces;
953+ for (unsigned I = 0 , E = Bindings.size (); I != E; ++I) {
954+ Binding &B = Bindings[I];
955+
956+ if (BS->ResClass != B.ResClass )
957+ // move to the next resource class spaces
958+ BS = &getBindingSpaces (B.ResClass );
959+
960+ RegisterSpace *S = &BS->Spaces .back ();
961+ assert (S->Space <= B.Space && " bindings not sorted correctly?" );
962+ if (B.Space != S->Space )
963+ // add new space
964+ S = &BS->Spaces .emplace_back (B.Space );
965+
966+ // the space is full - set flag to report overlapping binding later
967+ if (S->FreeRanges .empty ()) {
968+ OverlappingBinding = true ;
969+ continue ;
970+ }
971+
972+ // adjust the last free range lower bound, split it in two, or remove it
973+ BindingRange &LastFreeRange = S->FreeRanges .back ();
974+ assert (LastFreeRange.UpperBound == UINT32_MAX);
975+ if (LastFreeRange.LowerBound == B.LowerBound ) {
976+ if (B.UpperBound < UINT32_MAX)
977+ LastFreeRange.LowerBound = B.UpperBound + 1 ;
978+ else
979+ S->FreeRanges .pop_back ();
980+
981+ } else if (LastFreeRange.LowerBound < B.LowerBound ) {
982+ LastFreeRange.UpperBound = B.LowerBound - 1 ;
983+ if (B.UpperBound < UINT32_MAX)
984+ S->FreeRanges .emplace_back (B.UpperBound + 1 , UINT32_MAX);
985+ } else {
986+ OverlappingBinding = true ;
987+ if (B.UpperBound < UINT32_MAX)
988+ LastFreeRange.LowerBound =
989+ std::max (LastFreeRange.LowerBound , B.UpperBound + 1 );
990+ else
991+ S->FreeRanges .pop_back ();
992+ }
993+ }
994+ }
995+
996+ // ===----------------------------------------------------------------------===//
997+
882998AnalysisKey DXILResourceTypeAnalysis::Key;
883999AnalysisKey DXILResourceAnalysis::Key;
1000+ AnalysisKey DXILResourceBindingAnalysis::Key;
8841001
8851002DXILResourceMap DXILResourceAnalysis::run (Module &M,
8861003 ModuleAnalysisManager &AM) {
@@ -890,6 +1007,14 @@ DXILResourceMap DXILResourceAnalysis::run(Module &M,
8901007 return Data;
8911008}
8921009
1010+ DXILResourceBindingsInfo
1011+ DXILResourceBindingAnalysis::run (Module &M, ModuleAnalysisManager &AM) {
1012+ DXILResourceBindingsInfo Data;
1013+ DXILResourceTypeMap &DRTM = AM.getResult <DXILResourceTypeAnalysis>(M);
1014+ Data.populate (M, DRTM);
1015+ return Data;
1016+ }
1017+
8931018PreservedAnalyses DXILResourcePrinterPass::run (Module &M,
8941019 ModuleAnalysisManager &AM) {
8951020 DXILResourceMap &DRM = AM.getResult <DXILResourceAnalysis>(M);
0 commit comments