Skip to content

Commit 8e10a3f

Browse files
[flang][OpenMP] don't privatise loop index marked shared (llvm#108176)
Mark the symbol with OmpShared, and then check that later in lowering to avoid making a local loop index. OpenMP 5.2 says: "Loop iteration variables of loops that are not associated with any OpenMP directive maybe listed in data-sharing attribute clauses on the surrounding teams, parallel or taskgenerating construct, and on enclosed constructs, subject to other restrictions." Tests updated to match the extra OmpShared attribute. Add regression test for lowering to hlfir. Closes llvm#102961 --------- Co-authored-by: Tom Eccles <tom.eccles@arm.com>
1 parent 992a64a commit 8e10a3f

File tree

10 files changed

+143
-17
lines changed

10 files changed

+143
-17
lines changed

flang/lib/Lower/Bridge.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
13171317
bool isUnordered) {
13181318
if (isUnordered || sym.has<Fortran::semantics::HostAssocDetails>() ||
13191319
sym.has<Fortran::semantics::UseDetails>()) {
1320-
if (!shallowLookupSymbol(sym)) {
1320+
if (!shallowLookupSymbol(sym) &&
1321+
!sym.test(Fortran::semantics::Symbol::Flag::OmpShared)) {
13211322
// Do concurrent loop variables are not mapped yet since they are local
13221323
// to the Do concurrent scope (same for OpenMP loops).
13231324
mlir::OpBuilder::InsertPoint insPt = builder->saveInsertionPoint();

flang/lib/Semantics/resolve-directives.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -2121,11 +2121,14 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
21212121
}
21222122
return lastDeclSymbol;
21232123
};
2124-
auto makeSharedSymbol = [&]() {
2124+
auto makeSharedSymbol = [&](std::optional<Symbol::Flag> flag = {}) {
21252125
const Symbol *hostSymbol =
21262126
lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate();
2127-
MakeAssocSymbol(symbol->name(), *hostSymbol,
2127+
Symbol &assocSymbol = MakeAssocSymbol(symbol->name(), *hostSymbol,
21282128
context_.FindScope(dirContext.directiveSource));
2129+
if (flag) {
2130+
assocSymbol.set(*flag);
2131+
}
21292132
};
21302133
auto useLastDeclSymbol = [&]() {
21312134
if (lastDeclSymbol) {
@@ -2140,8 +2143,9 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
21402143

21412144
if (dsa.has_value()) {
21422145
if (dsa.value() == Symbol::Flag::OmpShared &&
2143-
(parallelDir || taskGenDir || teamsDir))
2144-
makeSharedSymbol();
2146+
(parallelDir || taskGenDir || teamsDir)) {
2147+
makeSharedSymbol(Symbol::Flag::OmpShared);
2148+
}
21452149
// Private symbols will have been declared already.
21462150
prevDSA = dsa;
21472151
continue;
@@ -2155,10 +2159,11 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
21552159
if (!parallelDir && !taskGenDir && !teamsDir) {
21562160
return;
21572161
}
2158-
if (dirContext.defaultDSA != Symbol::Flag::OmpShared)
2162+
if (dirContext.defaultDSA != Symbol::Flag::OmpShared) {
21592163
makePrivateSymbol(dirContext.defaultDSA);
2160-
else
2164+
} else {
21612165
makeSharedSymbol();
2166+
}
21622167
dsa = dirContext.defaultDSA;
21632168
} else if (parallelDir) {
21642169
// 2) parallel -> shared
+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
! RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
2+
! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
3+
4+
! --- Check that with shared(i) the variable outside the parallel section
5+
! --- is updated.
6+
! CHECK-LABEL: func.func @_QPomploop()
7+
! CHECK: %[[ALLOC_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomploopEi"}
8+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOC_I]] {uniq_name = "_QFomploopEi"} :
9+
! CHECK: omp.parallel {
10+
! CHECK: omp.sections {
11+
! CHECK: omp.section {
12+
! CHECK: %[[RES:.*]]:2 = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] =
13+
! CHECK: fir.store %[[ARG1]] to %[[DECL_I]]#1
14+
! CHECK: %[[UPDATE_ITER:.*]] = arith.addi %[[ARG0]], %{{.*}}
15+
! CHECK: %[[LOAD_I:.*]] = fir.load %[[DECL_I]]#1
16+
! CHECK: %[[RES_I:.*]] = arith.addi %[[LOAD_I]], %{{.*}}
17+
! CHECK: fir.result %[[UPDATE_ITER]], %[[RES_I]]
18+
! CHECK: }
19+
! CHECK: fir.store %[[RES]]#1 to %[[DECL_I]]#1
20+
! CHECK: omp.terminator
21+
! CHECK: }
22+
! CHECK: omp.terminator
23+
! CHECK: }
24+
! CHECK: return
25+
! CHECK: }
26+
subroutine omploop
27+
implicit none
28+
integer :: i, j
29+
i = 1
30+
j = 0
31+
!$omp parallel shared(i)
32+
!$omp sections
33+
do i=1,10
34+
j = j + i
35+
end do
36+
!$omp end sections
37+
!$omp end parallel
38+
end subroutine
39+
40+
! --- Check that with default(shared) the variable outside the parallel section
41+
! --- is NOT updated (i is private to the omp.parallel code)
42+
! CHECK-LABEL: func.func @_QPomploop2()
43+
! CHECK: %[[ALLOC_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomploop2Ei"}
44+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOC_I]] {uniq_name = "_QFomploop2Ei"} :
45+
! CHECK: omp.parallel {
46+
! CHECK: %[[ALLOC_PRIV_I:.*]] = fir.alloca i32 {bindc_name = "i", pinned}
47+
! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
48+
! CHECK: omp.sections {
49+
! CHECK: omp.section {
50+
! CHECK: %[[RES:.*]]:2 = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] =
51+
! CHECK-NOT: fir.store %[[ARG1]] to %[[DECL_I]]#1
52+
! CHECK: fir.store %[[ARG1]] to %[[DECL_PRIV_I]]#1
53+
! CHECK: %[[UPDATE_ITER:.*]] = arith.addi %[[ARG0]], %{{.*}}
54+
! CHECK: %[[LOAD_I:.*]] = fir.load %[[DECL_PRIV_I]]#1
55+
! CHECK: %[[RES_I:.*]] = arith.addi %[[LOAD_I]], %{{.*}}
56+
! CHECK: fir.result %[[UPDATE_ITER]], %[[RES_I]]
57+
! CHECK: }
58+
! CHECK: fir.store %[[RES]]#1 to %[[DECL_PRIV_I]]#1
59+
! CHECK: omp.terminator
60+
! CHECK: }
61+
! CHECK: omp.terminator
62+
! CHECK: }
63+
! CHECK: return
64+
! CHECK: }
65+
subroutine omploop2
66+
implicit none
67+
integer :: i, j
68+
i = 1
69+
j = 0
70+
!$omp parallel default(shared)
71+
!$omp sections
72+
do i=1,10
73+
j = j + i
74+
end do
75+
!$omp end sections
76+
!$omp end parallel
77+
end subroutine
78+
79+
80+
! --- Check that with no data-sharing the variable outside the parallel section
81+
! --- is NOT updated (i is private to the omp.parallel code)
82+
! CHECK-LABEL: func.func @_QPomploop3()
83+
! CHECK: %[[ALLOC_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomploop3Ei"}
84+
! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOC_I]] {uniq_name = "_QFomploop3Ei"} :
85+
! CHECK: omp.parallel {
86+
! CHECK: %[[ALLOC_PRIV_I:.*]] = fir.alloca i32 {bindc_name = "i", pinned}
87+
! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[ALLOC_PRIV_I]]
88+
! CHECK: omp.sections {
89+
! CHECK: omp.section {
90+
! CHECK: %[[RES:.*]]:2 = fir.do_loop %[[ARG0:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[ARG1:.*]] =
91+
! CHECK-NOT: fir.store %[[ARG1]] to %[[DECL_I]]#1
92+
! CHECK: fir.store %[[ARG1]] to %[[DECL_PRIV_I]]#1
93+
! CHECK: %[[UPDATE_ITER:.*]] = arith.addi %[[ARG0]], %{{.*}}
94+
! CHECK: %[[LOAD_I:.*]] = fir.load %[[DECL_PRIV_I]]#1
95+
! CHECK: %[[RES_I:.*]] = arith.addi %[[LOAD_I]], %{{.*}}
96+
! CHECK: fir.result %[[UPDATE_ITER]], %[[RES_I]]
97+
! CHECK: }
98+
! CHECK: fir.store %[[RES]]#1 to %[[DECL_PRIV_I]]#1
99+
! CHECK: omp.terminator
100+
! CHECK: }
101+
! CHECK: omp.terminator
102+
! CHECK: }
103+
! CHECK: return
104+
! CHECK: }
105+
subroutine omploop3
106+
implicit none
107+
integer :: i, j
108+
i = 1
109+
j = 0
110+
!$omp parallel
111+
!$omp sections
112+
do i=1,10
113+
j = j + i
114+
end do
115+
!$omp end sections
116+
!$omp end parallel
117+
end subroutine
118+
119+
120+

flang/test/Semantics/OpenMP/do20.f90

+1-1
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+
!DEF: /shared_iv/OtherConstruct1/i (OmpShared) HostAssoc INTEGER(4)
1414
do i = 0, 1
1515
end do
1616
!$omp end single

flang/test/Semantics/OpenMP/implicit-dsa.f90

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ subroutine implicit_dsa_test1
1515
!$omp task private(y) shared(z)
1616
!DEF: /implicit_dsa_test1/OtherConstruct1/x (OmpFirstPrivate, OmpImplicit) HostAssoc INTEGER(4)
1717
!DEF: /implicit_dsa_test1/OtherConstruct1/y (OmpPrivate) HostAssoc INTEGER(4)
18-
!DEF: /implicit_dsa_test1/OtherConstruct1/z HostAssoc INTEGER(4)
18+
!DEF: /implicit_dsa_test1/OtherConstruct1/z (OmpShared) HostAssoc INTEGER(4)
1919
x = y + z
2020
!$omp end task
2121

@@ -133,7 +133,7 @@ subroutine implicit_dsa_test6
133133
!$omp end parallel
134134

135135
!$omp parallel default(firstprivate) shared(y)
136-
!DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/y HostAssoc INTEGER(4)
136+
!DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/y (OmpShared) HostAssoc INTEGER(4)
137137
!DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/x (OmpFirstPrivate) HostAssocINTEGER(4)
138138
!DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/z (OmpFirstPrivate) HostAssocINTEGER(4)
139139
y = x + z

flang/test/Semantics/OpenMP/symbol01.f90

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ program mm
6262
!REF: /mm/OtherConstruct1/i
6363
!REF: /mm/OtherConstruct1/y
6464
x = a+i+y
65-
!DEF: /mm/OtherConstruct1/c HostAssoc REAL(4)
65+
!DEF: /mm/OtherConstruct1/c (OmpShared) HostAssoc REAL(4)
6666
c = 3.0
6767
end do
6868
end program

flang/test/Semantics/OpenMP/symbol02.f90

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
a = 3.
1616
!DEF: /MainProgram1/OtherConstruct1/b (OmpPrivate) HostAssoc REAL(4)
1717
b = 4
18-
!DEF: /MainProgram1/OtherConstruct1/c HostAssoc REAL(4)
18+
!DEF: /MainProgram1/OtherConstruct1/c (OmpShared) HostAssoc REAL(4)
1919
c = 5
20-
!DEF: /MainProgram1/OtherConstruct1/d HostAssoc REAL(4)
20+
!DEF: /MainProgram1/OtherConstruct1/d (OmpShared) HostAssoc REAL(4)
2121
d = 6
2222
!$omp end parallel
2323
!DEF: /MainProgram1/a (Implicit) ObjectEntity REAL(4)

flang/test/Semantics/OpenMP/symbol03.f90

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
!$omp parallel private(a) shared(b)
1010
!DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4)
1111
a = 3.
12-
!DEF: /MainProgram1/OtherConstruct1/b HostAssoc REAL(4)
12+
!DEF: /MainProgram1/OtherConstruct1/b (OmpShared) HostAssoc REAL(4)
1313
b = 4
1414
!$omp parallel private(b) shared(a)
15-
!DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/a HostAssoc REAL(4)
15+
!DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/a (OmpShared) HostAssoc REAL(4)
1616
a = 5.
1717
!DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/b (OmpPrivate) HostAssoc REAL(4)
1818
b = 6

flang/test/Semantics/OpenMP/symbol07.f90

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ subroutine function_call_in_region
2323
!$omp parallel default(none) private(a) shared(b)
2424
!DEF: /function_call_in_region/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4)
2525
!REF: /function_call_in_region/foo
26-
!DEF: /function_call_in_region/OtherConstruct1/b HostAssoc REAL(4)
26+
!DEF: /function_call_in_region/OtherConstruct1/b (OmpShared) HostAssoc REAL(4)
2727
a = foo(b)
2828
!$omp end parallel
2929
!REF: /function_call_in_region/a

flang/test/Semantics/OpenMP/symbol09.f90

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ subroutine function_call_in_region
2323
!$omp parallel default(none) private(a) shared(b)
2424
!DEF: /function_call_in_region/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4)
2525
!REF: /function_call_in_region/foo
26-
!DEF: /function_call_in_region/OtherConstruct1/b HostAssoc REAL(4)
26+
!DEF: /function_call_in_region/OtherConstruct1/b (OmpShared) HostAssoc REAL(4)
2727
a = foo(b)
2828
!$omp end parallel
2929
!REF: /function_call_in_region/a

0 commit comments

Comments
 (0)