Skip to content

Commit 9905728

Browse files
authored
[MLIR][OpenMP] Add Lowering support for OpenMP Declare Mapper directive (#117046)
This patch adds HLFIR/FIR lowering support for OpenMP Declare Mapper directive. Depends on #117045.
1 parent 270284d commit 9905728

File tree

7 files changed

+143
-50
lines changed

7 files changed

+143
-50
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ class AbstractConverter {
314314
mangleName(const Fortran::semantics::DerivedTypeSpec &) = 0;
315315
/// Unique a compiler generated name (add a containing scope specific prefix)
316316
virtual std::string mangleName(std::string &) = 0;
317+
/// Unique a compiler generated name (add a provided scope specific prefix)
318+
virtual std::string mangleName(std::string &, const semantics::Scope &) = 0;
317319
/// Return the field name for a derived type component inside a fir.record
318320
/// type.
319321
virtual std::string

flang/lib/Lower/Bridge.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
10491049
return Fortran::lower::mangle::mangleName(name, getCurrentScope(),
10501050
scopeBlockIdMap);
10511051
}
1052+
std::string
1053+
mangleName(std::string &name,
1054+
const Fortran::semantics::Scope &myScope) override final {
1055+
return Fortran::lower::mangle::mangleName(name, myScope, scopeBlockIdMap);
1056+
}
10521057
std::string getRecordTypeFieldName(
10531058
const Fortran::semantics::Symbol &component) override final {
10541059
return Fortran::lower::mangle::getRecordTypeFieldName(component,

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3119,7 +3119,51 @@ static void
31193119
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
31203120
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
31213121
const parser::OpenMPDeclareMapperConstruct &declareMapperConstruct) {
3122-
TODO(converter.getCurrentLocation(), "OpenMPDeclareMapperConstruct");
3122+
mlir::Location loc = converter.genLocation(declareMapperConstruct.source);
3123+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
3124+
lower::StatementContext stmtCtx;
3125+
const auto &spec =
3126+
std::get<parser::OmpMapperSpecifier>(declareMapperConstruct.t);
3127+
const auto &mapperName{std::get<std::optional<parser::Name>>(spec.t)};
3128+
const auto &varType{std::get<parser::TypeSpec>(spec.t)};
3129+
const auto &varName{std::get<parser::Name>(spec.t)};
3130+
assert(varType.declTypeSpec->category() ==
3131+
semantics::DeclTypeSpec::Category::TypeDerived &&
3132+
"Expected derived type");
3133+
3134+
std::string mapperNameStr;
3135+
if (mapperName.has_value()) {
3136+
mapperNameStr = mapperName->ToString();
3137+
mapperNameStr =
3138+
converter.mangleName(mapperNameStr, mapperName->symbol->owner());
3139+
} else {
3140+
mapperNameStr =
3141+
varType.declTypeSpec->derivedTypeSpec().name().ToString() + ".default";
3142+
mapperNameStr = converter.mangleName(
3143+
mapperNameStr, *varType.declTypeSpec->derivedTypeSpec().GetScope());
3144+
}
3145+
3146+
// Save current insertion point before moving to the module scope to create
3147+
// the DeclareMapperOp
3148+
mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
3149+
3150+
firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody());
3151+
auto mlirType = converter.genType(varType.declTypeSpec->derivedTypeSpec());
3152+
auto declMapperOp = firOpBuilder.create<mlir::omp::DeclareMapperOp>(
3153+
loc, mapperNameStr, mlirType);
3154+
auto &region = declMapperOp.getRegion();
3155+
firOpBuilder.createBlock(&region);
3156+
auto varVal = region.addArgument(firOpBuilder.getRefType(mlirType), loc);
3157+
converter.bindSymbol(*varName.symbol, varVal);
3158+
3159+
// Populate the declareMapper region with the map information.
3160+
mlir::omp::DeclareMapperInfoOperands clauseOps;
3161+
const auto *clauseList{
3162+
parser::Unwrap<parser::OmpClauseList>(declareMapperConstruct.t)};
3163+
List<Clause> clauses = makeClauses(*clauseList, semaCtx);
3164+
ClauseProcessor cp(converter, semaCtx, clauses);
3165+
cp.processMap(loc, stmtCtx, clauseOps);
3166+
firOpBuilder.create<mlir::omp::DeclareMapperInfoOp>(loc, clauseOps.mapVars);
31233167
}
31243168

31253169
static void

flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,8 @@ class MapInfoFinalizationPass
464464
for (auto *user : mapOp->getUsers()) {
465465
if (llvm::isa<mlir::omp::TargetOp, mlir::omp::TargetDataOp,
466466
mlir::omp::TargetUpdateOp, mlir::omp::TargetExitDataOp,
467-
mlir::omp::TargetEnterDataOp>(user))
467+
mlir::omp::TargetEnterDataOp,
468+
mlir::omp::DeclareMapperInfoOp>(user))
468469
return user;
469470

470471
if (auto mapUser = llvm::dyn_cast<mlir::omp::MapInfoOp>(user))
@@ -497,7 +498,9 @@ class MapInfoFinalizationPass
497498
// ourselves to the possibility of race conditions while this pass
498499
// undergoes frequent re-iteration for the near future. So we loop
499500
// over function in the module and then map.info inside of those.
500-
getOperation()->walk([&](mlir::func::FuncOp func) {
501+
getOperation()->walk([&](mlir::Operation *func) {
502+
if (!mlir::isa<mlir::func::FuncOp, mlir::omp::DeclareMapperOp>(func))
503+
return;
501504
// clear all local allocations we made for any boxes in any prior
502505
// iterations from previous function scopes.
503506
localBoxAllocas.clear();

flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
! This test checks lowering of OpenMP declare mapper Directive.
2+
3+
! RUN: split-file %s %t
4+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-1.f90 -o - | FileCheck %t/omp-declare-mapper-1.f90
5+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-2.f90 -o - | FileCheck %t/omp-declare-mapper-2.f90
6+
7+
!--- omp-declare-mapper-1.f90
8+
subroutine declare_mapper_1
9+
integer, parameter :: nvals = 250
10+
type my_type
11+
integer :: num_vals
12+
integer, allocatable :: values(:)
13+
end type
14+
15+
type my_type2
16+
type(my_type) :: my_type_var
17+
type(my_type) :: temp
18+
real, dimension(nvals) :: unmapped
19+
real, dimension(nvals) :: arr
20+
end type
21+
type(my_type2) :: t
22+
real :: x, y(nvals)
23+
!CHECK:omp.declare_mapper @[[MY_TYPE_MAPPER:_QQFdeclare_mapper_1my_type\.default]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_1Tmy_type\{num_vals:i32,values:!fir\.box<!fir\.heap<!fir\.array<\?xi32>>>\}>]] {
24+
!CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<[[MY_TYPE]]>):
25+
!CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFdeclare_mapper_1Evar"} : (!fir.ref<[[MY_TYPE]]>) -> (!fir.ref<[[MY_TYPE]]>, !fir.ref<[[MY_TYPE]]>)
26+
!CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"values"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<[[MY_TYPE]]>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
27+
!CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
28+
!CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
29+
!CHECK: %[[VAL_5:.*]] = arith.constant 0 : index
30+
!CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_3]], %[[VAL_5]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
31+
!CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
32+
!CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
33+
!CHECK: %[[VAL_9:.*]] = arith.constant 1 : index
34+
!CHECK: %[[VAL_10:.*]] = arith.subi %[[VAL_9]], %[[VAL_6]]#0 : index
35+
!CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_1]]#0{"num_vals"} : (!fir.ref<[[MY_TYPE]]>) -> !fir.ref<i32>
36+
!CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32>
37+
!CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i32) -> i64
38+
!CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i64) -> index
39+
!CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_14]], %[[VAL_6]]#0 : index
40+
!CHECK: %[[VAL_16:.*]] = omp.map.bounds lower_bound(%[[VAL_10]] : index) upper_bound(%[[VAL_15]] : index) extent(%[[VAL_6]]#1 : index) stride(%[[VAL_8]] : index) start_idx(%[[VAL_6]]#0 : index)
41+
!CHECK: %[[VAL_17:.*]] = arith.constant 1 : index
42+
!CHECK: %[[VAL_18:.*]] = fir.coordinate_of %[[VAL_1]]#0, %[[VAL_17]] : (!fir.ref<[[MY_TYPE]]>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
43+
!CHECK: %[[VAL_19:.*]] = fir.box_offset %[[VAL_18]] base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>
44+
!CHECK: %[[VAL_20:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i32) var_ptr_ptr(%[[VAL_19]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[VAL_16]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""}
45+
!CHECK: %[[VAL_21:.*]] = omp.map.info var_ptr(%[[VAL_18]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(to) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "var%[[VAL_22:.*]](1:var%[[VAL_23:.*]])"}
46+
!CHECK: %[[VAL_24:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref<[[MY_TYPE]]>, [[MY_TYPE]]) map_clauses(tofrom) capture(ByRef) members(%[[VAL_21]], %[[VAL_20]] : [1], [1, 0] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<[[MY_TYPE]]> {name = "var"}
47+
!CHECK: omp.declare_mapper.info map_entries(%[[VAL_24]], %[[VAL_21]], %[[VAL_20]] : !fir.ref<[[MY_TYPE]]>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>)
48+
!CHECK: }
49+
!$omp declare mapper (my_type :: var) map (var, var%values (1:var%num_vals))
50+
end subroutine declare_mapper_1
51+
52+
!--- omp-declare-mapper-2.f90
53+
subroutine declare_mapper_2
54+
integer, parameter :: nvals = 250
55+
type my_type
56+
integer :: num_vals
57+
integer, allocatable :: values(:)
58+
end type
59+
60+
type my_type2
61+
type(my_type) :: my_type_var
62+
type(my_type) :: temp
63+
real, dimension(nvals) :: unmapped
64+
real, dimension(nvals) :: arr
65+
end type
66+
type(my_type2) :: t
67+
real :: x, y(nvals)
68+
!CHECK:omp.declare_mapper @[[MY_TYPE_MAPPER:_QQFdeclare_mapper_2my_mapper]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_2Tmy_type2\{my_type_var:!fir\.type<_QFdeclare_mapper_2Tmy_type\{num_vals:i32,values:!fir\.box<!fir\.heap<!fir\.array<\?xi32>>>\}>,temp:!fir\.type<_QFdeclare_mapper_2Tmy_type\{num_vals:i32,values:!fir\.box<!fir\.heap<!fir\.array<\?xi32>>>\}>,unmapped:!fir\.array<250xf32>,arr:!fir\.array<250xf32>\}>]] {
69+
!CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<[[MY_TYPE]]>):
70+
!CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFdeclare_mapper_2Ev"} : (!fir.ref<[[MY_TYPE]]>) -> (!fir.ref<[[MY_TYPE]]>, !fir.ref<[[MY_TYPE]]>)
71+
!CHECK: %[[VAL_2:.*]] = arith.constant 250 : index
72+
!CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
73+
!CHECK: %[[VAL_4:.*]] = hlfir.designate %[[VAL_1]]#0{"arr"} shape %[[VAL_3]] : (!fir.ref<[[MY_TYPE]]>, !fir.shape<1>) -> !fir.ref<!fir.array<250xf32>>
74+
!CHECK: %[[VAL_5:.*]] = arith.constant 1 : index
75+
!CHECK: %[[VAL_6:.*]] = arith.constant 0 : index
76+
!CHECK: %[[VAL_7:.*]] = arith.subi %[[VAL_2]], %[[VAL_5]] : index
77+
!CHECK: %[[VAL_8:.*]] = omp.map.bounds lower_bound(%[[VAL_6]] : index) upper_bound(%[[VAL_7]] : index) extent(%[[VAL_2]] : index) stride(%[[VAL_5]] : index) start_idx(%[[VAL_5]] : index)
78+
!CHECK: %[[VAL_9:.*]] = omp.map.info var_ptr(%[[VAL_4]] : !fir.ref<!fir.array<250xf32>>, !fir.array<250xf32>) map_clauses(tofrom) capture(ByRef) bounds(%[[VAL_8]]) -> !fir.ref<!fir.array<250xf32>> {name = "v%[[VAL_10:.*]]"}
79+
!CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_1]]#0{"temp"} : (!fir.ref<[[MY_TYPE]]>) -> !fir.ref<!fir.type<_QFdeclare_mapper_2Tmy_type{num_vals:i32,values:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
80+
!CHECK: %[[VAL_12:.*]] = omp.map.info var_ptr(%[[VAL_11]] : !fir.ref<!fir.type<_QFdeclare_mapper_2Tmy_type{num_vals:i32,values:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>, !fir.type<_QFdeclare_mapper_2Tmy_type{num_vals:i32,values:!fir.box<!fir.heap<!fir.array<?xi32>>>}>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !fir.ref<!fir.type<_QFdeclare_mapper_2Tmy_type{num_vals:i32,values:!fir.box<!fir.heap<!fir.array<?xi32>>>}>> {name = "v%[[VAL_13:.*]]"}
81+
!CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref<[[MY_TYPE]]>, [[MY_TYPE]]) map_clauses(tofrom) capture(ByRef) members(%[[VAL_9]], %[[VAL_12]] : [3], [1] : !fir.ref<!fir.array<250xf32>>, !fir.ref<!fir.type<_QFdeclare_mapper_2Tmy_type{num_vals:i32,values:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<[[MY_TYPE]]> {name = "v", partial_map = true}
82+
!CHECK: omp.declare_mapper.info map_entries(%[[VAL_14]], %[[VAL_9]], %[[VAL_12]] : !fir.ref<[[MY_TYPE]]>, !fir.ref<!fir.array<250xf32>>, !fir.ref<!fir.type<_QFdeclare_mapper_2Tmy_type{num_vals:i32,values:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>)
83+
!CHECK: }
84+
!$omp declare mapper (my_mapper : my_type2 :: v) map (v%arr) map (alloc : v%temp)
85+
end subroutine declare_mapper_2

mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/ADT/TypeSwitch.h"
3333
#include "llvm/Frontend/OpenMP/OMPConstants.h"
3434
#include "llvm/Frontend/OpenMP/OMPDeviceConstants.h"
35+
#include "llvm/Support/Casting.h"
3536
#include <cstddef>
3637
#include <iterator>
3738
#include <optional>

0 commit comments

Comments
 (0)