@@ -43,7 +43,7 @@ static void initializeUsedResources(InstrDesc &ID,
4343
4444 // Populate resources consumed.
4545 using ResourcePlusCycles = std::pair<uint64_t , ResourceUsage>;
46- std::vector <ResourcePlusCycles> Worklist;
46+ SmallVector <ResourcePlusCycles, 4 > Worklist;
4747
4848 // Track cycles contributed by resources that are in a "Super" relationship.
4949 // This is required if we want to correctly match the behavior of method
@@ -109,6 +109,11 @@ static void initializeUsedResources(InstrDesc &ID,
109109
110110 uint64_t UsedResourceUnits = 0 ;
111111 uint64_t UsedResourceGroups = 0 ;
112+ auto GroupIt = find_if (Worklist, [](const ResourcePlusCycles &Elt) {
113+ return countPopulation (Elt.first ) > 1 ;
114+ });
115+ unsigned FirstGroupIdx = std::distance (Worklist.begin (), GroupIt);
116+ uint64_t ImpliedUsesOfResourceUnits = 0 ;
112117
113118 // Remove cycles contributed by smaller resources.
114119 for (unsigned I = 0 , E = Worklist.size (); I < E; ++I) {
@@ -127,6 +132,15 @@ static void initializeUsedResources(InstrDesc &ID,
127132 // Remove the leading 1 from the resource group mask.
128133 NormalizedMask ^= PowerOf2Floor (NormalizedMask);
129134 UsedResourceGroups |= (A.first ^ NormalizedMask);
135+
136+ uint64_t AvailableMask = NormalizedMask & ~UsedResourceUnits;
137+ if ((NormalizedMask != AvailableMask) &&
138+ countPopulation (AvailableMask) == 1 ) {
139+ // At simulation time, this resource group use will decay into a simple
140+ // use of the resource unit identified by `AvailableMask`.
141+ ImpliedUsesOfResourceUnits |= AvailableMask;
142+ UsedResourceUnits |= AvailableMask;
143+ }
130144 }
131145
132146 for (unsigned J = I + 1 ; J < E; ++J) {
@@ -139,6 +153,31 @@ static void initializeUsedResources(InstrDesc &ID,
139153 }
140154 }
141155
156+ // Look for implicit uses of processor resource units. These are resource
157+ // units which are indirectly consumed by resource groups, and that must be
158+ // always available on instruction issue.
159+ while (ImpliedUsesOfResourceUnits) {
160+ ID.ImplicitlyUsedProcResUnits |= ImpliedUsesOfResourceUnits;
161+ ImpliedUsesOfResourceUnits = 0 ;
162+ for (unsigned I = FirstGroupIdx, E = Worklist.size (); I < E; ++I) {
163+ ResourcePlusCycles &A = Worklist[I];
164+ if (!A.second .size ())
165+ continue ;
166+
167+ uint64_t NormalizedMask = A.first ;
168+ assert (countPopulation (NormalizedMask) > 1 );
169+ // Remove the leading 1 from the resource group mask.
170+ NormalizedMask ^= PowerOf2Floor (NormalizedMask);
171+ uint64_t AvailableMask = NormalizedMask & ~UsedResourceUnits;
172+ if ((NormalizedMask != AvailableMask) &&
173+ countPopulation (AvailableMask) != 1 )
174+ continue ;
175+
176+ UsedResourceUnits |= AvailableMask;
177+ ImpliedUsesOfResourceUnits |= AvailableMask;
178+ }
179+ }
180+
142181 // A SchedWrite may specify a number of cycles in which a resource group
143182 // is reserved. For example (on target x86; cpu Haswell):
144183 //
@@ -198,6 +237,8 @@ static void initializeUsedResources(InstrDesc &ID,
198237 BufferIDs ^= Current;
199238 }
200239 dbgs () << " \t\t Used Units=" << format_hex (ID.UsedProcResUnits , 16 ) << ' \n ' ;
240+ dbgs () << " \t\t Implicitly Used Units="
241+ << format_hex (ID.ImplicitlyUsedProcResUnits , 16 ) << ' \n ' ;
201242 dbgs () << " \t\t Used Groups=" << format_hex (ID.UsedProcResGroups , 16 )
202243 << ' \n ' ;
203244 });
0 commit comments