brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.2 KiB · 0d3d2f6 Raw
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