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,121 @@ SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
879
883
880
884
// ===----------------------------------------------------------------------===//
881
885
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
+
882
998
AnalysisKey DXILResourceTypeAnalysis::Key;
883
999
AnalysisKey DXILResourceAnalysis::Key;
1000
+ AnalysisKey DXILResourceBindingAnalysis::Key;
884
1001
885
1002
DXILResourceMap DXILResourceAnalysis::run (Module &M,
886
1003
ModuleAnalysisManager &AM) {
@@ -890,6 +1007,14 @@ DXILResourceMap DXILResourceAnalysis::run(Module &M,
890
1007
return Data;
891
1008
}
892
1009
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
+
893
1018
PreservedAnalyses DXILResourcePrinterPass::run (Module &M,
894
1019
ModuleAnalysisManager &AM) {
895
1020
DXILResourceMap &DRM = AM.getResult <DXILResourceAnalysis>(M);
0 commit comments