3333// permutations, fall back to keeping the types distinct by adding distinct
3434// brand types to the recursion groups to ensure they have different shapes.
3535//
36- // There are several possible algorithmic design for detecting when to generate
36+ // There are several possible algorithmic designs for detecting when to generate
3737// permutations and determining what permutations to generate. They trade off
3838// the amount of "wasted" work spent generating shapes that have already been
3939// used with the amount of work spent trying to avoid the wasted work and with
@@ -161,23 +161,30 @@ struct BrandTypeIterator {
161161 }
162162};
163163
164- // Create an adjacency list with edges from supertype to subtypes.
164+ // Create an adjacency list with edges from supertype to subtype and from
165+ // described type to descriptor.
165166std::vector<std::vector<Index>>
166- createSubtypeGraph (const std::vector<HeapType>& types) {
167+ createTypeOrderGraph (const std::vector<HeapType>& types) {
167168 std::unordered_map<HeapType, Index> indices;
168169 for (auto type : types) {
169170 indices.insert ({type, indices.size ()});
170171 }
171172
172- std::vector<std::vector<Index>> subtypeGraph (types.size ());
173+ std::vector<std::vector<Index>> typeOrderGraph (types.size ());
173174 for (Index i = 0 ; i < types.size (); ++i) {
174175 if (auto super = types[i].getDeclaredSuperType ()) {
175176 if (auto it = indices.find (*super); it != indices.end ()) {
176- subtypeGraph [it->second ].push_back (i);
177+ typeOrderGraph [it->second ].push_back (i);
177178 }
178179 }
180+ if (auto desc = types[i].getDescribedType ()) {
181+ // Described types must be in the same SCC / rec group.
182+ auto it = indices.find (*desc);
183+ assert (it != indices.end ());
184+ typeOrderGraph[it->second ].push_back (i);
185+ }
179186 }
180- return subtypeGraph ;
187+ return typeOrderGraph ;
181188}
182189
183190struct RecGroupInfo ;
@@ -199,13 +206,13 @@ struct GroupClassInfo {
199206 // group, offset by 1 iff there is a brand type. Used to ensure that we only
200207 // find emit permutations that respect the constraint that supertypes must be
201208 // ordered before subtypes.
202- std::vector<std::vector<Index>> subtypeGraph ;
209+ std::vector<std::vector<Index>> typeOrderGraph ;
203210 // A generator of valid permutations of the components in this class.
204211 TopologicalOrders orders;
205212
206- // Initialize `subtypeGraph ` and `orders` based on the canonical ordering
213+ // Initialize `typeOrderGraph ` and `orders` based on the canonical ordering
207214 // encoded by the group and permutation in `info`.
208- static std::vector<std::vector<Index>> initSubtypeGraph (RecGroupInfo& info);
215+ static std::vector<std::vector<Index>> initTypeOrderGraph (RecGroupInfo& info);
209216 GroupClassInfo (RecGroupInfo& info);
210217
211218 void advance (FeatureSet features) {
@@ -222,10 +229,10 @@ struct GroupClassInfo {
222229 brand.emplace ();
223230 // Make room in the subtype graph for the brand type, which goes at the
224231 // beginning of the canonical order.
225- subtypeGraph .insert (subtypeGraph .begin (), {{}});
232+ typeOrderGraph .insert (typeOrderGraph .begin (), {{}});
226233 // Adjust indices.
227- for (Index i = 1 ; i < subtypeGraph .size (); ++i) {
228- for (auto & edge : subtypeGraph [i]) {
234+ for (Index i = 1 ; i < typeOrderGraph .size (); ++i) {
235+ for (auto & edge : typeOrderGraph [i]) {
229236 ++edge;
230237 }
231238 }
@@ -237,7 +244,7 @@ struct GroupClassInfo {
237244 }
238245 // Start back at the initial permutation with the new brand.
239246 orders.~TopologicalOrders ();
240- new (&orders) TopologicalOrders (subtypeGraph );
247+ new (&orders) TopologicalOrders (typeOrderGraph );
241248 }
242249
243250 // Permute the types in the given group to match the current configuration in
@@ -266,7 +273,7 @@ struct RecGroupInfo {
266273};
267274
268275std::vector<std::vector<Index>>
269- GroupClassInfo::initSubtypeGraph (RecGroupInfo& info) {
276+ GroupClassInfo::initTypeOrderGraph (RecGroupInfo& info) {
270277 assert (!info.classInfo );
271278 assert (info.permutation .size () == info.group .size ());
272279
@@ -275,19 +282,19 @@ GroupClassInfo::initSubtypeGraph(RecGroupInfo& info) {
275282 canonical[info.permutation [i]] = info.group [i];
276283 }
277284
278- return createSubtypeGraph (canonical);
285+ return createTypeOrderGraph (canonical);
279286}
280287
281288GroupClassInfo::GroupClassInfo (RecGroupInfo& info)
282289 : singletonType(info.group.size() == 1
283290 ? std::optional<HeapType>(info.group[0 ])
284291 : std::nullopt),
285- brand(std::nullopt ), subtypeGraph(initSubtypeGraph (info)),
286- orders(subtypeGraph ) {}
292+ brand(std::nullopt ), typeOrderGraph(initTypeOrderGraph (info)),
293+ orders(typeOrderGraph ) {}
287294
288295void GroupClassInfo::permute (RecGroupInfo& info) {
289296 assert (info.group .size () == info.permutation .size ());
290- bool insertingBrand = info.group .size () < subtypeGraph .size ();
297+ bool insertingBrand = info.group .size () < typeOrderGraph .size ();
291298 // First, un-permute the group to get back to the canonical order, offset by 1
292299 // if we are newly inserting a brand.
293300 std::vector<HeapType> canonical (info.group .size () + insertingBrand);
@@ -422,9 +429,9 @@ struct MinimizeRecGroups : Pass {
422429 groups.emplace_back ();
423430
424431 // The SCC is not necessarily topologically sorted to have the supertypes
425- // come first. Fix that.
432+ // and described types come first. Fix that.
426433 std::vector<HeapType> sccTypes (scc.begin (), scc.end ());
427- auto deps = createSubtypeGraph (sccTypes);
434+ auto deps = createTypeOrderGraph (sccTypes);
428435 auto permutation = *TopologicalOrders (deps).begin ();
429436 groups.back ().group .resize (sccTypes.size ());
430437 for (Index i = 0 ; i < sccTypes.size (); ++i) {
0 commit comments