Skip to content

Commit b54cfa4

Browse files
[flang][acc] Implement MappableType's generatePrivateInit (#148302)
The recipe body generation was moved from lowering into FIR's implementation of MappableType API. And now since all Fortran variable types implement this type, lowering of OpenACC was updated to use this API directly. No test changes were needed - all of the private, firstprivate, and recipe tests get the same body as before.
1 parent 22b221d commit b54cfa4

File tree

4 files changed

+169
-116
lines changed

4 files changed

+169
-116
lines changed

flang/include/flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ struct OpenACCMappableModel
5252

5353
mlir::acc::VariableTypeCategory getTypeCategory(mlir::Type type,
5454
mlir::Value var) const;
55+
56+
mlir::Value generatePrivateInit(mlir::Type type, mlir::OpBuilder &builder,
57+
mlir::Location loc,
58+
mlir::TypedValue<mlir::acc::MappableType> var,
59+
llvm::StringRef varName,
60+
mlir::ValueRange extents,
61+
mlir::Value initVal) const;
5562
};
5663

5764
} // namespace fir::acc

flang/lib/Lower/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ add_flang_library(FortranLower
5151
FIRDialect
5252
FIRDialectSupport
5353
FIRBuilder
54+
FIROpenACCSupport
5455
FIRSupport
5556
FIRTransforms
5657
HLFIRDialect

flang/lib/Lower/OpenACC.cpp

Lines changed: 23 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -959,119 +959,6 @@ static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder,
959959
llvm::report_fatal_error("Unsupported OpenACC reduction type");
960960
}
961961

962-
template <typename RecipeOp>
963-
static void genPrivateLikeInitRegion(fir::FirOpBuilder &builder,
964-
RecipeOp recipe, mlir::Type argTy,
965-
mlir::Location loc,
966-
mlir::Value initValue) {
967-
mlir::Value retVal = recipe.getInitRegion().front().getArgument(0);
968-
mlir::Type unwrappedTy = fir::unwrapRefType(argTy);
969-
970-
llvm::StringRef initName;
971-
if constexpr (std::is_same_v<RecipeOp, mlir::acc::ReductionRecipeOp>)
972-
initName = accReductionInitName;
973-
else
974-
initName = accPrivateInitName;
975-
976-
auto getDeclareOpForType = [&](mlir::Type ty) -> hlfir::DeclareOp {
977-
auto alloca = builder.create<fir::AllocaOp>(loc, ty);
978-
return builder.create<hlfir::DeclareOp>(
979-
loc, alloca, initName, /*shape=*/nullptr, llvm::ArrayRef<mlir::Value>{},
980-
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
981-
};
982-
983-
if (fir::isa_trivial(unwrappedTy)) {
984-
auto declareOp = getDeclareOpForType(unwrappedTy);
985-
if (initValue) {
986-
auto convert = builder.createConvert(loc, unwrappedTy, initValue);
987-
builder.create<fir::StoreOp>(loc, convert, declareOp.getBase());
988-
}
989-
retVal = declareOp.getBase();
990-
} else if (auto seqTy =
991-
mlir::dyn_cast_or_null<fir::SequenceType>(unwrappedTy)) {
992-
if (fir::isa_trivial(seqTy.getEleTy())) {
993-
mlir::Value shape;
994-
llvm::SmallVector<mlir::Value> extents;
995-
if (seqTy.hasDynamicExtents()) {
996-
// Extents are passed as block arguments. First argument is the
997-
// original value.
998-
for (unsigned i = 1; i < recipe.getInitRegion().getArguments().size();
999-
++i)
1000-
extents.push_back(recipe.getInitRegion().getArgument(i));
1001-
shape = builder.create<fir::ShapeOp>(loc, extents);
1002-
} else {
1003-
shape = genShapeOp(builder, seqTy, loc);
1004-
}
1005-
auto alloca = builder.create<fir::AllocaOp>(
1006-
loc, seqTy, /*typeparams=*/mlir::ValueRange{}, extents);
1007-
auto declareOp = builder.create<hlfir::DeclareOp>(
1008-
loc, alloca, initName, shape, llvm::ArrayRef<mlir::Value>{},
1009-
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
1010-
1011-
if (initValue) {
1012-
mlir::Type idxTy = builder.getIndexType();
1013-
mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy());
1014-
llvm::SmallVector<fir::DoLoopOp> loops;
1015-
llvm::SmallVector<mlir::Value> ivs;
1016-
1017-
if (seqTy.hasDynamicExtents()) {
1018-
builder.create<hlfir::AssignOp>(loc, initValue, declareOp.getBase());
1019-
} else {
1020-
for (auto ext : seqTy.getShape()) {
1021-
auto lb = builder.createIntegerConstant(loc, idxTy, 0);
1022-
auto ub = builder.createIntegerConstant(loc, idxTy, ext - 1);
1023-
auto step = builder.createIntegerConstant(loc, idxTy, 1);
1024-
auto loop = builder.create<fir::DoLoopOp>(loc, lb, ub, step,
1025-
/*unordered=*/false);
1026-
builder.setInsertionPointToStart(loop.getBody());
1027-
loops.push_back(loop);
1028-
ivs.push_back(loop.getInductionVar());
1029-
}
1030-
auto coord = builder.create<fir::CoordinateOp>(
1031-
loc, refTy, declareOp.getBase(), ivs);
1032-
builder.create<fir::StoreOp>(loc, initValue, coord);
1033-
builder.setInsertionPointAfter(loops[0]);
1034-
}
1035-
}
1036-
retVal = declareOp.getBase();
1037-
}
1038-
} else if (auto boxTy =
1039-
mlir::dyn_cast_or_null<fir::BaseBoxType>(unwrappedTy)) {
1040-
mlir::Type innerTy = fir::unwrapRefType(boxTy.getEleTy());
1041-
if (fir::isa_trivial(innerTy)) {
1042-
retVal = getDeclareOpForType(unwrappedTy).getBase();
1043-
} else if (mlir::isa<fir::SequenceType>(innerTy)) {
1044-
fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
1045-
hlfir::Entity source = hlfir::Entity{retVal};
1046-
auto [temp, cleanup] = hlfir::createTempFromMold(loc, firBuilder, source);
1047-
if (fir::isa_ref_type(argTy)) {
1048-
// When the temp is created - it is not a reference - thus we can
1049-
// end up with a type inconsistency. Therefore ensure storage is created
1050-
// for it.
1051-
retVal = getDeclareOpForType(unwrappedTy).getBase();
1052-
mlir::Value storeDst = retVal;
1053-
if (fir::unwrapRefType(retVal.getType()) != temp.getType()) {
1054-
// `createTempFromMold` makes the unfortunate choice to lose the
1055-
// `fir.heap` and `fir.ptr` types when wrapping with a box. Namely,
1056-
// when wrapping a `fir.heap<fir.array>`, it will create instead a
1057-
// `fir.box<fir.array>`. Cast here to deal with this inconsistency.
1058-
storeDst = firBuilder.createConvert(
1059-
loc, firBuilder.getRefType(temp.getType()), retVal);
1060-
}
1061-
builder.create<fir::StoreOp>(loc, temp, storeDst);
1062-
} else {
1063-
retVal = temp;
1064-
}
1065-
} else {
1066-
TODO(loc, "Unsupported boxed type for OpenACC private-like recipe");
1067-
}
1068-
if (initValue) {
1069-
builder.create<hlfir::AssignOp>(loc, initValue, retVal);
1070-
}
1071-
}
1072-
builder.create<mlir::acc::YieldOp>(loc, retVal);
1073-
}
1074-
1075962
template <typename RecipeOp>
1076963
static RecipeOp genRecipeOp(
1077964
fir::FirOpBuilder &builder, mlir::ModuleOp mod, llvm::StringRef recipeName,
@@ -1100,15 +987,35 @@ static RecipeOp genRecipeOp(
1100987
}
1101988
}
1102989
}
1103-
builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
1104-
argsTy, argsLoc);
990+
auto initBlock = builder.createBlock(
991+
&recipe.getInitRegion(), recipe.getInitRegion().end(), argsTy, argsLoc);
1105992
builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
1106993
mlir::Value initValue;
1107994
if constexpr (std::is_same_v<RecipeOp, mlir::acc::ReductionRecipeOp>) {
1108995
assert(op != mlir::acc::ReductionOperator::AccNone);
1109996
initValue = getReductionInitValue(builder, loc, fir::unwrapRefType(ty), op);
1110997
}
1111-
genPrivateLikeInitRegion<RecipeOp>(builder, recipe, ty, loc, initValue);
998+
999+
// Since we reuse the same recipe for all variables of the same type - we
1000+
// cannot use the actual variable name. Thus use a temporary name.
1001+
llvm::StringRef initName;
1002+
if constexpr (std::is_same_v<RecipeOp, mlir::acc::ReductionRecipeOp>)
1003+
initName = accReductionInitName;
1004+
else
1005+
initName = accPrivateInitName;
1006+
1007+
auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
1008+
assert(mappableTy &&
1009+
"Expected that all variable types are considered mappable");
1010+
auto retVal = mappableTy.generatePrivateInit(
1011+
builder, loc,
1012+
mlir::cast<mlir::TypedValue<mlir::acc::MappableType>>(
1013+
initBlock->getArgument(0)),
1014+
initName,
1015+
initBlock->getArguments().take_back(initBlock->getArguments().size() - 1),
1016+
initValue);
1017+
builder.create<mlir::acc::YieldOp>(loc, retVal ? retVal
1018+
: initBlock->getArgument(0));
11121019
return recipe;
11131020
}
11141021

flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "mlir/Dialect/OpenACC/OpenACC.h"
2626
#include "mlir/IR/BuiltinOps.h"
2727
#include "mlir/Support/LLVM.h"
28+
#include "llvm/ADT/SmallVector.h"
2829
#include "llvm/ADT/TypeSwitch.h"
2930

3031
namespace fir::acc {
@@ -525,4 +526,141 @@ OpenACCPointerLikeModel<fir::LLVMPointerType>::getPointeeTypeCategory(
525526
return categorizePointee(pointer, varPtr, varType);
526527
}
527528

529+
static fir::ShapeOp genShapeOp(mlir::OpBuilder &builder,
530+
fir::SequenceType seqTy, mlir::Location loc) {
531+
llvm::SmallVector<mlir::Value> extents;
532+
mlir::Type idxTy = builder.getIndexType();
533+
for (auto extent : seqTy.getShape())
534+
extents.push_back(builder.create<mlir::arith::ConstantOp>(
535+
loc, idxTy, builder.getIntegerAttr(idxTy, extent)));
536+
return builder.create<fir::ShapeOp>(loc, extents);
537+
}
538+
539+
template <typename Ty>
540+
mlir::Value OpenACCMappableModel<Ty>::generatePrivateInit(
541+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
542+
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
543+
mlir::ValueRange extents, mlir::Value initVal) const {
544+
mlir::Value retVal;
545+
mlir::Type unwrappedTy = fir::unwrapRefType(type);
546+
mlir::ModuleOp mod = builder.getInsertionBlock()
547+
->getParent()
548+
->getParentOfType<mlir::ModuleOp>();
549+
fir::FirOpBuilder firBuilder(builder, mod);
550+
551+
auto getDeclareOpForType = [&](mlir::Type ty) -> hlfir::DeclareOp {
552+
auto alloca = firBuilder.create<fir::AllocaOp>(loc, ty);
553+
return firBuilder.create<hlfir::DeclareOp>(
554+
loc, alloca, varName, /*shape=*/nullptr, llvm::ArrayRef<mlir::Value>{},
555+
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
556+
};
557+
558+
if (fir::isa_trivial(unwrappedTy)) {
559+
auto declareOp = getDeclareOpForType(unwrappedTy);
560+
if (initVal) {
561+
auto convert = firBuilder.createConvert(loc, unwrappedTy, initVal);
562+
firBuilder.create<fir::StoreOp>(loc, convert, declareOp.getBase());
563+
}
564+
retVal = declareOp.getBase();
565+
} else if (auto seqTy =
566+
mlir::dyn_cast_or_null<fir::SequenceType>(unwrappedTy)) {
567+
if (fir::isa_trivial(seqTy.getEleTy())) {
568+
mlir::Value shape;
569+
if (seqTy.hasDynamicExtents()) {
570+
shape = firBuilder.create<fir::ShapeOp>(loc, llvm::to_vector(extents));
571+
} else {
572+
shape = genShapeOp(firBuilder, seqTy, loc);
573+
}
574+
auto alloca = firBuilder.create<fir::AllocaOp>(
575+
loc, seqTy, /*typeparams=*/mlir::ValueRange{}, extents);
576+
auto declareOp = firBuilder.create<hlfir::DeclareOp>(
577+
loc, alloca, varName, shape, llvm::ArrayRef<mlir::Value>{},
578+
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
579+
580+
if (initVal) {
581+
mlir::Type idxTy = firBuilder.getIndexType();
582+
mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy());
583+
llvm::SmallVector<fir::DoLoopOp> loops;
584+
llvm::SmallVector<mlir::Value> ivs;
585+
586+
if (seqTy.hasDynamicExtents()) {
587+
firBuilder.create<hlfir::AssignOp>(loc, initVal, declareOp.getBase());
588+
} else {
589+
for (auto ext : seqTy.getShape()) {
590+
auto lb = firBuilder.createIntegerConstant(loc, idxTy, 0);
591+
auto ub = firBuilder.createIntegerConstant(loc, idxTy, ext - 1);
592+
auto step = firBuilder.createIntegerConstant(loc, idxTy, 1);
593+
auto loop = firBuilder.create<fir::DoLoopOp>(loc, lb, ub, step,
594+
/*unordered=*/false);
595+
firBuilder.setInsertionPointToStart(loop.getBody());
596+
loops.push_back(loop);
597+
ivs.push_back(loop.getInductionVar());
598+
}
599+
auto coord = firBuilder.create<fir::CoordinateOp>(
600+
loc, refTy, declareOp.getBase(), ivs);
601+
firBuilder.create<fir::StoreOp>(loc, initVal, coord);
602+
firBuilder.setInsertionPointAfter(loops[0]);
603+
}
604+
}
605+
retVal = declareOp.getBase();
606+
}
607+
} else if (auto boxTy =
608+
mlir::dyn_cast_or_null<fir::BaseBoxType>(unwrappedTy)) {
609+
mlir::Type innerTy = fir::unwrapRefType(boxTy.getEleTy());
610+
if (fir::isa_trivial(innerTy)) {
611+
retVal = getDeclareOpForType(unwrappedTy).getBase();
612+
} else if (mlir::isa<fir::SequenceType>(innerTy)) {
613+
hlfir::Entity source = hlfir::Entity{var};
614+
auto [temp, cleanup] = hlfir::createTempFromMold(loc, firBuilder, source);
615+
if (fir::isa_ref_type(type)) {
616+
// When the temp is created - it is not a reference - thus we can
617+
// end up with a type inconsistency. Therefore ensure storage is created
618+
// for it.
619+
retVal = getDeclareOpForType(unwrappedTy).getBase();
620+
mlir::Value storeDst = retVal;
621+
if (fir::unwrapRefType(retVal.getType()) != temp.getType()) {
622+
// `createTempFromMold` makes the unfortunate choice to lose the
623+
// `fir.heap` and `fir.ptr` types when wrapping with a box. Namely,
624+
// when wrapping a `fir.heap<fir.array>`, it will create instead a
625+
// `fir.box<fir.array>`. Cast here to deal with this inconsistency.
626+
storeDst = firBuilder.createConvert(
627+
loc, firBuilder.getRefType(temp.getType()), retVal);
628+
}
629+
builder.create<fir::StoreOp>(loc, temp, storeDst);
630+
} else {
631+
retVal = temp;
632+
}
633+
} else {
634+
TODO(loc, "Unsupported boxed type for OpenACC private-like recipe");
635+
}
636+
if (initVal) {
637+
builder.create<hlfir::AssignOp>(loc, initVal, retVal);
638+
}
639+
}
640+
return retVal;
641+
}
642+
643+
template mlir::Value
644+
OpenACCMappableModel<fir::BaseBoxType>::generatePrivateInit(
645+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
646+
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
647+
mlir::ValueRange extents, mlir::Value initVal) const;
648+
649+
template mlir::Value
650+
OpenACCMappableModel<fir::ReferenceType>::generatePrivateInit(
651+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
652+
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
653+
mlir::ValueRange extents, mlir::Value initVal) const;
654+
655+
template mlir::Value OpenACCMappableModel<fir::HeapType>::generatePrivateInit(
656+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
657+
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
658+
mlir::ValueRange extents, mlir::Value initVal) const;
659+
660+
template mlir::Value
661+
OpenACCMappableModel<fir::PointerType>::generatePrivateInit(
662+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
663+
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
664+
mlir::ValueRange extents, mlir::Value initVal) const;
665+
528666
} // namespace fir::acc

0 commit comments

Comments
 (0)