Skip to content

Commit 29f5d5b

Browse files
authored
[flang][OpenMP] Fix privatization of procedure pointers (#130336)
Fixes #121720
1 parent 1b455df commit 29f5d5b

File tree

4 files changed

+251
-61
lines changed

4 files changed

+251
-61
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
12741274
[](const fir::FortranVariableOpInterface &box) {
12751275
return fir::FortranVariableOpInterface(box).isPointer();
12761276
},
1277+
[](const fir::AbstractBox &box) {
1278+
return fir::isBoxProcAddressType(box.getAddr().getType());
1279+
},
12771280
[](const auto &box) { return false; });
12781281

12791282
copyVarHLFIR(loc, dst, src, isBoxAllocatable, isBoxPointer, flags);

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ void Fortran::lower::genDeclareSymbol(
18431843
bool force) {
18441844
if (converter.getLoweringOptions().getLowerToHighLevelFIR() &&
18451845
(!Fortran::semantics::IsProcedure(sym) ||
1846-
Fortran::semantics::IsPointer(sym)) &&
1846+
Fortran::semantics::IsPointer(sym.GetUltimate())) &&
18471847
!sym.detailsIf<Fortran::semantics::CommonBlockDetails>()) {
18481848
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
18491849
const mlir::Location loc = genLocation(converter, sym);

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -554,70 +554,92 @@ std::string getTypeAsString(mlir::Type ty, const fir::KindMapping &kindMap,
554554
llvm::raw_string_ostream name{buf};
555555
if (!prefix.empty())
556556
name << "_";
557-
while (ty) {
558-
if (fir::isa_trivial(ty)) {
559-
if (mlir::isa<mlir::IndexType>(ty)) {
560-
name << "idx";
561-
} else if (ty.isIntOrIndex()) {
562-
name << 'i' << ty.getIntOrFloatBitWidth();
563-
} else if (mlir::isa<mlir::FloatType>(ty)) {
564-
name << 'f' << ty.getIntOrFloatBitWidth();
565-
} else if (auto cplxTy = mlir::dyn_cast_or_null<mlir::ComplexType>(ty)) {
566-
name << 'z';
567-
auto floatTy = mlir::cast<mlir::FloatType>(cplxTy.getElementType());
568-
name << floatTy.getWidth();
569-
} else if (auto logTy = mlir::dyn_cast_or_null<fir::LogicalType>(ty)) {
570-
name << 'l' << kindMap.getLogicalBitsize(logTy.getFKind());
557+
558+
std::function<void(mlir::Type)> appendTypeName = [&](mlir::Type ty) {
559+
while (ty) {
560+
if (fir::isa_trivial(ty)) {
561+
if (mlir::isa<mlir::IndexType>(ty)) {
562+
name << "idx";
563+
} else if (ty.isIntOrIndex()) {
564+
name << 'i' << ty.getIntOrFloatBitWidth();
565+
} else if (mlir::isa<mlir::FloatType>(ty)) {
566+
name << 'f' << ty.getIntOrFloatBitWidth();
567+
} else if (auto cplxTy =
568+
mlir::dyn_cast_or_null<mlir::ComplexType>(ty)) {
569+
name << 'z';
570+
auto floatTy = mlir::cast<mlir::FloatType>(cplxTy.getElementType());
571+
name << floatTy.getWidth();
572+
} else if (auto logTy = mlir::dyn_cast_or_null<fir::LogicalType>(ty)) {
573+
name << 'l' << kindMap.getLogicalBitsize(logTy.getFKind());
574+
} else {
575+
llvm::report_fatal_error("unsupported type");
576+
}
577+
break;
578+
} else if (mlir::isa<mlir::NoneType>(ty)) {
579+
name << "none";
580+
break;
581+
} else if (auto charTy = mlir::dyn_cast_or_null<fir::CharacterType>(ty)) {
582+
name << 'c' << kindMap.getCharacterBitsize(charTy.getFKind());
583+
if (charTy.getLen() == fir::CharacterType::unknownLen())
584+
name << "xU";
585+
else if (charTy.getLen() != fir::CharacterType::singleton())
586+
name << "x" << charTy.getLen();
587+
break;
588+
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
589+
for (auto extent : seqTy.getShape()) {
590+
if (extent == fir::SequenceType::getUnknownExtent())
591+
name << "Ux";
592+
else
593+
name << extent << 'x';
594+
}
595+
ty = seqTy.getEleTy();
596+
} else if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
597+
name << "ref_";
598+
ty = refTy.getEleTy();
599+
} else if (auto ptrTy = mlir::dyn_cast_or_null<fir::PointerType>(ty)) {
600+
name << "ptr_";
601+
ty = ptrTy.getEleTy();
602+
} else if (auto ptrTy =
603+
mlir::dyn_cast_or_null<fir::LLVMPointerType>(ty)) {
604+
name << "llvmptr_";
605+
ty = ptrTy.getEleTy();
606+
} else if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(ty)) {
607+
name << "heap_";
608+
ty = heapTy.getEleTy();
609+
} else if (auto classTy = mlir::dyn_cast_or_null<fir::ClassType>(ty)) {
610+
name << "class_";
611+
ty = classTy.getEleTy();
612+
} else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(ty)) {
613+
name << "box_";
614+
ty = boxTy.getEleTy();
615+
} else if (auto boxcharTy =
616+
mlir::dyn_cast_or_null<fir::BoxCharType>(ty)) {
617+
name << "boxchar_";
618+
ty = boxcharTy.getEleTy();
619+
} else if (auto boxprocTy =
620+
mlir::dyn_cast_or_null<fir::BoxProcType>(ty)) {
621+
name << "boxproc_";
622+
auto procTy = mlir::dyn_cast<mlir::FunctionType>(boxprocTy.getEleTy());
623+
assert(procTy.getNumResults() <= 1 &&
624+
"function type with more than one result");
625+
for (const auto &result : procTy.getResults())
626+
appendTypeName(result);
627+
name << "_args";
628+
for (const auto &arg : procTy.getInputs()) {
629+
name << '_';
630+
appendTypeName(arg);
631+
}
632+
break;
633+
} else if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(ty)) {
634+
name << "rec_" << recTy.getName();
635+
break;
571636
} else {
572637
llvm::report_fatal_error("unsupported type");
573638
}
574-
break;
575-
} else if (mlir::isa<mlir::NoneType>(ty)) {
576-
name << "none";
577-
break;
578-
} else if (auto charTy = mlir::dyn_cast_or_null<fir::CharacterType>(ty)) {
579-
name << 'c' << kindMap.getCharacterBitsize(charTy.getFKind());
580-
if (charTy.getLen() == fir::CharacterType::unknownLen())
581-
name << "xU";
582-
else if (charTy.getLen() != fir::CharacterType::singleton())
583-
name << "x" << charTy.getLen();
584-
break;
585-
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
586-
for (auto extent : seqTy.getShape()) {
587-
if (extent == fir::SequenceType::getUnknownExtent())
588-
name << "Ux";
589-
else
590-
name << extent << 'x';
591-
}
592-
ty = seqTy.getEleTy();
593-
} else if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
594-
name << "ref_";
595-
ty = refTy.getEleTy();
596-
} else if (auto ptrTy = mlir::dyn_cast_or_null<fir::PointerType>(ty)) {
597-
name << "ptr_";
598-
ty = ptrTy.getEleTy();
599-
} else if (auto ptrTy = mlir::dyn_cast_or_null<fir::LLVMPointerType>(ty)) {
600-
name << "llvmptr_";
601-
ty = ptrTy.getEleTy();
602-
} else if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(ty)) {
603-
name << "heap_";
604-
ty = heapTy.getEleTy();
605-
} else if (auto classTy = mlir::dyn_cast_or_null<fir::ClassType>(ty)) {
606-
name << "class_";
607-
ty = classTy.getEleTy();
608-
} else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(ty)) {
609-
name << "box_";
610-
ty = boxTy.getEleTy();
611-
} else if (auto boxcharTy = mlir::dyn_cast_or_null<fir::BoxCharType>(ty)) {
612-
name << "boxchar_";
613-
ty = boxcharTy.getEleTy();
614-
} else if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(ty)) {
615-
name << "rec_" << recTy.getName();
616-
break;
617-
} else {
618-
llvm::report_fatal_error("unsupported type");
619639
}
620-
}
640+
};
641+
642+
appendTypeName(ty);
621643
return buf;
622644
}
623645

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
! Test privatization of procedure pointers.
2+
3+
!RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
4+
!RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
5+
6+
program proc_ptr_test
7+
implicit none
8+
9+
contains
10+
11+
!CHECK: omp.private {type = private} @_QFFtest_namesEpf2_private_boxproc_z32_args_ref_3x4xf32_ref_z32 : !fir.boxproc<(!fir.ref<!fir.array<3x4xf32>>, !fir.ref<complex<f32>>) -> complex<f32>>
12+
!CHECK: omp.private {type = private} @_QFFtest_namesEpf1_private_boxproc_f32_args_ref_f32 : !fir.boxproc<(!fir.ref<f32>) -> f32>
13+
!CHECK: omp.private {type = private} @_QFFtest_namesEpf0_private_boxproc_i32_args : !fir.boxproc<() -> i32>
14+
!CHECK: omp.private {type = private} @_QFFtest_namesEps2_private_boxproc__args_ref_i32_boxchar_c8xU : !fir.boxproc<(!fir.ref<i32>, !fir.boxchar<1>) -> ()>
15+
!CHECK: omp.private {type = private} @_QFFtest_namesEps1_private_boxproc__args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> ()>
16+
!CHECK: omp.private {type = private} @_QFFtest_namesEps0_private_boxproc__args : !fir.boxproc<() -> ()>
17+
18+
!CHECK: omp.private {type = private} @_QFFtest_lastprivateEps_private_boxproc__args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> ()>
19+
!CHECK: omp.private {type = private} @_QFFtest_lastprivateEpf_private_boxproc_i32_args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> i32>
20+
21+
!CHECK: omp.private {type = firstprivate} @_QFFtest_firstprivateEps_firstprivate_boxproc__args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> ()> copy {
22+
!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> ()>>, %[[ARG1:.*]]: !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> ()>>):
23+
!CHECK: %[[TEMP:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> ()>>
24+
!CHECK: fir.store %[[TEMP]] to %[[ARG1]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> ()>>
25+
!CHECK: omp.yield(%[[ARG1]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> ()>>)
26+
!CHECK: }
27+
28+
!CHECK: omp.private {type = firstprivate} @_QFFtest_firstprivateEpf_firstprivate_boxproc_i32_args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> i32>
29+
!CHECK: omp.private {type = private} @_QFFtest_privateEps_private_boxproc__args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> ()>
30+
!CHECK: omp.private {type = private} @_QFFtest_privateEpf_private_boxproc_i32_args_ref_i32 : !fir.boxproc<(!fir.ref<i32>) -> i32>
31+
32+
!CHECK-LABEL: func private @_QFPtest_private
33+
!CHECK: %[[PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_privateEpf"}
34+
!CHECK: %[[PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_privateEps"}
35+
!CHECK: omp.parallel
36+
!CHECK: %[[PRIV_PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_privateEpf"}
37+
!CHECK: %[[PRIV_PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_privateEps"}
38+
!CHECK: %[[PF_VAL:.*]] = fir.load %[[PRIV_PF]]#0
39+
!CHECK: %[[PF_BOX:.*]] = fir.box_addr %[[PF_VAL]]
40+
!CHECK: fir.call %[[PF_BOX]]({{.*}})
41+
!CHECK: %[[PS_VAL:.*]] = fir.load %[[PRIV_PS]]#0
42+
!CHECK: %[[PS_BOX:.*]] = fir.box_addr %[[PS_VAL]]
43+
!CHECK: fir.call %[[PS_BOX]]({{.*}})
44+
subroutine test_private
45+
procedure(f), pointer :: pf
46+
procedure(sub), pointer :: ps
47+
integer :: res
48+
49+
!$omp parallel private(pf, ps)
50+
pf => f
51+
ps => sub
52+
res = pf(123)
53+
call ps(456)
54+
!$omp end parallel
55+
end subroutine
56+
57+
!CHECK-LABEL: func private @_QFPtest_firstprivate
58+
!CHECK: %[[PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_firstprivateEpf"}
59+
!CHECK: %[[PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_firstprivateEps"}
60+
!CHECK: omp.parallel
61+
!CHECK: %[[PRIV_PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_firstprivateEpf"}
62+
!CHECK: %[[PRIV_PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_firstprivateEps"}
63+
subroutine test_firstprivate
64+
procedure(f), pointer :: pf
65+
procedure(sub), pointer :: ps
66+
67+
!$omp parallel firstprivate(pf, ps)
68+
!$omp end parallel
69+
end subroutine
70+
71+
!CHECK-LABEL: func private @_QFPtest_lastprivate
72+
!CHECK: %[[PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_lastprivateEpf"}
73+
!CHECK: %[[PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_lastprivateEps"}
74+
!CHECK: omp.parallel
75+
!CHECK: %[[PRIV_PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_lastprivateEpf"}
76+
!CHECK: %[[PRIV_PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_lastprivateEps"}
77+
!CHECK: %[[PF_VAL:.*]] = fir.load %[[PRIV_PF]]#0
78+
!CHECK: fir.store %[[PF_VAL]] to %[[PF]]#0
79+
!CHECK: %[[PS_VAL:.*]] = fir.load %[[PRIV_PS]]#0
80+
!CHECK: fir.store %[[PS_VAL]] to %[[PS]]#0
81+
subroutine test_lastprivate
82+
procedure(f), pointer :: pf
83+
procedure(sub), pointer :: ps
84+
integer :: i
85+
86+
!$omp parallel do lastprivate(pf, ps)
87+
do i = 1, 5
88+
end do
89+
!$omp end parallel do
90+
end subroutine
91+
92+
!CHECK-LABEL: func private @_QFPtest_sections
93+
!CHECK: %[[PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_sectionsEpf"}
94+
!CHECK: %[[PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_sectionsEps"}
95+
!CHECK: %[[PRIV_PF:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_sectionsEpf"}
96+
!CHECK: %[[PF_VAL:.*]] = fir.load %[[PF]]#0
97+
!CHECK: fir.store %[[PF_VAL]] to %[[PRIV_PF]]#0
98+
!CHECK: %[[PRIV_PS:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}uniq_name = "_QFFtest_sectionsEps"}
99+
!CHECK: %[[PS_VAL:.*]] = fir.load %[[PS]]#0
100+
!CHECK: fir.store %[[PS_VAL]] to %[[PRIV_PS]]#0
101+
!CHECK: omp.sections
102+
!CHECK: %[[PF_VAL:.*]] = fir.load %[[PRIV_PF]]#0
103+
!CHECK: fir.store %[[PF_VAL]] to %[[PF]]#0
104+
!CHECK: %[[PS_VAL:.*]] = fir.load %[[PRIV_PS]]#0
105+
!CHECK: fir.store %[[PS_VAL]] to %[[PS]]#0
106+
subroutine test_sections
107+
procedure(f), pointer :: pf
108+
procedure(sub), pointer :: ps
109+
110+
!$omp sections firstprivate(pf, ps) lastprivate(pf, ps)
111+
!$omp end sections
112+
end subroutine
113+
114+
integer function f(arg)
115+
integer :: arg
116+
f = arg
117+
end function
118+
119+
subroutine sub(arg)
120+
integer :: arg
121+
end subroutine
122+
123+
subroutine test_names
124+
procedure(s0), pointer :: ps0
125+
procedure(s1), pointer :: ps1
126+
procedure(s2), pointer :: ps2
127+
128+
procedure(f0), pointer :: pf0
129+
procedure(f1), pointer :: pf1
130+
procedure(f2), pointer :: pf2
131+
132+
!$omp parallel private(ps0, ps1, ps2, pf0, pf1, pf2)
133+
!$omp end parallel
134+
end subroutine
135+
136+
subroutine s0
137+
end subroutine
138+
139+
subroutine s1(i)
140+
integer :: i
141+
end subroutine
142+
143+
subroutine s2(i, j)
144+
integer :: i
145+
character(*) :: j
146+
end subroutine
147+
148+
integer function f0
149+
f0 = 0
150+
end function
151+
152+
real function f1(r)
153+
real :: r
154+
155+
f1 = 0.0
156+
end function
157+
158+
function f2(a, c)
159+
real :: a(3, 4)
160+
complex :: f2, c
161+
162+
f2 = (0.0, 0.0)
163+
end function
164+
165+
end program

0 commit comments

Comments
 (0)