@@ -149,6 +149,17 @@ mlir::LogicalResult BoxTotalElementsConversion::matchAndRewrite(
149
149
150
150
class DoConcurrentConversion
151
151
: public mlir::OpRewritePattern<fir::DoConcurrentOp> {
152
+ // / Looks up from the operation from and returns the LocalitySpecifierOp with
153
+ // / name symbolName
154
+ static fir::LocalitySpecifierOp
155
+ findLocalizer (mlir::Operation *from, mlir::SymbolRefAttr symbolName) {
156
+ fir::LocalitySpecifierOp localizer =
157
+ mlir::SymbolTable::lookupNearestSymbolFrom<fir::LocalitySpecifierOp>(
158
+ from, symbolName);
159
+ assert (localizer && " localizer not found in the symbol table" );
160
+ return localizer;
161
+ }
162
+
152
163
public:
153
164
using mlir::OpRewritePattern<fir::DoConcurrentOp>::OpRewritePattern;
154
165
@@ -162,7 +173,59 @@ class DoConcurrentConversion
162
173
assert (loop.getRegion ().hasOneBlock ());
163
174
mlir::Block &loopBlock = loop.getRegion ().getBlocks ().front ();
164
175
165
- // Collect iteration variable(s) allocations do that we can move them
176
+ // Handle localization
177
+ if (!loop.getLocalVars ().empty ()) {
178
+ mlir::OpBuilder::InsertionGuard guard (rewriter);
179
+ rewriter.setInsertionPointToStart (&loop.getRegion ().front ());
180
+
181
+ std::optional<mlir::ArrayAttr> localSyms = loop.getLocalSyms ();
182
+
183
+ for (auto [localVar, localArg, localizerSym] : llvm::zip_equal (
184
+ loop.getLocalVars (), loop.getRegionLocalArgs (), *localSyms)) {
185
+ mlir::SymbolRefAttr localizerName =
186
+ llvm::cast<mlir::SymbolRefAttr>(localizerSym);
187
+ fir::LocalitySpecifierOp localizer = findLocalizer (loop, localizerName);
188
+
189
+ if (!localizer.getInitRegion ().empty () ||
190
+ !localizer.getDeallocRegion ().empty ())
191
+ TODO (localizer.getLoc (), " localizers with `init` and `dealloc` "
192
+ " regions are not handled yet." );
193
+
194
+ // TODO Should this be a heap allocation instead? For now, we allocate
195
+ // on the stack for each loop iteration.
196
+ mlir::Value localAlloc =
197
+ rewriter.create <fir::AllocaOp>(loop.getLoc (), localizer.getType ());
198
+
199
+ if (localizer.getLocalitySpecifierType () ==
200
+ fir::LocalitySpecifierType::LocalInit) {
201
+ // It is reasonable to make this assumption since, at this stage,
202
+ // control-flow ops are not converted yet. Therefore, things like `if`
203
+ // conditions will still be represented by their encapsulating `fir`
204
+ // dialect ops.
205
+ assert (localizer.getCopyRegion ().hasOneBlock () &&
206
+ " Expected localizer to have a single block." );
207
+ mlir::Block *beforeLocalInit = rewriter.getInsertionBlock ();
208
+ mlir::Block *afterLocalInit = rewriter.splitBlock (
209
+ rewriter.getInsertionBlock (), rewriter.getInsertionPoint ());
210
+ rewriter.cloneRegionBefore (localizer.getCopyRegion (), afterLocalInit);
211
+ mlir::Block *copyRegionBody = beforeLocalInit->getNextNode ();
212
+
213
+ rewriter.eraseOp (copyRegionBody->getTerminator ());
214
+ rewriter.mergeBlocks (afterLocalInit, copyRegionBody);
215
+ rewriter.mergeBlocks (copyRegionBody, beforeLocalInit,
216
+ {localVar, localArg});
217
+ }
218
+
219
+ rewriter.replaceAllUsesWith (localArg, localAlloc);
220
+ }
221
+
222
+ loop.getRegion ().front ().eraseArguments (loop.getNumInductionVars (),
223
+ loop.getNumLocalOperands ());
224
+ loop.getLocalVarsMutable ().clear ();
225
+ loop.setLocalSymsAttr (nullptr );
226
+ }
227
+
228
+ // Collect iteration variable(s) allocations so that we can move them
166
229
// outside the `fir.do_concurrent` wrapper.
167
230
llvm::SmallVector<mlir::Operation *> opsToMove;
168
231
for (mlir::Operation &op : llvm::drop_end (wrapperBlock))
0 commit comments