Files
clang-p2996/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp
Sergio Afonso 2747193058 [Flang][MLIR][OpenMP] Remove the early outlining interface (#78450)
After the removal of the OpenMP early outlining MLIR pass in #67319, the
`EarlyOutliningInterface` stopped doing any useful work. It used to be
necessary to tie the name of the function from which a target region was
outlined to that new function, so it would be used when translating to
LLVM IR in place of the outlined function's name.

This is not necessary anymore, so this patch removes all references to
this interface and uses of the `omp.outline_parent_name` discardable
attribute in tests.
2024-01-18 15:33:43 +00:00

200 lines
6.9 KiB
C++

//===- ExternalNameConversion.cpp -- convert name with external convention ===//
//
// 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/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
namespace fir {
#define GEN_PASS_DEF_EXTERNALNAMECONVERSION
#include "flang/Optimizer/Transforms/Passes.h.inc"
} // namespace fir
using namespace mlir;
//===----------------------------------------------------------------------===//
// Helper functions
//===----------------------------------------------------------------------===//
/// Mangle the name with gfortran convention.
std::string
mangleExternalName(const std::pair<fir::NameUniquer::NameKind,
fir::NameUniquer::DeconstructedName>
result,
bool appendUnderscore) {
if (result.first == fir::NameUniquer::NameKind::COMMON &&
result.second.name.empty())
return Fortran::common::blankCommonObjectName;
return Fortran::common::GetExternalAssemblyName(result.second.name,
appendUnderscore);
}
//===----------------------------------------------------------------------===//
// Rewrite patterns
//===----------------------------------------------------------------------===//
namespace {
struct MangleNameOnFuncOp : public mlir::OpRewritePattern<mlir::func::FuncOp> {
public:
using OpRewritePattern::OpRewritePattern;
MangleNameOnFuncOp(mlir::MLIRContext *ctx, bool appendUnderscore)
: mlir::OpRewritePattern<mlir::func::FuncOp>(ctx),
appendUnderscore(appendUnderscore) {}
mlir::LogicalResult
matchAndRewrite(mlir::func::FuncOp op,
mlir::PatternRewriter &rewriter) const override {
mlir::LogicalResult ret = success();
rewriter.startOpModification(op);
llvm::StringRef oldName = op.getSymName();
auto result = fir::NameUniquer::deconstruct(oldName);
if (fir::NameUniquer::isExternalFacingUniquedName(result)) {
auto newSymbol =
rewriter.getStringAttr(mangleExternalName(result, appendUnderscore));
// Try to update all SymbolRef's in the module that match the current op
if (mlir::ModuleOp mod = op->getParentOfType<mlir::ModuleOp>())
ret = op.replaceAllSymbolUses(newSymbol, mod);
op.setSymNameAttr(newSymbol);
mlir::SymbolTable::setSymbolName(op, newSymbol);
op->setAttr(fir::getInternalFuncNameAttrName(),
mlir::StringAttr::get(op->getContext(), oldName));
}
rewriter.finalizeOpModification(op);
return ret;
}
private:
bool appendUnderscore;
};
struct MangleNameForCommonBlock : public mlir::OpRewritePattern<fir::GlobalOp> {
public:
using OpRewritePattern::OpRewritePattern;
MangleNameForCommonBlock(mlir::MLIRContext *ctx, bool appendUnderscore)
: mlir::OpRewritePattern<fir::GlobalOp>(ctx),
appendUnderscore(appendUnderscore) {}
mlir::LogicalResult
matchAndRewrite(fir::GlobalOp op,
mlir::PatternRewriter &rewriter) const override {
rewriter.startOpModification(op);
auto result = fir::NameUniquer::deconstruct(
op.getSymref().getRootReference().getValue());
if (fir::NameUniquer::isExternalFacingUniquedName(result)) {
auto newName = mangleExternalName(result, appendUnderscore);
op.setSymrefAttr(mlir::SymbolRefAttr::get(op.getContext(), newName));
SymbolTable::setSymbolName(op, newName);
}
rewriter.finalizeOpModification(op);
return success();
}
private:
bool appendUnderscore;
};
struct MangleNameOnAddrOfOp : public mlir::OpRewritePattern<fir::AddrOfOp> {
public:
using OpRewritePattern::OpRewritePattern;
MangleNameOnAddrOfOp(mlir::MLIRContext *ctx, bool appendUnderscore)
: mlir::OpRewritePattern<fir::AddrOfOp>(ctx),
appendUnderscore(appendUnderscore) {}
mlir::LogicalResult
matchAndRewrite(fir::AddrOfOp op,
mlir::PatternRewriter &rewriter) const override {
auto result = fir::NameUniquer::deconstruct(
op.getSymbol().getRootReference().getValue());
if (fir::NameUniquer::isExternalFacingUniquedName(result)) {
auto newName = SymbolRefAttr::get(
op.getContext(), mangleExternalName(result, appendUnderscore));
rewriter.replaceOpWithNewOp<fir::AddrOfOp>(op, op.getResTy().getType(),
newName);
}
return success();
}
private:
bool appendUnderscore;
};
class ExternalNameConversionPass
: public fir::impl::ExternalNameConversionBase<ExternalNameConversionPass> {
public:
ExternalNameConversionPass(bool appendUnderscoring)
: appendUnderscores(appendUnderscoring) {}
ExternalNameConversionPass() { usePassOpt = true; }
mlir::ModuleOp getModule() { return getOperation(); }
void runOnOperation() override;
private:
bool appendUnderscores;
bool usePassOpt = false;
};
} // namespace
void ExternalNameConversionPass::runOnOperation() {
auto op = getOperation();
auto *context = &getContext();
appendUnderscores = (usePassOpt) ? appendUnderscoreOpt : appendUnderscores;
mlir::RewritePatternSet patterns(context);
patterns.insert<MangleNameOnFuncOp, MangleNameForCommonBlock,
MangleNameOnAddrOfOp>(context, appendUnderscores);
ConversionTarget target(*context);
target.addLegalDialect<fir::FIROpsDialect, LLVM::LLVMDialect,
acc::OpenACCDialect, omp::OpenMPDialect>();
target.addDynamicallyLegalOp<mlir::func::FuncOp>([](mlir::func::FuncOp op) {
return !fir::NameUniquer::needExternalNameMangling(op.getSymName());
});
target.addDynamicallyLegalOp<fir::GlobalOp>([](fir::GlobalOp op) {
return !fir::NameUniquer::needExternalNameMangling(
op.getSymref().getRootReference().getValue());
});
target.addDynamicallyLegalOp<fir::AddrOfOp>([](fir::AddrOfOp op) {
return !fir::NameUniquer::needExternalNameMangling(
op.getSymbol().getRootReference().getValue());
});
if (failed(applyPartialConversion(op, target, std::move(patterns))))
signalPassFailure();
}
std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() {
return std::make_unique<ExternalNameConversionPass>();
}
std::unique_ptr<mlir::Pass>
fir::createExternalNameConversionPass(bool appendUnderscoring) {
return std::make_unique<ExternalNameConversionPass>(appendUnderscoring);
}