Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {

private:
std::int64_t GetAssociatedLoopLevelFromClauses(const parser::AccClauseList &);
bool HasForceCollapseModifier(const parser::AccClauseList &);

Symbol::Flags dataSharingAttributeFlags{Symbol::Flag::AccShared,
Symbol::Flag::AccPrivate, Symbol::Flag::AccFirstPrivate,
Expand All @@ -333,7 +334,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
Symbol::Flag::AccDevicePtr, Symbol::Flag::AccDeviceResident,
Symbol::Flag::AccLink, Symbol::Flag::AccPresent};

void CheckAssociatedLoop(const parser::DoConstruct &);
void CheckAssociatedLoop(const parser::DoConstruct &, bool forceCollapsed);
void ResolveAccObjectList(const parser::AccObjectList &, Symbol::Flag);
void ResolveAccObject(const parser::AccObject &, Symbol::Flag);
Symbol *ResolveAcc(const parser::Name &, Symbol::Flag, Scope &);
Expand Down Expand Up @@ -1168,7 +1169,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
ClearDataSharingAttributeObjects();
SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
CheckAssociatedLoop(*outer);
CheckAssociatedLoop(*outer, HasForceCollapseModifier(clauseList));
return true;
}

Expand Down Expand Up @@ -1366,7 +1367,7 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
const auto &clauseList{std::get<parser::AccClauseList>(beginBlockDir.t)};
SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
CheckAssociatedLoop(*outer);
CheckAssociatedLoop(*outer, HasForceCollapseModifier(clauseList));
ClearDataSharingAttributeObjects();
return true;
}
Expand Down Expand Up @@ -1478,6 +1479,18 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
return true;
}

bool AccAttributeVisitor::HasForceCollapseModifier(
const parser::AccClauseList &x) {
for (const auto &clause : x.v) {
if (const auto *collapseClause{
std::get_if<parser::AccClause::Collapse>(&clause.u)}) {
const parser::AccCollapseArg &arg = collapseClause->v;
return std::get<bool>(arg.t);
}
}
return false;
}

std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
const parser::AccClauseList &x) {
std::int64_t collapseLevel{0};
Expand All @@ -1499,14 +1512,14 @@ std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
}

void AccAttributeVisitor::CheckAssociatedLoop(
const parser::DoConstruct &outerDoConstruct) {
const parser::DoConstruct &outerDoConstruct, bool forceCollapsed) {
std::int64_t level{GetContext().associatedLoopLevel};
if (level <= 0) { // collapse value was negative or 0
return;
}

const auto getNextDoConstruct =
[this](const parser::Block &block,
[this, forceCollapsed](const parser::Block &block,
std::int64_t &level) -> const parser::DoConstruct * {
for (const auto &entry : block) {
if (const auto *doConstruct = GetDoConstructIf(entry)) {
Expand All @@ -1524,7 +1537,9 @@ void AccAttributeVisitor::CheckAssociatedLoop(
"LOOP directive not expected in COLLAPSE loop nest"_err_en_US);
level = 0;
} else {
break;
if (!forceCollapsed) {
break;
}
}
}
return nullptr;
Expand Down
19 changes: 19 additions & 0 deletions flang/test/Semantics/OpenACC/acc-collapse-force.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
! RUN: %python %S/../test_errors.py %s %flang -fopenacc -fsyntax-only

! Check that loop with force collapse do not break in the semantic step.
subroutine sub3()
integer :: i, j
integer, parameter :: n = 100, m = 200
real, dimension(n, m) :: a
real, dimension(n) :: bb
real :: r
a = 1
r = 0
!$acc parallel loop collapse(force:2) copy(a)
do i = 1, n
bb(i) = r
do j = 1, m
a(i,j) = r * a(i,j)
enddo
enddo
end subroutine