@@ -879,58 +879,61 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
879879 return L < R;
880880 });
881881
882- // Remove the duplicate entries. Since direction is considered for equality
883- // a unique resource with more than one direction will not be deduped.
884- auto *const UniqueEnd = std::unique (
885- DiagCounterDirs.begin (), DiagCounterDirs.end (),
886- [](const auto &LHS, const auto &RHS) {
887- const auto L =
888- std::pair{std::get<const dxil::ResourceBindingInfo *>(LHS),
889- std::get<ResourceCounterDirection>(LHS)};
890- const auto R =
891- std::pair{std::get<const dxil::ResourceBindingInfo *>(RHS),
892- std::get<ResourceCounterDirection>(RHS)};
893- return L == R;
894- });
895-
896- // Actually erase the invalidated items
897- DiagCounterDirs.erase (UniqueEnd, DiagCounterDirs.end ());
898-
899- // If any duplicate entries still exist at this point then it must be a
900- // resource that was both incremented and decremented which is not allowed.
901- // Mark all those entries as invalid.
902882 {
903- auto *DupFirst = DiagCounterDirs.begin ();
904- auto *DupNext = DupFirst + 1 ;
905- auto *DupLast = DiagCounterDirs.end ();
906- for (; DupFirst < DupLast && DupNext < DupLast; ++DupFirst, ++DupNext) {
907- if (std::get<const dxil::ResourceBindingInfo *>(*DupFirst) ==
908- std::get<const dxil::ResourceBindingInfo *>(*DupNext)) {
909- std::get<ResourceCounterDirection>(*DupFirst) =
910- ResourceCounterDirection::Invalid;
911- std::get<ResourceCounterDirection>(*DupNext) =
883+ auto *SpanStart = DiagCounterDirs.begin ();
884+ auto *SpanEnd = SpanStart;
885+ auto *ItEnd = DiagCounterDirs.end ();
886+
887+ while (SpanStart < ItEnd) {
888+ while (SpanEnd < ItEnd &&
889+ std::get<const dxil::ResourceBindingInfo *>(*SpanStart) ==
890+ std::get<const dxil::ResourceBindingInfo *>(*SpanEnd))
891+ SpanEnd++;
892+
893+ // SpanStart : SpanEnd-1 are the same binding. Its an error if they aren't
894+ // all the same direction
895+ ResourceCounterDirection ResourceDir =
896+ std::get<ResourceCounterDirection>(*SpanStart);
897+ bool ValidUse = true ;
898+ for (auto *CheckIt = SpanStart; CheckIt < SpanEnd; ++CheckIt) {
899+ if (ResourceDir != std::get<ResourceCounterDirection>(*CheckIt)) {
900+ ValidUse = false ;
901+ break ;
902+ }
903+ }
904+
905+ // Update the direction and raise a diag when an invalid use is detected
906+ for (auto *RaiseIt = SpanStart; !ValidUse && RaiseIt < SpanEnd;
907+ ++RaiseIt) {
908+ std::get<ResourceCounterDirection>(*RaiseIt) =
912909 ResourceCounterDirection::Invalid;
913910
914- // Raise an error for every invalid entry
915911 StringRef Message =
916912 " RWStructuredBuffers may increment or decrement their "
917913 " counters, but not both." ;
918- const Function *FFirst = std::get<const Function *>(*DupFirst);
919- const CallInst *CIFirst = std::get<const CallInst *>(*DupFirst);
920- const Function *FNext = std::get<const Function *>(*DupNext);
921- const CallInst *CINext = std::get<const CallInst *>(*DupNext);
922- M.getContext ().diagnose (DiagnosticInfoGenericWithLoc (
923- Message, *FFirst, CIFirst->getDebugLoc ()));
924- M.getContext ().diagnose (DiagnosticInfoGenericWithLoc (
925- Message, *FNext, CINext->getDebugLoc ()));
914+ const Function *F = std::get<const Function *>(*RaiseIt);
915+ const CallInst *CI = std::get<const CallInst *>(*RaiseIt);
916+ M.getContext ().diagnose (
917+ DiagnosticInfoGenericWithLoc (Message, *F, CI->getDebugLoc ()));
926918 }
919+
920+ SpanStart = SpanEnd;
927921 }
928922 }
929923
930- // Copy the results into the final vec
924+ // Remove the duplicate entries. All entries with the same resource have the
925+ // same direction so it can be ignored.
926+ auto *const UniqueEnd =
927+ std::unique (DiagCounterDirs.begin (), DiagCounterDirs.end (),
928+ [](const auto &LHS, const auto &RHS) {
929+ return std::get<const dxil::ResourceBindingInfo *>(LHS) ==
930+ std::get<const dxil::ResourceBindingInfo *>(RHS);
931+ });
932+
933+ // Copy the results into the final location
931934 CounterDirections.clear ();
932- CounterDirections.reserve (DiagCounterDirs.size ());
933- std::transform (DiagCounterDirs.begin (), DiagCounterDirs. end () ,
935+ CounterDirections.reserve (UniqueEnd - DiagCounterDirs.begin ());
936+ std::transform (DiagCounterDirs.begin (), UniqueEnd ,
934937 std::back_inserter (CounterDirections), [](const auto &Item) {
935938 return std::pair{
936939 std::get<const dxil::ResourceBindingInfo *>(Item),
0 commit comments