[Mlir-commits] [mlir] [MLIR][Mem2Reg] Add support for region control flow and SCF (PR #185036)
Tobias Gysi
llvmlistbot at llvm.org
Sun Mar 8 12:14:11 PDT 2026
================
@@ -559,79 +674,121 @@ static void dominanceSort(SmallVector<Operation *> &ops, Region ®ion,
});
}
-void MemorySlotPromoter::removeBlockingUses() {
+void MemorySlotPromoter::removeBlockingUses(Region *region) {
+ auto *blockingUsesMapIt = info.userToBlockingUses.find(region);
+ if (blockingUsesMapIt == info.userToBlockingUses.end())
+ return;
+ BlockingUsesMap &blockingUsesMap = blockingUsesMapIt->second;
+
llvm::SmallVector<Operation *> usersToRemoveUses(
- llvm::make_first_range(info.userToBlockingUses));
+ llvm::make_first_range(blockingUsesMap));
// Sort according to dominance.
- dominanceSort(usersToRemoveUses, *slot.ptr.getParentBlock()->getParent(),
- blockIndexCache);
+ dominanceSort(usersToRemoveUses, *region, blockIndexCache);
- llvm::SmallVector<Operation *> toErase;
- // List of all replaced values in the slot.
- llvm::SmallVector<std::pair<Operation *, Value>> replacedValuesList;
- // Ops to visit with the `visitReplacedValues` method.
- llvm::SmallVector<PromotableOpInterface> toVisit;
for (Operation *toPromote : llvm::reverse(usersToRemoveUses)) {
if (auto toPromoteMemOp = dyn_cast<PromotableMemOpInterface>(toPromote)) {
Value reachingDef = reachingDefs.lookup(toPromoteMemOp);
// If no reaching definition is known, this use is outside the reach of
// the slot. The default value should thus be used.
+ // FIXME: This is too eager, and will generate default values even for
+ // pure stores. This cannot be removed easily as partial stores may
+ // still require a default value to complete.
if (!reachingDef)
reachingDef = getOrCreateDefaultValue();
builder.setInsertionPointAfter(toPromote);
- if (toPromoteMemOp.removeBlockingUses(
- slot, info.userToBlockingUses[toPromote], builder, reachingDef,
- dataLayout) == DeletionKind::Delete)
+ if (toPromoteMemOp.removeBlockingUses(slot, blockingUsesMap[toPromote],
+ builder, reachingDef,
+ dataLayout) == DeletionKind::Delete)
toErase.push_back(toPromote);
if (toPromoteMemOp.storesTo(slot))
if (Value replacedValue = replacedValuesMap[toPromoteMemOp])
- replacedValuesList.push_back({toPromoteMemOp, replacedValue});
+ replacedValues.push_back({toPromoteMemOp, replacedValue});
continue;
}
auto toPromoteBasic = cast<PromotableOpInterface>(toPromote);
builder.setInsertionPointAfter(toPromote);
- if (toPromoteBasic.removeBlockingUses(info.userToBlockingUses[toPromote],
+ if (toPromoteBasic.removeBlockingUses(blockingUsesMap[toPromote],
builder) == DeletionKind::Delete)
toErase.push_back(toPromote);
if (toPromoteBasic.requiresReplacedValues())
- toVisit.push_back(toPromoteBasic);
+ toVisitReplacedValues.push_back(toPromoteBasic);
}
- for (PromotableOpInterface op : toVisit) {
- builder.setInsertionPointAfter(op);
- op.visitReplacedValues(replacedValuesList, builder);
+}
+
+void MemorySlotPromoter::linkMergePoints() {
+ // We want to eliminate unused block arguments. In case connecting a block
+ // argument to its predecessor would trigger the use of the predecessor's
+ // unused block argument, we need to process merge points in an expanding
+ // worklist, `mergePointArgsToProcess`.
+
+ SmallPtrSet<BlockArgument, 8> mergePointArgsUnused;
+ SmallVector<BlockArgument> mergePointArgsToProcess;
+ for (Block *mergePoint : info.mergePoints) {
+ BlockArgument arg = mergePoint->getArguments().back();
+ if (arg.use_empty())
+ mergePointArgsUnused.insert(arg);
+ else
+ mergePointArgsToProcess.push_back(arg);
}
- for (Operation *toEraseOp : toErase)
- toEraseOp->erase();
+ while (!mergePointArgsToProcess.empty()) {
+ BlockArgument arg = mergePointArgsToProcess.pop_back_val();
+ Block *mergePoint = arg.getOwner();
- assert(slot.ptr.use_empty() &&
- "after promotion, the slot pointer should not be used anymore");
+ for (BlockOperand &use : mergePoint->getUses()) {
+ Value reachingDef = reachingAtBlockEnd[use.getOwner()->getBlock()];
+ if (!reachingDef)
+ reachingDef = getOrCreateDefaultValue();
+
+ // If the reaching definition is a block argument of an unused merge
+ // point, mark it as used and process it as such later.
+ auto reachingDefArgument = dyn_cast<BlockArgument>(reachingDef);
+ if (reachingDefArgument &&
+ mergePointArgsUnused.erase(reachingDefArgument))
----------------
gysit wrote:
Are this the region arguments introduced when promoting the region operations?
https://github.com/llvm/llvm-project/pull/185036
More information about the Mlir-commits
mailing list