1111#include " llvm/ADT/SmallString.h"
1212#include " llvm/ADT/StringRef.h"
1313#include " llvm/IR/Constants.h"
14+ #include " llvm/IR/DebugLoc.h"
1415#include " llvm/IR/DerivedTypes.h"
1516#include " llvm/IR/DiagnosticInfo.h"
1617#include " llvm/IR/Instructions.h"
2122#include " llvm/InitializePasses.h"
2223#include " llvm/Support/FormatVariadic.h"
2324#include < algorithm>
25+ #include < iterator>
2426
2527#define DEBUG_TYPE " dxil-resource"
2628
@@ -830,7 +832,8 @@ static bool isUpdateCounterIntrinsic(Function &F) {
830832}
831833
832834void DXILResourceCounterDirectionMap::populate (Module &M, DXILBindingMap &DBM) {
833- CounterDirections.clear ();
835+ std::vector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection, const Function*, const CallInst*>>
836+ DiagCounterDirs;
834837
835838 for (Function &F : M.functions ()) {
836839 if (!isUpdateCounterIntrinsic (F))
@@ -855,39 +858,59 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
855858 Value *HandleArg = CI->getArgOperand (0 );
856859 SmallVector<dxil::ResourceBindingInfo> RBInfos = DBM.findByUse (HandleArg);
857860 for (const dxil::ResourceBindingInfo RBInfo : RBInfos)
858- CounterDirections .emplace_back (RBInfo, Direction);
861+ DiagCounterDirs .emplace_back (RBInfo, Direction, &F, CI );
859862 }
860863 }
861864
862865 // An entry that is not in the map is considered unknown so its wasted
863866 // overhead and increased complexity to keep an entry explicitly marked
864867 // unknown
865868 const auto RemoveEnd = std::remove_if (
866- CounterDirections .begin (), CounterDirections .end (), [](const auto &Item) {
867- return Item. second == ResourceCounterDirection::Unknown;
869+ DiagCounterDirs .begin (), DiagCounterDirs .end (), [](const auto &Item) {
870+ return std::get<ResourceCounterDirection>( Item) == ResourceCounterDirection::Unknown;
868871 });
869872
870- // Order for fast lookup
871- std::sort (CounterDirections.begin (), RemoveEnd);
873+ // Sort by the Binding and Direction for fast lookup
874+ std::sort (DiagCounterDirs.begin (), RemoveEnd, [](const auto &LHS, const auto &RHS) {
875+ const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS), std::get<ResourceCounterDirection>(LHS)};
876+ const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS), std::get<ResourceCounterDirection>(RHS)};
877+ return L < R;
878+ });
872879
873880 // Remove the duplicate entries. Since direction is considered for equality
874881 // a unique resource with more than one direction will not be deduped.
875- const auto UniqueEnd = std::unique (CounterDirections.begin (), RemoveEnd);
882+ const auto UniqueEnd = std::unique (DiagCounterDirs.begin (), RemoveEnd, [](const auto &LHS, const auto &RHS) {
883+ const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS), std::get<ResourceCounterDirection>(LHS)};
884+ const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS), std::get<ResourceCounterDirection>(RHS)};
885+ return L == R;
886+ });
876887
877888 // Actually erase the items invalidated by remove_if + unique
878- CounterDirections .erase (UniqueEnd, CounterDirections .end ());
889+ DiagCounterDirs .erase (UniqueEnd, DiagCounterDirs .end ());
879890
880891 // If any duplicate entries still exist at this point then it must be a
881892 // resource that was both incremented and decremented which is not allowed.
882893 const auto DuplicateEntry = std::adjacent_find (
883- CounterDirections.begin (), CounterDirections.end (),
884- [](const auto &LHS, const auto &RHS) { return LHS.first == RHS.first ; });
885- if (DuplicateEntry == CounterDirections.end ())
894+ DiagCounterDirs.begin (), DiagCounterDirs.end (),
895+ [](const auto &LHS, const auto &RHS) {
896+ return std::get<dxil::ResourceBindingInfo>(LHS) == std::get<dxil::ResourceBindingInfo>(RHS);
897+ });
898+
899+ // Copy the results into the final vec
900+ CounterDirections.clear ();
901+ CounterDirections.reserve (DiagCounterDirs.size ());
902+ std::transform (DiagCounterDirs.begin (), DiagCounterDirs.end (), std::back_inserter (CounterDirections), [](const auto &Item){
903+ return std::pair{std::get<dxil::ResourceBindingInfo>(Item), std::get<ResourceCounterDirection>(Item)};
904+ });
905+
906+ if (DuplicateEntry == DiagCounterDirs.end ())
886907 return ;
887908
909+ const Function* F = std::get<const Function*>(*DuplicateEntry);
910+ const CallInst* CI = std::get<const CallInst*>(*DuplicateEntry);
888911 StringRef Message = " RWStructuredBuffers may increment or decrement their "
889912 " counters, but not both." ;
890- M.getContext ().diagnose (DiagnosticInfoGeneric (Message));
913+ M.getContext ().diagnose (DiagnosticInfoGenericWithLoc (Message, *F, CI-> getDebugLoc () ));
891914}
892915
893916void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage (
0 commit comments