[Flang][MIF] Allocation of NON-ALLOCATABLE SAVE coarray (#205847)
The goal of this PR is to add support for allocating NON-allocatable coarrays that are not in the `Main` program. All allocations will be performed in a function called `__mif_save_coarrays_allocate`. If this function exists, then LLVM::GlobalCtors is created (or modified). The initialization of the MIF with `mif.init` is moved too in a GlobalCtors with a priority of 0 to ensure that the initialization takes place before any MIF allocations. --------- Co-authored-by: Dan Bonachea <dobonachea@lbl.gov>
This commit is contained in:
1 parent
16bd5ce118
commit
5595710093
14 files changed
+283
-21
No files matched your search
@@ -76,6 +76,11 @@ mlir::Value genAllocateCoarray(
|
||||
std::nullopt,
|
||||
mlir::Value errMsg = {}, bool hasStat = false);
|
||||
|
||||
void genAllocateNonAllocatableSaveCoarray(AbstractConverter &converter,
|
||||
mlir::Location loc,
|
||||
const semantics::Symbol &sym,
|
||||
mlir::Value addr);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// COARRAY expressions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
|
||||
|
||||
static constexpr llvm::StringRef coarrayHandleSuffix = "_coarray_handle";
|
||||
static constexpr llvm::StringRef mifSaveCoarraysAllocName =
|
||||
"__mif_save_coarrays_allocate";
|
||||
|
||||
namespace mif {
|
||||
|
||||
@@ -22,6 +24,10 @@ mlir::Value genImageIndex(fir::FirOpBuilder &, mlir::Location loc,
|
||||
mlir::Value coarray, mlir::Value sub,
|
||||
mlir::Value team);
|
||||
|
||||
mlir::func::FuncOp getOrCreateInitFunc(fir::FirOpBuilder &builder,
|
||||
mlir::ModuleOp mod,
|
||||
llvm::StringRef name);
|
||||
|
||||
} // namespace mif
|
||||
|
||||
#endif // FORTRAN_OPTIMIZER_TRANSFORMS_MIFCOMMON_H_
|
||||
@@ -32,7 +32,12 @@ class region_Op<string mnemonic, list<Trait> traits = []>
|
||||
|
||||
def mif_InitOp : mif_Op<"init", []> {
|
||||
let summary = "Initialize the parallel environment";
|
||||
let description = [{This operation will initialize the parallel environment}];
|
||||
let description = [{
|
||||
This operation will initialize the parallel environment and shall be called
|
||||
prior to any other MIF operations.
|
||||
Any second or subsequent call to mif.init is guaranteed to return
|
||||
immediately with no effect.
|
||||
}];
|
||||
|
||||
let results = (outs I32:$stat);
|
||||
let assemblyFormat = "`->` type($stat) attr-dict";
|
||||
|
||||
@@ -691,6 +691,11 @@ def MIFOpConversion : Pass<"mif-convert", "mlir::ModuleOp"> {
|
||||
"mlir::cf::ControlFlowDialect", "mlir::DLTIDialect"];
|
||||
}
|
||||
|
||||
def EmitMIFGlobalCtors : Pass<"emit-mif-global-ctors", "mlir::ModuleOp"> {
|
||||
let summary = "Generate GlobalCtorOp to init MIF and allocate coarrays.";
|
||||
let dependentDialects = ["fir::FIROpsDialect", "mlir::LLVM::LLVMDialect"];
|
||||
}
|
||||
|
||||
def LoopInvariantCodeMotion : Pass<"flang-licm", "::mlir::func::FuncOp"> {
|
||||
let summary = "Hoist invariants from loops";
|
||||
let description = [{
|
||||
|
||||
@@ -6634,15 +6634,6 @@ private:
|
||||
if (sym.name() == "numeric_storage_size" && owner.IsModule() &&
|
||||
DEREF(owner.symbol()).name() == "iso_fortran_env")
|
||||
continue;
|
||||
|
||||
if (Fortran::evaluate::IsCoarray(sym) &&
|
||||
!Fortran::semantics::IsAllocatable(sym) &&
|
||||
Fortran::semantics::IsSaved(sym)) {
|
||||
mlir::Location loc = toLocation();
|
||||
TODO(
|
||||
loc,
|
||||
"coarray: non-ALLOCATABLE SAVE coarray outside the main program");
|
||||
}
|
||||
}
|
||||
Fortran::lower::defineModuleVariable(*this, var);
|
||||
}
|
||||
|
||||
@@ -698,10 +698,15 @@ static void instantiateGlobal(Fortran::lower::AbstractConverter &converter,
|
||||
mlir::StringAttr linkage = getLinkageAttribute(converter, var);
|
||||
fir::GlobalOp global;
|
||||
|
||||
if (Fortran::evaluate::IsCoarray(sym))
|
||||
if (Fortran::evaluate::IsCoarray(sym)) {
|
||||
if (hasFinalization(sym) || hasAllocatableDirectComponent(sym))
|
||||
TODO(loc, "coarray: coarray with an allocatable direct component and/or "
|
||||
"requiring finalization");
|
||||
const auto *details =
|
||||
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
|
||||
if (details && details->init())
|
||||
TODO(loc, "coarray: initialization");
|
||||
}
|
||||
|
||||
if (var.isModuleOrSubmoduleVariable()) {
|
||||
// A non-intrinsic module global is defined when lowering the module.
|
||||
@@ -2634,11 +2639,12 @@ void Fortran::lower::mapSymbolAttributes(
|
||||
assert(!Fortran::semantics::IsAllocatable(sym) &&
|
||||
"must be a non-ALLOCATABLE coarray");
|
||||
if (Fortran::semantics::IsSaved(sym) &&
|
||||
sym.owner().kind() != Fortran::semantics::Scope::Kind::MainProgram)
|
||||
TODO(loc,
|
||||
"coarray: non-ALLOCATABLE SAVE coarray outside the main program");
|
||||
;
|
||||
Fortran::lower::genAllocateCoarray(converter, loc, sym, addr);
|
||||
(sym.owner().kind() != Fortran::semantics::Scope::Kind::MainProgram ||
|
||||
var.isModuleOrSubmoduleVariable()))
|
||||
Fortran::lower::genAllocateNonAllocatableSaveCoarray(converter, loc, sym,
|
||||
addr);
|
||||
else
|
||||
Fortran::lower::genAllocateCoarray(converter, loc, sym, addr);
|
||||
::genDeclareSymbol(converter, symMap, sym, addr, len, extents, lbounds,
|
||||
replace);
|
||||
return;
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "flang/Optimizer/Builder/MIFCommon.h"
|
||||
#include "flang/Optimizer/Builder/Todo.h"
|
||||
#include "flang/Parser/parse-tree.h"
|
||||
#include "flang/Semantics/expression.h"
|
||||
#include "mlir/IR/IRMapping.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Synchronization statements
|
||||
@@ -449,6 +451,33 @@ mlir::Value Fortran::lower::genAllocateCoarray(
|
||||
return stat;
|
||||
}
|
||||
|
||||
void Fortran::lower::genAllocateNonAllocatableSaveCoarray(
|
||||
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
|
||||
const semantics::Symbol &sym, mlir::Value addr) {
|
||||
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
||||
mlir::ModuleOp mod = builder.getModule();
|
||||
mlir::IRMapping mapping;
|
||||
|
||||
auto func = mif::getOrCreateInitFunc(builder, mod, mifSaveCoarraysAllocName);
|
||||
bool funcIsEmpty = func.empty();
|
||||
|
||||
mlir::Block &entry = func.getBody().front();
|
||||
auto returnOp = entry.getTerminator();
|
||||
|
||||
mlir::OpBuilder::InsertionGuard guard(builder);
|
||||
builder.setInsertionPoint(returnOp);
|
||||
|
||||
// If the function is empty, then we add the MIF initialization operation
|
||||
// at the beginning.
|
||||
if (funcIsEmpty)
|
||||
mif::InitOp::create(builder, loc);
|
||||
|
||||
mlir::Operation &op = *addr.getDefiningOp();
|
||||
mlir::Operation *localAddrOp = builder.clone(op, mapping);
|
||||
Fortran::lower::genAllocateCoarray(converter, loc, sym,
|
||||
localAddrOp->getResult(0));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// COARRAY expressions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flang/Optimizer/Builder/MIFCommon.h"
|
||||
#include "flang/Lower/MultiImageFortran.h"
|
||||
#include "flang/Optimizer/Builder/FIRBuilder.h"
|
||||
#include "flang/Optimizer/Builder/HLFIRTools.h"
|
||||
#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
|
||||
@@ -80,3 +81,24 @@ mlir::Value mif::genImageIndex(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
(*subCastAndCleanup.second)();
|
||||
return imageIndex;
|
||||
}
|
||||
|
||||
mlir::func::FuncOp mif::getOrCreateInitFunc(fir::FirOpBuilder &builder,
|
||||
mlir::ModuleOp mod,
|
||||
llvm::StringRef name) {
|
||||
mlir::Location loc = mod.getLoc();
|
||||
auto funcType = builder.getFunctionType({}, {});
|
||||
auto func = builder.createFunction(loc, name, funcType);
|
||||
if (!func.empty())
|
||||
return func;
|
||||
|
||||
func.setPublic();
|
||||
mlir::OpBuilder::InsertionGuard guard(builder);
|
||||
builder.setInsertionPointToEnd(mod.getBody());
|
||||
|
||||
func.addEntryBlock();
|
||||
builder.setInsertionPointToEnd(&func.getBody().front());
|
||||
mif::InitOp::create(builder, loc);
|
||||
mlir::func::ReturnOp::create(builder, loc);
|
||||
|
||||
return func;
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
/// common to flang and the test tools.
|
||||
|
||||
#include "flang/Optimizer/Passes/Pipelines.h"
|
||||
#include "flang/Optimizer/Builder/MIFCommon.h"
|
||||
#include "flang/Optimizer/Dialect/FIROps.h"
|
||||
#include "flang/Optimizer/OpenACC/Passes.h"
|
||||
#include "mlir/Conversion/Passes.h"
|
||||
@@ -460,6 +461,7 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
|
||||
}
|
||||
|
||||
fir::addFIRToLLVMPass(pm, config);
|
||||
pm.addPass(fir::createEmitMIFGlobalCtors());
|
||||
|
||||
if (config.EnableOpenMP && !config.EnableOpenMPSimd) {
|
||||
// Remove all non target-related operations from host functions still
|
||||
|
||||
@@ -28,6 +28,7 @@ add_flang_library(FIRTransforms
|
||||
ControlFlowConverter.cpp
|
||||
ConvertComplexPow.cpp
|
||||
DebugTypeGenerator.cpp
|
||||
EmitMIFGlobalCtors.cpp
|
||||
ExternalNameConversion.cpp
|
||||
FIRToSCF.cpp
|
||||
FIRToMemRef.cpp
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
//===-- EmitMIFGlobalCtors.cpp --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flang/Optimizer/Builder/MIFCommon.h"
|
||||
#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
|
||||
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
|
||||
#include "flang/Optimizer/Dialect/FIRDialect.h"
|
||||
#include "flang/Optimizer/Dialect/FIROps.h"
|
||||
#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
|
||||
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
|
||||
namespace fir {
|
||||
#define GEN_PASS_DEF_EMITMIFGLOBALCTORS
|
||||
#include "flang/Optimizer/Transforms/Passes.h.inc"
|
||||
} // namespace fir
|
||||
|
||||
using namespace mlir;
|
||||
using namespace Fortran::runtime;
|
||||
|
||||
namespace {
|
||||
|
||||
class EmitMIFGlobalCtors
|
||||
: public fir::impl::EmitMIFGlobalCtorsBase<EmitMIFGlobalCtors> {
|
||||
public:
|
||||
void runOnOperation() override {
|
||||
mlir::ModuleOp mod = getOperation();
|
||||
mlir::MLIRContext *ctx = mod.getContext();
|
||||
mlir::OpBuilder builder(ctx);
|
||||
builder.setInsertionPointToEnd(mod.getBody());
|
||||
mlir::Location loc = builder.getUnknownLoc();
|
||||
|
||||
llvm::SmallVector<mlir::Attribute> funcs, priorities, data;
|
||||
mlir::Type i32Ty = mlir::IntegerType::get(ctx, 32);
|
||||
mlir::Attribute zeroAttr = mlir::LLVM::ZeroAttr::get(builder.getContext());
|
||||
|
||||
// Setting priority 0 for the initialization of mif.
|
||||
if (mod.lookupSymbol<mlir::LLVM::LLVMFuncOp>(mifSaveCoarraysAllocName)) {
|
||||
funcs.push_back(
|
||||
mlir::FlatSymbolRefAttr::get(ctx, mifSaveCoarraysAllocName));
|
||||
priorities.push_back(mlir::IntegerAttr::get(i32Ty, 0));
|
||||
data.push_back(zeroAttr);
|
||||
}
|
||||
|
||||
if (funcs.empty())
|
||||
return;
|
||||
|
||||
// We check whether a GlobalCtorsOp already exists to avoid having
|
||||
// multiple instances.
|
||||
mlir::LLVM::GlobalCtorsOp globalCtors;
|
||||
mod.walk([&](mlir::LLVM::GlobalCtorsOp op) { globalCtors = op; });
|
||||
|
||||
if (globalCtors) {
|
||||
llvm::SmallVector<mlir::Attribute> mergedFuncs(
|
||||
globalCtors.getCtors().begin(), globalCtors.getCtors().end());
|
||||
llvm::SmallVector<mlir::Attribute> mergedPriorities(
|
||||
globalCtors.getPriorities().begin(),
|
||||
globalCtors.getPriorities().end());
|
||||
llvm::SmallVector<mlir::Attribute> mergedData(
|
||||
globalCtors.getData().begin(), globalCtors.getData().end());
|
||||
|
||||
llvm::SmallDenseSet<llvm::StringRef> existingNames;
|
||||
for (auto attr : globalCtors.getCtors())
|
||||
existingNames.insert(
|
||||
llvm::cast<mlir::FlatSymbolRefAttr>(attr).getValue());
|
||||
|
||||
for (auto [func, priority, d] : llvm::zip(funcs, priorities, data)) {
|
||||
auto name = llvm::cast<mlir::FlatSymbolRefAttr>(func).getValue();
|
||||
if (!existingNames.contains(name)) {
|
||||
mergedFuncs.push_back(func);
|
||||
mergedPriorities.push_back(priority);
|
||||
mergedData.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
// Deleting the existing GlobalCtorsOp and creating a new one that
|
||||
// contains the merged attributes.
|
||||
builder.setInsertionPoint(globalCtors);
|
||||
mlir::LLVM::GlobalCtorsOp::create(builder, globalCtors.getLoc(),
|
||||
builder.getArrayAttr(mergedFuncs),
|
||||
builder.getArrayAttr(mergedPriorities),
|
||||
builder.getArrayAttr(mergedData));
|
||||
globalCtors.erase();
|
||||
} else {
|
||||
builder.setInsertionPointToEnd(mod.getBody());
|
||||
mlir::LLVM::GlobalCtorsOp::create(
|
||||
builder, loc, builder.getArrayAttr(funcs),
|
||||
builder.getArrayAttr(priorities), builder.getArrayAttr(data));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -184,6 +184,7 @@ func.func @_QQmain() {
|
||||
// PASSES-NEXT: LowerNontemporalPass
|
||||
// PASSES-NEXT: FIRToLLVMLowering
|
||||
// PASSES-NEXT: ReconcileUnrealizedCasts
|
||||
// PASSES-NEXT: EmitMIFGlobalCtors
|
||||
// PASSES-NEXT: HostOpFilteringPass
|
||||
// PASSES-NEXT: 'llvm.func' Pipeline
|
||||
// PASSES-NEXT: StackToSharedPass
|
||||
|
||||
@@ -1,8 +1,76 @@
|
||||
! RUN: not %flang_fc1 -emit-hlfir -fcoarray %s -o - 2>&1 | FileCheck %s
|
||||
! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - 2>&1 | FileCheck %s
|
||||
! RUN: %flang_fc1 -emit-llvm -fcoarray %s -o - 2>&1 | FileCheck %s --check-prefix=LLVM
|
||||
|
||||
!CHECK: not yet implemented: coarray: non-ALLOCATABLE SAVE coarray outside the main program
|
||||
! LLVM: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @__mif_save_coarrays_allocate, ptr null }]
|
||||
|
||||
subroutine test_coarray_save()
|
||||
implicit none
|
||||
real, SAVE :: n[*]
|
||||
real, SAVE :: m[*]
|
||||
real, SAVE :: p[*]
|
||||
end subroutine test_coarray_save
|
||||
|
||||
program main
|
||||
call test_coarray_save()
|
||||
end program
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtest_coarray_save()
|
||||
! CHECK: %0 = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %1 = fir.address_of(@_QFtest_coarray_saveEm) : !fir.ref<f32>
|
||||
! CHECK: %2:2 = hlfir.declare %1 {uniq_name = "_QFtest_coarray_saveEm"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
|
||||
! CHECK: %3 = fir.address_of(@_QFtest_coarray_saveEn) : !fir.ref<f32>
|
||||
! CHECK: %4:2 = hlfir.declare %3 {uniq_name = "_QFtest_coarray_saveEn"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
|
||||
! CHECK: %5 = fir.address_of(@_QFtest_coarray_saveEp) : !fir.ref<f32>
|
||||
! CHECK: %6:2 = hlfir.declare %5 {uniq_name = "_QFtest_coarray_saveEp"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
|
||||
! CHECK: return
|
||||
|
||||
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "MAIN"}
|
||||
! CHECK: %0 = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: fir.call @_QPtest_coarray_save() fastmath<contract> : () -> ()
|
||||
! CHECK: return
|
||||
|
||||
! CHECK: fir.global internal @_QFtest_coarray_saveEm : f32
|
||||
|
||||
! CHECK-LABEL: func.func @__mif_save_coarrays_allocate()
|
||||
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<0xi64>
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<1xi64>
|
||||
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.array<0xi64>
|
||||
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<1xi64>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.array<0xi64>
|
||||
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.array<1xi64>
|
||||
! CHECK: %[[INIT_STAT:.*]] = mif.init -> i32
|
||||
! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QFtest_coarray_saveEm) : !fir.ref<f32>
|
||||
! CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[C1_I64_0:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[C0:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_5]], %[[C0]] : (!fir.ref<!fir.array<1xi64>>, index) -> !fir.ref<i64>
|
||||
! CHECK: fir.store %[[C1_I64_0]] to %[[VAL_7]] : !fir.ref<i64>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.embox %[[VAL_5]] : (!fir.ref<!fir.array<1xi64>>) -> !fir.box<!fir.array<1xi64>>
|
||||
! CHECK: %[[C1_I64_1:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[VAL_9:.*]] = fir.embox %[[VAL_4]] : (!fir.ref<!fir.array<0xi64>>) -> !fir.box<!fir.array<0xi64>>
|
||||
! CHECK: mif.alloc_coarray %[[VAL_6]] lcobounds %[[VAL_8]] ucobounds %[[VAL_9]] {uniq_name = "_QFtest_coarray_saveEm"} : (!fir.ref<f32>, !fir.box<!fir.array<1xi64>>, !fir.box<!fir.array<0xi64>>) -> ()
|
||||
! CHECK: %[[VAL_10:.*]] = fir.address_of(@_QFtest_coarray_saveEn) : !fir.ref<f32>
|
||||
! CHECK: %[[C1_I64_2:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[C1_I64_3:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[C0_4:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_3]], %[[C0_4]] : (!fir.ref<!fir.array<1xi64>>, index) -> !fir.ref<i64>
|
||||
! CHECK: fir.store %[[C1_I64_3]] to %[[VAL_11]] : !fir.ref<i64>
|
||||
! CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_3]] : (!fir.ref<!fir.array<1xi64>>) -> !fir.box<!fir.array<1xi64>>
|
||||
! CHECK: %[[C1_I64_5:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_2]] : (!fir.ref<!fir.array<0xi64>>) -> !fir.box<!fir.array<0xi64>>
|
||||
! CHECK: mif.alloc_coarray %[[VAL_10]] lcobounds %[[VAL_12]] ucobounds %[[VAL_13]] {uniq_name = "_QFtest_coarray_saveEn"} : (!fir.ref<f32>, !fir.box<!fir.array<1xi64>>, !fir.box<!fir.array<0xi64>>) -> ()
|
||||
! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFtest_coarray_saveEp) : !fir.ref<f32>
|
||||
! CHECK: %[[C1_I64_6:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[C1_I64_7:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[C0_8:.*]] = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_1]], %[[C0_8]] : (!fir.ref<!fir.array<1xi64>>, index) -> !fir.ref<i64>
|
||||
! CHECK: fir.store %[[C1_I64_7]] to %[[VAL_15]] : !fir.ref<i64>
|
||||
! CHECK: %[[VAL_16:.*]] = fir.embox %[[VAL_1]] : (!fir.ref<!fir.array<1xi64>>) -> !fir.box<!fir.array<1xi64>>
|
||||
! CHECK: %[[VAL_C1_I64_9:.*]] = arith.constant 1 : i64
|
||||
! CHECK: %[[VAL_17:.*]] = fir.embox %[[VAL_0]] : (!fir.ref<!fir.array<0xi64>>) -> !fir.box<!fir.array<0xi64>>
|
||||
! CHECK: mif.alloc_coarray %[[VAL_14:.*]] lcobounds %[[VAL_16]] ucobounds %[[VAL_17]] {uniq_name = "_QFtest_coarray_saveEp"} : (!fir.ref<f32>, !fir.box<!fir.array<1xi64>>, !fir.box<!fir.array<0xi64>>) -> ()
|
||||
! CHECK: return
|
||||
|
||||
! CHECK: fir.global internal @_QFtest_coarray_saveEn : f32
|
||||
! CHECK: fir.global internal @_QFtest_coarray_saveEp : f32
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
! RUN: not %flang_fc1 -emit-hlfir -fcoarray %s -o - 2>&1 | FileCheck %s
|
||||
|
||||
!CHECK: not yet implemented: coarray: non-ALLOCATABLE SAVE coarray outside the main program
|
||||
! RUN: %flang_fc1 -emit-hlfir -fcoarray %s -o - | FileCheck %s
|
||||
! RUN: %flang_fc1 -emit-llvm -fcoarray %s -o - 2>&1 | FileCheck %s --check-prefix=LLVM
|
||||
|
||||
module m_coarray_test
|
||||
implicit none
|
||||
real :: module_coarray[*]
|
||||
end module m_coarray_test
|
||||
|
||||
program test
|
||||
use m_coarray_test
|
||||
end program
|
||||
|
||||
! LLVM: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @__mif_save_coarrays_allocate, ptr null }]
|
||||
|
||||
! CHECK-LABEL: func.func @__mif_save_coarrays_allocate()
|
||||
! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<0xi64>
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<1xi64>
|
||||
! CHECK: %[[INIT_STAT:.*]] = mif.init -> i32
|
||||
! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QMm_coarray_testEmodule_coarray) : !fir.ref<f32>
|
||||
! CHECK: %c1_i64 = arith.constant 1 : i64
|
||||
! CHECK: %c1_i64_0 = arith.constant 1 : i64
|
||||
! CHECK: %c0 = arith.constant 0 : index
|
||||
! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %c0 : (!fir.ref<!fir.array<1xi64>>, index) -> !fir.ref<i64>
|
||||
! CHECK: fir.store %c1_i64_0 to %[[VAL_3]] : !fir.ref<i64>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_1]] : (!fir.ref<!fir.array<1xi64>>) -> !fir.box<!fir.array<1xi64>>
|
||||
! CHECK: %c1_i64_1 = arith.constant 1 : i64
|
||||
! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_0]] : (!fir.ref<!fir.array<0xi64>>) -> !fir.box<!fir.array<0xi64>>
|
||||
! CHECK: mif.alloc_coarray %[[VAL_2]] lcobounds %[[VAL_4]] ucobounds %[[VAL_5]] {uniq_name = "_QMm_coarray_testEmodule_coarray"} : (!fir.ref<f32>, !fir.box<!fir.array<1xi64>>, !fir.box<!fir.array<0xi64>>) -> ()
|
||||
! CHECK: return
|
||||
Reference in new issue
Block a user