Skip to content

Commit 7952989

Browse files
luporlyuxuanchen1997
authored andcommitted
Revert "[flang][OpenMP] Fix copyprivate semantic checks" (#100478)
Summary: Reverts #95799 This caused errors in some internal test suites. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250571
1 parent 0c6e790 commit 7952989

File tree

15 files changed

+95
-250
lines changed

15 files changed

+95
-250
lines changed

flang/include/flang/Semantics/tools.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ bool IsIntrinsicConcat(
8787
bool IsGenericDefinedOp(const Symbol &);
8888
bool IsDefinedOperator(SourceName);
8989
std::string MakeOpName(SourceName);
90-
bool IsCommonBlockContaining(const Symbol &, const Symbol &);
9190

9291
// Returns true if maybeAncestor exists and is a proper ancestor of a
9392
// descendent scope (or symbol owner). Will be false, unlike Scope::Contains(),

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 48 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "flang/Parser/parse-tree.h"
2020
#include "flang/Parser/tools.h"
2121
#include "flang/Semantics/expression.h"
22-
#include "flang/Semantics/tools.h"
2322
#include <list>
2423
#include <map>
2524
#include <sstream>
@@ -730,6 +729,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
730729
void CheckNameInAllocateStmt(const parser::CharBlock &source,
731730
const parser::Name &ompObject, const parser::AllocateStmt &allocate);
732731

732+
bool HasSymbolInEnclosingScope(const Symbol &, Scope &);
733733
std::int64_t ordCollapseLevel{0};
734734

735735
void AddOmpRequiresToScope(Scope &, WithOmpDeclarative::RequiresFlags,
@@ -2085,22 +2085,16 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
20852085
}
20862086
}
20872087

2088-
// When handling each implicit rule for a given symbol, one of the
2089-
// following 3 actions may be taken:
2090-
// 1. Declare a new private symbol.
2091-
// 2. Create a new association symbol with no flags, that will represent
2092-
// a shared symbol in the current scope. Note that symbols without
2093-
// any private flags are considered as shared.
2094-
// 3. Use the last declared private symbol, by inserting a new symbol
2095-
// in the scope being processed, associated with it.
2096-
// If no private symbol was declared previously, then no association
2097-
// is needed and the symbol from the enclosing scope will be
2098-
// inherited by the current one.
2099-
//
2100-
// Because of how symbols are collected in lowering, not inserting a new
2101-
// symbol in the last case could lead to the conclusion that a symbol
2102-
// from an enclosing construct was declared in the current construct,
2103-
// which would result in wrong privatization code being generated.
2088+
// When handling each implicit rule, either a new private symbol is
2089+
// declared or the last declared symbol is used.
2090+
// In the latter case, it's necessary to insert a new symbol in the scope
2091+
// being processed, associated with the last declared symbol.
2092+
// This captures the fact that, although we are using the last declared
2093+
// symbol, its DSA could be different in this scope.
2094+
// Also, because of how symbols are collected in lowering, not inserting
2095+
// a new symbol in this scope could lead to the conclusion that the
2096+
// symbol was declared in this construct, which would result in wrong
2097+
// privatization code being generated.
21042098
// Consider the following example:
21052099
//
21062100
// !$omp parallel default(private) ! p1
@@ -2113,56 +2107,48 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
21132107
// (p2), it would use the x symbol definition from the enclosing scope.
21142108
// Then, when p2's default symbols were collected in lowering, the x
21152109
// symbol from the outer parallel construct (p1) would be collected, as
2116-
// it would have the private flag set.
2110+
// it would have the private flag set (note that symbols that don't have
2111+
// any private flag are considered as shared).
21172112
// This would make x appear to be defined in p2, causing it to be
21182113
// privatized in p2 and its privatization in p1 to be skipped.
2119-
auto makePrivateSymbol = [&](Symbol::Flag flag) {
2114+
auto declNewSymbol = [&](Symbol::Flag flag) {
21202115
Symbol *hostSymbol =
21212116
lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate();
21222117
lastDeclSymbol = DeclarePrivateAccessEntity(
21232118
*hostSymbol, flag, context_.FindScope(dirContext.directiveSource));
21242119
return lastDeclSymbol;
21252120
};
2126-
auto makeSharedSymbol = [&]() {
2127-
Symbol *hostSymbol =
2128-
lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate();
2129-
MakeAssocSymbol(symbol->name(), *hostSymbol,
2130-
context_.FindScope(dirContext.directiveSource));
2131-
};
21322121
auto useLastDeclSymbol = [&]() {
21332122
if (lastDeclSymbol)
21342123
MakeAssocSymbol(symbol->name(), *lastDeclSymbol,
21352124
context_.FindScope(dirContext.directiveSource));
21362125
};
21372126

2138-
bool taskGenDir = llvm::omp::taskGeneratingSet.test(dirContext.directive);
2139-
bool targetDir = llvm::omp::allTargetSet.test(dirContext.directive);
2140-
bool parallelDir = llvm::omp::allParallelSet.test(dirContext.directive);
2141-
bool teamsDir = llvm::omp::allTeamsSet.test(dirContext.directive);
2142-
21432127
if (dsa.has_value()) {
2144-
if (dsa.value() == Symbol::Flag::OmpShared &&
2145-
(parallelDir || taskGenDir || teamsDir))
2146-
makeSharedSymbol();
2147-
// Private symbols will have been declared already.
2128+
useLastDeclSymbol();
21482129
prevDSA = dsa;
21492130
continue;
21502131
}
21512132

2133+
bool taskGenDir = llvm::omp::taskGeneratingSet.test(dirContext.directive);
2134+
bool targetDir = llvm::omp::allTargetSet.test(dirContext.directive);
2135+
bool parallelDir = llvm::omp::allParallelSet.test(dirContext.directive);
2136+
21522137
if (dirContext.defaultDSA == Symbol::Flag::OmpPrivate ||
21532138
dirContext.defaultDSA == Symbol::Flag::OmpFirstPrivate ||
21542139
dirContext.defaultDSA == Symbol::Flag::OmpShared) {
21552140
// 1) default
21562141
// Allowed only with parallel, teams and task generating constructs.
2157-
assert(parallelDir || taskGenDir || teamsDir);
2142+
assert(parallelDir || taskGenDir ||
2143+
llvm::omp::allTeamsSet.test(dirContext.directive));
21582144
if (dirContext.defaultDSA != Symbol::Flag::OmpShared)
2159-
makePrivateSymbol(dirContext.defaultDSA);
2145+
declNewSymbol(dirContext.defaultDSA);
21602146
else
2161-
makeSharedSymbol();
2147+
useLastDeclSymbol();
21622148
dsa = dirContext.defaultDSA;
21632149
} else if (parallelDir) {
21642150
// 2) parallel -> shared
2165-
makeSharedSymbol();
2151+
useLastDeclSymbol();
21662152
dsa = Symbol::Flag::OmpShared;
21672153
} else if (!taskGenDir && !targetDir) {
21682154
// 3) enclosing context
@@ -2175,12 +2161,12 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
21752161
// TODO 5) dummy arg in orphaned taskgen construct -> firstprivate
21762162
if (prevDSA == Symbol::Flag::OmpShared) {
21772163
// 6) shared in enclosing context -> shared
2178-
makeSharedSymbol();
2164+
useLastDeclSymbol();
21792165
dsa = Symbol::Flag::OmpShared;
21802166
} else {
21812167
// 7) firstprivate
21822168
dsa = Symbol::Flag::OmpFirstPrivate;
2183-
makePrivateSymbol(*dsa)->set(Symbol::Flag::OmpImplicit);
2169+
declNewSymbol(*dsa)->set(Symbol::Flag::OmpImplicit);
21842170
}
21852171
}
21862172
prevDSA = dsa;
@@ -2584,59 +2570,20 @@ void ResolveOmpTopLevelParts(
25842570
});
25852571
}
25862572

2587-
static bool IsSymbolInCommonBlock(const Symbol &symbol) {
2588-
// TODO Improve the performance of this predicate function.
2589-
// Going through all symbols sequentially, in all common blocks, can be
2590-
// slow when there are many symbols. A possible optimization is to add
2591-
// an OmpInCommonBlock flag to Symbol, to make it possible to quickly
2592-
// test if a given symbol is in a common block.
2593-
for (const auto &cb : symbol.owner().commonBlocks()) {
2594-
if (IsCommonBlockContaining(cb.second.get(), symbol)) {
2595-
return true;
2596-
}
2597-
}
2598-
return false;
2599-
}
2600-
2601-
static bool IsSymbolThreadprivate(const Symbol &symbol) {
2573+
void OmpAttributeVisitor::CheckDataCopyingClause(
2574+
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
2575+
const auto *checkSymbol{&symbol};
26022576
if (const auto *details{symbol.detailsIf<HostAssocDetails>()}) {
2603-
return details->symbol().test(Symbol::Flag::OmpThreadprivate);
2604-
}
2605-
return symbol.test(Symbol::Flag::OmpThreadprivate);
2606-
}
2607-
2608-
static bool IsSymbolPrivate(const Symbol &symbol) {
2609-
if (symbol.test(Symbol::Flag::OmpPrivate) ||
2610-
symbol.test(Symbol::Flag::OmpFirstPrivate)) {
2611-
return true;
2612-
}
2613-
// A symbol that has not gone through constructs that may privatize the
2614-
// original symbol may be predetermined as private.
2615-
// (OMP 5.2 5.1.1 - Variables Referenced in a Construct)
2616-
if (symbol == symbol.GetUltimate()) {
2617-
switch (symbol.owner().kind()) {
2618-
case Scope::Kind::MainProgram:
2619-
case Scope::Kind::Subprogram:
2620-
case Scope::Kind::BlockConstruct:
2621-
return !symbol.attrs().test(Attr::SAVE) &&
2622-
!symbol.attrs().test(Attr::PARAMETER) && !IsAssumedShape(symbol) &&
2623-
!IsSymbolInCommonBlock(symbol);
2624-
default:
2625-
return false;
2626-
}
2577+
checkSymbol = &details->symbol();
26272578
}
2628-
return false;
2629-
}
26302579

2631-
void OmpAttributeVisitor::CheckDataCopyingClause(
2632-
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
26332580
if (ompFlag == Symbol::Flag::OmpCopyIn) {
26342581
// List of items/objects that can appear in a 'copyin' clause must be
26352582
// 'threadprivate'
2636-
if (!IsSymbolThreadprivate(symbol)) {
2583+
if (!checkSymbol->test(Symbol::Flag::OmpThreadprivate)) {
26372584
context_.Say(name.source,
26382585
"Non-THREADPRIVATE object '%s' in COPYIN clause"_err_en_US,
2639-
symbol.name());
2586+
checkSymbol->name());
26402587
}
26412588
} else if (ompFlag == Symbol::Flag::OmpCopyPrivate &&
26422589
GetContext().directive == llvm::omp::Directive::OMPD_single) {
@@ -2649,13 +2596,18 @@ void OmpAttributeVisitor::CheckDataCopyingClause(
26492596
"COPYPRIVATE variable '%s' may not appear on a PRIVATE or "
26502597
"FIRSTPRIVATE clause on a SINGLE construct"_err_en_US,
26512598
symbol.name());
2652-
} else if (!IsSymbolThreadprivate(symbol) && !IsSymbolPrivate(symbol)) {
2599+
} else {
26532600
// List of items/objects that can appear in a 'copyprivate' clause must be
26542601
// either 'private' or 'threadprivate' in enclosing context.
2655-
context_.Say(name.source,
2656-
"COPYPRIVATE variable '%s' is not PRIVATE or THREADPRIVATE in "
2657-
"outer context"_err_en_US,
2658-
symbol.name());
2602+
if (!checkSymbol->test(Symbol::Flag::OmpThreadprivate) &&
2603+
!(HasSymbolInEnclosingScope(symbol, currScope()) &&
2604+
(symbol.test(Symbol::Flag::OmpPrivate) ||
2605+
symbol.test(Symbol::Flag::OmpFirstPrivate)))) {
2606+
context_.Say(name.source,
2607+
"COPYPRIVATE variable '%s' is not PRIVATE or THREADPRIVATE in "
2608+
"outer context"_err_en_US,
2609+
symbol.name());
2610+
}
26592611
}
26602612
}
26612613
}
@@ -2725,6 +2677,12 @@ void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source,
27252677
}
27262678
}
27272679

2680+
bool OmpAttributeVisitor::HasSymbolInEnclosingScope(
2681+
const Symbol &symbol, Scope &scope) {
2682+
const auto symbols{scope.parent().GetSymbols()};
2683+
return llvm::is_contained(symbols, symbol);
2684+
}
2685+
27282686
// Goes through the names in an OmpObjectList and checks if each name appears
27292687
// in the given allocate statement
27302688
void OmpAttributeVisitor::CheckAllNamesInAllocateStmt(

flang/test/Semantics/OpenMP/copyprivate04.f90

Lines changed: 0 additions & 112 deletions
This file was deleted.

flang/test/Semantics/OpenMP/do05-positivecase.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ program omp_do
2020
!$omp parallel default(shared)
2121
!$omp do
2222
!DEF: /omp_do/OtherConstruct2/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
23-
!DEF: /omp_do/OtherConstruct2/n HostAssoc INTEGER(4)
23+
!REF: /omp_do/n
2424
do i=1,n
2525
!$omp parallel
2626
!$omp single
2727
!DEF: /work EXTERNAL (Subroutine) ProcEntity
28-
!DEF: /omp_do/OtherConstruct2/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4)
28+
!REF: /omp_do/OtherConstruct2/OtherConstruct1/i
2929
call work(i, 1)
3030
!$omp end single
3131
!$omp end parallel

flang/test/Semantics/OpenMP/do20.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ subroutine shared_iv
1010

1111
!$omp parallel shared(i)
1212
!$omp single
13-
!DEF: /shared_iv/OtherConstruct1/i HostAssoc INTEGER(4)
13+
!REF: /shared_iv/i
1414
do i = 0, 1
1515
end do
1616
!$omp end single

0 commit comments

Comments
 (0)