Skip to content

Commit 44b22f6

Browse files
committed
[flang] add lifetime markers to alloca created in stack-arrays
1 parent 32f8132 commit 44b22f6

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, of 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)