mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 07:31:28 +00:00
[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.
This commit is contained in:
parent
04c473bea3
commit
52b7045fbb
@ -607,6 +607,12 @@ public:
|
||||
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
|
||||
&useDeviceSymbols) const;
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
processMotionClauses(Fortran::semantics::SemanticsContext &semanticsContext,
|
||||
Fortran::lower::StatementContext &stmtCtx,
|
||||
llvm::SmallVectorImpl<mlir::Value> &mapOperands);
|
||||
|
||||
// Call this method for these clauses that should be supported but are not
|
||||
// implemented yet. It triggers a compilation error if any of the given
|
||||
// clauses is found.
|
||||
@ -1893,6 +1899,47 @@ bool ClauseProcessor::processUseDevicePtr(
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ClauseProcessor::processMotionClauses(
|
||||
Fortran::semantics::SemanticsContext &semanticsContext,
|
||||
Fortran::lower::StatementContext &stmtCtx,
|
||||
llvm::SmallVectorImpl<mlir::Value> &mapOperands) {
|
||||
return findRepeatableClause<T>(
|
||||
[&](const T *motionClause, const Fortran::parser::CharBlock &source) {
|
||||
mlir::Location clauseLocation = converter.genLocation(source);
|
||||
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
|
||||
|
||||
static_assert(std::is_same_v<T, ClauseProcessor::ClauseTy::To> ||
|
||||
std::is_same_v<T, ClauseProcessor::ClauseTy::From>);
|
||||
|
||||
// TODO Support motion modifiers: present, mapper, iterator.
|
||||
constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
|
||||
std::is_same_v<T, ClauseProcessor::ClauseTy::To>
|
||||
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
|
||||
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
|
||||
|
||||
for (const Fortran::parser::OmpObject &ompObject : motionClause->v.v) {
|
||||
llvm::SmallVector<mlir::Value> bounds;
|
||||
std::stringstream asFortran;
|
||||
Fortran::lower::AddrAndBoundsInfo info =
|
||||
Fortran::lower::gatherDataOperandAddrAndBounds<
|
||||
Fortran::parser::OmpObject, mlir::omp::DataBoundsOp,
|
||||
mlir::omp::DataBoundsType>(
|
||||
converter, firOpBuilder, semanticsContext, stmtCtx, ompObject,
|
||||
clauseLocation, asFortran, bounds, treatIndexAsSection);
|
||||
|
||||
mlir::Value mapOp = createMapInfoOp(
|
||||
firOpBuilder, clauseLocation, info.addr, asFortran, bounds,
|
||||
static_cast<
|
||||
std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
|
||||
mapTypeBits),
|
||||
mlir::omp::VariableCaptureKind::ByRef, info.addr.getType());
|
||||
|
||||
mapOperands.push_back(mapOp);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
void ClauseProcessor::processTODO(mlir::Location currentLocation,
|
||||
llvm::omp::Directive directive) const {
|
||||
@ -2416,10 +2463,10 @@ genDataOp(Fortran::lower::AbstractConverter &converter,
|
||||
|
||||
template <typename OpTy>
|
||||
static OpTy
|
||||
genEnterExitDataOp(Fortran::lower::AbstractConverter &converter,
|
||||
Fortran::semantics::SemanticsContext &semanticsContext,
|
||||
mlir::Location currentLocation,
|
||||
const Fortran::parser::OmpClauseList &clauseList) {
|
||||
genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter,
|
||||
Fortran::semantics::SemanticsContext &semanticsContext,
|
||||
mlir::Location currentLocation,
|
||||
const Fortran::parser::OmpClauseList &clauseList) {
|
||||
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
|
||||
Fortran::lower::StatementContext stmtCtx;
|
||||
mlir::Value ifClauseOperand, deviceOperand;
|
||||
@ -2436,6 +2483,10 @@ genEnterExitDataOp(Fortran::lower::AbstractConverter &converter,
|
||||
directiveName =
|
||||
Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetExitData;
|
||||
directive = llvm::omp::Directive::OMPD_target_exit_data;
|
||||
} else if constexpr (std::is_same_v<OpTy, mlir::omp::UpdateDataOp>) {
|
||||
directiveName =
|
||||
Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetUpdate;
|
||||
directive = llvm::omp::Directive::OMPD_target_update;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2444,8 +2495,18 @@ genEnterExitDataOp(Fortran::lower::AbstractConverter &converter,
|
||||
cp.processIf(directiveName, ifClauseOperand);
|
||||
cp.processDevice(stmtCtx, deviceOperand);
|
||||
cp.processNowait(nowaitAttr);
|
||||
cp.processMap(currentLocation, directive, semanticsContext, stmtCtx,
|
||||
mapOperands);
|
||||
|
||||
if constexpr (std::is_same_v<OpTy, mlir::omp::UpdateDataOp>) {
|
||||
cp.processMotionClauses<Fortran::parser::OmpClause::To>(
|
||||
semanticsContext, stmtCtx, mapOperands);
|
||||
cp.processMotionClauses<Fortran::parser::OmpClause::From>(
|
||||
semanticsContext, stmtCtx, mapOperands);
|
||||
|
||||
} else {
|
||||
cp.processMap(currentLocation, directive, semanticsContext, stmtCtx,
|
||||
mapOperands);
|
||||
}
|
||||
|
||||
cp.processTODO<Fortran::parser::OmpClause::Depend>(currentLocation,
|
||||
directive);
|
||||
|
||||
@ -2847,15 +2908,17 @@ genOmpSimpleStandalone(Fortran::lower::AbstractConverter &converter,
|
||||
genDataOp(converter, eval, semanticsContext, currentLocation, opClauseList);
|
||||
break;
|
||||
case llvm::omp::Directive::OMPD_target_enter_data:
|
||||
genEnterExitDataOp<mlir::omp::EnterDataOp>(converter, semanticsContext,
|
||||
currentLocation, opClauseList);
|
||||
genEnterExitUpdateDataOp<mlir::omp::EnterDataOp>(
|
||||
converter, semanticsContext, currentLocation, opClauseList);
|
||||
break;
|
||||
case llvm::omp::Directive::OMPD_target_exit_data:
|
||||
genEnterExitDataOp<mlir::omp::ExitDataOp>(converter, semanticsContext,
|
||||
currentLocation, opClauseList);
|
||||
genEnterExitUpdateDataOp<mlir::omp::ExitDataOp>(
|
||||
converter, semanticsContext, currentLocation, opClauseList);
|
||||
break;
|
||||
case llvm::omp::Directive::OMPD_target_update:
|
||||
TODO(currentLocation, "OMPD_target_update");
|
||||
genEnterExitUpdateDataOp<mlir::omp::UpdateDataOp>(
|
||||
converter, semanticsContext, currentLocation, opClauseList);
|
||||
break;
|
||||
case llvm::omp::Directive::OMPD_ordered:
|
||||
TODO(currentLocation, "OMPD_ordered");
|
||||
}
|
||||
|
@ -133,6 +133,100 @@ subroutine omp_target_exit_device
|
||||
!$omp target exit data map(from: a) device(d)
|
||||
end subroutine omp_target_exit_device
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `to` clause
|
||||
!===============================================================================
|
||||
|
||||
subroutine omp_target_update_to
|
||||
integer :: a(1024)
|
||||
|
||||
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_update_toEa"}
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
|
||||
!CHECK: %[[TO_MAP:.*]] = omp.map_info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
|
||||
!CHECK-SAME: map_clauses(to) capture(ByRef)
|
||||
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
||||
|
||||
!CHECK: omp.target_update_data
|
||||
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update to(a)
|
||||
end subroutine omp_target_update_to
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `from` clause
|
||||
!===============================================================================
|
||||
|
||||
subroutine omp_target_update_from
|
||||
integer :: a(1024)
|
||||
|
||||
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_update_fromEa"}
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
|
||||
!CHECK: %[[FROM_MAP:.*]] = omp.map_info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
|
||||
!CHECK-SAME: map_clauses(from) capture(ByRef)
|
||||
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
||||
|
||||
!CHECK: omp.target_update_data
|
||||
!CHECK-SAME: motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update from(a)
|
||||
end subroutine omp_target_update_from
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `if` clause
|
||||
!===============================================================================
|
||||
|
||||
subroutine omp_target_update_if
|
||||
integer :: a(1024)
|
||||
logical :: i
|
||||
|
||||
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
!CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1
|
||||
|
||||
!CHECK: %[[TO_MAP:.*]] = omp.map_info
|
||||
|
||||
!CHECK: omp.target_update_data if(%[[COND]] : i1)
|
||||
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update to(a) if(i)
|
||||
end subroutine omp_target_update_if
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `device` clause
|
||||
!===============================================================================
|
||||
|
||||
subroutine omp_target_update_device
|
||||
integer :: a(1024)
|
||||
|
||||
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
!CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32
|
||||
|
||||
!CHECK: %[[TO_MAP:.*]] = omp.map_info
|
||||
|
||||
!CHECK: omp.target_update_data
|
||||
!CHECK-SAME: device(%[[DEVICE]] : i32)
|
||||
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update to(a) device(1)
|
||||
end subroutine omp_target_update_device
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `nowait` clause
|
||||
!===============================================================================
|
||||
|
||||
subroutine omp_target_update_nowait
|
||||
integer :: a(1024)
|
||||
|
||||
!CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
|
||||
!CHECK: %[[TO_MAP:.*]] = omp.map_info
|
||||
|
||||
!CHECK: omp.target_update_data
|
||||
!CHECK-SAME: nowait
|
||||
!CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update to(a) nowait
|
||||
end subroutine omp_target_update_nowait
|
||||
|
||||
!===============================================================================
|
||||
! Target_Data with region
|
||||
!===============================================================================
|
||||
|
@ -134,6 +134,94 @@ subroutine omp_target_exit_device
|
||||
!$omp target exit data map(from: a) device(d)
|
||||
end subroutine omp_target_exit_device
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `to` clause
|
||||
!===============================================================================
|
||||
|
||||
!CHECK-LABEL: func.func @_QPomp_target_update_to() {
|
||||
subroutine omp_target_update_to
|
||||
integer :: a(1024)
|
||||
|
||||
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
|
||||
!CHECK: %[[TO_MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
|
||||
!CHECK-SAME: map_clauses(to) capture(ByRef)
|
||||
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
||||
|
||||
!CHECK: omp.target_update_data motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update to(a)
|
||||
end subroutine omp_target_update_to
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `from` clause
|
||||
!===============================================================================
|
||||
|
||||
!CHECK-LABEL: func.func @_QPomp_target_update_from() {
|
||||
subroutine omp_target_update_from
|
||||
integer :: a(1024)
|
||||
|
||||
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
|
||||
!CHECK: %[[FROM_MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>)
|
||||
!CHECK-SAME: map_clauses(from) capture(ByRef)
|
||||
!CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"}
|
||||
|
||||
!CHECK: omp.target_update_data motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>)
|
||||
!$omp target update from(a)
|
||||
end subroutine omp_target_update_from
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `if` clause
|
||||
!===============================================================================
|
||||
|
||||
!CHECK-LABEL: func.func @_QPomp_target_update_if() {
|
||||
subroutine omp_target_update_if
|
||||
integer :: a(1024)
|
||||
logical :: i
|
||||
|
||||
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
!CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1
|
||||
|
||||
!CHECK: omp.target_update_data if(%[[COND]] : i1) motion_entries
|
||||
!$omp target update from(a) if(i)
|
||||
end subroutine omp_target_update_if
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `device` clause
|
||||
!===============================================================================
|
||||
|
||||
!CHECK-LABEL: func.func @_QPomp_target_update_device() {
|
||||
subroutine omp_target_update_device
|
||||
integer :: a(1024)
|
||||
logical :: i
|
||||
|
||||
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
!CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32
|
||||
|
||||
!CHECK: omp.target_update_data device(%[[DEVICE]] : i32) motion_entries
|
||||
!$omp target update from(a) device(1)
|
||||
end subroutine omp_target_update_device
|
||||
|
||||
!===============================================================================
|
||||
! Target_Update `nowait` clause
|
||||
!===============================================================================
|
||||
|
||||
!CHECK-LABEL: func.func @_QPomp_target_update_nowait() {
|
||||
subroutine omp_target_update_nowait
|
||||
integer :: a(1024)
|
||||
logical :: i
|
||||
|
||||
!CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}})
|
||||
!CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds
|
||||
|
||||
!CHECK: omp.target_update_data nowait motion_entries
|
||||
!$omp target update from(a) nowait
|
||||
end subroutine omp_target_update_nowait
|
||||
|
||||
!===============================================================================
|
||||
! Target_Data with region
|
||||
!===============================================================================
|
||||
|
Loading…
Reference in New Issue
Block a user