@@ -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,52 @@ 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
+ mlir::Value localAlloc =
190
+ rewriter.create <fir::AllocaOp>(loop.getLoc (), localizer.getType ());
191
+
192
+ if (localizer.getLocalitySpecifierType () ==
193
+ fir::LocalitySpecifierType::LocalInit) {
194
+ // It is reasonable to make this assumption since, at this stage,
195
+ // control-flow ops are not converted yet. Therefore, things like `if`
196
+ // conditions will still be represented by their encapsulating `fir`
197
+ // dialect ops.
198
+ assert (localizer.getCopyRegion ().hasOneBlock () &&
199
+ " Expected localizer to have a single block." );
200
+ mlir::Block *beforeLocalInit = rewriter.getInsertionBlock ();
201
+ mlir::Block *afterLocalInit = rewriter.splitBlock (
202
+ rewriter.getInsertionBlock (), rewriter.getInsertionPoint ());
203
+ rewriter.cloneRegionBefore (localizer.getCopyRegion (), afterLocalInit);
204
+ mlir::Block *copyRegionBody = beforeLocalInit->getNextNode ();
205
+
206
+ rewriter.eraseOp (copyRegionBody->getTerminator ());
207
+ rewriter.mergeBlocks (afterLocalInit, copyRegionBody);
208
+ rewriter.mergeBlocks (copyRegionBody, beforeLocalInit,
209
+ {localVar, localArg});
210
+ }
211
+
212
+ rewriter.replaceAllUsesWith (localArg, localAlloc);
213
+ }
214
+
215
+ loop.getRegion ().front ().eraseArguments (loop.getNumInductionVars (),
216
+ loop.getNumLocalOperands ());
217
+ loop.getLocalVarsMutable ().clear ();
218
+ loop.setLocalSymsAttr (nullptr );
219
+ }
220
+
221
+ // Collect iteration variable(s) allocations so that we can move them
166
222
// outside the `fir.do_concurrent` wrapper.
167
223
llvm::SmallVector<mlir::Operation *> opsToMove;
168
224
for (mlir::Operation &op : llvm::drop_end (wrapperBlock))
0 commit comments