Skip to content

Commit 9a0a68f

Browse files
committed
replace with iterative version instead
1 parent d49b5ea commit 9a0a68f

File tree

1 file changed

+84
-56
lines changed

1 file changed

+84
-56
lines changed

mlir/lib/Target/LLVMIR/DebugImporter.cpp

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -318,73 +318,101 @@ getRecSelfConstructor(llvm::DINode *node) {
318318
.Default(CtorType());
319319
}
320320

321-
/// An attribute replacer that replaces nested recursive decls with recursive
322-
/// self-references instead.
323-
///
321+
/// An iterative attribute replacer that also handles pruning recursive types.
324322
/// - Recurses down the attribute tree while replacing attributes based on the
325323
/// provided replacement map.
326324
/// - Keeps track of the currently open recursive declarations, and upon
327-
/// encountering a duplicate declaration, replace with a self-ref instead.
328-
static Attribute replaceAndPruneRecursiveTypesImpl(
329-
Attribute node,
330-
const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping,
331-
DenseSet<DistinctAttr> &openDecls) {
332-
DistinctAttr recId;
333-
if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(node)) {
334-
recId = recType.getRecId();
335-
336-
// Configure context.
337-
if (recId) {
338-
if (recType.isRecSelf()) {
339-
// Replace selfRef based on the provided mapping.
340-
if (DINodeAttr replacement = mapping.lookup(recType))
341-
return replaceAndPruneRecursiveTypesImpl(replacement, mapping,
342-
openDecls);
343-
return node;
344-
}
325+
/// encountering a duplicate declaration, replace with a self-reference.
326+
static Attribute replaceAndPruneRecursiveTypes(
327+
Attribute baseNode,
328+
const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping) {
345329

346-
auto [_, inserted] = openDecls.insert(recId);
347-
if (!inserted) {
348-
// This is a nested decl. Replace with recSelf.
349-
return recType.getRecSelf(recId);
330+
struct ReplacementState {
331+
// The attribute being replaced.
332+
Attribute node;
333+
// The nested elements of `node`.
334+
SmallVector<Attribute> attrs;
335+
SmallVector<Type> types;
336+
// The current attr being walked on (index into `attrs`).
337+
size_t attrIndex;
338+
// Whether or not any attr was replaced.
339+
bool changed;
340+
341+
void replaceCurrAttr(Attribute attr) {
342+
Attribute &target = attrs[attrIndex];
343+
if (attr != target) {
344+
changed = true;
345+
target = attr;
350346
}
351347
}
352-
}
348+
};
353349

354-
// Collect sub attrs.
355-
SmallVector<Attribute> attrs;
356-
SmallVector<Type> types;
357-
node.walkImmediateSubElements(
358-
[&attrs](Attribute attr) { attrs.push_back(attr); },
359-
[&types](Type type) { types.push_back(type); });
360-
361-
// Recurse into attributes.
362-
bool changed = false;
363-
for (auto it = attrs.begin(); it != attrs.end(); it++) {
364-
Attribute replaced =
365-
replaceAndPruneRecursiveTypesImpl(*it, mapping, openDecls);
366-
if (replaced != *it) {
367-
*it = replaced;
368-
changed = true;
369-
}
370-
}
350+
// Every iteration, perform replacement on the attribute at `attrIndex` at the
351+
// top of `workStack`.
352+
// If `attrIndex` reaches past the size of `attrs`, replace `node` with
353+
// `attrs` & `types`, and pop off a stack frame and assign the replacement to
354+
// the attr being replaced on the previous stack frame.
355+
SmallVector<ReplacementState> workStack;
356+
workStack.push_back({nullptr, {baseNode}, {}, 0, false});
371357

372-
Attribute result = node;
373-
if (changed)
374-
result = result.replaceImmediateSubElements(attrs, types);
358+
DenseSet<DistinctAttr> openDecls;
359+
while (workStack.size() > 1 || workStack.back().attrIndex == 0) {
360+
ReplacementState &state = workStack.back();
361+
362+
// Check for popping condition.
363+
if (state.attrIndex == state.attrs.size()) {
364+
Attribute result = state.node;
365+
if (state.changed)
366+
result = result.replaceImmediateSubElements(state.attrs, state.types);
367+
368+
// Reset context.
369+
if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(state.node))
370+
if (DistinctAttr recId = recType.getRecId())
371+
openDecls.erase(recId);
372+
373+
workStack.pop_back();
374+
ReplacementState &prevState = workStack.back();
375+
prevState.replaceCurrAttr(result);
376+
++prevState.attrIndex;
377+
continue;
378+
}
375379

376-
// Reset context.
377-
if (recId)
378-
openDecls.erase(recId);
380+
Attribute node = state.attrs[state.attrIndex];
381+
if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(node)) {
382+
if (DistinctAttr recId = recType.getRecId()) {
383+
if (recType.isRecSelf()) {
384+
// Replace selfRef based on the provided mapping and re-walk from the
385+
// replacement node (do not increment attrIndex).
386+
if (DINodeAttr replacement = mapping.lookup(recType)) {
387+
state.replaceCurrAttr(replacement);
388+
continue;
389+
}
390+
391+
// Otherwise, nothing to do. Advance to next attr.
392+
++state.attrIndex;
393+
continue;
394+
}
395+
396+
// Configure context.
397+
auto [_, inserted] = openDecls.insert(recId);
398+
if (!inserted) {
399+
// This is a nested decl. Replace with recSelf. Nothing more to do.
400+
state.replaceCurrAttr(recType.getRecSelf(recId));
401+
++state.attrIndex;
402+
continue;
403+
}
404+
}
405+
}
379406

380-
return result;
381-
}
407+
// Recurse into this node.
408+
workStack.push_back({node, {}, {}, 0, false});
409+
ReplacementState &newState = workStack.back();
410+
node.walkImmediateSubElements(
411+
[&newState](Attribute attr) { newState.attrs.push_back(attr); },
412+
[&newState](Type type) { newState.types.push_back(type); });
413+
};
382414

383-
static Attribute replaceAndPruneRecursiveTypes(
384-
DINodeAttr node,
385-
const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping) {
386-
DenseSet<DistinctAttr> openDecls;
387-
return replaceAndPruneRecursiveTypesImpl(node, mapping, openDecls);
415+
return workStack.back().attrs.front();
388416
}
389417

390418
DINodeAttr DebugImporter::RecursionPruner::pruneOrPushTranslationStack(

0 commit comments

Comments
 (0)