Skip to content

Commit 1f5b6ae

Browse files
authored
[flang] optionally add lifetime markers to alloca created in stack-arrays (#140901)
Flang at Ofast usually produces executables that consume more stack that other Fortran compilers. This is in part because the alloca created from temporary heap allocation by the StackArray pass are created at the function scope level without lifetimes, and LLVM does not/is not able to merge alloca that do not have overlapping lifetimes. This patch adds an option to generate LLVM lifetime in the StackArray pass at the previous heap allocation/free using the LLVM dialect operation for it.
1 parent 72a8893 commit 1f5b6ae

File tree

7 files changed

+234
-25
lines changed

7 files changed

+234
-25
lines changed

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ llvm::SmallVector<mlir::Value>
879879
elideLengthsAlreadyInType(mlir::Type type, mlir::ValueRange lenParams);
880880

881881
/// Get the address space which should be used for allocas
882-
uint64_t getAllocaAddressSpace(mlir::DataLayout *dataLayout);
882+
uint64_t getAllocaAddressSpace(const mlir::DataLayout *dataLayout);
883883

884884
/// The two vectors of MLIR values have the following property:
885885
/// \p extents1[i] must have the same value as \p extents2[i]
@@ -913,6 +913,18 @@ void genDimInfoFromBox(fir::FirOpBuilder &builder, mlir::Location loc,
913913
llvm::SmallVectorImpl<mlir::Value> *extents,
914914
llvm::SmallVectorImpl<mlir::Value> *strides);
915915

916+
/// Generate an LLVM dialect lifetime start marker at the current insertion
917+
/// point given an fir.alloca and its constant size in bytes. Returns the value
918+
/// to be passed to the lifetime end marker.
919+
mlir::Value genLifetimeStart(mlir::OpBuilder &builder, mlir::Location loc,
920+
fir::AllocaOp alloc, int64_t size,
921+
const mlir::DataLayout *dl);
922+
923+
/// Generate an LLVM dialect lifetime end marker at the current insertion point
924+
/// given an llvm.ptr value and the constant size in bytes of its storage.
925+
void genLifetimeEnd(mlir::OpBuilder &builder, mlir::Location loc,
926+
mlir::Value mem, int64_t size);
927+
916928
} // namespace fir::factory
917929

918930
#endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H

flang/include/flang/Optimizer/Dialect/FIROpsSupport.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ static constexpr llvm::StringRef getInternalFuncNameAttrName() {
125125
return "fir.internal_name";
126126
}
127127

128+
/// Attribute to mark alloca that have been given a lifetime marker so that
129+
/// later pass do not try adding new ones.
130+
static constexpr llvm::StringRef getHasLifetimeMarkerAttrName() {
131+
return "fir.has_lifetime";
132+
}
133+
128134
/// Does the function, \p func, have a host-associations tuple argument?
129135
/// Some internal procedures may have access to host procedure variables.
130136
bool hasHostAssociationArgument(mlir::func::FuncOp func);
@@ -221,6 +227,12 @@ inline bool hasBindcAttr(mlir::Operation *op) {
221227
return hasProcedureAttr<fir::FortranProcedureFlagsEnum::bind_c>(op);
222228
}
223229

230+
/// Get the allocation size of a given alloca if it has compile time constant
231+
/// size.
232+
std::optional<int64_t> getAllocaByteSize(fir::AllocaOp alloca,
233+
const mlir::DataLayout &dl,
234+
const fir::KindMapping &kindMap);
235+
224236
/// Return true, if \p rebox operation keeps the input array
225237
/// continuous if it is initially continuous.
226238
/// When \p checkWhole is false, then the checking is only done

flang/include/flang/Optimizer/Transforms/Passes.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ def StackArrays : Pass<"stack-arrays", "mlir::func::FuncOp"> {
285285
Convert heap allocations for arrays, even those of unknown size, into stack
286286
allocations.
287287
}];
288-
let dependentDialects = [ "fir::FIROpsDialect" ];
288+
let dependentDialects = [
289+
"fir::FIROpsDialect", "mlir::DLTIDialect", "mlir::LLVM::LLVMDialect"
290+
];
289291
}
290292

291293
def StackReclaim : Pass<"stack-reclaim"> {

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1868,7 +1868,8 @@ void fir::factory::setInternalLinkage(mlir::func::FuncOp func) {
18681868
func->setAttr("llvm.linkage", linkage);
18691869
}
18701870

1871-
uint64_t fir::factory::getAllocaAddressSpace(mlir::DataLayout *dataLayout) {
1871+
uint64_t
1872+
fir::factory::getAllocaAddressSpace(const mlir::DataLayout *dataLayout) {
18721873
if (dataLayout)
18731874
if (mlir::Attribute addrSpace = dataLayout->getAllocaMemorySpace())
18741875
return mlir::cast<mlir::IntegerAttr>(addrSpace).getUInt();
@@ -1940,3 +1941,20 @@ void fir::factory::genDimInfoFromBox(
19401941
strides->push_back(dimInfo.getByteStride());
19411942
}
19421943
}
1944+
1945+
mlir::Value fir::factory::genLifetimeStart(mlir::OpBuilder &builder,
1946+
mlir::Location loc,
1947+
fir::AllocaOp alloc, int64_t size,
1948+
const mlir::DataLayout *dl) {
1949+
mlir::Type ptrTy = mlir::LLVM::LLVMPointerType::get(
1950+
alloc.getContext(), getAllocaAddressSpace(dl));
1951+
mlir::Value cast =
1952+
builder.create<fir::ConvertOp>(loc, ptrTy, alloc.getResult());
1953+
builder.create<mlir::LLVM::LifetimeStartOp>(loc, size, cast);
1954+
return cast;
1955+
}
1956+
1957+
void fir::factory::genLifetimeEnd(mlir::OpBuilder &builder, mlir::Location loc,
1958+
mlir::Value cast, int64_t size) {
1959+
builder.create<mlir::LLVM::LifetimeEndOp>(loc, size, cast);
1960+
}

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4804,6 +4804,19 @@ bool fir::reboxPreservesContinuity(fir::ReboxOp rebox, bool checkWhole) {
48044804
return false;
48054805
}
48064806

4807+
std::optional<int64_t> fir::getAllocaByteSize(fir::AllocaOp alloca,
4808+
const mlir::DataLayout &dl,
4809+
const fir::KindMapping &kindMap) {
4810+
mlir::Type type = alloca.getInType();
4811+
// TODO: should use the constant operands when all info is not available in
4812+
// the type.
4813+
if (!alloca.isDynamic())
4814+
if (auto sizeAndAlignment =
4815+
getTypeSizeAndAlignment(alloca.getLoc(), type, dl, kindMap))
4816+
return sizeAndAlignment->first;
4817+
return std::nullopt;
4818+
}
4819+
48074820
//===----------------------------------------------------------------------===//
48084821
// DeclareOp
48094822
//===----------------------------------------------------------------------===//

flang/lib/Optimizer/Transforms/StackArrays.cpp

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
#include "flang/Optimizer/Dialect/FIROps.h"
1414
#include "flang/Optimizer/Dialect/FIRType.h"
1515
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
16+
#include "flang/Optimizer/Support/DataLayout.h"
1617
#include "flang/Optimizer/Transforms/Passes.h"
1718
#include "mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h"
1819
#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
1920
#include "mlir/Analysis/DataFlow/DenseAnalysis.h"
2021
#include "mlir/Analysis/DataFlowFramework.h"
22+
#include "mlir/Dialect/DLTI/DLTI.h"
2123
#include "mlir/Dialect/Func/IR/FuncOps.h"
24+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
2225
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
2326
#include "mlir/IR/Builders.h"
2427
#include "mlir/IR/Diagnostics.h"
@@ -48,6 +51,11 @@ static llvm::cl::opt<std::size_t> maxAllocsPerFunc(
4851
"to 0 for no limit."),
4952
llvm::cl::init(1000), llvm::cl::Hidden);
5053

54+
static llvm::cl::opt<bool> emitLifetimeMarkers(
55+
"stack-arrays-lifetime",
56+
llvm::cl::desc("Add lifetime markers to generated constant size allocas"),
57+
llvm::cl::init(false), llvm::cl::Hidden);
58+
5159
namespace {
5260

5361
/// The state of an SSA value at each program point
@@ -189,8 +197,11 @@ class AllocMemConversion : public mlir::OpRewritePattern<fir::AllocMemOp> {
189197
public:
190198
explicit AllocMemConversion(
191199
mlir::MLIRContext *ctx,
192-
const StackArraysAnalysisWrapper::AllocMemMap &candidateOps)
193-
: OpRewritePattern(ctx), candidateOps{candidateOps} {}
200+
const StackArraysAnalysisWrapper::AllocMemMap &candidateOps,
201+
std::optional<mlir::DataLayout> &dl,
202+
std::optional<fir::KindMapping> &kindMap)
203+
: OpRewritePattern(ctx), candidateOps{candidateOps}, dl{dl},
204+
kindMap{kindMap} {}
194205

195206
llvm::LogicalResult
196207
matchAndRewrite(fir::AllocMemOp allocmem,
@@ -206,6 +217,9 @@ class AllocMemConversion : public mlir::OpRewritePattern<fir::AllocMemOp> {
206217
/// Handle to the DFA (already run)
207218
const StackArraysAnalysisWrapper::AllocMemMap &candidateOps;
208219

220+
const std::optional<mlir::DataLayout> &dl;
221+
const std::optional<fir::KindMapping> &kindMap;
222+
209223
/// If we failed to find an insertion point not inside a loop, see if it would
210224
/// be safe to use an llvm.stacksave/llvm.stackrestore inside the loop
211225
static InsertionPoint findAllocaLoopInsertionPoint(
@@ -218,8 +232,12 @@ class AllocMemConversion : public mlir::OpRewritePattern<fir::AllocMemOp> {
218232
mlir::PatternRewriter &rewriter) const;
219233

220234
/// Inserts a stacksave before oldAlloc and a stackrestore after each freemem
221-
void insertStackSaveRestore(fir::AllocMemOp &oldAlloc,
235+
void insertStackSaveRestore(fir::AllocMemOp oldAlloc,
222236
mlir::PatternRewriter &rewriter) const;
237+
/// Emit lifetime markers for newAlloc between oldAlloc and each freemem.
238+
/// If the allocation is dynamic, no life markers are emitted.
239+
void insertLifetimeMarkers(fir::AllocMemOp oldAlloc, fir::AllocaOp newAlloc,
240+
mlir::PatternRewriter &rewriter) const;
223241
};
224242

225243
class StackArraysPass : public fir::impl::StackArraysBase<StackArraysPass> {
@@ -740,14 +758,34 @@ AllocMemConversion::insertAlloca(fir::AllocMemOp &oldAlloc,
740758

741759
llvm::StringRef uniqName = unpackName(oldAlloc.getUniqName());
742760
llvm::StringRef bindcName = unpackName(oldAlloc.getBindcName());
743-
return rewriter.create<fir::AllocaOp>(loc, varTy, uniqName, bindcName,
744-
oldAlloc.getTypeparams(),
745-
oldAlloc.getShape());
761+
auto alloca = rewriter.create<fir::AllocaOp>(loc, varTy, uniqName, bindcName,
762+
oldAlloc.getTypeparams(),
763+
oldAlloc.getShape());
764+
if (emitLifetimeMarkers)
765+
insertLifetimeMarkers(oldAlloc, alloca, rewriter);
766+
767+
return alloca;
768+
}
769+
770+
static void
771+
visitFreeMemOp(fir::AllocMemOp oldAlloc,
772+
const std::function<void(mlir::Operation *)> &callBack) {
773+
for (mlir::Operation *user : oldAlloc->getUsers()) {
774+
if (auto declareOp = mlir::dyn_cast_if_present<fir::DeclareOp>(user)) {
775+
for (mlir::Operation *user : declareOp->getUsers()) {
776+
if (mlir::isa<fir::FreeMemOp>(user))
777+
callBack(user);
778+
}
779+
}
780+
781+
if (mlir::isa<fir::FreeMemOp>(user))
782+
callBack(user);
783+
}
746784
}
747785

748786
void AllocMemConversion::insertStackSaveRestore(
749-
fir::AllocMemOp &oldAlloc, mlir::PatternRewriter &rewriter) const {
750-
auto oldPoint = rewriter.saveInsertionPoint();
787+
fir::AllocMemOp oldAlloc, mlir::PatternRewriter &rewriter) const {
788+
mlir::OpBuilder::InsertionGuard insertGuard(rewriter);
751789
auto mod = oldAlloc->getParentOfType<mlir::ModuleOp>();
752790
fir::FirOpBuilder builder{rewriter, mod};
753791

@@ -758,21 +796,30 @@ void AllocMemConversion::insertStackSaveRestore(
758796
builder.setInsertionPoint(user);
759797
builder.genStackRestore(user->getLoc(), sp);
760798
};
799+
visitFreeMemOp(oldAlloc, createStackRestoreCall);
800+
}
761801

762-
for (mlir::Operation *user : oldAlloc->getUsers()) {
763-
if (auto declareOp = mlir::dyn_cast_if_present<fir::DeclareOp>(user)) {
764-
for (mlir::Operation *user : declareOp->getUsers()) {
765-
if (mlir::isa<fir::FreeMemOp>(user))
766-
createStackRestoreCall(user);
767-
}
768-
}
769-
770-
if (mlir::isa<fir::FreeMemOp>(user)) {
771-
createStackRestoreCall(user);
772-
}
802+
void AllocMemConversion::insertLifetimeMarkers(
803+
fir::AllocMemOp oldAlloc, fir::AllocaOp newAlloc,
804+
mlir::PatternRewriter &rewriter) const {
805+
if (!dl || !kindMap)
806+
return;
807+
llvm::StringRef attrName = fir::getHasLifetimeMarkerAttrName();
808+
// Do not add lifetime markers if the alloca already has any.
809+
if (newAlloc->hasAttr(attrName))
810+
return;
811+
if (std::optional<int64_t> size =
812+
fir::getAllocaByteSize(newAlloc, *dl, *kindMap)) {
813+
mlir::OpBuilder::InsertionGuard insertGuard(rewriter);
814+
rewriter.setInsertionPoint(oldAlloc);
815+
mlir::Value ptr = fir::factory::genLifetimeStart(
816+
rewriter, newAlloc.getLoc(), newAlloc, *size, &*dl);
817+
visitFreeMemOp(oldAlloc, [&](mlir::Operation *op) {
818+
rewriter.setInsertionPoint(op);
819+
fir::factory::genLifetimeEnd(rewriter, op->getLoc(), ptr, *size);
820+
});
821+
newAlloc->setAttr(attrName, rewriter.getUnitAttr());
773822
}
774-
775-
rewriter.restoreInsertionPoint(oldPoint);
776823
}
777824

778825
StackArraysPass::StackArraysPass(const StackArraysPass &pass)
@@ -809,7 +856,16 @@ void StackArraysPass::runOnOperation() {
809856
config.setRegionSimplificationLevel(
810857
mlir::GreedySimplifyRegionLevel::Disabled);
811858

812-
patterns.insert<AllocMemConversion>(&context, *candidateOps);
859+
auto module = func->getParentOfType<mlir::ModuleOp>();
860+
std::optional<mlir::DataLayout> dl =
861+
module ? fir::support::getOrSetMLIRDataLayout(
862+
module, /*allowDefaultLayout=*/false)
863+
: std::nullopt;
864+
std::optional<fir::KindMapping> kindMap;
865+
if (module)
866+
kindMap = fir::getKindMapping(module);
867+
868+
patterns.insert<AllocMemConversion>(&context, *candidateOps, dl, kindMap);
813869
if (mlir::failed(mlir::applyOpPatternsGreedily(
814870
opsToConvert, std::move(patterns), config))) {
815871
mlir::emitError(func->getLoc(), "error in stack arrays optimization\n");
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Test insertion of llvm.lifetime for allocmem turn into alloca with constant size.
2+
// RUN: fir-opt --stack-arrays -stack-arrays-lifetime %s | FileCheck %s
3+
4+
module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"} {
5+
6+
func.func @_QPcst_alloca(%arg0: !fir.ref<!fir.array<100000xf32>> {fir.bindc_name = "x"}) {
7+
%c1 = arith.constant 1 : index
8+
%c100000 = arith.constant 100000 : index
9+
%0 = fir.dummy_scope : !fir.dscope
10+
%1 = fir.shape %c100000 : (index) -> !fir.shape<1>
11+
%2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFcst_allocaEx"} : (!fir.ref<!fir.array<100000xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<100000xf32>>
12+
%3 = fir.allocmem !fir.array<100000xf32> {bindc_name = ".tmp.array", uniq_name = ""}
13+
%4 = fir.declare %3(%1) {uniq_name = ".tmp.array"} : (!fir.heap<!fir.array<100000xf32>>, !fir.shape<1>) -> !fir.heap<!fir.array<100000xf32>>
14+
fir.do_loop %arg1 = %c1 to %c100000 step %c1 unordered {
15+
%9 = fir.array_coor %2(%1) %arg1 : (!fir.ref<!fir.array<100000xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
16+
%10 = fir.load %9 : !fir.ref<f32>
17+
%11 = arith.addf %10, %10 fastmath<contract> : f32
18+
%12 = fir.array_coor %4(%1) %arg1 : (!fir.heap<!fir.array<100000xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
19+
fir.store %11 to %12 : !fir.ref<f32>
20+
}
21+
%5 = fir.convert %4 : (!fir.heap<!fir.array<100000xf32>>) -> !fir.ref<!fir.array<100000xf32>>
22+
fir.call @_QPbar(%5) fastmath<contract> : (!fir.ref<!fir.array<100000xf32>>) -> ()
23+
fir.freemem %4 : !fir.heap<!fir.array<100000xf32>>
24+
%6 = fir.allocmem !fir.array<100000xi32> {bindc_name = ".tmp.array", uniq_name = ""}
25+
%7 = fir.declare %6(%1) {uniq_name = ".tmp.array"} : (!fir.heap<!fir.array<100000xi32>>, !fir.shape<1>) -> !fir.heap<!fir.array<100000xi32>>
26+
fir.do_loop %arg1 = %c1 to %c100000 step %c1 unordered {
27+
%9 = fir.array_coor %2(%1) %arg1 : (!fir.ref<!fir.array<100000xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
28+
%10 = fir.load %9 : !fir.ref<f32>
29+
%11 = fir.convert %10 : (f32) -> i32
30+
%12 = fir.array_coor %7(%1) %arg1 : (!fir.heap<!fir.array<100000xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
31+
fir.store %11 to %12 : !fir.ref<i32>
32+
}
33+
%8 = fir.convert %7 : (!fir.heap<!fir.array<100000xi32>>) -> !fir.ref<!fir.array<100000xi32>>
34+
fir.call @_QPibar(%8) fastmath<contract> : (!fir.ref<!fir.array<100000xi32>>) -> ()
35+
fir.freemem %7 : !fir.heap<!fir.array<100000xi32>>
36+
return
37+
}
38+
// CHECK-LABEL: func.func @_QPcst_alloca(
39+
// CHECK-DAG: %[[VAL_0:.*]] = fir.alloca !fir.array<100000xf32> {bindc_name = ".tmp.array", fir.has_lifetime}
40+
// CHECK-DAG: %[[VAL_2:.*]] = fir.alloca !fir.array<100000xi32> {bindc_name = ".tmp.array", fir.has_lifetime}
41+
// CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.array<100000xf32>>) -> !llvm.ptr
42+
// CHECK: llvm.intr.lifetime.start 400000, %[[VAL_9]] : !llvm.ptr
43+
// CHECK: fir.do_loop
44+
// CHECK: fir.call @_QPbar(
45+
// CHECK: llvm.intr.lifetime.end 400000, %[[VAL_9]] : !llvm.ptr
46+
// CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<100000xi32>>) -> !llvm.ptr
47+
// CHECK: llvm.intr.lifetime.start 400000, %[[VAL_17]] : !llvm.ptr
48+
// CHECK: fir.do_loop
49+
// CHECK: fir.call @_QPibar(
50+
// CHECK: llvm.intr.lifetime.end 400000, %[[VAL_17]] : !llvm.ptr
51+
52+
53+
func.func @_QPdyn_alloca(%arg0: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "x"}, %arg1: !fir.ref<i64> {fir.bindc_name = "n"}) {
54+
%c1 = arith.constant 1 : index
55+
%c0 = arith.constant 0 : index
56+
%0 = fir.dummy_scope : !fir.dscope
57+
%1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFdyn_allocaEn"} : (!fir.ref<i64>, !fir.dscope) -> !fir.ref<i64>
58+
%2 = fir.load %1 : !fir.ref<i64>
59+
%3 = fir.convert %2 : (i64) -> index
60+
%4 = arith.cmpi sgt, %3, %c0 : index
61+
%5 = arith.select %4, %3, %c0 : index
62+
%6 = fir.shape %5 : (index) -> !fir.shape<1>
63+
%7 = fir.declare %arg0(%6) dummy_scope %0 {uniq_name = "_QFdyn_allocaEx"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<?xf32>>
64+
%8 = fir.allocmem !fir.array<?xf32>, %5 {bindc_name = ".tmp.array", uniq_name = ""}
65+
%9 = fir.declare %8(%6) {uniq_name = ".tmp.array"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.heap<!fir.array<?xf32>>
66+
fir.do_loop %arg2 = %c1 to %5 step %c1 unordered {
67+
%14 = fir.array_coor %7(%6) %arg2 : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
68+
%15 = fir.load %14 : !fir.ref<f32>
69+
%16 = arith.addf %15, %15 fastmath<contract> : f32
70+
%17 = fir.array_coor %9(%6) %arg2 : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
71+
fir.store %16 to %17 : !fir.ref<f32>
72+
}
73+
%10 = fir.convert %9 : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
74+
fir.call @_QPbar(%10) fastmath<contract> : (!fir.ref<!fir.array<?xf32>>) -> ()
75+
fir.freemem %9 : !fir.heap<!fir.array<?xf32>>
76+
%11 = fir.allocmem !fir.array<?xf32>, %5 {bindc_name = ".tmp.array", uniq_name = ""}
77+
%12 = fir.declare %11(%6) {uniq_name = ".tmp.array"} : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.heap<!fir.array<?xf32>>
78+
fir.do_loop %arg2 = %c1 to %5 step %c1 unordered {
79+
%14 = fir.array_coor %7(%6) %arg2 : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
80+
%15 = fir.load %14 : !fir.ref<f32>
81+
%16 = arith.mulf %15, %15 fastmath<contract> : f32
82+
%17 = fir.array_coor %12(%6) %arg2 : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
83+
fir.store %16 to %17 : !fir.ref<f32>
84+
}
85+
%13 = fir.convert %12 : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
86+
fir.call @_QPbar(%13) fastmath<contract> : (!fir.ref<!fir.array<?xf32>>) -> ()
87+
fir.freemem %12 : !fir.heap<!fir.array<?xf32>>
88+
return
89+
}
90+
// CHECK-LABEL: func.func @_QPdyn_alloca(
91+
// CHECK-NOT: llvm.intr.lifetime.start
92+
// CHECK: return
93+
94+
func.func private @_QPbar(!fir.ref<!fir.array<100000xf32>>)
95+
func.func private @_QPibar(!fir.ref<!fir.array<100000xi32>>)
96+
}

0 commit comments

Comments
 (0)