@@ -315,6 +315,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
315315
316316private:
317317 std::int64_t GetAssociatedLoopLevelFromClauses (const parser::AccClauseList &);
318+ bool HasForceCollapseModifier (const parser::AccClauseList &);
318319
319320 Symbol::Flags dataSharingAttributeFlags{Symbol::Flag::AccShared,
320321 Symbol::Flag::AccPrivate, Symbol::Flag::AccFirstPrivate,
@@ -333,7 +334,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
333334 Symbol::Flag::AccDevicePtr, Symbol::Flag::AccDeviceResident,
334335 Symbol::Flag::AccLink, Symbol::Flag::AccPresent};
335336
336- void CheckAssociatedLoop (const parser::DoConstruct &);
337+ void CheckAssociatedLoop (const parser::DoConstruct &, bool forceCollapsed );
337338 void ResolveAccObjectList (const parser::AccObjectList &, Symbol::Flag);
338339 void ResolveAccObject (const parser::AccObject &, Symbol::Flag);
339340 Symbol *ResolveAcc (const parser::Name &, Symbol::Flag, Scope &);
@@ -1168,7 +1169,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
11681169 ClearDataSharingAttributeObjects ();
11691170 SetContextAssociatedLoopLevel (GetAssociatedLoopLevelFromClauses (clauseList));
11701171 const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t )};
1171- CheckAssociatedLoop (*outer);
1172+ CheckAssociatedLoop (*outer, HasForceCollapseModifier (clauseList) );
11721173 return true ;
11731174}
11741175
@@ -1366,7 +1367,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
13661367 const auto &clauseList{std::get<parser::AccClauseList>(beginBlockDir.t )};
13671368 SetContextAssociatedLoopLevel (GetAssociatedLoopLevelFromClauses (clauseList));
13681369 const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t )};
1369- CheckAssociatedLoop (*outer);
1370+ CheckAssociatedLoop (*outer, HasForceCollapseModifier (clauseList) );
13701371 ClearDataSharingAttributeObjects ();
13711372 return true ;
13721373}
@@ -1478,6 +1479,18 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
14781479 return true ;
14791480}
14801481
1482+ bool AccAttributeVisitor::HasForceCollapseModifier (
1483+ const parser::AccClauseList &x) {
1484+ for (const auto &clause : x.v ) {
1485+ if (const auto *collapseClause{
1486+ std::get_if<parser::AccClause::Collapse>(&clause.u )}) {
1487+ const parser::AccCollapseArg &arg = collapseClause->v ;
1488+ return std::get<bool >(arg.t );
1489+ }
1490+ }
1491+ return false ;
1492+ }
1493+
14811494std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses (
14821495 const parser::AccClauseList &x) {
14831496 std::int64_t collapseLevel{0 };
@@ -1499,14 +1512,14 @@ std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
14991512}
15001513
15011514void AccAttributeVisitor::CheckAssociatedLoop (
1502- const parser::DoConstruct &outerDoConstruct) {
1515+ const parser::DoConstruct &outerDoConstruct, bool forceCollapsed ) {
15031516 std::int64_t level{GetContext ().associatedLoopLevel };
15041517 if (level <= 0 ) { // collapse value was negative or 0
15051518 return ;
15061519 }
15071520
15081521 const auto getNextDoConstruct =
1509- [this ](const parser::Block &block,
1522+ [this , forceCollapsed ](const parser::Block &block,
15101523 std::int64_t &level) -> const parser::DoConstruct * {
15111524 for (const auto &entry : block) {
15121525 if (const auto *doConstruct = GetDoConstructIf (entry)) {
@@ -1524,7 +1537,9 @@ void AccAttributeVisitor::CheckAssociatedLoop(
15241537 " LOOP directive not expected in COLLAPSE loop nest" _err_en_US);
15251538 level = 0 ;
15261539 } else {
1527- break ;
1540+ if (!forceCollapsed) {
1541+ break ;
1542+ }
15281543 }
15291544 }
15301545 return nullptr ;
0 commit comments