diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index d9f52025fe104..5ebef0b8d701f 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -629,7 +629,8 @@ def OptimizeArrayRepacking def MIFOpConversion : Pass<"mif-convert", "mlir::ModuleOp"> { let summary = "Convert some MIF operations to runtime calls"; - let dependentDialects = ["fir::FIROpsDialect", "mlir::LLVM::LLVMDialect"]; + let dependentDialects = ["fir::FIROpsDialect", "mlir::LLVM::LLVMDialect", + "mlir::cf::ControlFlowDialect"]; } def LoopInvariantCodeMotion : Pass<"flang-licm", "::mlir::func::FuncOp"> { diff --git a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp index 0d3d2f6c144ff..192b78626ce06 100644 --- a/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/MIFOpConversion.cpp @@ -16,6 +16,7 @@ #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Optimizer/Support/DataLayout.h" #include "flang/Optimizer/Support/InternalNames.h" +#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/IR/Matchers.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" @@ -519,6 +520,28 @@ struct MIFFormTeamOpConversion } }; +/// Generate runtime call to 'prif_end_team' from mif.end_team operation. +fir::CallOp genPrifEndTeamCallOp(mif::EndTeamOp op, + mlir::PatternRewriter &rewriter) { + auto mod = op->template getParentOfType(); + fir::FirOpBuilder builder(rewriter, mod); + mlir::Location loc = op.getLoc(); + mlir::Type errmsgTy = getPRIFErrmsgType(builder); + mlir::FunctionType ftype = mlir::FunctionType::get( + builder.getContext(), + /*inputs*/ {getPRIFStatType(builder), errmsgTy, errmsgTy}, + /*results*/ {}); + mlir::func::FuncOp funcOp = + builder.createFunction(loc, getPRIFProcName("end_team"), ftype); + + mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); + auto [errmsgArg, errmsgAllocArg] = + genErrmsgPRIF(builder, loc, op.getErrmsg()); + llvm::SmallVector args = fir::runtime::createArguments( + builder, loc, ftype, stat, errmsgArg, errmsgAllocArg); + return fir::CallOp::create(rewriter, loc, funcOp, args); +} + /// Convert mif.change_team operation to runtime call of 'prif_change_team' struct MIFChangeTeamOpConversion : public mlir::OpRewritePattern { @@ -529,7 +552,6 @@ struct MIFChangeTeamOpConversion mlir::PatternRewriter &rewriter) const override { auto mod = op->template getParentOfType(); fir::FirOpBuilder builder(rewriter, mod); - builder.setInsertionPoint(op); mlir::Location loc = op.getLoc(); mlir::Type errmsgTy = getPRIFErrmsgType(builder); @@ -546,47 +568,41 @@ struct MIFChangeTeamOpConversion genErrmsgPRIF(builder, loc, op.getErrmsg()); llvm::SmallVector args = fir::runtime::createArguments( builder, loc, ftype, op.getTeam(), stat, errmsgArg, errmsgAllocArg); - fir::CallOp::create(builder, loc, funcOp, args); - mlir::Operation *changeOp = op.getOperation(); - auto &bodyRegion = op.getRegion(); - mlir::Block &bodyBlock = bodyRegion.front(); + mlir::Operation *changeTeamOp = op.getOperation(); + mlir::Block *currentBlock = changeTeamOp->getBlock(); + + mlir::Block *newBlock = rewriter.splitBlock( + currentBlock, std::next(changeTeamOp->getIterator())); + rewriter.setInsertionPoint(changeTeamOp); + // Creation of the call to prif_change_team + fir::CallOp::create(rewriter, loc, funcOp, args); + + // Inlining all the region into the new block + mlir::Region &teamRegion = op.getRegion(); + mlir::Block *firstBlock = &teamRegion.front(); + mlir::Block *lastBlock = &teamRegion.back(); + rewriter.inlineRegionBefore(teamRegion, newBlock); + + rewriter.setInsertionPointToEnd(currentBlock); + mlir::cf::BranchOp::create(rewriter, loc, firstBlock); + + // Removing mif.end_team operation and add the call to prif_end_team. + if (auto endTeamOp = + mlir::dyn_cast(lastBlock->getTerminator())) { + rewriter.setInsertionPoint(endTeamOp); + genPrifEndTeamCallOp(endTeamOp, rewriter); + mlir::cf::BranchOp::create(rewriter, loc, newBlock); + rewriter.eraseOp(endTeamOp); + } else + fir::emitFatalError(loc, + "internal error: missing expected mif::EndTeamOp"); - rewriter.inlineBlockBefore(&bodyBlock, changeOp); rewriter.eraseOp(op); return mlir::success(); } }; -/// Convert mif.end_team operation to runtime call of 'prif_end_team' -struct MIFEndTeamOpConversion : public mlir::OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - mlir::LogicalResult - matchAndRewrite(mif::EndTeamOp op, - mlir::PatternRewriter &rewriter) const override { - auto mod = op->template getParentOfType(); - fir::FirOpBuilder builder(rewriter, mod); - mlir::Location loc = op.getLoc(); - mlir::Type errmsgTy = getPRIFErrmsgType(builder); - mlir::FunctionType ftype = mlir::FunctionType::get( - builder.getContext(), - /*inputs*/ {getPRIFStatType(builder), errmsgTy, errmsgTy}, - /*results*/ {}); - mlir::func::FuncOp funcOp = - builder.createFunction(loc, getPRIFProcName("end_team"), ftype); - - mlir::Value stat = genStatPRIF(builder, loc, op.getStat()); - auto [errmsgArg, errmsgAllocArg] = - genErrmsgPRIF(builder, loc, op.getErrmsg()); - llvm::SmallVector args = fir::runtime::createArguments( - builder, loc, ftype, stat, errmsgArg, errmsgAllocArg); - fir::CallOp callOp = fir::CallOp::create(builder, loc, funcOp, args); - rewriter.replaceOp(op, callOp); - return mlir::success(); - } -}; - /// Convert mif.get_team operation to runtime call of 'prif_get_team' struct MIFGetTeamOpConversion : public mlir::OpRewritePattern { using OpRewritePattern::OpRewritePattern; @@ -675,7 +691,7 @@ class MIFOpConversion : public fir::impl::MIFOpConversionBase { mif::populateMIFOpConversionPatterns(patterns); - target.addLegalDialect(); + target.addLegalDialect(); target.addLegalOp(); if (mlir::failed(mlir::applyPartialConversion(getOperation(), target, @@ -689,13 +705,11 @@ class MIFOpConversion : public fir::impl::MIFOpConversionBase { } // namespace void mif::populateMIFOpConversionPatterns(mlir::RewritePatternSet &patterns) { - patterns.insert( - patterns.getContext()); + patterns.insert< + MIFInitOpConversion, MIFThisImageOpConversion, MIFNumImagesOpConversion, + MIFSyncAllOpConversion, MIFSyncImagesOpConversion, + MIFSyncMemoryOpConversion, MIFSyncTeamOpConversion, + MIFCoBroadcastOpConversion, MIFCoMaxOpConversion, MIFCoMinOpConversion, + MIFCoSumOpConversion, MIFFormTeamOpConversion, MIFChangeTeamOpConversion, + MIFGetTeamOpConversion, MIFTeamNumberOpConversion>(patterns.getContext()); } diff --git a/flang/test/Fir/MIF/change_team2.mlir b/flang/test/Fir/MIF/change_team2.mlir new file mode 100644 index 0000000000000..7ce2510a88656 --- /dev/null +++ b/flang/test/Fir/MIF/change_team2.mlir @@ -0,0 +1,158 @@ +// RUN: fir-opt --mif-convert %s | FileCheck %s +// mlir generated by the example in flang/test/Lower/MIF/change_team2.f90 + +func.func @_QQmain() { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.alloca i32 {bindc_name = "image_status", uniq_name = "_QFEimage_status"} + %2:2 = hlfir.declare %1 {uniq_name = "_QFEimage_status"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %3 = fir.alloca i32 {bindc_name = "new_team", uniq_name = "_QFEnew_team"} + %4:2 = hlfir.declare %3 {uniq_name = "_QFEnew_team"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %5 = fir.address_of(@_QMiso_fortran_envECstat_failed_image) : !fir.ref + %6:2 = hlfir.declare %5 {fortran_attrs = #fir.var_attrs, uniq_name = "_QMiso_fortran_envECstat_failed_image"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %7 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "team", uniq_name = "_QFEteam"} + %8:2 = hlfir.declare %7 {uniq_name = "_QFEteam"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) + %9 = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref> + fir.copy %9 to %8#0 no_overlap : !fir.ref>, !fir.ref> + %10 = mif.this_image : () -> i32 + %c2_i32 = arith.constant 2 : i32 + %11 = arith.remsi %10, %c2_i32 : i32 + %c1_i32 = arith.constant 1 : i32 + %12 = arith.addi %11, %c1_i32 : i32 + hlfir.assign %12 to %4#0 : i32, !fir.ref + %13 = fir.load %4#0 : !fir.ref + %14 = fir.embox %8#0 : (!fir.ref>) -> !fir.box> + mif.form_team team_number %13 team_var %14 : (i32, !fir.box>) -> () + %15 = fir.embox %8#0 : (!fir.ref>) -> !fir.box> + mif.change_team %15 : (!fir.box>) { + %22 = mif.team_number : () -> i64 + %23 = fir.convert %22 : (i64) -> i32 + %24 = fir.load %4#0 : !fir.ref + %25 = arith.cmpi ne, %23, %24 : i32 + cf.cond_br %25, ^bb1, ^bb2 + ^bb1: // pred: ^bb0 + %c1_i32_5 = arith.constant 1 : i32 + %false_6 = arith.constant false + %false_7 = arith.constant false + fir.call @_FortranAStopStatement(%c1_i32_5, %false_6, %false_7) fastmath : (i32, i1, i1) -> () + fir.unreachable + ^bb2: // pred: ^bb0 + mif.end_team : () -> () + } + %c0_i128 = arith.constant 0 : i128 + %16:3 = hlfir.associate %c0_i128 {adapt.valuebyref} : (i128) -> (!fir.ref, !fir.ref, i1) + %17 = fir.call @_QFPruntime_popcnt(%16#0) fastmath : (!fir.ref) -> i32 + %c0_i32 = arith.constant 0 : i32 + %18 = arith.cmpi ne, %17, %c0_i32 : i32 + hlfir.end_associate %16#1, %16#2 : !fir.ref, i1 + cf.cond_br %18, ^bb1, ^bb2 +^bb1: // pred: ^bb0 + %c2_i32_0 = arith.constant 2 : i32 + %false = arith.constant false + %false_1 = arith.constant false + fir.call @_FortranAStopStatement(%c2_i32_0, %false, %false_1) fastmath : (i32, i1, i1) -> () + fir.unreachable +^bb2: // pred: ^bb0 + %c1_i128 = arith.constant 1 : i128 + %19:3 = hlfir.associate %c1_i128 {adapt.valuebyref} : (i128) -> (!fir.ref, !fir.ref, i1) + %20 = fir.call @_QFPruntime_poppar(%19#0) fastmath : (!fir.ref) -> i32 + %c1_i32_2 = arith.constant 1 : i32 + %21 = arith.cmpi ne, %20, %c1_i32_2 : i32 + hlfir.end_associate %19#1, %19#2 : !fir.ref, i1 + cf.cond_br %21, ^bb3, ^bb4 +^bb3: // pred: ^bb2 + %c3_i32 = arith.constant 3 : i32 + %false_3 = arith.constant false + %false_4 = arith.constant false + fir.call @_FortranAStopStatement(%c3_i32, %false_3, %false_4) fastmath : (i32, i1, i1) -> () + fir.unreachable +^bb4: // pred: ^bb2 + return +} + +// CHECK: %[[VAL_0:.*]] = fir.alloca i64 +// CHECK: %[[VAL_1:.*]] = fir.alloca i64 +// CHECK: %[[VAL_2:.*]] = fir.alloca i32 +// CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope +// CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "image_status", uniq_name = "_QFEimage_status"} +// CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFEimage_status"} : (!fir.ref) -> (!fir.ref, !fir.ref) +// CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "new_team", uniq_name = "_QFEnew_team"} +// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEnew_team"} : (!fir.ref) -> (!fir.ref, !fir.ref) +// CHECK: %[[VAL_8:.*]] = fir.address_of(@_QMiso_fortran_envECstat_failed_image) : !fir.ref +// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QMiso_fortran_envECstat_failed_image"} : (!fir.ref) -> (!fir.ref, !fir.ref) +// CHECK: %[[VAL_10:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_team_type{_QM__fortran_builtinsT__builtin_team_type.__id:i64}> {bindc_name = "team", uniq_name = "_QFEteam"} +// CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFEteam"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +// CHECK: %[[VAL_12:.*]] = fir.address_of(@_QQ_QM__fortran_builtinsT__builtin_team_type.DerivedInit) : !fir.ref> +// CHECK: fir.copy %[[VAL_12]] to %[[VAL_11]]#0 no_overlap : !fir.ref>, !fir.ref> +// CHECK: %[[VAL_13:.*]] = fir.absent !fir.box +// CHECK: fir.call @_QMprifPprif_this_image_no_coarray(%[[VAL_13]], %[[VAL_2]]) : (!fir.box, !fir.ref) -> () +// CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_2]] : !fir.ref +// CHECK: %[[C2_i32:.*]] = arith.constant 2 : i32 +// CHECK: %[[VAL_15:.*]] = arith.remsi %[[VAL_14]], %[[C2_i32]] : i32 +// CHECK: %[[C1_i32:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_15]], %[[C1_i32]] : i32 +// CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_7]]#0 : i32, !fir.ref +// CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref +// CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref>) -> !fir.box> +// CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (i32) -> i64 +// CHECK: fir.store %[[VAL_19]] to %[[VAL_1]] : !fir.ref +// CHECK: %[[VAL_20:.*]] = fir.absent !fir.ref +// CHECK: %[[VAL_21:.*]] = fir.absent !fir.ref +// CHECK: %[[VAL_22:.*]] = fir.absent !fir.box> +// CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.box>) -> !fir.box +// CHECK: fir.call @_QMprifPprif_form_team(%[[VAL_1]], %[[VAL_23]], %[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_22]]) : (!fir.ref, !fir.box, !fir.ref, !fir.ref, !fir.box>, !fir.box>) -> () +// CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_11]]#0 : (!fir.ref>) -> !fir.box> +// CHECK: %[[VAL_25:.*]] = fir.absent !fir.ref +// CHECK: %[[VAL_26:.*]] = fir.absent !fir.box> +// CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_24]] : (!fir.box>) -> !fir.box +// CHECK: fir.call @_QMprifPprif_change_team(%[[VAL_27]], %[[VAL_25]], %[[VAL_26]], %[[VAL_26]]) : (!fir.box, !fir.ref, !fir.box>, !fir.box>) -> () +// CHECK: cf.br ^bb1 +// CHECK: ^bb1: // pred: ^bb0 +// CHECK: %[[VAL_28:.*]] = fir.absent !fir.box +// CHECK: fir.call @_QMprifPprif_team_number(%[[VAL_28]], %[[VAL_0]]) : (!fir.box, !fir.ref) -> () +// CHECK: %[[VAL_29:.*]] = fir.load %0 : !fir.ref +// CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i64) -> i32 +// CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref +// CHECK: %[[VAL_32:.*]] = arith.cmpi ne, %[[VAL_30]], %[[VAL_31]] : i32 +// CHECK: cf.cond_br %[[VAL_32]], ^bb2, ^bb3 +// CHECK: ^bb2: // pred: ^bb1 +// CHECK: %[[C1_i32_0:.*]] = arith.constant 1 : i32 +// CHECK: %[[FALSE:.*]] = arith.constant false +// CHECK: %[[FALSE_1:.*]] = arith.constant false +// CHECK: fir.call @_FortranAStopStatement(%[[C1_i32_0]], %[[FALSE]], %[[FALSE_1]]) fastmath : (i32, i1, i1) -> () +// CHECK: fir.unreachable +// CHECK: ^bb3: // pred: ^bb1 +// CHECK: %[[VAL_33:.*]] = fir.absent !fir.ref +// CHECK: %[[VAL_34:.*]] = fir.absent !fir.box> +// CHECK: fir.call @_QMprifPprif_end_team(%[[VAL_33]], %[[VAL_34]], %[[VAL_34]]) : (!fir.ref, !fir.box>, !fir.box>) -> () +// CHECK: cf.br ^bb4 +// CHECK: ^bb4: // pred: ^bb3 +// CHECK: %[[C0_i128:.*]] = arith.constant 0 : i128 +// CHECK: %[[VAL_35:.*]]:3 = hlfir.associate %[[C0_i128]] {adapt.valuebyref} : (i128) -> (!fir.ref, !fir.ref, i1) +// CHECK: %[[VAL_36:.*]] = fir.call @_QFPruntime_popcnt(%[[VAL_35]]#0) fastmath : (!fir.ref) -> i32 +// CHECK: %[[C0_i32:.*]] = arith.constant 0 : i32 +// CHECK: %[[VAL_37:.*]] = arith.cmpi ne, %[[VAL_36]], %[[C0_i32]] : i32 +// CHECK: hlfir.end_associate %[[VAL_35]]#1, %[[VAL_35]]#2 : !fir.ref, i1 +// CHECK: cf.cond_br %[[VAL_37]], ^bb5, ^bb6 +// CHECK: ^bb5: // pred: ^bb4 +// CHECK: %[[C2_i32_2:.*]] = arith.constant 2 : i32 +// CHECK: %[[FALSE_3:.*]] = arith.constant false +// CHECK: %[[FALSE_4:.*]] = arith.constant false +// CHECK: fir.call @_FortranAStopStatement(%[[C2_i32_2]], %[[FALSE_3]], %[[FALSE_4]]) fastmath : (i32, i1, i1) -> () +// CHECK: fir.unreachable +// CHECK: ^bb6: // pred: ^bb4 +// CHECK: %[[C1_i128:.*]] = arith.constant 1 : i128 +// CHECK: %[[VAL_38:.*]]:3 = hlfir.associate %[[C1_i128]] {adapt.valuebyref} : (i128) -> (!fir.ref, !fir.ref, i1) +// CHECK: %[[VAL_39:.*]] = fir.call @_QFPruntime_poppar(%[[VAL_38]]#0) fastmath : (!fir.ref) -> i32 +// CHECK: %[[C1_i32_5:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_40:.*]] = arith.cmpi ne, %[[VAL_39]], %[[C1_i32_5]] : i32 +// CHECK: hlfir.end_associate %[[VAL_38]]#1, %[[VAL_38]]#2 : !fir.ref, i1 +// CHECK: cf.cond_br %40, ^bb7, ^bb8 +// CHECK: ^bb7: // pred: ^bb6 +// CHECK: %[[C3_i32:.*]] = arith.constant 3 : i32 +// CHECK: %[[FALSE_6:.*]] = arith.constant false +// CHECK: %[[FALSE_7:.*]] = arith.constant false +// CHECK: fir.call @_FortranAStopStatement(%[[C3_i32]], %[[FALSE_6]], %[[FALSE_7]]) fastmath : (i32, i1, i1) -> () +// CHECK: fir.unreachable +// CHECK: ^bb8: // pred: ^bb6 +// CHECK: return + diff --git a/flang/test/Lower/MIF/change_team2.f90 b/flang/test/Lower/MIF/change_team2.f90 index 68a60bb4ffc1a..58131cd98c455 100644 --- a/flang/test/Lower/MIF/change_team2.f90 +++ b/flang/test/Lower/MIF/change_team2.f90 @@ -9,12 +9,25 @@ integer :: new_team, image_status new_team = mod(this_image(),2)+1 form team (new_team,team) - ! COARRAY: mif.change_team %[[TEAM:.*]] : ({{.*}}) { change team (team) if (team_number() /= new_team) STOP 1 end team - ! COARRAY: mif.end_team - ! COARRAY: } + ! COARRAY: mif.change_team %[[TEAM:.*]] : ({{.*}}) { + ! COARRAY: %[[VAL_1:.*]] = mif.team_number : () -> i64 + ! COARRAY: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i64) -> i32 + ! COARRAY: %[[VAL_3:.*]] = fir.load %[[VAR_1:.*]]#0 : !fir.ref + ! COARRAY: %[[VAL_4:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i32 + ! COARRAY: cf.cond_br %[[VAL_4]], ^bb1, ^bb2 + ! COARRAY: ^bb1: // pred: ^bb0 + ! COARRAY: %[[C1_I32:.*]] = arith.constant 1 : i32 + ! COARRAY: %[[FALSE_1:.*]] = arith.constant false + ! COARRAY: %[[FALSE_2:.*]] = arith.constant false + ! COARRAY: fir.call @_FortranAStopStatement(%[[C1_I32]], %[[FALSE_1]], %[[FALSE_2]]) fastmath : (i32, i1, i1) -> () + ! COARRAY: fir.unreachable + ! COARRAY: ^bb2: // pred: ^bb0 + ! COARRAY: mif.end_team : () -> () + ! COARRAY: } + if (runtime_popcnt(0_16) /= 0) STOP 2 if (runtime_poppar(1_16) /= 1) STOP 3 contains