@@ -315,6 +315,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
315
315
316
316
private:
317
317
std::int64_t GetAssociatedLoopLevelFromClauses (const parser::AccClauseList &);
318
+ bool HasForceCollapseModifier (const parser::AccClauseList &);
318
319
319
320
Symbol::Flags dataSharingAttributeFlags{Symbol::Flag::AccShared,
320
321
Symbol::Flag::AccPrivate, Symbol::Flag::AccFirstPrivate,
@@ -333,7 +334,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
333
334
Symbol::Flag::AccDevicePtr, Symbol::Flag::AccDeviceResident,
334
335
Symbol::Flag::AccLink, Symbol::Flag::AccPresent};
335
336
336
- void CheckAssociatedLoop (const parser::DoConstruct &);
337
+ void CheckAssociatedLoop (const parser::DoConstruct &, bool forceCollapsed );
337
338
void ResolveAccObjectList (const parser::AccObjectList &, Symbol::Flag);
338
339
void ResolveAccObject (const parser::AccObject &, Symbol::Flag);
339
340
Symbol *ResolveAcc (const parser::Name &, Symbol::Flag, Scope &);
@@ -1168,7 +1169,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
1168
1169
ClearDataSharingAttributeObjects ();
1169
1170
SetContextAssociatedLoopLevel (GetAssociatedLoopLevelFromClauses (clauseList));
1170
1171
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t )};
1171
- CheckAssociatedLoop (*outer);
1172
+ CheckAssociatedLoop (*outer, HasForceCollapseModifier (clauseList) );
1172
1173
return true ;
1173
1174
}
1174
1175
@@ -1366,7 +1367,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
1366
1367
const auto &clauseList{std::get<parser::AccClauseList>(beginBlockDir.t )};
1367
1368
SetContextAssociatedLoopLevel (GetAssociatedLoopLevelFromClauses (clauseList));
1368
1369
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t )};
1369
- CheckAssociatedLoop (*outer);
1370
+ CheckAssociatedLoop (*outer, HasForceCollapseModifier (clauseList) );
1370
1371
ClearDataSharingAttributeObjects ();
1371
1372
return true ;
1372
1373
}
@@ -1478,6 +1479,18 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
1478
1479
return true ;
1479
1480
}
1480
1481
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
+
1481
1494
std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses (
1482
1495
const parser::AccClauseList &x) {
1483
1496
std::int64_t collapseLevel{0 };
@@ -1499,14 +1512,14 @@ std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
1499
1512
}
1500
1513
1501
1514
void AccAttributeVisitor::CheckAssociatedLoop (
1502
- const parser::DoConstruct &outerDoConstruct) {
1515
+ const parser::DoConstruct &outerDoConstruct, bool forceCollapsed ) {
1503
1516
std::int64_t level{GetContext ().associatedLoopLevel };
1504
1517
if (level <= 0 ) { // collapse value was negative or 0
1505
1518
return ;
1506
1519
}
1507
1520
1508
1521
const auto getNextDoConstruct =
1509
- [this ](const parser::Block &block,
1522
+ [this , forceCollapsed ](const parser::Block &block,
1510
1523
std::int64_t &level) -> const parser::DoConstruct * {
1511
1524
for (const auto &entry : block) {
1512
1525
if (const auto *doConstruct = GetDoConstructIf (entry)) {
@@ -1524,7 +1537,9 @@ void AccAttributeVisitor::CheckAssociatedLoop(
1524
1537
" LOOP directive not expected in COLLAPSE loop nest" _err_en_US);
1525
1538
level = 0 ;
1526
1539
} else {
1527
- break ;
1540
+ if (!forceCollapsed) {
1541
+ break ;
1542
+ }
1528
1543
}
1529
1544
}
1530
1545
return nullptr ;
0 commit comments