@@ -172,81 +172,85 @@ class CanonicalizationOfOmp {
172172 if (auto *endDir{
173173 GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) {
174174 auto &endDirName = endDir->DirName ();
175- if (endDirName.v == llvm::omp::Directive::OMPD_fuse)
176- endFuseNeeded = false ;
177- std::get<std::optional<parser::OmpEndLoopDirective>>(x. t ) =
178- std::move (*endDir );
179- nextIt = block. erase (nextIt);
175+ if (endDirName.v != llvm::omp::Directive::OMPD_fuse) {
176+ std::get<std::optional<parser::OmpEndLoopDirective>>(x. t ) =
177+ std::move (*endDir);
178+ nextIt = block. erase (nextIt );
179+ }
180180 }
181181 }
182182 } else {
183183 messages_.Say (beginName.source ,
184184 " DO loop after the %s directive must have loop control" _err_en_US,
185185 parser::ToUpperCaseLetters (beginName.source .ToString ()));
186- endFuseNeeded = false ;
187186 }
188187 } else if (auto *ompLoopCons{
189188 GetOmpIf<parser::OpenMPLoopConstruct>(*nextIt)}) {
190- // We should allow UNROLL and TILE constructs to be inserted between an
191- // OpenMP Loop Construct and the DO loop itself
189+ // We should allow loop transformation constructs to be inserted between
190+ // an OpenMP Loop Construct and the DO loop itself
192191 auto &nestedBeginDirective = ompLoopCons->BeginDir ();
193192 auto &nestedBeginName = nestedBeginDirective.DirName ();
194193 if (llvm::omp::loopTransformationSet.test (nestedBeginName.v )) {
195194 if (nestedBeginName.v == llvm::omp::Directive::OMPD_unroll &&
196195 llvm::omp::loopTransformationSet.test (beginName.v )) {
197- // if a loop has been unrolled, the user can not then tile that loop
198- // as it has been unrolled
196+ // if a loop has been unrolled, the user can not then transform that
197+ // loop as it has been unrolled
199198 const parser::OmpClauseList &unrollClauseList{
200199 nestedBeginDirective.Clauses ()};
201200 if (unrollClauseList.v .empty ()) {
202201 // if the clause list is empty for an unroll construct, we assume
203202 // the loop is being fully unrolled
204203 transformUnrollError (beginName, messages_);
205- endFuseNeeded = false ;
206204 } else {
207205 // parse the clauses for the unroll directive to find the full
208206 // clause
209207 for (auto &clause : unrollClauseList.v ) {
210208 if (clause.Id () == llvm::omp::OMPC_full) {
211209 transformUnrollError (beginName, messages_);
212- endFuseNeeded = false ;
213210 }
214211 }
215212 }
216213 }
217- // iterate through the remaining block items to find the end directive
218- // for the unroll/tile directive.
219- parser::Block::iterator endIt;
220- endIt = nextIt;
221- while (endIt != block.end ()) {
214+ RewriteOpenMPLoopConstruct (*ompLoopCons, block, nextIt);
215+ auto &loopConsList =
216+ std::get<std::list<parser::NestedConstruct>>(x.t );
217+ loopConsList.push_back (parser::NestedConstruct{
218+ common::Indirection{std::move (*ompLoopCons)}});
219+ nextIt = block.erase (nextIt);
220+ // check the following block item to find the end directive
221+ // for the loop transform directive.
222+ if (nextIt != block.end ()) {
222223 if (auto *endDir{
223- GetConstructIf<parser::OmpEndLoopDirective>(*endIt )}) {
224+ GetConstructIf<parser::OmpEndLoopDirective>(*nextIt )}) {
224225 auto &endDirName = endDir->DirName ();
225- if (endDirName.v == beginName.v ) {
226- if (endDirName.v == llvm::omp::Directive::OMPD_fuse)
227- endFuseNeeded = false ;
226+ if (endDirName.v == beginName.v &&
227+ endDirName.v != llvm::omp::Directive::OMPD_fuse) {
228228 std::get<std::optional<parser::OmpEndLoopDirective>>(x.t ) =
229229 std::move (*endDir);
230- endIt = block.erase (endIt);
231- continue ;
230+ nextIt = block.erase (nextIt);
232231 }
233232 }
234- ++endIt;
235233 }
236- RewriteOpenMPLoopConstruct (*ompLoopCons, block, nextIt);
237- auto &loopConsList = std::get<std::list<parser::NestedConstruct>>(x.t );
238- loopConsList.push_back (parser::NestedConstruct{
239- common::Indirection{std::move (*ompLoopCons)}});
240- nextIt = block.erase (nextIt);
241234 } else {
242235 messages_.Say (nestedBeginName.source ,
243236 " Only Loop Transformation Constructs or Loop Nests can be nested within Loop Constructs" _err_en_US,
244237 parser::ToUpperCaseLetters (nestedBeginName.source .ToString ()));
245- endFuseNeeded = false ;
246238 }
247239 } else {
248240 missingDoConstruct (beginName, messages_);
249- endFuseNeeded = false ;
241+ }
242+
243+ if (endFuseNeeded && nextIt != block.end ()) {
244+ if (auto *endDir{
245+ GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) {
246+ auto &endDirName = endDir->DirName ();
247+ if (endDirName.v == llvm::omp::Directive::OMPD_fuse) {
248+ endFuseNeeded = false ;
249+ std::get<std::optional<parser::OmpEndLoopDirective>>(x.t ) =
250+ std::move (*endDir);
251+ nextIt = block.erase (nextIt);
252+ }
253+ }
250254 }
251255 if (endFuseNeeded)
252256 continue ;
0 commit comments