Skip to content

Commit 02b3cfd

Browse files
committed
[flang][OpenMP] Fix privatization of procedure pointers
Fixes #121720
1 parent 6c9a9d9 commit 02b3cfd

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
@@ -1842,7 +1842,7 @@ void Fortran::lower::genDeclareSymbol(
18421842
bool force) {
18431843
if (converter.getLoweringOptions().getLowerToHighLevelFIR() &&
18441844
(!Fortran::semantics::IsProcedure(sym) ||
1845-
Fortran::semantics::IsPointer(sym)) &&
1845+
Fortran::semantics::IsPointer(sym.GetUltimate())) &&
18461846
!sym.detailsIf<Fortran::semantics::CommonBlockDetails>()) {
18471847
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
18481848
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
@@ -553,70 +553,92 @@ std::string getTypeAsString(mlir::Type ty, const fir::KindMapping &kindMap,
553553
llvm::raw_string_ostream name{buf};
554554
if (!prefix.empty())
555555
name << "_";
556-
while (ty) {
557-
if (fir::isa_trivial(ty)) {
558-
if (mlir::isa<mlir::IndexType>(ty)) {
559-
name << "idx";
560-
} else if (ty.isIntOrIndex()) {
561-
name << 'i' << ty.getIntOrFloatBitWidth();
562-
} else if (mlir::isa<mlir::FloatType>(ty)) {
563-
name << 'f' << ty.getIntOrFloatBitWidth();
564-
} else if (auto cplxTy = mlir::dyn_cast_or_null<mlir::ComplexType>(ty)) {
565-
name << 'z';
566-
auto floatTy = mlir::cast<mlir::FloatType>(cplxTy.getElementType());
567-
name << floatTy.getWidth();
568-
} else if (auto logTy = mlir::dyn_cast_or_null<fir::LogicalType>(ty)) {
569-
name << 'l' << kindMap.getLogicalBitsize(logTy.getFKind());
556+
557+
std::function<void(mlir::Type)> appendTypeName = [&](mlir::Type ty) {
558+
while (ty) {
559+
if (fir::isa_trivial(ty)) {
560+
if (mlir::isa<mlir::IndexType>(ty)) {
561+
name << "idx";
562+
} else if (ty.isIntOrIndex()) {
563+
name << 'i' << ty.getIntOrFloatBitWidth();
564+
} else if (mlir::isa<mlir::FloatType>(ty)) {
565+
name << 'f' << ty.getIntOrFloatBitWidth();
566+
} else if (auto cplxTy =
567+
mlir::dyn_cast_or_null<mlir::ComplexType>(ty)) {
568+
name << 'z';
569+
auto floatTy = mlir::cast<mlir::FloatType>(cplxTy.getElementType());
570+
name << floatTy.getWidth();
571+
} else if (auto logTy = mlir::dyn_cast_or_null<fir::LogicalType>(ty)) {
572+
name << 'l' << kindMap.getLogicalBitsize(logTy.getFKind());
573+
} else {
574+
llvm::report_fatal_error("unsupported type");
575+
}
576+
break;
577+
} else if (mlir::isa<mlir::NoneType>(ty)) {
578+
name << "none";
579+
break;
580+
} else if (auto charTy = mlir::dyn_cast_or_null<fir::CharacterType>(ty)) {
581+
name << 'c' << kindMap.getCharacterBitsize(charTy.getFKind());
582+
if (charTy.getLen() == fir::CharacterType::unknownLen())
583+
name << "xU";
584+
else if (charTy.getLen() != fir::CharacterType::singleton())
585+
name << "x" << charTy.getLen();
586+
break;
587+
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
588+
for (auto extent : seqTy.getShape()) {
589+
if (extent == fir::SequenceType::getUnknownExtent())
590+
name << "Ux";
591+
else
592+
name << extent << 'x';
593+
}
594+
ty = seqTy.getEleTy();
595+
} else if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
596+
name << "ref_";
597+
ty = refTy.getEleTy();
598+
} else if (auto ptrTy = mlir::dyn_cast_or_null<fir::PointerType>(ty)) {
599+
name << "ptr_";
600+
ty = ptrTy.getEleTy();
601+
} else if (auto ptrTy =
602+
mlir::dyn_cast_or_null<fir::LLVMPointerType>(ty)) {
603+
name << "llvmptr_";
604+
ty = ptrTy.getEleTy();
605+
} else if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(ty)) {
606+
name << "heap_";
607+
ty = heapTy.getEleTy();
608+
} else if (auto classTy = mlir::dyn_cast_or_null<fir::ClassType>(ty)) {
609+
name << "class_";
610+
ty = classTy.getEleTy();
611+
} else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(ty)) {
612+
name << "box_";
613+
ty = boxTy.getEleTy();
614+
} else if (auto boxcharTy =
615+
mlir::dyn_cast_or_null<fir::BoxCharType>(ty)) {
616+
name << "boxchar_";
617+
ty = boxcharTy.getEleTy();
618+
} else if (auto boxprocTy =
619+
mlir::dyn_cast_or_null<fir::BoxProcType>(ty)) {
620+
name << "boxproc_";
621+
auto procTy = mlir::dyn_cast<mlir::FunctionType>(boxprocTy.getEleTy());
622+
assert(procTy.getNumResults() <= 1 &&
623+
"function type with more than one result");
624+
for (const auto &result : procTy.getResults())
625+
appendTypeName(result);
626+
name << "_args";
627+
for (const auto &arg : procTy.getInputs()) {
628+
name << '_';
629+
appendTypeName(arg);
630+
}
631+
break;
632+
} else if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(ty)) {
633+
name << "rec_" << recTy.getName();
634+
break;
570635
} else {
571636
llvm::report_fatal_error("unsupported type");
572637
}
573-
break;
574-
} else if (mlir::isa<mlir::NoneType>(ty)) {
575-
name << "none";
576-
break;
577-
} else if (auto charTy = mlir::dyn_cast_or_null<fir::CharacterType>(ty)) {
578-
name << 'c' << kindMap.getCharacterBitsize(charTy.getFKind());
579-
if (charTy.getLen() == fir::CharacterType::unknownLen())
580-
name << "xU";
581-
else if (charTy.getLen() != fir::CharacterType::singleton())
582-
name << "x" << charTy.getLen();
583-
break;
584-
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
585-
for (auto extent : seqTy.getShape()) {
586-
if (extent == fir::SequenceType::getUnknownExtent())
587-
name << "Ux";
588-
else
589-
name << extent << 'x';
590-
}
591-
ty = seqTy.getEleTy();
592-
} else if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
593-
name << "ref_";
594-
ty = refTy.getEleTy();
595-
} else if (auto ptrTy = mlir::dyn_cast_or_null<fir::PointerType>(ty)) {
596-
name << "ptr_";
597-
ty = ptrTy.getEleTy();
598-
} else if (auto ptrTy = mlir::dyn_cast_or_null<fir::LLVMPointerType>(ty)) {
599-
name << "llvmptr_";
600-
ty = ptrTy.getEleTy();
601-
} else if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(ty)) {
602-
name << "heap_";
603-
ty = heapTy.getEleTy();
604-
} else if (auto classTy = mlir::dyn_cast_or_null<fir::ClassType>(ty)) {
605-
name << "class_";
606-
ty = classTy.getEleTy();
607-
} else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(ty)) {
608-
name << "box_";
609-
ty = boxTy.getEleTy();
610-
} else if (auto boxcharTy = mlir::dyn_cast_or_null<fir::BoxCharType>(ty)) {
611-
name << "boxchar_";
612-
ty = boxcharTy.getEleTy();
613-
} else if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(ty)) {
614-
name << "rec_" << recTy.getName();
615-
break;
616-
} else {
617-
llvm::report_fatal_error("unsupported type");
618638
}
619-
}
639+
};
640+
641+
appendTypeName(ty);
620642
return buf;
621643
}
622644

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)