Skip to content

Commit

Permalink
[flang] Fix some memory leaks (#121050)
Browse files Browse the repository at this point in the history
This commit fixes some but not all memory leaks in Flang. There are
still 91 tests that fail with ASAN.

- Use `mlir::OwningOpRef` instead of `std::unique_ptr`. The latter does
not free allocations of nested blocks.
- Pass `ModuleOp` as value instead of reference.
- Add few missing deallocations in test cases and other places.
  • Loading branch information
matthias-springer authored Dec 25, 2024
1 parent c29536b commit c870632
Show file tree
Hide file tree
Showing 18 changed files with 85 additions and 67 deletions.
3 changes: 2 additions & 1 deletion flang/include/flang/Frontend/FrontendActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "flang/Semantics/semantics.h"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OwningOpRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Module.h"
#include <memory>
Expand Down Expand Up @@ -215,8 +216,8 @@ class CodeGenAction : public FrontendAction {
CodeGenAction(BackendActionTy act) : action{act} {};
/// @name MLIR
/// {
std::unique_ptr<mlir::ModuleOp> mlirModule;
std::unique_ptr<mlir::MLIRContext> mlirCtx;
mlir::OwningOpRef<mlir::ModuleOp> mlirModule;
/// }

/// @name LLVM IR
Expand Down
4 changes: 2 additions & 2 deletions flang/include/flang/Lower/AbstractConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ struct SymbolBox;
namespace pft {
struct Variable;
struct FunctionLikeUnit;
}
} // namespace pft

using SomeExpr = Fortran::evaluate::Expr<Fortran::evaluate::SomeType>;
using SymbolRef = Fortran::common::Reference<const Fortran::semantics::Symbol>;
Expand Down Expand Up @@ -295,7 +295,7 @@ class AbstractConverter {
/// Get the OpBuilder
virtual fir::FirOpBuilder &getFirOpBuilder() = 0;
/// Get the ModuleOp
virtual mlir::ModuleOp &getModuleOp() = 0;
virtual mlir::ModuleOp getModuleOp() = 0;
/// Get the MLIRContext
virtual mlir::MLIRContext &getMLIRContext() = 0;
/// Unique a symbol (add a containing scope specific prefix)
Expand Down
6 changes: 4 additions & 2 deletions flang/include/flang/Lower/Bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OwningOpRef.h"
#include <set>

namespace llvm {
Expand Down Expand Up @@ -83,7 +84,8 @@ class LoweringBridge {
mlir::MLIRContext &getMLIRContext() { return context; }

/// Get the ModuleOp. It can never be null, which is asserted in the ctor.
mlir::ModuleOp &getModule() { return *module.get(); }
mlir::ModuleOp getModule() { return *module; }
mlir::ModuleOp getModuleAndRelease() { return module.release(); }

const Fortran::common::IntrinsicTypeDefaultKinds &getDefaultKinds() const {
return defaultKinds;
Expand Down Expand Up @@ -166,7 +168,7 @@ class LoweringBridge {
const Fortran::evaluate::TargetCharacteristics &targetCharacteristics;
const Fortran::parser::AllCookedSources *cooked;
mlir::MLIRContext &context;
std::unique_ptr<mlir::ModuleOp> module;
mlir::OwningOpRef<mlir::ModuleOp> module;
fir::KindMapping &kindMap;
const Fortran::lower::LoweringOptions &loweringOptions;
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults;
Expand Down
8 changes: 4 additions & 4 deletions flang/include/flang/Lower/OpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace llvm {
template <typename T, unsigned N>
class SmallVector;
class StringRef;
}
} // namespace llvm

namespace mlir {
class Location;
Expand All @@ -44,7 +44,7 @@ struct OpenACCRoutineConstruct;
namespace semantics {
class SemanticsContext;
class Symbol;
}
} // namespace semantics

namespace lower {

Expand Down Expand Up @@ -78,11 +78,11 @@ void genOpenACCDeclarativeConstruct(AbstractConverter &,
AccRoutineInfoMappingList &);
void genOpenACCRoutineConstruct(AbstractConverter &,
Fortran::semantics::SemanticsContext &,
mlir::ModuleOp &,
mlir::ModuleOp,
const parser::OpenACCRoutineConstruct &,
AccRoutineInfoMappingList &);

void finalizeOpenACCRoutineAttachment(mlir::ModuleOp &,
void finalizeOpenACCRoutineAttachment(mlir::ModuleOp,
AccRoutineInfoMappingList &);

/// Get a acc.private.recipe op for the given type or create it if it does not
Expand Down
4 changes: 2 additions & 2 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ struct OffloadModuleOpts {
// Shares assinging of the OpenMP OffloadModuleInterface and its assorted
// attributes accross Flang tools (bbc/flang)
[[maybe_unused]] static void setOffloadModuleInterfaceAttributes(
mlir::ModuleOp &module, OffloadModuleOpts Opts) {
mlir::ModuleOp module, OffloadModuleOpts Opts) {
// Should be registered by the OpenMPDialect
if (auto offloadMod = llvm::dyn_cast<mlir::omp::OffloadModuleInterface>(
module.getOperation())) {
Expand All @@ -198,7 +198,7 @@ struct OffloadModuleOpts {
}

[[maybe_unused]] static void setOpenMPVersionAttribute(
mlir::ModuleOp &module, int64_t version) {
mlir::ModuleOp module, int64_t version) {
module.getOperation()->setAttr(
mlir::StringAttr::get(module.getContext(), llvm::Twine{"omp.version"}),
mlir::omp::VersionAttr::get(module.getContext(), version));
Expand Down
22 changes: 14 additions & 8 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ bool PrescanAndSemaDebugAction::beginSourceFileAction() {
(runSemanticChecks() || true) && (generateRtTypeTables() || true);
}

static void addDependentLibs(mlir::ModuleOp &mlirModule, CompilerInstance &ci) {
static void addDependentLibs(mlir::ModuleOp mlirModule, CompilerInstance &ci) {
const std::vector<std::string> &libs =
ci.getInvocation().getCodeGenOpts().DependentLibs;
if (libs.empty()) {
Expand All @@ -171,7 +171,7 @@ static void addDependentLibs(mlir::ModuleOp &mlirModule, CompilerInstance &ci) {
// Add to MLIR code target specific items which are dependent on target
// configuration specified by the user.
// Clang equivalent function: AMDGPUTargetCodeGenInfo::emitTargetGlobals
static void addAMDGPUSpecificMLIRItems(mlir::ModuleOp &mlirModule,
static void addAMDGPUSpecificMLIRItems(mlir::ModuleOp mlirModule,
CompilerInstance &ci) {
const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
const llvm::Triple triple(targetOpts.triple);
Expand Down Expand Up @@ -269,7 +269,7 @@ bool CodeGenAction::beginSourceFileAction() {
return false;
}

mlirModule = std::make_unique<mlir::ModuleOp>(module.release());
mlirModule = std::move(module);
const llvm::DataLayout &dl = targetMachine.createDataLayout();
fir::support::setMLIRDataLayout(*mlirModule, dl);
return true;
Expand Down Expand Up @@ -303,21 +303,21 @@ bool CodeGenAction::beginSourceFileAction() {
ci.getInvocation().getFrontendOpts().features, targetMachine,
ci.getInvocation().getTargetOpts(), ci.getInvocation().getCodeGenOpts());

// Fetch module from lb, so we can set
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());

if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP)) {
setOffloadModuleInterfaceAttributes(*mlirModule,
setOffloadModuleInterfaceAttributes(lb.getModule(),
ci.getInvocation().getLangOpts());
setOpenMPVersionAttribute(*mlirModule,
setOpenMPVersionAttribute(lb.getModule(),
ci.getInvocation().getLangOpts().OpenMPVersion);
}

// Create a parse tree and lower it to FIR
Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
lb.lower(parseTree, ci.getSemanticsContext());

// Fetch module from lb, so we can set
mlirModule = lb.getModuleAndRelease();

// Add target specific items like dependent libraries, target specific
// constants etc.
addDependentLibs(*mlirModule, ci);
Expand Down Expand Up @@ -961,6 +961,9 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,

// Run the passes
codeGenPasses.run(llvmModule);

// Cleanup
delete tlii;
}

void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
Expand Down Expand Up @@ -1043,6 +1046,9 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {

// Run the passes.
mpm.run(*llvmModule, mam);

// Cleanup
delete tlii;
}

// This class handles optimization remark messages requested if
Expand Down
28 changes: 12 additions & 16 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {

fir::FirOpBuilder &getFirOpBuilder() override final { return *builder; }

mlir::ModuleOp &getModuleOp() override final { return bridge.getModule(); }
mlir::ModuleOp getModuleOp() override final { return bridge.getModule(); }

mlir::MLIRContext &getMLIRContext() override final {
return bridge.getMLIRContext();
Expand Down Expand Up @@ -6137,10 +6137,7 @@ void Fortran::lower::LoweringBridge::lower(
}

void Fortran::lower::LoweringBridge::parseSourceFile(llvm::SourceMgr &srcMgr) {
mlir::OwningOpRef<mlir::ModuleOp> owningRef =
mlir::parseSourceFile<mlir::ModuleOp>(srcMgr, &context);
module.reset(new mlir::ModuleOp(owningRef.get().getOperation()));
owningRef.release();
module = mlir::parseSourceFile<mlir::ModuleOp>(srcMgr, &context);
}

Fortran::lower::LoweringBridge::LoweringBridge(
Expand Down Expand Up @@ -6207,19 +6204,18 @@ Fortran::lower::LoweringBridge::LoweringBridge(
};

// Create the module and attach the attributes.
module = std::make_unique<mlir::ModuleOp>(
module = mlir::OwningOpRef<mlir::ModuleOp>(
mlir::ModuleOp::create(getPathLocation()));
assert(module.get() && "module was not created");
fir::setTargetTriple(*module.get(), triple);
fir::setKindMapping(*module.get(), kindMap);
fir::setTargetCPU(*module.get(), targetMachine.getTargetCPU());
fir::setTuneCPU(*module.get(), targetOpts.cpuToTuneFor);
fir::setTargetFeatures(*module.get(), targetMachine.getTargetFeatureString());
fir::support::setMLIRDataLayout(*module.get(),
targetMachine.createDataLayout());
fir::setIdent(*module.get(), Fortran::common::getFlangFullVersion());
assert(*module && "module was not created");
fir::setTargetTriple(*module, triple);
fir::setKindMapping(*module, kindMap);
fir::setTargetCPU(*module, targetMachine.getTargetCPU());
fir::setTuneCPU(*module, targetOpts.cpuToTuneFor);
fir::setTargetFeatures(*module, targetMachine.getTargetFeatureString());
fir::support::setMLIRDataLayout(*module, targetMachine.createDataLayout());
fir::setIdent(*module, Fortran::common::getFlangFullVersion());
if (cgOpts.RecordCommandLine)
fir::setCommandline(*module.get(), *cgOpts.RecordCommandLine);
fir::setCommandline(*module, *cgOpts.RecordCommandLine);
}

void Fortran::lower::genCleanUpInRegionIfAny(
Expand Down
14 changes: 8 additions & 6 deletions flang/lib/Lower/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2670,11 +2670,13 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
asyncOnlyDeviceTypes);
attachEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
dataClauseOperands.end());
} else if(const auto *defaultClause =
std::get_if<Fortran::parser::AccClause::Default>(&clause.u)) {
} else if (const auto *defaultClause =
std::get_if<Fortran::parser::AccClause::Default>(
&clause.u)) {
if ((defaultClause->v).v == llvm::acc::DefaultValue::ACC_Default_none)
hasDefaultNone = true;
else if ((defaultClause->v).v == llvm::acc::DefaultValue::ACC_Default_present)
else if ((defaultClause->v).v ==
llvm::acc::DefaultValue::ACC_Default_present)
hasDefaultPresent = true;
}
}
Expand Down Expand Up @@ -3830,7 +3832,7 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,

static void
genDeclareInModule(Fortran::lower::AbstractConverter &converter,
mlir::ModuleOp &moduleOp,
mlir::ModuleOp moduleOp,
const Fortran::parser::AccClauseList &accClauseList) {
mlir::OpBuilder modBuilder(moduleOp.getBodyRegion());
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
Expand Down Expand Up @@ -3981,7 +3983,7 @@ static void attachRoutineInfo(mlir::func::FuncOp func,

void Fortran::lower::genOpenACCRoutineConstruct(
Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semanticsContext, mlir::ModuleOp &mod,
Fortran::semantics::SemanticsContext &semanticsContext, mlir::ModuleOp mod,
const Fortran::parser::OpenACCRoutineConstruct &routineConstruct,
Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
Expand Down Expand Up @@ -4139,7 +4141,7 @@ void Fortran::lower::genOpenACCRoutineConstruct(
}

void Fortran::lower::finalizeOpenACCRoutineAttachment(
mlir::ModuleOp &mod,
mlir::ModuleOp mod,
Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
for (auto &mapping : accRoutineInfos) {
mlir::func::FuncOp funcOp =
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Optimizer/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3087,7 +3087,7 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
private:
static void addComdat(mlir::LLVM::GlobalOp &global,
mlir::ConversionPatternRewriter &rewriter,
mlir::ModuleOp &module) {
mlir::ModuleOp module) {
const char *comdatName = "__llvm_comdat";
mlir::LLVM::ComdatOp comdatOp =
module.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName);
Expand Down
3 changes: 1 addition & 2 deletions flang/unittests/Frontend/CodeGenActionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ class LLVMConversionFailureCodeGenAction : public CodeGenAction {
mlirCtx->loadDialect<test::DummyDialect>();

mlir::Location loc(mlir::UnknownLoc::get(mlirCtx.get()));
mlirModule =
std::make_unique<mlir::ModuleOp>(mlir::ModuleOp::create(loc, "mod"));
mlirModule = mlir::ModuleOp::create(loc, "mod");

mlir::OpBuilder builder(mlirCtx.get());
builder.setInsertionPointToStart(&mlirModule->getRegion().front());
Expand Down
9 changes: 5 additions & 4 deletions flang/unittests/Optimizer/Builder/CharacterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,20 @@ struct CharacterTest : public testing::Test {

// Set up a Module with a dummy function operation inside.
// Set the insertion point in the function entry block.
mlir::ModuleOp mod = builder.create<mlir::ModuleOp>(loc);
mlir::func::FuncOp func = mlir::func::FuncOp::create(
moduleOp = builder.create<mlir::ModuleOp>(loc);
builder.setInsertionPointToStart(moduleOp->getBody());
mlir::func::FuncOp func = builder.create<mlir::func::FuncOp>(
loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt));
auto *entryBlock = func.addEntryBlock();
mod.push_back(mod);
builder.setInsertionPointToStart(entryBlock);

firBuilder = std::make_unique<fir::FirOpBuilder>(mod, *kindMap);
firBuilder = std::make_unique<fir::FirOpBuilder>(builder, *kindMap);
}

fir::FirOpBuilder &getBuilder() { return *firBuilder; }

mlir::MLIRContext context;
mlir::OwningOpRef<mlir::ModuleOp> moduleOp;
std::unique_ptr<fir::KindMapping> kindMap;
std::unique_ptr<fir::FirOpBuilder> firBuilder;
};
Expand Down
9 changes: 5 additions & 4 deletions flang/unittests/Optimizer/Builder/ComplexTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ struct ComplexTest : public testing::Test {

// Set up a Module with a dummy function operation inside.
// Set the insertion point in the function entry block.
mlir::ModuleOp mod = builder.create<mlir::ModuleOp>(loc);
mlir::func::FuncOp func = mlir::func::FuncOp::create(
moduleOp = builder.create<mlir::ModuleOp>(loc);
builder.setInsertionPointToStart(moduleOp->getBody());
mlir::func::FuncOp func = builder.create<mlir::func::FuncOp>(
loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt));
auto *entryBlock = func.addEntryBlock();
mod.push_back(mod);
builder.setInsertionPointToStart(entryBlock);

kindMap = std::make_unique<fir::KindMapping>(&context);
firBuilder = std::make_unique<fir::FirOpBuilder>(mod, *kindMap);
firBuilder = std::make_unique<fir::FirOpBuilder>(builder, *kindMap);
helper = std::make_unique<fir::factory::Complex>(*firBuilder, loc);

// Init commonly used types
Expand All @@ -46,6 +46,7 @@ struct ComplexTest : public testing::Test {
}

mlir::MLIRContext context;
mlir::OwningOpRef<mlir::ModuleOp> moduleOp;
std::unique_ptr<fir::KindMapping> kindMap;
std::unique_ptr<fir::FirOpBuilder> firBuilder;
std::unique_ptr<fir::factory::Complex> helper;
Expand Down
9 changes: 5 additions & 4 deletions flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,20 @@ struct FIRBuilderTest : public testing::Test {

// Set up a Module with a dummy function operation inside.
// Set the insertion point in the function entry block.
mlir::ModuleOp mod = builder.create<mlir::ModuleOp>(loc);
mlir::func::FuncOp func = mlir::func::FuncOp::create(
moduleOp = builder.create<mlir::ModuleOp>(loc);
builder.setInsertionPointToStart(moduleOp->getBody());
mlir::func::FuncOp func = builder.create<mlir::func::FuncOp>(
loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt));
auto *entryBlock = func.addEntryBlock();
mod.push_back(mod);
builder.setInsertionPointToStart(entryBlock);

firBuilder = std::make_unique<fir::FirOpBuilder>(mod, kindMap);
firBuilder = std::make_unique<fir::FirOpBuilder>(builder, kindMap);
}

fir::FirOpBuilder &getBuilder() { return *firBuilder; }

mlir::MLIRContext context;
mlir::OwningOpRef<mlir::ModuleOp> moduleOp;
std::unique_ptr<fir::FirOpBuilder> firBuilder;
};

Expand Down
Loading

0 comments on commit c870632

Please sign in to comment.