1111#include " llvm/ADT/SmallString.h"
1212#include " llvm/ADT/StringRef.h"
1313#include " llvm/IR/Constants.h"
14- #include " llvm/IR/DebugLoc.h"
1514#include " llvm/IR/DerivedTypes.h"
1615#include " llvm/IR/DiagnosticInfo.h"
1716#include " llvm/IR/Instructions.h"
2221#include " llvm/InitializePasses.h"
2322#include " llvm/Support/FormatVariadic.h"
2423#include < algorithm>
25- #include < iterator>
2624
2725#define DEBUG_TYPE " dxil-resource"
2826
@@ -832,11 +830,6 @@ static bool isUpdateCounterIntrinsic(Function &F) {
832830}
833831
834832void DXILResourceCounterDirectionMap::populate (Module &M, DXILBindingMap &DBM) {
835- SmallVector<
836- std::tuple<const dxil::ResourceBindingInfo *, ResourceCounterDirection,
837- const Function *, const CallInst *>>
838- DiagCounterDirs;
839-
840833 for (Function &F : M.functions ()) {
841834 if (!isUpdateCounterIntrinsic (F))
842835 continue ;
@@ -863,82 +856,42 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
863856 SmallVector<const dxil::ResourceBindingInfo *> RBInfos =
864857 DBM.findByUse (HandleArg);
865858 for (const dxil::ResourceBindingInfo *RBInfo : RBInfos)
866- DiagCounterDirs .emplace_back (RBInfo, Direction, &F, CI );
859+ CounterDirections .emplace_back (RBInfo, Direction);
867860 }
868861 }
869862
870863 // Sort by the Binding and Direction for fast lookup
871- std::sort (DiagCounterDirs.begin (), DiagCounterDirs.end (),
872- [](const auto &LHS, const auto &RHS) {
873- const auto L =
874- std::pair{std::get<const dxil::ResourceBindingInfo *>(LHS),
875- std::get<ResourceCounterDirection>(LHS)};
876- const auto R =
877- std::pair{std::get<const dxil::ResourceBindingInfo *>(RHS),
878- std::get<ResourceCounterDirection>(RHS)};
879- return L < R;
880- });
864+ std::sort (CounterDirections.begin (), CounterDirections.end ());
881865
882- {
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- }
866+ // Remove the duplicate entries. Since direction is considered for equality
867+ // a unique resource with more than one direction will not be deduped.
868+ auto UniqueEnd =
869+ std::unique (CounterDirections.begin (), CounterDirections.end ());
904870
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) =
871+ // If any duplicate entries still exist at this point then it must be a
872+ // resource that was both incremented and decremented which is not allowed.
873+ // Mark all those entries as invalid.
874+ {
875+ auto DupFirst = CounterDirections.begin ();
876+ auto DupNext = DupFirst + 1 ;
877+ auto DupLast = UniqueEnd;
878+ for (; DupFirst < DupLast && DupNext < DupLast; ++DupFirst, ++DupNext) {
879+ if (std::get<const dxil::ResourceBindingInfo *>(*DupFirst) ==
880+ std::get<const dxil::ResourceBindingInfo *>(*DupNext)) {
881+ std::get<ResourceCounterDirection>(*DupFirst) =
882+ ResourceCounterDirection::Invalid;
883+ std::get<ResourceCounterDirection>(*DupNext) =
909884 ResourceCounterDirection::Invalid;
910-
911- StringRef Message =
912- " RWStructuredBuffers may increment or decrement their "
913- " counters, but not both." ;
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 ()));
918885 }
919-
920- SpanStart = SpanEnd;
921886 }
922887 }
923888
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
934- CounterDirections.clear ();
935- CounterDirections.reserve (UniqueEnd - DiagCounterDirs.begin ());
936- std::transform (DiagCounterDirs.begin (), UniqueEnd,
937- std::back_inserter (CounterDirections), [](const auto &Item) {
938- return std::pair{
939- std::get<const dxil::ResourceBindingInfo *>(Item),
940- std::get<ResourceCounterDirection>(Item)};
941- });
889+ // Remove the duplicate entries again now that each duplicate resource has the
890+ // same direction for each entry leaving one entry per RBI
891+ UniqueEnd = std::unique (CounterDirections.begin (), UniqueEnd);
892+
893+ // Actually erase the invalidated items
894+ CounterDirections.erase (UniqueEnd, CounterDirections.end ());
942895}
943896
944897ResourceCounterDirection DXILResourceCounterDirectionMap::operator [](
0 commit comments