forked from OSchip/llvm-project
[flang] [OpenMP] OmpVisitor framework for Name Resolution
This is a preliminary framework to do the name resolution for data references on the OpenMP clauses. Unlike data references in the OpenMP region, clauses determining the data-sharing or data-mapping attributes are straightforward and the resolution process could be extended to do the name resolution in the OpenMP region. It is hard to determine what kind of checks can be done in this visitor and what checks should be done later after name resolution. But the guide line is that `After the completion of this phase, every Name corresponds to a Symbol with proper OpenMP attribute(s) determined unless an error occurred.` 1. Take data-sharing clauses as example, create new symbol for variable that require private access within the OpenMP region. Declare the entity implicitly if necessary. The new symbol has `HostAssocDetails`, which is mentioned in the `OpenMP-semantics.md`. 2. For `Shared` or `ThreadPrivate`, no symbol needs to be created. OpenMP attribute Flag `OmpThreadprivate` needs to be marked for `Threadprivate` because the `threadprivate` attribute remains the same whenever these variables are referenced in the program. `Names` in `Shared` clause need to be resolved to associate the symbols in the clause enclosing scope (contains the OpenMP directive) but `OmpShared` does not need to be marked. Declare the entity implicitly if necessary. 3. For `COMMON block`, when a named common block appears in a list, it has the same meaning as if every explicit member of the common block appeared in the list. Also, a common block name specified in a data-sharing attribute clause must be declared to be a common block in the same scoping unit in which the data-sharing attribute clause appears. So, if a named common block appears on a `PRIVATE` clause, all its members should have new symbols created within the OpenMP region (scope). For later Semantic checks and CG, a new symbol is also created for common block name with `HostAssocDetails`. There are many things are still on the TODO list: - Better error/warning messages with directive/clause source provenance - Resolve variables referenced in the OpenMP region, for example, `private(tt%a)` is not allowed but `tt%a = 1` is allowed in the OpenMP region and a private version of `tt` maybe created for the region. The functions created in the `OmpVisitor` should be able to handle the name resolution on the statement too (more data structures may be introduced). This is a big portion and may require some interface changes to distinguish a reference is on `OpenMP directive/clause` or `statements within OpenMP region`. - Same data reference appears on multiple data-sharing clauses. - Take association into consideration for example Pointer association, `ASSOCIATE` construct, and etc. - Handle `Array Sections` and `Array or Structure Element`. - Handle all the name resolution for directives/clauses that have `parser::Name`. - More tests Original-commit: flang-compiler/f18@b2ea520885
This commit is contained in:
parent
f6a5a3f45e
commit
4ca8c5dc5c
|
@ -929,7 +929,7 @@ private:
|
|||
|
||||
// Resolve construct entities and statement entities.
|
||||
// Check that construct names don't conflict with other names.
|
||||
class ConstructVisitor : public DeclarationVisitor {
|
||||
class ConstructVisitor : public virtual DeclarationVisitor {
|
||||
public:
|
||||
bool Pre(const parser::ConcurrentHeader &);
|
||||
bool Pre(const parser::LocalitySpec::Local &);
|
||||
|
@ -1037,11 +1037,201 @@ private:
|
|||
void PopAssociation();
|
||||
};
|
||||
|
||||
static const parser::Name *GetDesignatorNameIf(
|
||||
const parser::Designator &designator) {
|
||||
const auto *dataRef{std::get_if<parser::DataRef>(&designator.u)};
|
||||
return dataRef ? std::get_if<parser::Name>(&dataRef->u) : nullptr;
|
||||
}
|
||||
|
||||
static constexpr Symbol::Flags ompFlagsRequireNewSymbol{
|
||||
Symbol::Flag::OmpPrivate, Symbol::Flag::OmpLinear,
|
||||
Symbol::Flag::OmpFirstPrivate, Symbol::Flag::OmpLastPrivate,
|
||||
Symbol::Flag::OmpReduction};
|
||||
|
||||
static constexpr Symbol::Flags ompFlagsRequireMark{
|
||||
Symbol::Flag::OmpThreadprivate};
|
||||
|
||||
// Resolve OpenMP construct entities and statement (TODO) entities
|
||||
class OmpVisitor : public virtual DeclarationVisitor {
|
||||
public:
|
||||
bool Pre(const parser::OpenMPBlockConstruct &) {
|
||||
PushScope(Scope::Kind::Block, nullptr);
|
||||
return true;
|
||||
}
|
||||
void Post(const parser::OpenMPBlockConstruct &) { PopScope(); }
|
||||
bool Pre(const parser::OpenMPLoopConstruct &) {
|
||||
PushScope(Scope::Kind::Block, nullptr);
|
||||
return true;
|
||||
}
|
||||
void Post(const parser::OpenMPLoopConstruct &) { PopScope(); }
|
||||
|
||||
bool Pre(const parser::OpenMPThreadprivate &x) {
|
||||
PushScope(Scope::Kind::Block, nullptr);
|
||||
const auto &list{std::get<parser::OmpObjectList>(x.t)};
|
||||
ResolveOmpObjectList(list, Symbol::Flag::OmpThreadprivate);
|
||||
PopScope();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Pre(const parser::OmpClause::Shared &x) {
|
||||
ResolveOmpObjectList(x.v, Symbol::Flag::OmpShared);
|
||||
return false;
|
||||
}
|
||||
bool Pre(const parser::OmpClause::Private &x) {
|
||||
ResolveOmpObjectList(x.v, Symbol::Flag::OmpPrivate);
|
||||
return false;
|
||||
}
|
||||
bool Pre(const parser::OmpClause::Firstprivate &x) {
|
||||
ResolveOmpObjectList(x.v, Symbol::Flag::OmpFirstPrivate);
|
||||
return false;
|
||||
}
|
||||
bool Pre(const parser::OmpClause::Lastprivate &x) {
|
||||
ResolveOmpObjectList(x.v, Symbol::Flag::OmpLastPrivate);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
// TODO: resolve variables referenced in the OpenMP region
|
||||
void ResolveOmpObjectList(const parser::OmpObjectList &, Symbol::Flag);
|
||||
void ResolveOmpObject(const parser::OmpObject &, Symbol::Flag);
|
||||
Symbol *ResolveOmp(const parser::Name &, Symbol::Flag);
|
||||
Symbol *ResolveOmp(Symbol &, Symbol::Flag);
|
||||
Symbol *ResolveOmpCommonBlockName(const parser::Name *, Symbol::Flag);
|
||||
Symbol *DeclarePrivateAccessEntity(const parser::Name &, Symbol::Flag);
|
||||
Symbol *DeclarePrivateAccessEntity(Symbol &, Symbol::Flag);
|
||||
Symbol *DeclareOrMarkOtherAccessEntity(const parser::Name &, Symbol::Flag);
|
||||
Symbol *DeclareOrMarkOtherAccessEntity(Symbol &, Symbol::Flag);
|
||||
};
|
||||
|
||||
Symbol *OmpVisitor::ResolveOmpCommonBlockName(
|
||||
const parser::Name *name, Symbol::Flag ompFlag) {
|
||||
if (auto *prev{name ? currScope().parent().FindCommonBlock(name->source)
|
||||
: nullptr}) {
|
||||
auto *created{FindInScope(currScope(), name->source)};
|
||||
if (!created) {
|
||||
auto &symbol{MakeSymbol(*name, HostAssocDetails{*prev})};
|
||||
symbol.set(ompFlag);
|
||||
name->symbol = &symbol;
|
||||
} else {
|
||||
name->symbol = created;
|
||||
}
|
||||
return prev;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OmpVisitor::ResolveOmpObjectList(
|
||||
const parser::OmpObjectList &ompObjectList, Symbol::Flag ompFlag) {
|
||||
for (const auto &ompObject : ompObjectList.v) {
|
||||
ResolveOmpObject(ompObject, ompFlag);
|
||||
}
|
||||
}
|
||||
|
||||
void OmpVisitor::ResolveOmpObject(
|
||||
const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
|
||||
const auto &kind{std::get<parser::OmpObject::Kind>(ompObject.t)};
|
||||
const auto &designator{std::get<parser::Designator>(ompObject.t)};
|
||||
const auto *name{GetDesignatorNameIf(designator)};
|
||||
if (kind == parser::OmpObject::Kind::Object) {
|
||||
if (name) {
|
||||
ResolveOmp(*name, ompFlag);
|
||||
} else if (const auto *designatorName{ResolveDesignator(designator)};
|
||||
designatorName->symbol) {
|
||||
if (const auto *details{
|
||||
designatorName->symbol->detailsIf<ObjectEntityDetails>()}) {
|
||||
if (details->IsArray()) {
|
||||
// TODO: check Array Sections
|
||||
} else if (designatorName->symbol->owner().IsDerivedType()) {
|
||||
// TODO: check Structure Component
|
||||
} else {
|
||||
Say(designatorName->source,
|
||||
"Fortran Substrings are not allowed on OpenMP "
|
||||
"directives or clauses"_err_en_US);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // common block
|
||||
if (auto *symbol{ResolveOmpCommonBlockName(name, ompFlag)}) {
|
||||
// 2.15.3 When a named common block appears in a list, it has the same
|
||||
// meaning as if every explicit member of the common block appeared in
|
||||
// the list
|
||||
for (Symbol *object : symbol->get<CommonBlockDetails>().objects()) {
|
||||
ResolveOmp(*object, ompFlag);
|
||||
}
|
||||
} else {
|
||||
Say(designator.source, // 2.15.3
|
||||
"COMMON block must be declared in the same scoping unit "
|
||||
"in which the directive or clause appears"_err_en_US);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *OmpVisitor::ResolveOmp(const parser::Name &name, Symbol::Flag ompFlag) {
|
||||
if (ompFlagsRequireNewSymbol.test(ompFlag)) {
|
||||
return DeclarePrivateAccessEntity(name, ompFlag);
|
||||
} else {
|
||||
return DeclareOrMarkOtherAccessEntity(name, ompFlag);
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *OmpVisitor::ResolveOmp(Symbol &symbol, Symbol::Flag ompFlag) {
|
||||
if (ompFlagsRequireNewSymbol.test(ompFlag)) {
|
||||
return DeclarePrivateAccessEntity(symbol, ompFlag);
|
||||
} else {
|
||||
return DeclareOrMarkOtherAccessEntity(symbol, ompFlag);
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *OmpVisitor::DeclarePrivateAccessEntity(
|
||||
const parser::Name &name, Symbol::Flag ompFlag) {
|
||||
Symbol &prev{FindOrDeclareEnclosingEntity(name)};
|
||||
if (prev.owner() != currScope()) {
|
||||
auto &symbol{MakeSymbol(name, HostAssocDetails{prev})};
|
||||
symbol.set(ompFlag);
|
||||
name.symbol = &symbol; // override resolution to parent
|
||||
return &symbol;
|
||||
} else {
|
||||
return &prev;
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *OmpVisitor::DeclarePrivateAccessEntity(
|
||||
Symbol &object, Symbol::Flag ompFlag) {
|
||||
if (object.owner() != currScope() &&
|
||||
!FindInScope(currScope(), object.name())) {
|
||||
auto &symbol{MakeSymbol(object.name(), Attrs{}, HostAssocDetails{object})};
|
||||
symbol.set(ompFlag);
|
||||
return &symbol;
|
||||
} else {
|
||||
return &object;
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *OmpVisitor::DeclareOrMarkOtherAccessEntity(
|
||||
const parser::Name &name, Symbol::Flag ompFlag) {
|
||||
Symbol &prev{FindOrDeclareEnclosingEntity(name)};
|
||||
name.symbol = &prev;
|
||||
if (ompFlagsRequireMark.test(ompFlag)) {
|
||||
prev.set(ompFlag);
|
||||
}
|
||||
return &prev;
|
||||
}
|
||||
|
||||
Symbol *OmpVisitor::DeclareOrMarkOtherAccessEntity(
|
||||
Symbol &object, Symbol::Flag ompFlag) {
|
||||
if (ompFlagsRequireMark.test(ompFlag)) {
|
||||
object.set(ompFlag);
|
||||
}
|
||||
return &object;
|
||||
}
|
||||
|
||||
// Walk the parse tree and resolve names to symbols.
|
||||
class ResolveNamesVisitor : public virtual ScopeHandler,
|
||||
public ModuleVisitor,
|
||||
public SubprogramVisitor,
|
||||
public ConstructVisitor {
|
||||
public ConstructVisitor,
|
||||
public OmpVisitor {
|
||||
public:
|
||||
using ArraySpecVisitor::Post;
|
||||
using ConstructVisitor::Post;
|
||||
|
@ -1054,6 +1244,8 @@ public:
|
|||
using InterfaceVisitor::Pre;
|
||||
using ModuleVisitor::Post;
|
||||
using ModuleVisitor::Pre;
|
||||
using OmpVisitor::Post;
|
||||
using OmpVisitor::Pre;
|
||||
using ScopeHandler::Post;
|
||||
using ScopeHandler::Pre;
|
||||
using SubprogramVisitor::Post;
|
||||
|
|
|
@ -450,8 +450,15 @@ public:
|
|||
CrayPointer, CrayPointee,
|
||||
LocalityLocal, // named in LOCAL locality-spec
|
||||
LocalityLocalInit, // named in LOCAL_INIT locality-spec
|
||||
LocalityShared // named in SHARED locality-spec
|
||||
);
|
||||
LocalityShared, // named in SHARED locality-spec
|
||||
|
||||
// OpenMP data-sharing attribute
|
||||
OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
|
||||
// OpenMP data-mapping attribute
|
||||
OmpMapTo, OmpMapFrom, OmpMapAlloc, OmpMapRelease, OmpMapDelete,
|
||||
// OpenMP miscellaneous flags
|
||||
OmpReduction, OmpDeclareSimd, OmpDeclareTarget, OmpThreadprivate,
|
||||
OmpDeclareReduction, OmpFlushed, OmpCriticalLock, OmpIfSpecified);
|
||||
using Flags = common::EnumSet<Flag, Flag_enumSize>;
|
||||
|
||||
const Scope &owner() const { return *owner_; }
|
||||
|
|
|
@ -41,6 +41,16 @@ public:
|
|||
template<typename T> void Post(const parser::Statement<T> &) {
|
||||
currStmt_ = std::nullopt;
|
||||
}
|
||||
bool Pre(const parser::OmpClause &clause) {
|
||||
currStmt_ = clause.source;
|
||||
return true;
|
||||
}
|
||||
void Post(const parser::OmpClause &) { currStmt_ = std::nullopt; }
|
||||
bool Pre(const parser::OpenMPThreadprivate &dir) {
|
||||
currStmt_ = dir.source;
|
||||
return true;
|
||||
}
|
||||
void Post(const parser::OpenMPThreadprivate &) { currStmt_ = std::nullopt; }
|
||||
void Post(const parser::Name &name);
|
||||
|
||||
private:
|
||||
|
|
|
@ -154,6 +154,13 @@ set(ERROR_TESTS
|
|||
expr-errors01.f90
|
||||
expr-errors02.f90
|
||||
null01.f90
|
||||
omp-resolve01.f90
|
||||
omp-resolve02.f90
|
||||
omp-symbol01.f90
|
||||
omp-symbol02.f90
|
||||
omp-symbol03.f90
|
||||
omp-symbol04.f90
|
||||
omp-symbol05.f90
|
||||
omp-clause-validity01.f90
|
||||
omp-loop-association.f90
|
||||
# omp-nested01.f90
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! 2.4 An array section designates a subset of the elements in an array. Although
|
||||
! Substring shares similar syntax but cannot be treated as valid array section.
|
||||
|
||||
character*8 c, b
|
||||
character a
|
||||
|
||||
b = "HIFROMPGI"
|
||||
c = b(2:7)
|
||||
!ERROR: Fortran Substrings are not allowed on OpenMP directives or clauses
|
||||
!$omp parallel private(c(1:3))
|
||||
a = c(1:1)
|
||||
!$omp end parallel
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! Test the effect to name resolution from illegal clause
|
||||
|
||||
!a = 1.0
|
||||
b = 2
|
||||
!$omp parallel private(a) shared(b)
|
||||
a = 3.
|
||||
b = 4
|
||||
!ERROR: LASTPRIVATE clause is not allowed on the PARALLEL directive
|
||||
!$omp parallel private(a) shared(b) lastprivate(a)
|
||||
a = 5.
|
||||
b = 6
|
||||
!$omp end parallel
|
||||
!$omp end parallel
|
||||
print *,a, b
|
||||
end
|
|
@ -0,0 +1,80 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! Test clauses that accept list.
|
||||
! 2.1 Directive Format
|
||||
! A list consists of a comma-separated collection of one or more list items.
|
||||
! A list item is a variable, array section or common block name (enclosed in
|
||||
! slashes).
|
||||
|
||||
!DEF: /md Module
|
||||
module md
|
||||
!DEF: /md/myty PUBLIC DerivedType
|
||||
type :: myty
|
||||
!DEF: /md/myty/a ObjectEntity REAL(4)
|
||||
real :: a
|
||||
!DEF: /md/myty/b ObjectEntity INTEGER(4)
|
||||
integer :: b
|
||||
end type myty
|
||||
end module md
|
||||
!DEF: /mm MainProgram
|
||||
program mm
|
||||
!REF: /md
|
||||
use :: md
|
||||
!DEF: /mm/c CommonBlockDetails
|
||||
!DEF: /mm/x ObjectEntity REAL(4)
|
||||
!DEF: /mm/y ObjectEntity REAL(4)
|
||||
common /c/x, y
|
||||
!REF: /mm/x
|
||||
!REF: /mm/y
|
||||
real x, y
|
||||
!DEF: /mm/myty Use
|
||||
!DEF: /mm/t ObjectEntity TYPE(myty)
|
||||
type(myty) :: t
|
||||
!DEF: /mm/b ObjectEntity INTEGER(4)
|
||||
integer b(10)
|
||||
!REF: /mm/t
|
||||
!REF: /md/myty/a
|
||||
t%a = 3.14
|
||||
!REF: /mm/t
|
||||
!REF: /md/myty/b
|
||||
t%b = 1
|
||||
!REF: /mm/b
|
||||
b = 2
|
||||
!DEF: /mm/a (Implicit) ObjectEntity REAL(4)
|
||||
a = 1.0
|
||||
!DEF: /mm/c (Implicit) ObjectEntity REAL(4)
|
||||
c = 2.0
|
||||
!$omp parallel do private(a,t,/c/)
|
||||
!DEF: /mm/i (Implicit) ObjectEntity INTEGER(4)
|
||||
do i=1,10
|
||||
!DEF: /mm/Block1/a (OmpPrivate) HostAssoc REAL(4)
|
||||
!REF: /mm/b
|
||||
!REF: /mm/i
|
||||
a = a+b(i)
|
||||
!DEF: /mm/Block1/t (OmpPrivate) HostAssoc TYPE(myty)
|
||||
!REF: /md/myty/a
|
||||
!REF: /mm/i
|
||||
t%a = i
|
||||
!DEF: /mm/Block1/y (OmpPrivate) HostAssoc REAL(4)
|
||||
y = 0.
|
||||
!DEF: /mm/Block1/x (OmpPrivate) HostAssoc REAL(4)
|
||||
!REF: /mm/Block1/a
|
||||
!REF: /mm/i
|
||||
!REF: /mm/Block1/y
|
||||
x = a+i+y
|
||||
end do
|
||||
end program
|
|
@ -0,0 +1,39 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! 1.4.1 Structure of the OpenMP Memory Model
|
||||
|
||||
! Test implicit declaration in the OpenMP directive enclosing scope
|
||||
! through clause; also test to avoid creating multiple symbols for
|
||||
! the same variable
|
||||
|
||||
!DEF: /MainProgram1/b (Implicit) ObjectEntity REAL(4)
|
||||
b = 2
|
||||
!DEF: /MainProgram1/c (Implicit) ObjectEntity REAL(4)
|
||||
c = 0
|
||||
!$omp parallel private(a,b) shared(c,c,d,d)
|
||||
!DEF: /MainProgram1/Block1/a (OmpPrivate) HostAssoc REAL(4)
|
||||
a = 3.
|
||||
!DEF: /MainProgram1/Block1/b (OmpPrivate) HostAssoc REAL(4)
|
||||
b = 4
|
||||
!REF: /MainProgram1/c
|
||||
c = 5
|
||||
!DEF: /MainProgram1/d (Implicit) ObjectEntity REAL(4)
|
||||
d = 6
|
||||
!$omp end parallel
|
||||
!DEF: /MainProgram1/a (Implicit) ObjectEntity REAL(4)
|
||||
print *, a
|
||||
end program
|
|
@ -0,0 +1,38 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! 1.4.1 Structure of the OpenMP Memory Model
|
||||
! In the inner OpenMP region, SHARED `a` refers to the `a` in the outer OpenMP
|
||||
! region; PRIVATE `b` refers to the new `b` in the same OpenMP region
|
||||
|
||||
!DEF: /MainProgram1/b (Implicit) ObjectEntity REAL(4)
|
||||
b = 2
|
||||
!$omp parallel private(a) shared(b)
|
||||
!DEF: /MainProgram1/Block1/a (OmpPrivate) HostAssoc REAL(4)
|
||||
a = 3.
|
||||
!REF: /MainProgram1/b
|
||||
b = 4
|
||||
!$omp parallel private(b) shared(a)
|
||||
!REF: /MainProgram1/Block1/a
|
||||
a = 5.
|
||||
!DEF: /MainProgram1/Block1/Block1/b (OmpPrivate) HostAssoc REAL(4)
|
||||
b = 6
|
||||
!$omp end parallel
|
||||
!$omp end parallel
|
||||
!DEF: /MainProgram1/a (Implicit) ObjectEntity REAL(4)
|
||||
!REF: /MainProgram1/b
|
||||
print *, a, b
|
||||
end program
|
|
@ -0,0 +1,37 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! 2.15.3 Data-Sharing Attribute Clauses
|
||||
! Both PARALLEL and DO (worksharing) directives need to create new scope,
|
||||
! so PRIVATE `a` will have new symbol in each region
|
||||
|
||||
!DEF: /MainProgram1/a ObjectEntity REAL(8)
|
||||
real*8 a
|
||||
!REF: /MainProgram1/a
|
||||
a = 3.14
|
||||
!$omp parallel private(a)
|
||||
!DEF: /MainProgram1/Block1/a (OmpPrivate) HostAssoc REAL(8)
|
||||
a = 2.
|
||||
!$omp do private(a)
|
||||
!DEF: /MainProgram1/i (Implicit) ObjectEntity INTEGER(4)
|
||||
do i=1,10
|
||||
!DEF: /MainProgram1/Block1/Block1/a (OmpPrivate) HostAssoc REAL(8)
|
||||
a = 1.
|
||||
end do
|
||||
!$omp end parallel
|
||||
!REF: /MainProgram1/a
|
||||
print *, a
|
||||
end program
|
|
@ -0,0 +1,54 @@
|
|||
! Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
!
|
||||
! Licensed under the Apache License, Version 2.0 (the "License");
|
||||
! you may not use this file except in compliance with the License.
|
||||
! You may obtain a copy of the License at
|
||||
!
|
||||
! http://www.apache.org/licenses/LICENSE-2.0
|
||||
!
|
||||
! Unless required by applicable law or agreed to in writing, software
|
||||
! distributed under the License is distributed on an "AS IS" BASIS,
|
||||
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
! See the License for the specific language governing permissions and
|
||||
! limitations under the License.
|
||||
|
||||
!OPTIONS: -fopenmp
|
||||
|
||||
! 2.15.2 threadprivate Directive
|
||||
! The threadprivate directive specifies that variables are replicated,
|
||||
! with each thread having its own copy. When threadprivate variables are
|
||||
! referenced in the OpenMP region, we know they are already private to
|
||||
! their threads, so no new symbol needs to be created.
|
||||
|
||||
!DEF: /mm Module
|
||||
module mm
|
||||
!$omp threadprivate (i)
|
||||
contains
|
||||
!DEF: /mm/foo PUBLIC (Subroutine) Subprogram
|
||||
subroutine foo
|
||||
!DEF: /mm/foo/a ObjectEntity INTEGER(4)
|
||||
integer :: a = 3
|
||||
!$omp parallel
|
||||
!REF: /mm/foo/a
|
||||
a = 1
|
||||
!DEF: /mm/i PUBLIC (Implicit, OmpThreadprivate) ObjectEntity INTEGER(4)
|
||||
!REF: /mm/foo/a
|
||||
i = a
|
||||
!$omp end parallel
|
||||
!REF: /mm/foo/a
|
||||
print *, a
|
||||
block
|
||||
!DEF: /mm/foo/Block2/i ObjectEntity REAL(4)
|
||||
real i
|
||||
!REF: /mm/foo/Block2/i
|
||||
i = 3.14
|
||||
end block
|
||||
end subroutine foo
|
||||
end module mm
|
||||
!DEF: /tt MainProgram
|
||||
program tt
|
||||
!REF: /mm
|
||||
use :: mm
|
||||
!DEF: /tt/foo (Subroutine) Use
|
||||
call foo
|
||||
end program tt
|
Loading…
Reference in New Issue