702 lines · cpp
1//===-- MIFOpConversion.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Optimizer/Transforms/MIFOpConversion.h"10#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"11#include "flang/Optimizer/Builder/Todo.h"12#include "flang/Optimizer/CodeGen/TypeConverter.h"13#include "flang/Optimizer/Dialect/FIRDialect.h"14#include "flang/Optimizer/Dialect/FIROps.h"15#include "flang/Optimizer/Dialect/MIF/MIFOps.h"16#include "flang/Optimizer/HLFIR/HLFIROps.h"17#include "flang/Optimizer/Support/DataLayout.h"18#include "flang/Optimizer/Support/InternalNames.h"19#include "mlir/IR/Matchers.h"20#include "mlir/Transforms/DialectConversion.h"21#include "mlir/Transforms/GreedyPatternRewriteDriver.h"22 23namespace fir {24#define GEN_PASS_DEF_MIFOPCONVERSION25#include "flang/Optimizer/Transforms/Passes.h.inc"26} // namespace fir27 28using namespace mlir;29using namespace Fortran::runtime;30 31namespace {32 33// Default prefix for subroutines of PRIF compiled with LLVM34static std::string getPRIFProcName(std::string fmt) {35 std::ostringstream oss;36 oss << "prif_" << fmt;37 return fir::NameUniquer::doProcedure({"prif"}, {}, oss.str());38}39 40static mlir::Type getPRIFStatType(fir::FirOpBuilder &builder) {41 return builder.getRefType(builder.getI32Type());42}43 44static mlir::Type getPRIFErrmsgType(fir::FirOpBuilder &builder) {45 return fir::BoxType::get(fir::CharacterType::get(46 builder.getContext(), 1, fir::CharacterType::unknownLen()));47}48 49// Most PRIF functions take `errmsg` and `errmsg_alloc` as two optional50// arguments of intent (out). One is allocatable, the other is not.51// It is the responsibility of the compiler to ensure that the appropriate52// optional argument is passed, and at most one must be provided in a given53// call.54// Depending on the type of `errmsg`, this function will return the pair55// corresponding to (`errmsg`, `errmsg_alloc`).56static std::pair<mlir::Value, mlir::Value>57genErrmsgPRIF(fir::FirOpBuilder &builder, mlir::Location loc,58 mlir::Value errmsg) {59 mlir::Value absent =60 fir::AbsentOp::create(builder, loc, getPRIFErrmsgType(builder));61 if (!errmsg)62 return {absent, absent};63 64 bool isAllocatableErrmsg = fir::isAllocatableType(errmsg.getType());65 mlir::Value errMsg = isAllocatableErrmsg ? absent : errmsg;66 mlir::Value errMsgAlloc = isAllocatableErrmsg ? errmsg : absent;67 return {errMsg, errMsgAlloc};68}69 70static mlir::Value genStatPRIF(fir::FirOpBuilder &builder, mlir::Location loc,71 mlir::Value stat) {72 if (!stat)73 return fir::AbsentOp::create(builder, loc, getPRIFStatType(builder));74 return stat;75}76 77/// Convert mif.init operation to runtime call of 'prif_init'78struct MIFInitOpConversion : public mlir::OpRewritePattern<mif::InitOp> {79 using OpRewritePattern::OpRewritePattern;80 81 mlir::LogicalResult82 matchAndRewrite(mif::InitOp op,83 mlir::PatternRewriter &rewriter) const override {84 auto mod = op->template getParentOfType<mlir::ModuleOp>();85 fir::FirOpBuilder builder(rewriter, mod);86 mlir::Location loc = op.getLoc();87 88 mlir::Type i32Ty = builder.getI32Type();89 mlir::Value result = builder.createTemporary(loc, i32Ty);90 mlir::FunctionType ftype = mlir::FunctionType::get(91 builder.getContext(),92 /*inputs*/ {builder.getRefType(i32Ty)}, /*results*/ {});93 mlir::func::FuncOp funcOp =94 builder.createFunction(loc, getPRIFProcName("init"), ftype);95 llvm::SmallVector<mlir::Value> args =96 fir::runtime::createArguments(builder, loc, ftype, result);97 fir::CallOp::create(builder, loc, funcOp, args);98 rewriter.replaceOpWithNewOp<fir::LoadOp>(op, result);99 return mlir::success();100 }101};102 103/// Convert mif.this_image operation to PRIF runtime call104struct MIFThisImageOpConversion105 : public mlir::OpRewritePattern<mif::ThisImageOp> {106 using OpRewritePattern::OpRewritePattern;107 108 mlir::LogicalResult109 matchAndRewrite(mif::ThisImageOp op,110 mlir::PatternRewriter &rewriter) const override {111 auto mod = op->template getParentOfType<mlir::ModuleOp>();112 fir::FirOpBuilder builder(rewriter, mod);113 mlir::Location loc = op.getLoc();114 115 if (op.getCoarray())116 TODO(loc, "mif.this_image op with coarray argument.");117 else {118 mlir::Type i32Ty = builder.getI32Type();119 mlir::Type boxTy = fir::BoxType::get(rewriter.getNoneType());120 mlir::Value result = builder.createTemporary(loc, i32Ty);121 mlir::FunctionType ftype = mlir::FunctionType::get(122 builder.getContext(),123 /*inputs*/ {boxTy, builder.getRefType(i32Ty)}, /*results*/ {});124 mlir::Value teamArg = op.getTeam();125 if (!op.getTeam())126 teamArg = fir::AbsentOp::create(builder, loc, boxTy);127 128 mlir::func::FuncOp funcOp = builder.createFunction(129 loc, getPRIFProcName("this_image_no_coarray"), ftype);130 llvm::SmallVector<mlir::Value> args =131 fir::runtime::createArguments(builder, loc, ftype, teamArg, result);132 fir::CallOp::create(builder, loc, funcOp, args);133 rewriter.replaceOpWithNewOp<fir::LoadOp>(op, result);134 return mlir::success();135 }136 }137};138 139/// Convert mif.num_images operation to runtime call of140/// prif_num_images_with_{team|team_number}141struct MIFNumImagesOpConversion142 : public mlir::OpRewritePattern<mif::NumImagesOp> {143 using OpRewritePattern::OpRewritePattern;144 145 mlir::LogicalResult146 matchAndRewrite(mif::NumImagesOp op,147 mlir::PatternRewriter &rewriter) const override {148 auto mod = op->template getParentOfType<mlir::ModuleOp>();149 fir::FirOpBuilder builder(rewriter, mod);150 mlir::Location loc = op.getLoc();151 152 mlir::Type i32Ty = builder.getI32Type();153 mlir::Type i64Ty = builder.getI64Type();154 mlir::Type boxTy = fir::BoxType::get(rewriter.getNoneType());155 mlir::Value result = builder.createTemporary(loc, i32Ty);156 157 mlir::func::FuncOp funcOp;158 llvm::SmallVector<mlir::Value> args;159 if (!op.getTeam() && !op.getTeamNumber()) {160 mlir::FunctionType ftype = mlir::FunctionType::get(161 builder.getContext(),162 /*inputs*/ {builder.getRefType(i32Ty)}, /*results*/ {});163 funcOp =164 builder.createFunction(loc, getPRIFProcName("num_images"), ftype);165 args = fir::runtime::createArguments(builder, loc, ftype, result);166 } else {167 if (op.getTeam()) {168 mlir::FunctionType ftype =169 mlir::FunctionType::get(builder.getContext(),170 /*inputs*/171 {boxTy, builder.getRefType(i32Ty)},172 /*results*/ {});173 funcOp = builder.createFunction(174 loc, getPRIFProcName("num_images_with_team"), ftype);175 args = fir::runtime::createArguments(builder, loc, ftype, op.getTeam(),176 result);177 } else {178 mlir::Value teamNumber = builder.createTemporary(loc, i64Ty);179 mlir::Value cst = op.getTeamNumber();180 if (op.getTeamNumber().getType() != i64Ty)181 cst = fir::ConvertOp::create(builder, loc, i64Ty, op.getTeamNumber());182 fir::StoreOp::create(builder, loc, cst, teamNumber);183 mlir::FunctionType ftype = mlir::FunctionType::get(184 builder.getContext(),185 /*inputs*/ {builder.getRefType(i64Ty), builder.getRefType(i32Ty)},186 /*results*/ {});187 funcOp = builder.createFunction(188 loc, getPRIFProcName("num_images_with_team_number"), ftype);189 args = fir::runtime::createArguments(builder, loc, ftype, teamNumber,190 result);191 }192 }193 fir::CallOp::create(builder, loc, funcOp, args);194 rewriter.replaceOpWithNewOp<fir::LoadOp>(op, result);195 return mlir::success();196 }197};198 199/// Convert mif.sync_all operation to runtime call of 'prif_sync_all'200struct MIFSyncAllOpConversion : public mlir::OpRewritePattern<mif::SyncAllOp> {201 using OpRewritePattern::OpRewritePattern;202 203 mlir::LogicalResult204 matchAndRewrite(mif::SyncAllOp op,205 mlir::PatternRewriter &rewriter) const override {206 auto mod = op->template getParentOfType<mlir::ModuleOp>();207 fir::FirOpBuilder builder(rewriter, mod);208 mlir::Location loc = op.getLoc();209 210 mlir::Type errmsgTy = getPRIFErrmsgType(builder);211 mlir::FunctionType ftype = mlir::FunctionType::get(212 builder.getContext(),213 /*inputs*/ {getPRIFStatType(builder), errmsgTy, errmsgTy},214 /*results*/ {});215 mlir::func::FuncOp funcOp =216 builder.createFunction(loc, getPRIFProcName("sync_all"), ftype);217 218 auto [errmsgArg, errmsgAllocArg] =219 genErrmsgPRIF(builder, loc, op.getErrmsg());220 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());221 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(222 builder, loc, ftype, stat, errmsgArg, errmsgAllocArg);223 rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args);224 return mlir::success();225 }226};227 228/// Convert mif.sync_images operation to runtime call of 'prif_sync_images'229struct MIFSyncImagesOpConversion230 : public mlir::OpRewritePattern<mif::SyncImagesOp> {231 using OpRewritePattern::OpRewritePattern;232 233 mlir::LogicalResult234 matchAndRewrite(mif::SyncImagesOp op,235 mlir::PatternRewriter &rewriter) const override {236 auto mod = op->template getParentOfType<mlir::ModuleOp>();237 fir::FirOpBuilder builder(rewriter, mod);238 mlir::Location loc = op.getLoc();239 240 mlir::Type errmsgTy = getPRIFErrmsgType(builder);241 mlir::Type imgSetTy = fir::BoxType::get(fir::SequenceType::get(242 {fir::SequenceType::getUnknownExtent()}, builder.getI32Type()));243 mlir::FunctionType ftype = mlir::FunctionType::get(244 builder.getContext(),245 /*inputs*/246 {imgSetTy, getPRIFStatType(builder), errmsgTy, errmsgTy},247 /*results*/ {});248 mlir::func::FuncOp funcOp =249 builder.createFunction(loc, getPRIFProcName("sync_images"), ftype);250 251 // If imageSet is scalar, PRIF require to pass an array of size 1.252 mlir::Value imageSet = op.getImageSet();253 if (!imageSet)254 imageSet = fir::AbsentOp::create(builder, loc, imgSetTy);255 else if (auto boxTy = mlir::dyn_cast<fir::BoxType>(imageSet.getType())) {256 if (!mlir::isa<fir::SequenceType>(boxTy.getEleTy())) {257 mlir::Value one =258 builder.createIntegerConstant(loc, builder.getI32Type(), 1);259 mlir::Value shape = fir::ShapeOp::create(builder, loc, one);260 imageSet =261 fir::ReboxOp::create(builder, loc,262 fir::BoxType::get(fir::SequenceType::get(263 {1}, builder.getI32Type())),264 imageSet, shape, mlir::Value{});265 }266 }267 auto [errmsgArg, errmsgAllocArg] =268 genErrmsgPRIF(builder, loc, op.getErrmsg());269 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());270 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(271 builder, loc, ftype, imageSet, stat, errmsgArg, errmsgAllocArg);272 rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args);273 return mlir::success();274 }275};276 277/// Convert mif.sync_memory operation to runtime call of 'prif_sync_memory'278struct MIFSyncMemoryOpConversion279 : public mlir::OpRewritePattern<mif::SyncMemoryOp> {280 using OpRewritePattern::OpRewritePattern;281 282 mlir::LogicalResult283 matchAndRewrite(mif::SyncMemoryOp op,284 mlir::PatternRewriter &rewriter) const override {285 auto mod = op->template getParentOfType<mlir::ModuleOp>();286 fir::FirOpBuilder builder(rewriter, mod);287 mlir::Location loc = op.getLoc();288 289 mlir::Type errmsgTy = getPRIFErrmsgType(builder);290 mlir::FunctionType ftype = mlir::FunctionType::get(291 builder.getContext(),292 /*inputs*/ {getPRIFStatType(builder), errmsgTy, errmsgTy},293 /*results*/ {});294 mlir::func::FuncOp funcOp =295 builder.createFunction(loc, getPRIFProcName("sync_memory"), ftype);296 297 auto [errmsgArg, errmsgAllocArg] =298 genErrmsgPRIF(builder, loc, op.getErrmsg());299 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());300 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(301 builder, loc, ftype, stat, errmsgArg, errmsgAllocArg);302 rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args);303 return mlir::success();304 }305};306 307/// Convert mif.sync_team operation to runtime call of 'prif_sync_team'308struct MIFSyncTeamOpConversion309 : public mlir::OpRewritePattern<mif::SyncTeamOp> {310 using OpRewritePattern::OpRewritePattern;311 312 mlir::LogicalResult313 matchAndRewrite(mif::SyncTeamOp op,314 mlir::PatternRewriter &rewriter) const override {315 auto mod = op->template getParentOfType<mlir::ModuleOp>();316 fir::FirOpBuilder builder(rewriter, mod);317 mlir::Location loc = op.getLoc();318 319 mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());320 mlir::Type errmsgTy = getPRIFErrmsgType(builder);321 mlir::FunctionType ftype = mlir::FunctionType::get(322 builder.getContext(),323 /*inputs*/ {boxTy, getPRIFStatType(builder), errmsgTy, errmsgTy},324 /*results*/ {});325 mlir::func::FuncOp funcOp =326 builder.createFunction(loc, getPRIFProcName("sync_team"), ftype);327 328 auto [errmsgArg, errmsgAllocArg] =329 genErrmsgPRIF(builder, loc, op.getErrmsg());330 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());331 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(332 builder, loc, ftype, op.getTeam(), stat, errmsgArg, errmsgAllocArg);333 rewriter.replaceOpWithNewOp<fir::CallOp>(op, funcOp, args);334 return mlir::success();335 }336};337 338/// Generate call to collective subroutines except co_reduce339/// A must be lowered as a box340static fir::CallOp genCollectiveSubroutine(fir::FirOpBuilder &builder,341 mlir::Location loc, mlir::Value A,342 mlir::Value image, mlir::Value stat,343 mlir::Value errmsg,344 std::string coName) {345 mlir::Value rootImage;346 mlir::Type i32Ty = builder.getI32Type();347 if (!image)348 rootImage = fir::AbsentOp::create(builder, loc, builder.getRefType(i32Ty));349 else {350 rootImage = builder.createTemporary(loc, i32Ty);351 if (image.getType() != i32Ty)352 image = fir::ConvertOp::create(builder, loc, i32Ty, image);353 fir::StoreOp::create(builder, loc, image, rootImage);354 }355 356 mlir::Type errmsgTy = getPRIFErrmsgType(builder);357 mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());358 mlir::FunctionType ftype =359 mlir::FunctionType::get(builder.getContext(),360 /*inputs*/361 {boxTy, builder.getRefType(builder.getI32Type()),362 getPRIFStatType(builder), errmsgTy, errmsgTy},363 /*results*/ {});364 mlir::func::FuncOp funcOp = builder.createFunction(loc, coName, ftype);365 366 auto [errmsgArg, errmsgAllocArg] = genErrmsgPRIF(builder, loc, errmsg);367 if (!stat)368 stat = fir::AbsentOp::create(builder, loc, getPRIFStatType(builder));369 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(370 builder, loc, ftype, A, rootImage, stat, errmsgArg, errmsgAllocArg);371 return fir::CallOp::create(builder, loc, funcOp, args);372}373 374/// Convert mif.co_broadcast operation to runtime call of 'prif_co_broadcast'375struct MIFCoBroadcastOpConversion376 : public mlir::OpRewritePattern<mif::CoBroadcastOp> {377 using OpRewritePattern::OpRewritePattern;378 379 mlir::LogicalResult380 matchAndRewrite(mif::CoBroadcastOp op,381 mlir::PatternRewriter &rewriter) const override {382 auto mod = op->template getParentOfType<mlir::ModuleOp>();383 fir::FirOpBuilder builder(rewriter, mod);384 mlir::Location loc = op.getLoc();385 386 fir::CallOp callOp = genCollectiveSubroutine(387 builder, loc, op.getA(), op.getSourceImage(), op.getStat(),388 op.getErrmsg(), getPRIFProcName("co_broadcast"));389 rewriter.replaceOp(op, callOp);390 return mlir::success();391 }392};393 394/// Convert mif.co_max operation to runtime call of 'prif_co_max'395struct MIFCoMaxOpConversion : public mlir::OpRewritePattern<mif::CoMaxOp> {396 using OpRewritePattern::OpRewritePattern;397 398 mlir::LogicalResult399 matchAndRewrite(mif::CoMaxOp op,400 mlir::PatternRewriter &rewriter) const override {401 auto mod = op->template getParentOfType<mlir::ModuleOp>();402 fir::FirOpBuilder builder(rewriter, mod);403 mlir::Location loc = op.getLoc();404 405 fir::CallOp callOp;406 mlir::Type argTy =407 fir::unwrapSequenceType(fir::unwrapPassByRefType(op.getA().getType()));408 if (mlir::isa<fir::CharacterType>(argTy))409 callOp = genCollectiveSubroutine(410 builder, loc, op.getA(), op.getResultImage(), op.getStat(),411 op.getErrmsg(), getPRIFProcName("co_max_character"));412 else413 callOp = genCollectiveSubroutine(414 builder, loc, op.getA(), op.getResultImage(), op.getStat(),415 op.getErrmsg(), getPRIFProcName("co_max"));416 rewriter.replaceOp(op, callOp);417 return mlir::success();418 }419};420 421/// Convert mif.co_min operation to runtime call of 'prif_co_min'422struct MIFCoMinOpConversion : public mlir::OpRewritePattern<mif::CoMinOp> {423 using OpRewritePattern::OpRewritePattern;424 425 mlir::LogicalResult426 matchAndRewrite(mif::CoMinOp op,427 mlir::PatternRewriter &rewriter) const override {428 auto mod = op->template getParentOfType<mlir::ModuleOp>();429 fir::FirOpBuilder builder(rewriter, mod);430 mlir::Location loc = op.getLoc();431 432 fir::CallOp callOp;433 mlir::Type argTy =434 fir::unwrapSequenceType(fir::unwrapPassByRefType(op.getA().getType()));435 if (mlir::isa<fir::CharacterType>(argTy))436 callOp = genCollectiveSubroutine(437 builder, loc, op.getA(), op.getResultImage(), op.getStat(),438 op.getErrmsg(), getPRIFProcName("co_min_character"));439 else440 callOp = genCollectiveSubroutine(441 builder, loc, op.getA(), op.getResultImage(), op.getStat(),442 op.getErrmsg(), getPRIFProcName("co_min"));443 rewriter.replaceOp(op, callOp);444 return mlir::success();445 }446};447 448/// Convert mif.co_sum operation to runtime call of 'prif_co_sum'449struct MIFCoSumOpConversion : public mlir::OpRewritePattern<mif::CoSumOp> {450 using OpRewritePattern::OpRewritePattern;451 452 mlir::LogicalResult453 matchAndRewrite(mif::CoSumOp op,454 mlir::PatternRewriter &rewriter) const override {455 auto mod = op->template getParentOfType<mlir::ModuleOp>();456 fir::FirOpBuilder builder(rewriter, mod);457 mlir::Location loc = op.getLoc();458 459 fir::CallOp callOp = genCollectiveSubroutine(460 builder, loc, op.getA(), op.getResultImage(), op.getStat(),461 op.getErrmsg(), getPRIFProcName("co_sum"));462 rewriter.replaceOp(op, callOp);463 return mlir::success();464 }465};466 467/// Convert mif.form_team operation to runtime call of 'prif_form_team'468struct MIFFormTeamOpConversion469 : public mlir::OpRewritePattern<mif::FormTeamOp> {470 using OpRewritePattern::OpRewritePattern;471 472 mlir::LogicalResult473 matchAndRewrite(mif::FormTeamOp op,474 mlir::PatternRewriter &rewriter) const override {475 auto mod = op->template getParentOfType<mlir::ModuleOp>();476 fir::FirOpBuilder builder(rewriter, mod);477 mlir::Location loc = op.getLoc();478 mlir::Type errmsgTy = getPRIFErrmsgType(builder);479 mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());480 mlir::FunctionType ftype = mlir::FunctionType::get(481 builder.getContext(),482 /*inputs*/483 {builder.getRefType(builder.getI64Type()), boxTy,484 builder.getRefType(builder.getI32Type()), getPRIFStatType(builder),485 errmsgTy, errmsgTy},486 /*results*/ {});487 mlir::func::FuncOp funcOp =488 builder.createFunction(loc, getPRIFProcName("form_team"), ftype);489 490 mlir::Type i64Ty = builder.getI64Type();491 mlir::Value teamNumber = builder.createTemporary(loc, i64Ty);492 mlir::Value t =493 (op.getTeamNumber().getType() == i64Ty)494 ? op.getTeamNumber()495 : fir::ConvertOp::create(builder, loc, i64Ty, op.getTeamNumber());496 fir::StoreOp::create(builder, loc, t, teamNumber);497 498 mlir::Type i32Ty = builder.getI32Type();499 mlir::Value newIndex;500 if (op.getNewIndex()) {501 newIndex = builder.createTemporary(loc, i32Ty);502 mlir::Value ni =503 (op.getNewIndex().getType() == i32Ty)504 ? op.getNewIndex()505 : fir::ConvertOp::create(builder, loc, i32Ty, op.getNewIndex());506 fir::StoreOp::create(builder, loc, ni, newIndex);507 } else508 newIndex = fir::AbsentOp::create(builder, loc, builder.getRefType(i32Ty));509 510 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());511 auto [errmsgArg, errmsgAllocArg] =512 genErrmsgPRIF(builder, loc, op.getErrmsg());513 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(514 builder, loc, ftype, teamNumber, op.getTeamVar(), newIndex, stat,515 errmsgArg, errmsgAllocArg);516 fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args);517 rewriter.replaceOp(op, callOp);518 return mlir::success();519 }520};521 522/// Convert mif.change_team operation to runtime call of 'prif_change_team'523struct MIFChangeTeamOpConversion524 : public mlir::OpRewritePattern<mif::ChangeTeamOp> {525 using OpRewritePattern::OpRewritePattern;526 527 mlir::LogicalResult528 matchAndRewrite(mif::ChangeTeamOp op,529 mlir::PatternRewriter &rewriter) const override {530 auto mod = op->template getParentOfType<mlir::ModuleOp>();531 fir::FirOpBuilder builder(rewriter, mod);532 builder.setInsertionPoint(op);533 534 mlir::Location loc = op.getLoc();535 mlir::Type errmsgTy = getPRIFErrmsgType(builder);536 mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());537 mlir::FunctionType ftype = mlir::FunctionType::get(538 builder.getContext(),539 /*inputs*/ {boxTy, getPRIFStatType(builder), errmsgTy, errmsgTy},540 /*results*/ {});541 mlir::func::FuncOp funcOp =542 builder.createFunction(loc, getPRIFProcName("change_team"), ftype);543 544 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());545 auto [errmsgArg, errmsgAllocArg] =546 genErrmsgPRIF(builder, loc, op.getErrmsg());547 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(548 builder, loc, ftype, op.getTeam(), stat, errmsgArg, errmsgAllocArg);549 fir::CallOp::create(builder, loc, funcOp, args);550 551 mlir::Operation *changeOp = op.getOperation();552 auto &bodyRegion = op.getRegion();553 mlir::Block &bodyBlock = bodyRegion.front();554 555 rewriter.inlineBlockBefore(&bodyBlock, changeOp);556 rewriter.eraseOp(op);557 return mlir::success();558 }559};560 561/// Convert mif.end_team operation to runtime call of 'prif_end_team'562struct MIFEndTeamOpConversion : public mlir::OpRewritePattern<mif::EndTeamOp> {563 using OpRewritePattern::OpRewritePattern;564 565 mlir::LogicalResult566 matchAndRewrite(mif::EndTeamOp op,567 mlir::PatternRewriter &rewriter) const override {568 auto mod = op->template getParentOfType<mlir::ModuleOp>();569 fir::FirOpBuilder builder(rewriter, mod);570 mlir::Location loc = op.getLoc();571 mlir::Type errmsgTy = getPRIFErrmsgType(builder);572 mlir::FunctionType ftype = mlir::FunctionType::get(573 builder.getContext(),574 /*inputs*/ {getPRIFStatType(builder), errmsgTy, errmsgTy},575 /*results*/ {});576 mlir::func::FuncOp funcOp =577 builder.createFunction(loc, getPRIFProcName("end_team"), ftype);578 579 mlir::Value stat = genStatPRIF(builder, loc, op.getStat());580 auto [errmsgArg, errmsgAllocArg] =581 genErrmsgPRIF(builder, loc, op.getErrmsg());582 llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(583 builder, loc, ftype, stat, errmsgArg, errmsgAllocArg);584 fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args);585 rewriter.replaceOp(op, callOp);586 return mlir::success();587 }588};589 590/// Convert mif.get_team operation to runtime call of 'prif_get_team'591struct MIFGetTeamOpConversion : public mlir::OpRewritePattern<mif::GetTeamOp> {592 using OpRewritePattern::OpRewritePattern;593 594 mlir::LogicalResult595 matchAndRewrite(mif::GetTeamOp op,596 mlir::PatternRewriter &rewriter) const override {597 auto mod = op->template getParentOfType<mlir::ModuleOp>();598 fir::FirOpBuilder builder(rewriter, mod);599 mlir::Location loc = op.getLoc();600 601 mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());602 mlir::Type lvlTy = builder.getRefType(builder.getI32Type());603 mlir::FunctionType ftype =604 mlir::FunctionType::get(builder.getContext(),605 /*inputs*/ {lvlTy, boxTy},606 /*results*/ {});607 mlir::func::FuncOp funcOp =608 builder.createFunction(loc, getPRIFProcName("get_team"), ftype);609 610 mlir::Value level = op.getLevel();611 if (!level)612 level = fir::AbsentOp::create(builder, loc, lvlTy);613 else {614 mlir::Value cst = op.getLevel();615 mlir::Type i32Ty = builder.getI32Type();616 level = builder.createTemporary(loc, i32Ty);617 if (cst.getType() != i32Ty)618 cst = builder.createConvert(loc, i32Ty, cst);619 fir::StoreOp::create(builder, loc, cst, level);620 }621 mlir::Type resultType = op.getResult().getType();622 mlir::Type baseTy = fir::unwrapRefType(resultType);623 mlir::Value team = builder.createTemporary(loc, baseTy);624 fir::EmboxOp box = fir::EmboxOp::create(builder, loc, resultType, team);625 626 llvm::SmallVector<mlir::Value> args =627 fir::runtime::createArguments(builder, loc, ftype, level, box);628 fir::CallOp::create(builder, loc, funcOp, args);629 630 rewriter.replaceOp(op, box);631 return mlir::success();632 }633};634 635/// Convert mif.team_number operation to runtime call of 'prif_team_number'636struct MIFTeamNumberOpConversion637 : public mlir::OpRewritePattern<mif::TeamNumberOp> {638 using OpRewritePattern::OpRewritePattern;639 640 mlir::LogicalResult641 matchAndRewrite(mif::TeamNumberOp op,642 mlir::PatternRewriter &rewriter) const override {643 auto mod = op->template getParentOfType<mlir::ModuleOp>();644 fir::FirOpBuilder builder(rewriter, mod);645 mlir::Location loc = op.getLoc();646 mlir::Type i64Ty = builder.getI64Type();647 mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());648 mlir::FunctionType ftype =649 mlir::FunctionType::get(builder.getContext(),650 /*inputs*/ {boxTy, builder.getRefType(i64Ty)},651 /*results*/ {});652 mlir::func::FuncOp funcOp =653 builder.createFunction(loc, getPRIFProcName("team_number"), ftype);654 655 mlir::Value team = op.getTeam();656 if (!team)657 team = fir::AbsentOp::create(builder, loc, boxTy);658 659 mlir::Value result = builder.createTemporary(loc, i64Ty);660 llvm::SmallVector<mlir::Value> args =661 fir::runtime::createArguments(builder, loc, ftype, team, result);662 fir::CallOp::create(builder, loc, funcOp, args);663 fir::LoadOp load = fir::LoadOp::create(builder, loc, result);664 rewriter.replaceOp(op, load);665 return mlir::success();666 }667};668 669class MIFOpConversion : public fir::impl::MIFOpConversionBase<MIFOpConversion> {670public:671 void runOnOperation() override {672 auto *ctx = &getContext();673 mlir::RewritePatternSet patterns(ctx);674 mlir::ConversionTarget target(*ctx);675 676 mif::populateMIFOpConversionPatterns(patterns);677 678 target.addLegalDialect<fir::FIROpsDialect>();679 target.addLegalOp<mlir::ModuleOp>();680 681 if (mlir::failed(mlir::applyPartialConversion(getOperation(), target,682 std::move(patterns)))) {683 mlir::emitError(mlir::UnknownLoc::get(ctx),684 "error in MIF op conversion\n");685 return signalPassFailure();686 }687 }688};689} // namespace690 691void mif::populateMIFOpConversionPatterns(mlir::RewritePatternSet &patterns) {692 patterns.insert<MIFInitOpConversion, MIFThisImageOpConversion,693 MIFNumImagesOpConversion, MIFSyncAllOpConversion,694 MIFSyncImagesOpConversion, MIFSyncMemoryOpConversion,695 MIFSyncTeamOpConversion, MIFCoBroadcastOpConversion,696 MIFCoMaxOpConversion, MIFCoMinOpConversion,697 MIFCoSumOpConversion, MIFFormTeamOpConversion,698 MIFChangeTeamOpConversion, MIFEndTeamOpConversion,699 MIFGetTeamOpConversion, MIFTeamNumberOpConversion>(700 patterns.getContext());701}702