Skip to content

Commit 52b7045

Browse files
authored
[flang][MLIR][OpenMP] Emit UpdateDataOp from !$omp target update (#75345)
Emits MLIR op corresponding to `!$omp target update` directive. So far, only motion types: `to` and `from` are supported. Motion modifiers: `present`, `mapper`, and `iterator` are not supported yet. This is a follow up to #75047 & #75159, only the last commit is relevant to this PR.
1 parent 04c473b commit 52b7045

File tree

3 files changed

+256
-11
lines changed

3 files changed

+256
-11
lines changed

flang/lib/Lower/OpenMP.cpp

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,12 @@ class ClauseProcessor {
607607
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
608608
&useDeviceSymbols) const;
609609

610+
template <typename T>
611+
bool
612+
processMotionClauses(Fortran::semantics::SemanticsContext &semanticsContext,
613+
Fortran::lower::StatementContext &stmtCtx,
614+
llvm::SmallVectorImpl<mlir::Value> &mapOperands);
615+
610616
// Call this method for these clauses that should be supported but are not
611617
// implemented yet. It triggers a compilation error if any of the given
612618
// clauses is found.
@@ -1893,6 +1899,47 @@ bool ClauseProcessor::processUseDevicePtr(
18931899
});
18941900
}
18951901

1902+
template <typename T>
1903+
bool ClauseProcessor::processMotionClauses(
1904+
Fortran::semantics::SemanticsContext &semanticsContext,
1905+
Fortran::lower::StatementContext &stmtCtx,
1906+
llvm::SmallVectorImpl<mlir::Value> &mapOperands) {
1907+
return findRepeatableClause<T>(
1908+
[&](const T *motionClause, const Fortran::parser::CharBlock &source) {
1909+
mlir::Location clauseLocation = converter.genLocation(source);
1910+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1911+
1912+
static_assert(std::is_same_v<T, ClauseProcessor::ClauseTy::To> ||
1913+
std::is_same_v<T, ClauseProcessor::ClauseTy::From>);
1914+
1915+
// TODO Support motion modifiers: present, mapper, iterator.
1916+
constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
1917+
std::is_same_v<T, ClauseProcessor::ClauseTy::To>
1918+
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
1919+
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1920+
1921+
for (const Fortran::parser::OmpObject &ompObject : motionClause->v.v) {
1922+
llvm::SmallVector<mlir::Value> bounds;
1923+
std::stringstream asFortran;
1924+
Fortran::lower::AddrAndBoundsInfo info =
1925+
Fortran::lower::gatherDataOperandAddrAndBounds<
1926+
Fortran::parser::OmpObject, mlir::omp::DataBoundsOp,
1927+
mlir::omp::DataBoundsType>(
1928+
converter, firOpBuilder, semanticsContext, stmtCtx, ompObject,
1929+
clauseLocation, asFortran, bounds, treatIndexAsSection);
1930+
1931+
mlir::Value mapOp = createMapInfoOp(
1932+
firOpBuilder, clauseLocation, info.addr, asFortran, bounds,
1933+
static_cast<
1934+
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
1935+
mapTypeBits),
1936+
mlir::omp::VariableCaptureKind::ByRef, info.addr.getType());
1937+
1938+
mapOperands.push_back(mapOp);
1939+
}
1940+
});
1941+
}
1942+
18961943
template <typename... Ts>
18971944
void ClauseProcessor::processTODO(mlir::Location currentLocation,
18981945
llvm::omp::Directive directive) const {
@@ -2416,10 +2463,10 @@ genDataOp(Fortran::lower::AbstractConverter &converter,
24162463

24172464
template <typename OpTy>
24182465
static OpTy
2419-
genEnterExitDataOp(Fortran::lower::AbstractConverter &converter,
2420-
Fortran::semantics::SemanticsContext &semanticsContext,
2421-
mlir::Location currentLocation,
2422-
const Fortran::parser::OmpClauseList &clauseList) {
2466+
genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter,
2467+
Fortran::semantics::SemanticsContext &semanticsContext,
2468+
mlir::Location currentLocation,
2469+
const Fortran::parser::OmpClauseList &clauseList) {
24232470
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
24242471
Fortran::lower::StatementContext stmtCtx;
24252472
mlir::Value ifClauseOperand, deviceOperand;
@@ -2436,6 +2483,10 @@ genEnterExitDataOp(Fortran::lower::AbstractConverter &converter,
24362483
directiveName =
24372484
Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetExitData;
24382485
directive = llvm::omp::Directive::OMPD_target_exit_data;
2486+
} else if constexpr (std::is_same_v<OpTy, mlir::omp::UpdateDataOp>) {
2487+
directiveName =
2488+
Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetUpdate;
2489+
directive = llvm::omp::Directive::OMPD_target_update;
24392490
} else {
24402491
return nullptr;
24412492
}
@@ -2444,8 +2495,18 @@ genEnterExitDataOp(Fortran::lower::AbstractConverter &converter,
24442495
cp.processIf(directiveName, ifClauseOperand);
24452496
cp.processDevice(stmtCtx, deviceOperand);
24462497
cp.processNowait(nowaitAttr);
2447-
cp.processMap(currentLocation, directive, semanticsContext, stmtCtx,
2448-
mapOperands);
2498+
2499+
if constexpr (std::is_same_v<OpTy, mlir::omp::UpdateDataOp>) {
2500+
cp.processMotionClauses<Fortran::parser::OmpClause::To>(
2501+
semanticsContext, stmtCtx, mapOperands);
2502+
cp.processMotionClauses<Fortran::parser::OmpClause::From>(
2503+
semanticsContext, stmtCtx, mapOperands);
2504+
2505+
} else {
2506+
cp.processMap(currentLocation, directive, semanticsContext, stmtCtx,
2507+
mapOperands);
2508+
}
2509+
24492510
cp.processTODO<Fortran::parser::OmpClause::Depend>(currentLocation,
24502511
directive);
24512512

@@ -2847,15 +2908,17 @@ genOmpSimpleStandalone(Fortran::lower::AbstractConverter &converter,
28472908
genDataOp(converter, eval, semanticsContext, currentLocation, opClauseList);
28482909
break;
28492910
case llvm::omp::Directive::OMPD_target_enter_data:
2850-
genEnterExitDataOp<mlir::omp::EnterDataOp>(converter, semanticsContext,
2851-
currentLocation, opClauseList);
2911+
genEnterExitUpdateDataOp<mlir::omp::EnterDataOp>(
2912+
converter, semanticsContext, currentLocation, opClauseList);
28522913
break;
28532914
case llvm::omp::Directive::OMPD_target_exit_data:
2854-
genEnterExitDataOp<mlir::omp::ExitDataOp>(converter, semanticsContext,
2855-
currentLocation, opClauseList);
2915+
genEnterExitUpdateDataOp<mlir::omp::ExitDataOp>(
2916+
converter, semanticsContext, currentLocation, opClauseList);
28562917
break;
28572918
case llvm::omp::Directive::OMPD_target_update:
2858-
TODO(currentLocation, "OMPD_target_update");
2919+
genEnterExitUpdateDataOp<mlir::omp::UpdateDataOp>(
2920+
converter, semanticsContext, currentLocation, opClauseList);
2921+
break;
28592922
case llvm::omp::Directive::OMPD_ordered:
28602923
TODO(currentLocation, "OMPD_ordered");
28612924
}

flang/test/Lower/OpenMP/FIR/target.f90

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,100 @@ subroutine omp_target_exit_device
133133
!$omp target exit data map(from: a) device(d)
134134
end subroutine omp_target_exit_device
135135

136+
!===============================================================================
137+
! Target_Update `to` clause
138+
!===============================================================================
139+
140+
subroutine omp_target_update_to
141+
integer :: a(1024)
142+
143+
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_update_toEa"}
144+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
145+
146+
!CHECK: %[[TO_MAP:.*]] = omp.map_info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
147+
!CHECK-SAME: map_clauses(to) capture(ByRef)
148+
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
149+
150+
!CHECK: omp.target_update_data
151+
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
152+
!$omp target update to(a)
153+
end subroutine omp_target_update_to
154+
155+
!===============================================================================
156+
! Target_Update `from` clause
157+
!===============================================================================
158+
159+
subroutine omp_target_update_from
160+
integer :: a(1024)
161+
162+
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_update_fromEa"}
163+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
164+
165+
!CHECK: %[[FROM_MAP:.*]] = omp.map_info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
166+
!CHECK-SAME: map_clauses(from) capture(ByRef)
167+
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
168+
169+
!CHECK: omp.target_update_data
170+
!CHECK-SAME: motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>)
171+
!$omp target update from(a)
172+
end subroutine omp_target_update_from
173+
174+
!===============================================================================
175+
! Target_Update `if` clause
176+
!===============================================================================
177+
178+
subroutine omp_target_update_if
179+
integer :: a(1024)
180+
logical :: i
181+
182+
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca
183+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
184+
!CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1
185+
186+
!CHECK: %[[TO_MAP:.*]] = omp.map_info
187+
188+
!CHECK: omp.target_update_data if(%[[COND]] : i1)
189+
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
190+
!$omp target update to(a) if(i)
191+
end subroutine omp_target_update_if
192+
193+
!===============================================================================
194+
! Target_Update `device` clause
195+
!===============================================================================
196+
197+
subroutine omp_target_update_device
198+
integer :: a(1024)
199+
200+
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca
201+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
202+
!CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32
203+
204+
!CHECK: %[[TO_MAP:.*]] = omp.map_info
205+
206+
!CHECK: omp.target_update_data
207+
!CHECK-SAME: device(%[[DEVICE]] : i32)
208+
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
209+
!$omp target update to(a) device(1)
210+
end subroutine omp_target_update_device
211+
212+
!===============================================================================
213+
! Target_Update `nowait` clause
214+
!===============================================================================
215+
216+
subroutine omp_target_update_nowait
217+
integer :: a(1024)
218+
219+
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca
220+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
221+
222+
!CHECK: %[[TO_MAP:.*]] = omp.map_info
223+
224+
!CHECK: omp.target_update_data
225+
!CHECK-SAME: nowait
226+
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
227+
!$omp target update to(a) nowait
228+
end subroutine omp_target_update_nowait
229+
136230
!===============================================================================
137231
! Target_Data with region
138232
!===============================================================================

flang/test/Lower/OpenMP/target.f90

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,94 @@ subroutine omp_target_exit_device
134134
!$omp target exit data map(from: a) device(d)
135135
end subroutine omp_target_exit_device
136136

137+
!===============================================================================
138+
! Target_Update `to` clause
139+
!===============================================================================
140+
141+
!CHECK-LABEL: func.func @_QPomp_target_update_to() {
142+
subroutine omp_target_update_to
143+
integer :: a(1024)
144+
145+
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
146+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
147+
148+
!CHECK: %[[TO_MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
149+
!CHECK-SAME: map_clauses(to) capture(ByRef)
150+
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
151+
152+
!CHECK: omp.target_update_data motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
153+
!$omp target update to(a)
154+
end subroutine omp_target_update_to
155+
156+
!===============================================================================
157+
! Target_Update `from` clause
158+
!===============================================================================
159+
160+
!CHECK-LABEL: func.func @_QPomp_target_update_from() {
161+
subroutine omp_target_update_from
162+
integer :: a(1024)
163+
164+
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
165+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
166+
167+
!CHECK: %[[FROM_MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
168+
!CHECK-SAME: map_clauses(from) capture(ByRef)
169+
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
170+
171+
!CHECK: omp.target_update_data motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>)
172+
!$omp target update from(a)
173+
end subroutine omp_target_update_from
174+
175+
!===============================================================================
176+
! Target_Update `if` clause
177+
!===============================================================================
178+
179+
!CHECK-LABEL: func.func @_QPomp_target_update_if() {
180+
subroutine omp_target_update_if
181+
integer :: a(1024)
182+
logical :: i
183+
184+
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
185+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
186+
!CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1
187+
188+
!CHECK: omp.target_update_data if(%[[COND]] : i1) motion_entries
189+
!$omp target update from(a) if(i)
190+
end subroutine omp_target_update_if
191+
192+
!===============================================================================
193+
! Target_Update `device` clause
194+
!===============================================================================
195+
196+
!CHECK-LABEL: func.func @_QPomp_target_update_device() {
197+
subroutine omp_target_update_device
198+
integer :: a(1024)
199+
logical :: i
200+
201+
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
202+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
203+
!CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32
204+
205+
!CHECK: omp.target_update_data device(%[[DEVICE]] : i32) motion_entries
206+
!$omp target update from(a) device(1)
207+
end subroutine omp_target_update_device
208+
209+
!===============================================================================
210+
! Target_Update `nowait` clause
211+
!===============================================================================
212+
213+
!CHECK-LABEL: func.func @_QPomp_target_update_nowait() {
214+
subroutine omp_target_update_nowait
215+
integer :: a(1024)
216+
logical :: i
217+
218+
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
219+
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
220+
221+
!CHECK: omp.target_update_data nowait motion_entries
222+
!$omp target update from(a) nowait
223+
end subroutine omp_target_update_nowait
224+
137225
!===============================================================================
138226
! Target_Data with region
139227
!===============================================================================

0 commit comments

Comments
 (0)