Skip to content

Commit b025d69

Browse files
authored
[flang][OpenMP] Make object identity more precise (#94495)
Derived type components may use a given `Symbol` regardless of what parent objects they are a part of. Because of that, simply using a symbol address is not sufficient to determine object identity. Make the designator a part of the IdTy. To compare identities, when symbols are equal (and non-null), compare the designators.
1 parent 8725b67 commit b025d69

File tree

3 files changed

+75
-18
lines changed

3 files changed

+75
-18
lines changed

flang/lib/Lower/OpenMP/Clauses.h

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,30 +36,64 @@ struct TypeTy : public evaluate::SomeType {
3636
bool operator==(const TypeTy &t) const { return true; }
3737
};
3838

39-
using IdTy = semantics::Symbol *;
39+
template <typename ExprTy>
40+
struct IdTyTemplate {
41+
// "symbol" is always non-null for id's of actual objects.
42+
Fortran::semantics::Symbol *symbol;
43+
std::optional<ExprTy> designator;
44+
45+
bool operator==(const IdTyTemplate &other) const {
46+
// If symbols are different, then the objects are different.
47+
if (symbol != other.symbol)
48+
return false;
49+
if (symbol == nullptr)
50+
return true;
51+
// Equal symbols don't necessarily indicate identical objects,
52+
// for example, a derived object component may use a single symbol,
53+
// which will refer to different objects for different designators,
54+
// e.g. a%c and b%c.
55+
return designator == other.designator;
56+
}
57+
58+
operator bool() const { return symbol != nullptr; }
59+
};
60+
4061
using ExprTy = SomeExpr;
4162

4263
template <typename T>
4364
using List = tomp::ListT<T>;
4465
} // namespace Fortran::lower::omp
4566

67+
// Specialization of the ObjectT template
4668
namespace tomp::type {
4769
template <>
48-
struct ObjectT<Fortran::lower::omp::IdTy, Fortran::lower::omp::ExprTy> {
49-
using IdTy = Fortran::lower::omp::IdTy;
70+
struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
71+
Fortran::lower::omp::ExprTy> {
72+
using IdTy = Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>;
5073
using ExprTy = Fortran::lower::omp::ExprTy;
5174

52-
IdTy id() const { return symbol; }
53-
Fortran::semantics::Symbol *sym() const { return symbol; }
54-
const std::optional<ExprTy> &ref() const { return designator; }
75+
IdTy id() const { return identity; }
76+
Fortran::semantics::Symbol *sym() const { return identity.symbol; }
77+
const std::optional<ExprTy> &ref() const { return identity.designator; }
5578

56-
IdTy symbol;
57-
std::optional<ExprTy> designator;
79+
IdTy identity;
5880
};
5981
} // namespace tomp::type
6082

6183
namespace Fortran::lower::omp {
84+
using IdTy = IdTyTemplate<ExprTy>;
85+
}
6286

87+
namespace std {
88+
template <>
89+
struct hash<Fortran::lower::omp::IdTy> {
90+
size_t operator()(const Fortran::lower::omp::IdTy &id) const {
91+
return static_cast<size_t>(reinterpret_cast<uintptr_t>(id.symbol));
92+
}
93+
};
94+
} // namespace std
95+
96+
namespace Fortran::lower::omp {
6397
using Object = tomp::ObjectT<IdTy, ExprTy>;
6498
using ObjectList = tomp::ObjectListT<IdTy, ExprTy>;
6599

flang/lib/Lower/OpenMP/Utils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ void addChildIndexAndMapToParent(
188188
std::map<const semantics::Symbol *,
189189
llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
190190
mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx) {
191-
std::optional<evaluate::DataRef> dataRef = ExtractDataRef(object.designator);
191+
std::optional<evaluate::DataRef> dataRef = ExtractDataRef(object.ref());
192192
assert(dataRef.has_value() &&
193193
"DataRef could not be extracted during mapping of derived type "
194194
"cannot proceed");
Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
22
! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
33

4-
! CHECK: %[[V0:[0-9]+]] = fir.alloca !fir.type<_QFfooTt0{a0:i32,a1:i32}> {bindc_name = "a", uniq_name = "_QFfooEa"}
5-
! CHECK: %[[V1:[0-9]+]]:2 = hlfir.declare %[[V0]] {uniq_name = "_QFfooEa"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>)
6-
! CHECK: %[[V2:[0-9]+]] = hlfir.designate %[[V1]]#0{"a1"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> !fir.ref<i32>
4+
! CHECK-LABEL: func.func @_QPfoo1
5+
! CHECK: %[[V0:[0-9]+]] = fir.alloca !fir.type<_QFfoo1Tt0{a0:i32,a1:i32}> {bindc_name = "a", uniq_name = "_QFfoo1Ea"}
6+
! CHECK: %[[V1:[0-9]+]]:2 = hlfir.declare %[[V0]] {uniq_name = "_QFfoo1Ea"} : (!fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>) -> (!fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>, !fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>)
7+
! CHECK: %[[V2:[0-9]+]] = hlfir.designate %[[V1]]#0{"a1"} : (!fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>) -> !fir.ref<i32>
78
! CHECK: %[[V3:[0-9]+]] = omp.map.info var_ptr(%[[V2]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a%a1"}
8-
! CHECK: %[[V4:[0-9]+]] = omp.map.info var_ptr(%[[V1]]#1 : !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.type<_QFfooTt0{a0:i32,a1:i32}>) map_clauses(tofrom) capture(ByRef) members(%[[V3]] : [1] : !fir.ref<i32>) -> !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>> {name = "a", partial_map = true}
9-
! CHECK: omp.target map_entries(%[[V3]] -> %arg0, %[[V4]] -> %arg1 : !fir.ref<i32>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) {
10-
! CHECK: ^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>):
11-
! CHECK: %[[V5:[0-9]+]]:2 = hlfir.declare %arg1 {uniq_name = "_QFfooEa"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>)
9+
! CHECK: %[[V4:[0-9]+]] = omp.map.info var_ptr(%[[V1]]#1 : !fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>, !fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>) map_clauses(tofrom) capture(ByRef) members(%[[V3]] : [1] : !fir.ref<i32>) -> !fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>> {name = "a", partial_map = true}
10+
! CHECK: omp.target map_entries(%[[V3]] -> %arg0, %[[V4]] -> %arg1 : !fir.ref<i32>, !fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>) {
11+
! CHECK: ^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>):
12+
! CHECK: %[[V5:[0-9]+]]:2 = hlfir.declare %arg1 {uniq_name = "_QFfoo1Ea"} : (!fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>) -> (!fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>, !fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>)
1213
! CHECK: %c0_i32 = arith.constant 0 : i32
13-
! CHECK: %[[V6:[0-9]+]] = hlfir.designate %[[V5]]#0{"a1"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> !fir.ref<i32>
14+
! CHECK: %[[V6:[0-9]+]] = hlfir.designate %[[V5]]#0{"a1"} : (!fir.ref<!fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>>) -> !fir.ref<i32>
1415
! CHECK: hlfir.assign %c0_i32 to %[[V6]] : i32, !fir.ref<i32>
1516
! CHECK: omp.terminator
1617
! CHECK: }
1718

18-
subroutine foo()
19+
subroutine foo1()
1920
implicit none
2021

2122
type t0
@@ -29,3 +30,25 @@ subroutine foo()
2930
!$omp end target
3031
end
3132

33+
34+
! CHECK-LABEL: func.func @_QPfoo2
35+
! CHECK-DAG: omp.map.info var_ptr(%{{[0-9]+}} : {{.*}} map_clauses(to) capture(ByRef) bounds(%{{[0-9]+}}) -> {{.*}} {name = "t%b(1_8)%a(1)"}
36+
! CHECK-DAG: omp.map.info var_ptr(%{{[0-9]+}} : {{.*}} map_clauses(from) capture(ByRef) bounds(%{{[0-9]+}}) -> {{.*}} {name = "u%b(1_8)%a(1)"}
37+
subroutine foo2()
38+
implicit none
39+
40+
type t0
41+
integer :: a(10)
42+
end type
43+
44+
type t1
45+
type(t0) :: b(10)
46+
end type
47+
48+
type(t1) :: t, u
49+
50+
!$omp target map(to: t%b(1)%a(1)) map(from: u%b(1)%a(1))
51+
t%b(1)%a(1) = u%b(1)%a(1)
52+
!$omp end target
53+
54+
end

0 commit comments

Comments
 (0)