8
8
9
9
#include " llvm/Analysis/DXILResource.h"
10
10
#include " llvm/ADT/APInt.h"
11
+ #include " llvm/ADT/STLExtras.h"
11
12
#include " llvm/ADT/SmallString.h"
13
+ #include " llvm/ADT/SmallVector.h"
12
14
#include " llvm/IR/Constants.h"
13
15
#include " llvm/IR/DerivedTypes.h"
14
16
#include " llvm/IR/DiagnosticInfo.h"
19
21
#include " llvm/IR/Module.h"
20
22
#include " llvm/InitializePasses.h"
21
23
#include " llvm/Support/FormatVariadic.h"
24
+ #include < climits>
25
+ #include < cstdint>
22
26
23
27
#define DEBUG_TYPE " dxil-resource"
24
28
@@ -879,8 +883,126 @@ SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
879
883
880
884
// ===----------------------------------------------------------------------===//
881
885
886
+ void DXILResourceBindingInfo::populate (Module &M, DXILResourceTypeMap &DRTM) {
887
+ struct Binding {
888
+ ResourceClass RC;
889
+ uint32_t Space;
890
+ uint32_t LowerBound;
891
+ uint32_t UpperBound;
892
+ Binding (ResourceClass RC, uint32_t Space, uint32_t LowerBound,
893
+ uint32_t UpperBound)
894
+ : RC(RC), Space(Space), LowerBound(LowerBound), UpperBound(UpperBound) {
895
+ }
896
+ };
897
+ SmallVector<Binding> Bindings;
898
+
899
+ // collect all of the llvm.dx.resource.handlefrombinding calls;
900
+ // make a note if there is llvm.dx.resource.handlefromimplicitbinding
901
+ for (Function &F : M.functions ()) {
902
+ if (!F.isDeclaration ())
903
+ continue ;
904
+
905
+ switch (F.getIntrinsicID ()) {
906
+ default :
907
+ continue ;
908
+ case Intrinsic::dx_resource_handlefrombinding: {
909
+ auto *HandleTy = cast<TargetExtType>(F.getReturnType ());
910
+ ResourceTypeInfo &RTI = DRTM[HandleTy];
911
+
912
+ for (User *U : F.users ())
913
+ if (CallInst *CI = dyn_cast<CallInst>(U)) {
914
+ uint32_t Space =
915
+ cast<ConstantInt>(CI->getArgOperand (0 ))->getZExtValue ();
916
+ uint32_t LowerBound =
917
+ cast<ConstantInt>(CI->getArgOperand (1 ))->getZExtValue ();
918
+ int32_t Size =
919
+ cast<ConstantInt>(CI->getArgOperand (2 ))->getZExtValue ();
920
+
921
+ // negative size means unbounded resource array;
922
+ // upper bound register overflow should be detected in Sema
923
+ assert ((Size < 0 || (unsigned )LowerBound + Size - 1 <= UINT32_MAX) &&
924
+ " upper bound register overflow" );
925
+ uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1 ;
926
+ Bindings.emplace_back (RTI.getResourceClass (), Space, LowerBound,
927
+ UpperBound);
928
+ }
929
+ break ;
930
+ }
931
+ case Intrinsic::dx_resource_handlefromimplicitbinding: {
932
+ ImplicitBinding = true ;
933
+ break ;
934
+ }
935
+ }
936
+ }
937
+
938
+ // sort all the collected bindings
939
+ llvm::stable_sort (Bindings, [](auto &LHS, auto &RHS) {
940
+ return std::tie (LHS.RC , LHS.Space , LHS.LowerBound ) <
941
+ std::tie (RHS.RC , RHS.Space , RHS.LowerBound );
942
+ });
943
+
944
+ // remove duplicates
945
+ Binding *NewEnd = llvm::unique (Bindings, [](auto &LHS, auto &RHS) {
946
+ return std::tie (LHS.RC , LHS.Space , LHS.LowerBound , LHS.UpperBound ) ==
947
+ std::tie (RHS.RC , RHS.Space , RHS.LowerBound , RHS.UpperBound );
948
+ });
949
+ if (NewEnd != Bindings.end ())
950
+ Bindings.erase (NewEnd);
951
+
952
+ // Go over the sorted bindings and build up lists of free register ranges
953
+ // for each binding type and used spaces. Bindings are sorted by resource
954
+ // class, space, and lower bound register slot.
955
+ BindingSpaces *BS = &SRVSpaces;
956
+ for (unsigned I = 0 , E = Bindings.size (); I != E; ++I) {
957
+ Binding &B = Bindings[I];
958
+
959
+ if (BS->RC != B.RC )
960
+ // move to the next resource class spaces
961
+ BS = &getBindingSpaces (B.RC );
962
+
963
+ RegisterSpace *S = BS->Spaces .empty () ? &BS->Spaces .emplace_back (B.Space )
964
+ : &BS->Spaces .back ();
965
+ assert (S->Space <= B.Space && " bindings not sorted correctly?" );
966
+ if (B.Space != S->Space )
967
+ // add new space
968
+ S = &BS->Spaces .emplace_back (B.Space );
969
+
970
+ // the space is full - set flag to report overlapping binding later
971
+ if (S->FreeRanges .empty ()) {
972
+ OverlappingBinding = true ;
973
+ continue ;
974
+ }
975
+
976
+ // adjust the last free range lower bound, split it in two, or remove it
977
+ BindingRange &LastFreeRange = S->FreeRanges .back ();
978
+ assert (LastFreeRange.UpperBound == UINT32_MAX);
979
+ if (LastFreeRange.LowerBound == B.LowerBound ) {
980
+ if (B.UpperBound < UINT32_MAX)
981
+ LastFreeRange.LowerBound = B.UpperBound + 1 ;
982
+ else
983
+ S->FreeRanges .pop_back ();
984
+ } else if (LastFreeRange.LowerBound < B.LowerBound ) {
985
+ LastFreeRange.UpperBound = B.LowerBound - 1 ;
986
+ if (B.UpperBound < UINT32_MAX)
987
+ S->FreeRanges .emplace_back (B.UpperBound + 1 , UINT32_MAX);
988
+ } else {
989
+ // FIXME: This only detects overlapping bindings that are not an exact
990
+ // match (llvm/llvm-project#110723)
991
+ OverlappingBinding = true ;
992
+ if (B.UpperBound < UINT32_MAX)
993
+ LastFreeRange.LowerBound =
994
+ std::max (LastFreeRange.LowerBound , B.UpperBound + 1 );
995
+ else
996
+ S->FreeRanges .pop_back ();
997
+ }
998
+ }
999
+ }
1000
+
1001
+ // ===----------------------------------------------------------------------===//
1002
+
882
1003
AnalysisKey DXILResourceTypeAnalysis::Key;
883
1004
AnalysisKey DXILResourceAnalysis::Key;
1005
+ AnalysisKey DXILResourceBindingAnalysis::Key;
884
1006
885
1007
DXILResourceMap DXILResourceAnalysis::run (Module &M,
886
1008
ModuleAnalysisManager &AM) {
@@ -890,6 +1012,14 @@ DXILResourceMap DXILResourceAnalysis::run(Module &M,
890
1012
return Data;
891
1013
}
892
1014
1015
+ DXILResourceBindingInfo
1016
+ DXILResourceBindingAnalysis::run (Module &M, ModuleAnalysisManager &AM) {
1017
+ DXILResourceBindingInfo Data;
1018
+ DXILResourceTypeMap &DRTM = AM.getResult <DXILResourceTypeAnalysis>(M);
1019
+ Data.populate (M, DRTM);
1020
+ return Data;
1021
+ }
1022
+
893
1023
PreservedAnalyses DXILResourcePrinterPass::run (Module &M,
894
1024
ModuleAnalysisManager &AM) {
895
1025
DXILResourceMap &DRM = AM.getResult <DXILResourceAnalysis>(M);
@@ -952,3 +1082,33 @@ char DXILResourceWrapperPass::ID = 0;
952
1082
ModulePass *llvm::createDXILResourceWrapperPassPass () {
953
1083
return new DXILResourceWrapperPass ();
954
1084
}
1085
+
1086
+ DXILResourceBindingWrapperPass::DXILResourceBindingWrapperPass ()
1087
+ : ModulePass(ID) {}
1088
+
1089
+ DXILResourceBindingWrapperPass::~DXILResourceBindingWrapperPass () = default ;
1090
+
1091
+ void DXILResourceBindingWrapperPass::getAnalysisUsage (AnalysisUsage &AU) const {
1092
+ AU.addRequiredTransitive <DXILResourceTypeWrapperPass>();
1093
+ AU.setPreservesAll ();
1094
+ }
1095
+
1096
+ bool DXILResourceBindingWrapperPass::runOnModule (Module &M) {
1097
+ BindingInfo.reset (new DXILResourceBindingInfo ());
1098
+
1099
+ DXILResourceTypeMap &DRTM =
1100
+ getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap ();
1101
+ BindingInfo->populate (M, DRTM);
1102
+
1103
+ return false ;
1104
+ }
1105
+
1106
+ void DXILResourceBindingWrapperPass::releaseMemory () { BindingInfo.reset (); }
1107
+
1108
+ INITIALIZE_PASS (DXILResourceBindingWrapperPass, " dxil-resource-binding" ,
1109
+ " DXIL Resource Binding Analysis" , false , true )
1110
+ char DXILResourceBindingWrapperPass::ID = 0;
1111
+
1112
+ ModulePass *llvm::createDXILResourceBindingWrapperPassPass () {
1113
+ return new DXILResourceWrapperPass ();
1114
+ }
0 commit comments