[flang-commits] [flang] [flang][fir] Add rewrite pattern to convert `fir.do_concurrent` to `fir.do_loop` (PR #132207)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Mon Mar 24 01:12:12 PDT 2025


================
@@ -122,6 +124,59 @@ mlir::LogicalResult BoxTotalElementsConversion::matchAndRewrite(
   return mlir::failure();
 }
 
+class DoConcurrentConversion
+    : public mlir::OpRewritePattern<fir::DoConcurrentOp> {
+public:
+  using mlir::OpRewritePattern<fir::DoConcurrentOp>::OpRewritePattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::DoConcurrentOp doConcurentOp,
+                  mlir::PatternRewriter &rewriter) const override {
+    assert(doConcurentOp.getRegion().hasOneBlock());
+    mlir::Block &wrapperBlock = doConcurentOp.getRegion().getBlocks().front();
+    auto loop =
+        mlir::cast<fir::DoConcurrentLoopOp>(wrapperBlock.getTerminator());
+    assert(loop.getRegion().hasOneBlock());
+    mlir::Block &loopBlock = loop.getRegion().getBlocks().front();
+
+    // Collect iteration variable(s) allocations do that we can move them
+    // outside the `fir.do_concurrent` wrapper.
+    llvm::SmallVector<mlir::Operation *> opsToMove;
+    for (mlir::Operation &op : llvm::drop_end(wrapperBlock))
+      opsToMove.push_back(&op);
+
+    mlir::Block &parentRegionEntry = doConcurentOp->getParentRegion()->front();
+    auto allocIt = (&parentRegionEntry == doConcurentOp->getBlock())
+                       ? doConcurentOp->getIterator()
+                       : parentRegionEntry.getTerminator()->getIterator();
+
+    for (mlir::Operation *op : opsToMove)
+      rewriter.moveOpBefore(op, allocIt->getBlock(), allocIt);
+
+    rewriter.setInsertionPointAfter(doConcurentOp);
+    fir::DoLoopOp innermostUnorderdLoop;
+    mlir::IRMapping mapper;
+
+    for (auto [lb, ub, st, iv] :
+         llvm::zip_equal(loop.getLowerBound(), loop.getUpperBound(),
+                         loop.getStep(), *loop.getLoopInductionVars())) {
+      innermostUnorderdLoop = rewriter.create<fir::DoLoopOp>(
+          doConcurentOp.getLoc(), lb, ub, st,
+          /*unordred=*/true, /*finalCountValue=*/false,
+          /*iterArgs=*/std::nullopt, loop.getReduceOperands(),
+          loop.getReduceAttrsAttr());
+      mapper.map(iv, innermostUnorderdLoop.getInductionVar());
+      rewriter.setInsertionPointToStart(innermostUnorderdLoop.getBody());
+    }
+
+    for (mlir::Operation &op : loopBlock)
+      rewriter.clone(op, mapper);
----------------
ergawy wrote:

Doesn't this violate the [restrictions of pattern rewriting](https://mlir.llvm.org/docs/PatternRewriter/#restrictions)?

```
All IR mutations, including creation, must be performed by the given PatternRewriter. This class provides hooks for performing all of the possible mutations that may take place within a pattern. For example, this means that an operation should not be erased via its erase method. To erase an operation, the appropriate PatternRewriter hook (in this case eraseOp) should be used instead.
```

I see `takeBody` is used in other paces where a pattern rewriter is available though, so I might be missing something.

https://github.com/llvm/llvm-project/pull/132207


More information about the flang-commits mailing list