@@ -53,7 +53,7 @@ class GenericLoopConversionPattern
5353
5454 switch (combinedInfo) {
5555 case GenericLoopCombinedInfo::Standalone:
56- rewriteToSimdLoop (loopOp, rewriter);
56+ rewriteStandaloneLoop (loopOp, rewriter);
5757 break ;
5858 case GenericLoopCombinedInfo::TargetParallelLoop:
5959 llvm_unreachable (" not yet implemented: `parallel loop` direcitve" );
@@ -87,7 +87,10 @@ class GenericLoopConversionPattern
8787 << loopOp->getName () << " operation" ;
8888 };
8989
90- if (loopOp.getBindKind ())
90+ // For standalone directives, `bind` is already supported. Other combined
91+ // forms will be supported in a follow-up PR.
92+ if (combinedInfo != GenericLoopCombinedInfo::Standalone &&
93+ loopOp.getBindKind ())
9194 return todo (" bind" );
9295
9396 if (loopOp.getOrder ())
@@ -119,7 +122,27 @@ class GenericLoopConversionPattern
119122 return result;
120123 }
121124
122- // / Rewrites standalone `loop` directives to equivalent `simd` constructs.
125+ void rewriteStandaloneLoop (mlir::omp::LoopOp loopOp,
126+ mlir::ConversionPatternRewriter &rewriter) const {
127+ using namespace mlir ::omp;
128+ std::optional<ClauseBindKind> bindKind = loopOp.getBindKind ();
129+
130+ if (!bindKind.has_value ())
131+ return rewriteToSimdLoop (loopOp, rewriter);
132+
133+ switch (*loopOp.getBindKind ()) {
134+ case ClauseBindKind::Parallel:
135+ return rewriteToWsloop (loopOp, rewriter);
136+ case ClauseBindKind::Teams:
137+ return rewriteToDistrbute (loopOp, rewriter);
138+ case ClauseBindKind::Thread:
139+ return rewriteToSimdLoop (loopOp, rewriter);
140+ }
141+ }
142+
143+ // / Rewrites standalone `loop` (without `bind` clause or with
144+ // / `bind(parallel)`) directives to equivalent `simd` constructs.
145+ // /
123146 // / The reasoning behind this decision is that according to the spec (version
124147 // / 5.2, section 11.7.1):
125148 // /
@@ -147,30 +170,57 @@ class GenericLoopConversionPattern
147170 // / the directive.
148171 void rewriteToSimdLoop (mlir::omp::LoopOp loopOp,
149172 mlir::ConversionPatternRewriter &rewriter) const {
150- loopOp.emitWarning (" Detected standalone OpenMP `loop` directive, the "
151- " associated loop will be rewritten to `simd`." );
152- mlir::omp::SimdOperands simdClauseOps;
153- simdClauseOps.privateVars = loopOp.getPrivateVars ();
173+ loopOp.emitWarning (
174+ " Detected standalone OpenMP `loop` directive with thread binding, "
175+ " the associated loop will be rewritten to `simd`." );
176+ rewriteToSingleWrapperOp<mlir::omp::SimdOp, mlir::omp::SimdOperands>(
177+ loopOp, rewriter);
178+ }
179+
180+ void rewriteToDistrbute (mlir::omp::LoopOp loopOp,
181+ mlir::ConversionPatternRewriter &rewriter) const {
182+ rewriteToSingleWrapperOp<mlir::omp::DistributeOp,
183+ mlir::omp::DistributeOperands>(loopOp, rewriter);
184+ }
185+
186+ void rewriteToWsloop (mlir::omp::LoopOp loopOp,
187+ mlir::ConversionPatternRewriter &rewriter) const {
188+ rewriteToSingleWrapperOp<mlir::omp::WsloopOp, mlir::omp::WsloopOperands>(
189+ loopOp, rewriter);
190+ }
191+
192+ // TODO Suggestion by Sergio: tag auto-generated operations for constructs
193+ // that weren't part of the original program, that would be useful
194+ // information for debugging purposes later on. This new attribute could be
195+ // used for `omp.loop`, but also for `do concurrent` transformations,
196+ // `workshare`, `workdistribute`, etc. The tag could be used for all kinds of
197+ // auto-generated operations using a dialect attribute (named something like
198+ // `omp.origin` or `omp.derived`) and perhaps hold the name of the operation
199+ // it was derived from, the reason it was transformed or something like that
200+ // we could use when emitting any messages related to it later on.
201+ template <typename OpTy, typename OpOperandsTy>
202+ void
203+ rewriteToSingleWrapperOp (mlir::omp::LoopOp loopOp,
204+ mlir::ConversionPatternRewriter &rewriter) const {
205+ OpOperandsTy clauseOps;
206+ clauseOps.privateVars = loopOp.getPrivateVars ();
154207
155208 auto privateSyms = loopOp.getPrivateSyms ();
156209 if (privateSyms)
157- simdClauseOps.privateSyms .assign (privateSyms->begin (),
158- privateSyms->end ());
210+ clauseOps.privateSyms .assign (privateSyms->begin (), privateSyms->end ());
159211
160- Fortran::common::openmp::EntryBlockArgs simdArgs ;
161- simdArgs .priv .vars = simdClauseOps .privateVars ;
212+ Fortran::common::openmp::EntryBlockArgs args ;
213+ args .priv .vars = clauseOps .privateVars ;
162214
163- auto simdOp =
164- rewriter.create <mlir::omp::SimdOp>(loopOp.getLoc (), simdClauseOps);
165- mlir::Block *simdBlock =
166- genEntryBlock (rewriter, simdArgs, simdOp.getRegion ());
215+ auto wrapperOp = rewriter.create <OpTy>(loopOp.getLoc (), clauseOps);
216+ mlir::Block *opBlock = genEntryBlock (rewriter, args, wrapperOp.getRegion ());
167217
168218 mlir::IRMapping mapper;
169219 mlir::Block &loopBlock = *loopOp.getRegion ().begin ();
170220
171- for (auto [loopOpArg, simdopArg ] :
172- llvm::zip_equal (loopBlock.getArguments (), simdBlock ->getArguments ()))
173- mapper.map (loopOpArg, simdopArg );
221+ for (auto [loopOpArg, opArg ] :
222+ llvm::zip_equal (loopBlock.getArguments (), opBlock ->getArguments ()))
223+ mapper.map (loopOpArg, opArg );
174224
175225 rewriter.clone (*loopOp.begin (), mapper);
176226 }
0 commit comments