@@ -335,27 +335,45 @@ bool ResourceInfo::operator==(const ResourceInfo &RHS) const {
335
335
if (std::tie (Symbol, Name, Binding, RC, Kind) !=
336
336
std::tie (RHS.Symbol , RHS.Name , RHS.Binding , RHS.RC , RHS.Kind ))
337
337
return false ;
338
- if (isCBuffer ())
339
- return CBufferSize == RHS.CBufferSize ;
340
- if (isSampler ())
341
- return SamplerTy == RHS.SamplerTy ;
342
- if (isUAV () && UAVFlags != RHS.UAVFlags )
338
+ if (isCBuffer () && RHS.isCBuffer () && CBufferSize != RHS.CBufferSize )
343
339
return false ;
344
-
345
- if (isStruct ())
346
- return Struct == RHS.Struct ;
347
- if (isFeedback ())
348
- return Feedback == RHS.Feedback ;
349
- if (isTyped () && Typed != RHS.Typed )
340
+ if (isSampler () && RHS.isSampler () && SamplerTy != RHS.SamplerTy )
341
+ return false ;
342
+ if (isUAV () && RHS.isUAV () && UAVFlags != RHS.UAVFlags )
343
+ return false ;
344
+ if (isStruct () && RHS.isStruct () && Struct != RHS.Struct )
345
+ return false ;
346
+ if (isFeedback () && RHS.isFeedback () && Feedback != RHS.Feedback )
347
+ return false ;
348
+ if (isTyped () && RHS.isTyped () && Typed != RHS.Typed )
349
+ return false ;
350
+ if (isMultiSample () && RHS.isMultiSample () && MultiSample != RHS.MultiSample )
350
351
return false ;
351
-
352
- if (isMultiSample ())
353
- return MultiSample == RHS.MultiSample ;
354
-
355
- assert ((Kind == ResourceKind::RawBuffer) && " Unhandled resource kind" );
356
352
return true ;
357
353
}
358
354
355
+ bool ResourceInfo::operator <(const ResourceInfo &RHS) const {
356
+ // Skip the symbol to avoid non-determinism, and the name to keep a consistent
357
+ // ordering even when we strip reflection data.
358
+ if (std::tie (Binding, RC, Kind) < std::tie (RHS.Binding , RHS.RC , RHS.Kind ))
359
+ return true ;
360
+ if (isCBuffer () && RHS.isCBuffer () && CBufferSize < RHS.CBufferSize )
361
+ return true ;
362
+ if (isSampler () && RHS.isSampler () && SamplerTy < RHS.SamplerTy )
363
+ return true ;
364
+ if (isUAV () && RHS.isUAV () && UAVFlags < RHS.UAVFlags )
365
+ return true ;
366
+ if (isStruct () && RHS.isStruct () && Struct < RHS.Struct )
367
+ return true ;
368
+ if (isFeedback () && RHS.isFeedback () && Feedback < RHS.Feedback )
369
+ return true ;
370
+ if (isTyped () && RHS.isTyped () && Typed < RHS.Typed )
371
+ return true ;
372
+ if (isMultiSample () && RHS.isMultiSample () && MultiSample < RHS.MultiSample )
373
+ return true ;
374
+ return false ;
375
+ }
376
+
359
377
MDTuple *ResourceInfo::getAsMetadata (LLVMContext &Ctx) const {
360
378
SmallVector<Metadata *, 11 > MDVals;
361
379
@@ -534,18 +552,10 @@ namespace {
534
552
class ResourceMapper {
535
553
Module &M;
536
554
LLVMContext &Context;
537
- DXILResourceMap &Resources;
538
-
539
- // In DXC, Record ID is unique per resource type. Match that.
540
- uint32_t NextUAV = 0 ;
541
- uint32_t NextSRV = 0 ;
542
- uint32_t NextCBuf = 0 ;
543
- uint32_t NextSmp = 0 ;
555
+ SmallVector<std::pair<CallInst *, dxil::ResourceInfo>> Resources;
544
556
545
557
public:
546
- ResourceMapper (Module &M,
547
- MapVector<CallInst *, dxil::ResourceInfo> &Resources)
548
- : M(M), Context(M.getContext()), Resources(Resources) {}
558
+ ResourceMapper (Module &M) : M(M), Context(M.getContext()) {}
549
559
550
560
void diagnoseHandle (CallInst *CI, const Twine &Msg,
551
561
DiagnosticSeverity Severity = DS_Error) {
@@ -585,13 +595,11 @@ class ResourceMapper {
585
595
// TODO: We don't actually keep track of the name right now...
586
596
StringRef Name = " " ;
587
597
588
- auto [It, Success] = Resources.try_emplace (CI, RC, Kind, Symbol, Name);
589
- assert (Success && " Mapping the same CallInst again?" );
590
- (void )Success;
591
- // We grab a pointer into the map's storage, which isn't generally safe.
592
- // Since we're just using this to fill in the info the map won't mutate and
593
- // the pointer stays valid for as long as we need it to.
594
- ResourceInfo *RI = &(It->second );
598
+ // Note that we return a pointer into the vector's storage. This is okay as
599
+ // long as we don't add more elements until we're done with the pointer.
600
+ auto &Pair =
601
+ Resources.emplace_back (CI, ResourceInfo{RC, Kind, Symbol, Name});
602
+ ResourceInfo *RI = &Pair.second ;
595
603
596
604
if (RI->isUAV ())
597
605
// TODO: We need analysis for GloballyCoherent and HasCounter
@@ -658,27 +666,18 @@ class ResourceMapper {
658
666
if (!RI)
659
667
return nullptr ;
660
668
661
- uint32_t NextID;
662
- if (RI->isCBuffer ())
663
- NextID = NextCBuf++;
664
- else if (RI->isSampler ())
665
- NextID = NextSmp++;
666
- else if (RI->isUAV ())
667
- NextID = NextUAV++;
668
- else
669
- NextID = NextSRV++;
670
-
671
669
uint32_t Space = cast<ConstantInt>(CI->getArgOperand (0 ))->getZExtValue ();
672
670
uint32_t LowerBound =
673
671
cast<ConstantInt>(CI->getArgOperand (1 ))->getZExtValue ();
674
672
uint32_t Size = cast<ConstantInt>(CI->getArgOperand (2 ))->getZExtValue ();
675
673
676
- RI->bind (NextID, Space, LowerBound, Size);
674
+ // We use a binding ID of zero for now - these will be filled in later.
675
+ RI->bind (0U , Space, LowerBound, Size);
677
676
678
677
return RI;
679
678
}
680
679
681
- void mapResources () {
680
+ DXILResourceMap mapResources () {
682
681
for (Function &F : M.functions ()) {
683
682
if (!F.isDeclaration ())
684
683
continue ;
@@ -697,11 +696,68 @@ class ResourceMapper {
697
696
break ;
698
697
}
699
698
}
699
+
700
+ return DXILResourceMap (std::move (Resources));
700
701
}
701
702
};
702
703
703
704
} // namespace
704
705
706
+ DXILResourceMap::DXILResourceMap (
707
+ SmallVectorImpl<std::pair<CallInst *, dxil::ResourceInfo>> &&CIToRI) {
708
+ if (CIToRI.empty ())
709
+ return ;
710
+
711
+ llvm::stable_sort (CIToRI, [](auto &LHS, auto &RHS) {
712
+ // Sort by resource class first for grouping purposes, and then by the rest
713
+ // of the fields so that we can remove duplicates.
714
+ ResourceClass LRC = LHS.second .getResourceClass ();
715
+ ResourceClass RRC = RHS.second .getResourceClass ();
716
+ return std::tie (LRC, LHS.second ) < std::tie (RRC, RHS.second );
717
+ });
718
+ for (auto [CI, RI] : CIToRI) {
719
+ if (Resources.empty () || RI != Resources.back ())
720
+ Resources.push_back (RI);
721
+ CallMap[CI] = Resources.size () - 1 ;
722
+ }
723
+
724
+ unsigned Size = Resources.size ();
725
+ // In DXC, Record ID is unique per resource type. Match that.
726
+ FirstUAV = FirstCBuffer = FirstSampler = Size;
727
+ uint32_t NextID = 0 ;
728
+ for (unsigned I = 0 , E = Size; I != E; ++I) {
729
+ ResourceInfo &RI = Resources[I];
730
+ if (RI.isUAV () && FirstUAV == Size) {
731
+ FirstUAV = I;
732
+ NextID = 0 ;
733
+ } else if (RI.isCBuffer () && FirstCBuffer == Size) {
734
+ FirstCBuffer = I;
735
+ NextID = 0 ;
736
+ } else if (RI.isSampler () && FirstSampler == Size) {
737
+ FirstSampler = I;
738
+ NextID = 0 ;
739
+ }
740
+
741
+ // Adjust the resource binding to use the next ID.
742
+ const ResourceInfo::ResourceBinding &Binding = RI.getBinding ();
743
+ RI.bind (NextID++, Binding.Space , Binding.LowerBound , Binding.Size );
744
+ }
745
+ }
746
+
747
+ void DXILResourceMap::print (raw_ostream &OS) const {
748
+ for (unsigned I = 0 , E = Resources.size (); I != E; ++I) {
749
+ OS << " Binding " << I << " :\n " ;
750
+ Resources[I].print (OS);
751
+ OS << " \n " ;
752
+ }
753
+
754
+ for (const auto &[CI, Index] : CallMap) {
755
+ OS << " Call bound to " << Index << " :" ;
756
+ CI->print (OS);
757
+ OS << " \n " ;
758
+ }
759
+ }
760
+
705
761
// ===----------------------------------------------------------------------===//
706
762
// DXILResourceAnalysis and DXILResourcePrinterPass
707
763
@@ -710,24 +766,14 @@ AnalysisKey DXILResourceAnalysis::Key;
710
766
711
767
DXILResourceMap DXILResourceAnalysis::run (Module &M,
712
768
ModuleAnalysisManager &AM) {
713
- DXILResourceMap Data;
714
- ResourceMapper (M, Data).mapResources ();
769
+ DXILResourceMap Data = ResourceMapper (M).mapResources ();
715
770
return Data;
716
771
}
717
772
718
773
PreservedAnalyses DXILResourcePrinterPass::run (Module &M,
719
774
ModuleAnalysisManager &AM) {
720
- DXILResourceMap &Data =
721
- AM.getResult <DXILResourceAnalysis>(M);
722
-
723
- for (const auto &[Handle, Info] : Data) {
724
- OS << " Binding for " ;
725
- Handle->print (OS);
726
- OS << " \n " ;
727
- Info.print (OS);
728
- OS << " \n " ;
729
- }
730
-
775
+ DXILResourceMap &DRM = AM.getResult <DXILResourceAnalysis>(M);
776
+ DRM.print (OS);
731
777
return PreservedAnalyses::all ();
732
778
}
733
779
@@ -745,8 +791,7 @@ void DXILResourceWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
745
791
}
746
792
747
793
bool DXILResourceWrapperPass::runOnModule (Module &M) {
748
- ResourceMap.reset (new DXILResourceMap ());
749
- ResourceMapper (M, *ResourceMap).mapResources ();
794
+ ResourceMap.reset (new DXILResourceMap (ResourceMapper (M).mapResources ()));
750
795
return false ;
751
796
}
752
797
@@ -757,13 +802,7 @@ void DXILResourceWrapperPass::print(raw_ostream &OS, const Module *) const {
757
802
OS << " No resource map has been built!\n " ;
758
803
return ;
759
804
}
760
- for (const auto &[Handle, Info] : *ResourceMap) {
761
- OS << " Binding for " ;
762
- Handle->print (OS);
763
- OS << " \n " ;
764
- Info.print (OS);
765
- OS << " \n " ;
766
- }
805
+ ResourceMap->print (OS);
767
806
}
768
807
769
808
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0 commit comments