Valentin Clement (バレンタイン クレメン) 29d857f183
[flang] Add stack reclaim pass to reclaim allocas in loop (#95309)
Some passes in the flang pipeline are creating `fir.alloca` operation
like `hlfir.concat`. When these allocas are located in a loop, the stack
can quickly be used too much leading to segfaults.

This behavior can be seen in
https://github.com/jacobwilliams/json-fortran/blob/master/src/tests/jf_test_36.F90

This patch insert a call to LLVM stacksave/stackrestore in the body of
the loop to reclaim the alloca in its scope.

This PR is an alternative implementation to #95173
2024-06-14 10:21:58 -07:00

53 lines
1.7 KiB
C++

//===- StackReclaim.cpp -- Insert stacksave/stackrestore in region --------===//
//
// 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/Common/Fortran.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Pass/Pass.h"
namespace fir {
#define GEN_PASS_DEF_STACKRECLAIM
#include "flang/Optimizer/Transforms/Passes.h.inc"
} // namespace fir
using namespace mlir;
namespace {
class StackReclaimPass : public fir::impl::StackReclaimBase<StackReclaimPass> {
public:
using StackReclaimBase<StackReclaimPass>::StackReclaimBase;
void runOnOperation() override;
};
} // namespace
void StackReclaimPass::runOnOperation() {
auto *op = getOperation();
auto *context = &getContext();
mlir::OpBuilder builder(context);
mlir::Type voidPtr = mlir::LLVM::LLVMPointerType::get(context);
op->walk([&](fir::DoLoopOp loopOp) {
mlir::Location loc = loopOp.getLoc();
if (!loopOp.getRegion().getOps<fir::AllocaOp>().empty()) {
builder.setInsertionPointToStart(&loopOp.getRegion().front());
auto stackSaveOp = builder.create<LLVM::StackSaveOp>(loc, voidPtr);
auto *terminator = loopOp.getRegion().back().getTerminator();
builder.setInsertionPoint(terminator);
builder.create<LLVM::StackRestoreOp>(loc, stackSaveOp);
}
});
}