@@ -53,7 +53,7 @@ class GenericLoopConversionPattern
53
53
54
54
switch (combinedInfo) {
55
55
case GenericLoopCombinedInfo::Standalone:
56
- rewriteToSimdLoop (loopOp, rewriter);
56
+ rewriteStandaloneLoop (loopOp, rewriter);
57
57
break ;
58
58
case GenericLoopCombinedInfo::TargetParallelLoop:
59
59
llvm_unreachable (" not yet implemented: `parallel loop` direcitve" );
@@ -87,7 +87,10 @@ class GenericLoopConversionPattern
87
87
<< loopOp->getName () << " operation" ;
88
88
};
89
89
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 ())
91
94
return todo (" bind" );
92
95
93
96
if (loopOp.getOrder ())
@@ -119,7 +122,27 @@ class GenericLoopConversionPattern
119
122
return result;
120
123
}
121
124
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
+ // /
123
146
// / The reasoning behind this decision is that according to the spec (version
124
147
// / 5.2, section 11.7.1):
125
148
// /
@@ -147,30 +170,57 @@ class GenericLoopConversionPattern
147
170
// / the directive.
148
171
void rewriteToSimdLoop (mlir::omp::LoopOp loopOp,
149
172
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 ();
154
207
155
208
auto privateSyms = loopOp.getPrivateSyms ();
156
209
if (privateSyms)
157
- simdClauseOps.privateSyms .assign (privateSyms->begin (),
158
- privateSyms->end ());
210
+ clauseOps.privateSyms .assign (privateSyms->begin (), privateSyms->end ());
159
211
160
- Fortran::common::openmp::EntryBlockArgs simdArgs ;
161
- simdArgs .priv .vars = simdClauseOps .privateVars ;
212
+ Fortran::common::openmp::EntryBlockArgs args ;
213
+ args .priv .vars = clauseOps .privateVars ;
162
214
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 ());
167
217
168
218
mlir::IRMapping mapper;
169
219
mlir::Block &loopBlock = *loopOp.getRegion ().begin ();
170
220
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 );
174
224
175
225
rewriter.clone (*loopOp.begin (), mapper);
176
226
}
0 commit comments