@@ -335,27 +335,45 @@ bool ResourceInfo::operator==(const ResourceInfo &RHS) const {
335335 if (std::tie (Symbol, Name, Binding, RC, Kind) !=
336336 std::tie (RHS.Symbol , RHS.Name , RHS.Binding , RHS.RC , RHS.Kind ))
337337 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 )
343339 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 )
350351 return false ;
351-
352- if (isMultiSample ())
353- return MultiSample == RHS.MultiSample ;
354-
355- assert ((Kind == ResourceKind::RawBuffer) && " Unhandled resource kind" );
356352 return true ;
357353}
358354
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+
359377MDTuple *ResourceInfo::getAsMetadata (LLVMContext &Ctx) const {
360378 SmallVector<Metadata *, 11 > MDVals;
361379
@@ -534,18 +552,10 @@ namespace {
534552class ResourceMapper {
535553 Module &M;
536554 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;
544556
545557public:
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()) {}
549559
550560 void diagnoseHandle (CallInst *CI, const Twine &Msg,
551561 DiagnosticSeverity Severity = DS_Error) {
@@ -585,13 +595,11 @@ class ResourceMapper {
585595 // TODO: We don't actually keep track of the name right now...
586596 StringRef Name = " " ;
587597
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 ;
595603
596604 if (RI->isUAV ())
597605 // TODO: We need analysis for GloballyCoherent and HasCounter
@@ -658,27 +666,18 @@ class ResourceMapper {
658666 if (!RI)
659667 return nullptr ;
660668
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-
671669 uint32_t Space = cast<ConstantInt>(CI->getArgOperand (0 ))->getZExtValue ();
672670 uint32_t LowerBound =
673671 cast<ConstantInt>(CI->getArgOperand (1 ))->getZExtValue ();
674672 uint32_t Size = cast<ConstantInt>(CI->getArgOperand (2 ))->getZExtValue ();
675673
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);
677676
678677 return RI;
679678 }
680679
681- void mapResources () {
680+ DXILResourceMap mapResources () {
682681 for (Function &F : M.functions ()) {
683682 if (!F.isDeclaration ())
684683 continue ;
@@ -697,11 +696,68 @@ class ResourceMapper {
697696 break ;
698697 }
699698 }
699+
700+ return DXILResourceMap (std::move (Resources));
700701 }
701702};
702703
703704} // namespace
704705
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+
705761// ===----------------------------------------------------------------------===//
706762// DXILResourceAnalysis and DXILResourcePrinterPass
707763
@@ -710,24 +766,14 @@ AnalysisKey DXILResourceAnalysis::Key;
710766
711767DXILResourceMap DXILResourceAnalysis::run (Module &M,
712768 ModuleAnalysisManager &AM) {
713- DXILResourceMap Data;
714- ResourceMapper (M, Data).mapResources ();
769+ DXILResourceMap Data = ResourceMapper (M).mapResources ();
715770 return Data;
716771}
717772
718773PreservedAnalyses DXILResourcePrinterPass::run (Module &M,
719774 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);
731777 return PreservedAnalyses::all ();
732778}
733779
@@ -745,8 +791,7 @@ void DXILResourceWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
745791}
746792
747793bool DXILResourceWrapperPass::runOnModule (Module &M) {
748- ResourceMap.reset (new DXILResourceMap ());
749- ResourceMapper (M, *ResourceMap).mapResources ();
794+ ResourceMap.reset (new DXILResourceMap (ResourceMapper (M).mapResources ()));
750795 return false ;
751796}
752797
@@ -757,13 +802,7 @@ void DXILResourceWrapperPass::print(raw_ostream &OS, const Module *) const {
757802 OS << " No resource map has been built!\n " ;
758803 return ;
759804 }
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);
767806}
768807
769808#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0 commit comments