aboutsummaryrefslogtreecommitdiff
path: root/flang/lib
diff options
context:
space:
mode:
authorjeanPerier <jperier@nvidia.com>2023-12-06 14:20:06 +0100
committerGitHub <noreply@github.com>2023-12-06 14:20:06 +0100
commite59e848805f57bd52ebbb0f7f7d4d951e6af597c (patch)
treee83a8776a07bd467dc9d44547b1af660b2303f8d /flang/lib
parentd77067d08a3f56dc2d0e6c95bd2852c943df743a (diff)
downloadllvm-e59e848805f57bd52ebbb0f7f7d4d951e6af597c.zip
llvm-e59e848805f57bd52ebbb0f7f7d4d951e6af597c.tar.gz
llvm-e59e848805f57bd52ebbb0f7f7d4d951e6af597c.tar.bz2
[flang] Updating drivers to create data layout before semantics (#73301)
Preliminary patch to change lowering/code generation to use llvm::DataLayout information instead of generating "sizeof" GEP (see https://github.com/llvm/llvm-project/issues/71507). Fortran Semantic analysis needs to know about the target type size and alignment to deal with common blocks, and intrinsics like C_SIZEOF/TRANSFER. This information should be obtained from the llvm::DataLayout so that it is consistent during the whole compilation flow. This change is changing flang-new and bbc drivers to: 1. Create the llvm::TargetMachine so that the data layout of the target can be obtained before semantics. 2. Sharing bbc/flang-new set-up of the SemanticConstext.targetCharateristics from the llvm::TargetMachine. For now, the actual part that set-up the Fortran type size and alignment from the llvm::DataLayout is left TODO so that this change is mostly an NFC impacting the drivers. 3. Let the lowering bridge set-up the mlir::Module datalayout attributes since it is doing it for the target attribute, and that allows the llvm data layout information to be available during lowering. For flang-new, the changes are code shuffling: the `llvm::TargetMachine` instance is moved to `CompilerInvocation` class so that it can be used to set-up the semantic contexts. `setMLIRDataLayout` is moved to `flang/Optimizer/Support/DataLayout.h` (it will need to be used from codegen pass for fir-opt target independent testing.)), and the code setting-up semantics targetCharacteristics is moved to `Tools/TargetSetup.h` so that it can be shared with bbc. As a consequence, LLVM targets must be registered when running semantics, and it is not possible to run semantics for a target that is not registered with the -triple option (hence the power pc specific modules can only be built if the PowerPC target is available.
Diffstat (limited to 'flang/lib')
-rw-r--r--flang/lib/Frontend/CompilerInstance.cpp134
-rw-r--r--flang/lib/Frontend/CompilerInvocation.cpp23
-rw-r--r--flang/lib/Frontend/FrontendActions.cpp177
-rw-r--r--flang/lib/Lower/Bridge.cpp6
-rw-r--r--flang/lib/Optimizer/Support/CMakeLists.txt2
-rw-r--r--flang/lib/Optimizer/Support/DataLayout.cpp47
6 files changed, 212 insertions, 177 deletions
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index 328b377..a6b8f1a 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -17,11 +17,15 @@
#include "flang/Parser/parsing.h"
#include "flang/Parser/provenance.h"
#include "flang/Semantics/semantics.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/TargetParser.h"
#include "llvm/TargetParser/Triple.h"
using namespace Fortran::frontend;
@@ -156,8 +160,10 @@ bool CompilerInstance::executeAction(FrontendAction &act) {
invoc.setFortranOpts();
// Set the encoding to read all input files in based on user input.
allSources->set_encoding(invoc.getFortranOpts().encoding);
+ if (!setUpTargetMachine())
+ return false;
// Create the semantics context
- semaContext = invoc.getSemanticsCtx(*allCookedSources);
+ semaContext = invoc.getSemanticsCtx(*allCookedSources, getTargetMachine());
// Set options controlling lowering to FIR.
invoc.setLoweringOptions();
@@ -197,3 +203,129 @@ CompilerInstance::createDiagnostics(clang::DiagnosticOptions *opts,
}
return diags;
}
+
+// Get feature string which represents combined explicit target features
+// for AMD GPU and the target features specified by the user
+static std::string
+getExplicitAndImplicitAMDGPUTargetFeatures(clang::DiagnosticsEngine &diags,
+ const TargetOptions &targetOpts,
+ const llvm::Triple triple) {
+ llvm::StringRef cpu = targetOpts.cpu;
+ llvm::StringMap<bool> implicitFeaturesMap;
+ std::string errorMsg;
+ // Get the set of implicit target features
+ llvm::AMDGPU::fillAMDGPUFeatureMap(cpu, triple, implicitFeaturesMap);
+
+ // Add target features specified by the user
+ for (auto &userFeature : targetOpts.featuresAsWritten) {
+ std::string userKeyString = userFeature.substr(1);
+ implicitFeaturesMap[userKeyString] = (userFeature[0] == '+');
+ }
+
+ if (!llvm::AMDGPU::insertWaveSizeFeature(cpu, triple, implicitFeaturesMap,
+ errorMsg)) {
+ unsigned diagID = diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
+ "Unsupported feature ID: %0");
+ diags.Report(diagID) << errorMsg.data();
+ return std::string();
+ }
+
+ llvm::SmallVector<std::string> featuresVec;
+ for (auto &implicitFeatureItem : implicitFeaturesMap) {
+ featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
+ implicitFeatureItem.first().str())
+ .str());
+ }
+ llvm::sort(featuresVec);
+ return llvm::join(featuresVec, ",");
+}
+
+// Get feature string which represents combined explicit target features
+// for NVPTX and the target features specified by the user/
+// TODO: Have a more robust target conf like `clang/lib/Basic/Targets/NVPTX.cpp`
+static std::string
+getExplicitAndImplicitNVPTXTargetFeatures(clang::DiagnosticsEngine &diags,
+ const TargetOptions &targetOpts,
+ const llvm::Triple triple) {
+ llvm::StringRef cpu = targetOpts.cpu;
+ llvm::StringMap<bool> implicitFeaturesMap;
+ std::string errorMsg;
+ bool ptxVer = false;
+
+ // Add target features specified by the user
+ for (auto &userFeature : targetOpts.featuresAsWritten) {
+ llvm::StringRef userKeyString(llvm::StringRef(userFeature).drop_front(1));
+ implicitFeaturesMap[userKeyString.str()] = (userFeature[0] == '+');
+ // Check if the user provided a PTX version
+ if (userKeyString.startswith("ptx"))
+ ptxVer = true;
+ }
+
+ // Set the default PTX version to `ptx61` if none was provided.
+ // TODO: set the default PTX version based on the chip.
+ if (!ptxVer)
+ implicitFeaturesMap["ptx61"] = true;
+
+ // Set the compute capability.
+ implicitFeaturesMap[cpu.str()] = true;
+
+ llvm::SmallVector<std::string> featuresVec;
+ for (auto &implicitFeatureItem : implicitFeaturesMap) {
+ featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
+ implicitFeatureItem.first().str())
+ .str());
+ }
+ llvm::sort(featuresVec);
+ return llvm::join(featuresVec, ",");
+}
+
+std::string CompilerInstance::getTargetFeatures() {
+ const TargetOptions &targetOpts = getInvocation().getTargetOpts();
+ const llvm::Triple triple(targetOpts.triple);
+
+ // Clang does not append all target features to the clang -cc1 invocation.
+ // Some target features are parsed implicitly by clang::TargetInfo child
+ // class. Clang::TargetInfo classes are the basic clang classes and
+ // they cannot be reused by Flang.
+ // That's why we need to extract implicit target features and add
+ // them to the target features specified by the user
+ if (triple.isAMDGPU()) {
+ return getExplicitAndImplicitAMDGPUTargetFeatures(getDiagnostics(),
+ targetOpts, triple);
+ } else if (triple.isNVPTX()) {
+ return getExplicitAndImplicitNVPTXTargetFeatures(getDiagnostics(),
+ targetOpts, triple);
+ }
+ return llvm::join(targetOpts.featuresAsWritten.begin(),
+ targetOpts.featuresAsWritten.end(), ",");
+}
+
+bool CompilerInstance::setUpTargetMachine() {
+ const TargetOptions &targetOpts = getInvocation().getTargetOpts();
+ const std::string &theTriple = targetOpts.triple;
+
+ // Create `Target`
+ std::string error;
+ const llvm::Target *theTarget =
+ llvm::TargetRegistry::lookupTarget(theTriple, error);
+ if (!theTarget) {
+ getDiagnostics().Report(clang::diag::err_fe_unable_to_create_target)
+ << error;
+ return false;
+ }
+
+ // Create `TargetMachine`
+ const auto &CGOpts = getInvocation().getCodeGenOpts();
+ std::optional<llvm::CodeGenOptLevel> OptLevelOrNone =
+ llvm::CodeGenOpt::getLevel(CGOpts.OptimizationLevel);
+ assert(OptLevelOrNone && "Invalid optimization level!");
+ llvm::CodeGenOptLevel OptLevel = *OptLevelOrNone;
+ std::string featuresStr = getTargetFeatures();
+ targetMachine.reset(theTarget->createTargetMachine(
+ theTriple, /*CPU=*/targetOpts.cpu,
+ /*Features=*/featuresStr, llvm::TargetOptions(),
+ /*Reloc::Model=*/CGOpts.getRelocationModel(),
+ /*CodeModel::Model=*/std::nullopt, OptLevel));
+ assert(targetMachine && "Failed to create TargetMachine");
+ return true;
+}
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index c623969..b3f32bb 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -18,6 +18,7 @@
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
#include "flang/Semantics/semantics.h"
+#include "flang/Tools/TargetSetup.h"
#include "flang/Version.inc"
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/DiagnosticDriver.h"
@@ -1347,7 +1348,8 @@ void CompilerInvocation::setFortranOpts() {
std::unique_ptr<Fortran::semantics::SemanticsContext>
CompilerInvocation::getSemanticsCtx(
- Fortran::parser::AllCookedSources &allCookedSources) {
+ Fortran::parser::AllCookedSources &allCookedSources,
+ const llvm::TargetMachine &targetMachine) {
auto &fortranOptions = getFortranOpts();
auto semanticsContext = std::make_unique<semantics::SemanticsContext>(
@@ -1360,21 +1362,10 @@ CompilerInvocation::getSemanticsCtx(
.set_moduleFileSuffix(getModuleFileSuffix())
.set_underscoring(getCodeGenOpts().Underscoring);
- llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
- // FIXME: Handle real(3) ?
- if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
- semanticsContext->targetCharacteristics().DisableType(
- Fortran::common::TypeCategory::Real, /*kind=*/10);
- }
-
- std::string version = Fortran::common::getFlangFullVersion();
- semanticsContext->targetCharacteristics()
- .set_compilerOptionsString(allCompilerInvocOpts)
- .set_compilerVersionString(version);
-
- if (targetTriple.isPPC())
- semanticsContext->targetCharacteristics().set_isPPC(true);
-
+ std::string compilerVersion = Fortran::common::getFlangFullVersion();
+ Fortran::tools::setUpTargetCharacteristics(
+ semanticsContext->targetCharacteristics(), targetMachine, compilerVersion,
+ allCompilerInvocOpts);
return semanticsContext;
}
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 1be95cc..b114c55 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -21,6 +21,7 @@
#include "flang/Lower/Support/Verifier.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
+#include "flang/Optimizer/Support/DataLayout.h"
#include "flang/Optimizer/Support/InitFIR.h"
#include "flang/Optimizer/Support/Utils.h"
#include "flang/Optimizer/Transforms/Passes.h"
@@ -53,7 +54,6 @@
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
-#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
@@ -65,7 +65,6 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/TargetParser/TargetParser.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <memory>
#include <system_error>
@@ -139,111 +138,6 @@ bool PrescanAndSemaDebugAction::beginSourceFileAction() {
(generateRtTypeTables() || true);
}
-// Get feature string which represents combined explicit target features
-// for AMD GPU and the target features specified by the user
-static std::string
-getExplicitAndImplicitAMDGPUTargetFeatures(CompilerInstance &ci,
- const TargetOptions &targetOpts,
- const llvm::Triple triple) {
- llvm::StringRef cpu = targetOpts.cpu;
- llvm::StringMap<bool> implicitFeaturesMap;
- std::string errorMsg;
- // Get the set of implicit target features
- llvm::AMDGPU::fillAMDGPUFeatureMap(cpu, triple, implicitFeaturesMap);
-
- // Add target features specified by the user
- for (auto &userFeature : targetOpts.featuresAsWritten) {
- std::string userKeyString = userFeature.substr(1);
- implicitFeaturesMap[userKeyString] = (userFeature[0] == '+');
- }
-
- if (!llvm::AMDGPU::insertWaveSizeFeature(cpu, triple, implicitFeaturesMap,
- errorMsg)) {
- unsigned diagID = ci.getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Error, "Unsupported feature ID: %0");
- ci.getDiagnostics().Report(diagID) << errorMsg.data();
- return std::string();
- }
-
- llvm::SmallVector<std::string> featuresVec;
- for (auto &implicitFeatureItem : implicitFeaturesMap) {
- featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
- implicitFeatureItem.first().str())
- .str());
- }
- llvm::sort(featuresVec);
- return llvm::join(featuresVec, ",");
-}
-
-// Get feature string which represents combined explicit target features
-// for NVPTX and the target features specified by the user/
-// TODO: Have a more robust target conf like `clang/lib/Basic/Targets/NVPTX.cpp`
-static std::string
-getExplicitAndImplicitNVPTXTargetFeatures(CompilerInstance &ci,
- const TargetOptions &targetOpts,
- const llvm::Triple triple) {
- llvm::StringRef cpu = targetOpts.cpu;
- llvm::StringMap<bool> implicitFeaturesMap;
- std::string errorMsg;
- bool ptxVer = false;
-
- // Add target features specified by the user
- for (auto &userFeature : targetOpts.featuresAsWritten) {
- llvm::StringRef userKeyString(llvm::StringRef(userFeature).drop_front(1));
- implicitFeaturesMap[userKeyString.str()] = (userFeature[0] == '+');
- // Check if the user provided a PTX version
- if (userKeyString.startswith("ptx"))
- ptxVer = true;
- }
-
- // Set the default PTX version to `ptx61` if none was provided.
- // TODO: set the default PTX version based on the chip.
- if (!ptxVer)
- implicitFeaturesMap["ptx61"] = true;
-
- // Set the compute capability.
- implicitFeaturesMap[cpu.str()] = true;
-
- llvm::SmallVector<std::string> featuresVec;
- for (auto &implicitFeatureItem : implicitFeaturesMap) {
- featuresVec.push_back((llvm::Twine(implicitFeatureItem.second ? "+" : "-") +
- implicitFeatureItem.first().str())
- .str());
- }
- llvm::sort(featuresVec);
- return llvm::join(featuresVec, ",");
-}
-
-// Produces the string which represents target feature
-static std::string getTargetFeatures(CompilerInstance &ci) {
- const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
- const llvm::Triple triple(targetOpts.triple);
-
- // Clang does not append all target features to the clang -cc1 invocation.
- // Some target features are parsed implicitly by clang::TargetInfo child
- // class. Clang::TargetInfo classes are the basic clang classes and
- // they cannot be reused by Flang.
- // That's why we need to extract implicit target features and add
- // them to the target features specified by the user
- if (triple.isAMDGPU()) {
- return getExplicitAndImplicitAMDGPUTargetFeatures(ci, targetOpts, triple);
- } else if (triple.isNVPTX()) {
- return getExplicitAndImplicitNVPTXTargetFeatures(ci, targetOpts, triple);
- }
- return llvm::join(targetOpts.featuresAsWritten.begin(),
- targetOpts.featuresAsWritten.end(), ",");
-}
-
-static void setMLIRDataLayout(mlir::ModuleOp &mlirModule,
- const llvm::DataLayout &dl) {
- mlir::MLIRContext *context = mlirModule.getContext();
- mlirModule->setAttr(
- mlir::LLVM::LLVMDialect::getDataLayoutAttrName(),
- mlir::StringAttr::get(context, dl.getStringRepresentation()));
- mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, context);
- mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
-}
-
static void addDependentLibs(mlir::ModuleOp &mlirModule, CompilerInstance &ci) {
const std::vector<std::string> &libs =
ci.getInvocation().getCodeGenOpts().DependentLibs;
@@ -352,6 +246,8 @@ bool CodeGenAction::beginSourceFileAction() {
fir::support::loadDialects(*mlirCtx);
fir::support::registerLLVMTranslation(*mlirCtx);
+ const llvm::TargetMachine &targetMachine = ci.getTargetMachine();
+
// If the input is an MLIR file, just parse it and return.
if (this->getCurrentInput().getKind().getLanguage() == Language::MLIR) {
llvm::SourceMgr sourceMgr;
@@ -369,10 +265,8 @@ bool CodeGenAction::beginSourceFileAction() {
}
mlirModule = std::make_unique<mlir::ModuleOp>(module.release());
- if (!setUpTargetMachine())
- return false;
- const llvm::DataLayout &dl = tm->createDataLayout();
- setMLIRDataLayout(*mlirModule, dl);
+ const llvm::DataLayout &dl = targetMachine.createDataLayout();
+ fir::support::setMLIRDataLayout(*mlirModule, dl);
return true;
}
@@ -394,6 +288,8 @@ bool CodeGenAction::beginSourceFileAction() {
ci.getSemanticsContext().defaultKinds();
fir::KindMapping kindMap(mlirCtx.get(), llvm::ArrayRef<fir::KindTy>{
fir::fromDefaultKinds(defKinds)});
+ const llvm::DataLayout &dl = targetMachine.createDataLayout();
+
lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(
*mlirCtx, ci.getSemanticsContext(), defKinds,
ci.getSemanticsContext().intrinsics(),
@@ -401,27 +297,22 @@ bool CodeGenAction::beginSourceFileAction() {
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
kindMap, ci.getInvocation().getLoweringOpts(),
ci.getInvocation().getFrontendOpts().envDefaults,
- ci.getInvocation().getFrontendOpts().features);
+ ci.getInvocation().getFrontendOpts().features, &dl);
// Fetch module from lb, so we can set
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());
- if (!setUpTargetMachine())
- return false;
-
if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP)) {
setOffloadModuleInterfaceAttributes(*mlirModule,
ci.getInvocation().getLangOpts());
- setOffloadModuleInterfaceTargetAttribute(*mlirModule, tm->getTargetCPU(),
- tm->getTargetFeatureString());
+ setOffloadModuleInterfaceTargetAttribute(
+ *mlirModule, targetMachine.getTargetCPU(),
+ targetMachine.getTargetFeatureString());
setOpenMPVersionAttribute(*mlirModule,
ci.getInvocation().getLangOpts().OpenMPVersion);
}
- const llvm::DataLayout &dl = tm->createDataLayout();
- setMLIRDataLayout(*mlirModule, dl);
-
// Create a parse tree and lower it to FIR
Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
lb.lower(parseTree, ci.getSemanticsContext());
@@ -830,7 +721,7 @@ getVScaleRange(CompilerInstance &ci,
return std::pair<unsigned, unsigned>(
langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
- std::string featuresStr = getTargetFeatures(ci);
+ std::string featuresStr = ci.getTargetFeatures();
if (featuresStr.find("+sve") != std::string::npos)
return std::pair<unsigned, unsigned>(1, 16);
@@ -911,38 +802,6 @@ void CodeGenAction::generateLLVMIR() {
}
}
-bool CodeGenAction::setUpTargetMachine() {
- CompilerInstance &ci = this->getInstance();
-
- const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
- const std::string &theTriple = targetOpts.triple;
-
- // Create `Target`
- std::string error;
- const llvm::Target *theTarget =
- llvm::TargetRegistry::lookupTarget(theTriple, error);
- if (!theTarget) {
- ci.getDiagnostics().Report(clang::diag::err_fe_unable_to_create_target)
- << error;
- return false;
- }
-
- // Create `TargetMachine`
- const auto &CGOpts = ci.getInvocation().getCodeGenOpts();
- std::optional<llvm::CodeGenOptLevel> OptLevelOrNone =
- llvm::CodeGenOpt::getLevel(CGOpts.OptimizationLevel);
- assert(OptLevelOrNone && "Invalid optimization level!");
- llvm::CodeGenOptLevel OptLevel = *OptLevelOrNone;
- std::string featuresStr = getTargetFeatures(ci);
- tm.reset(theTarget->createTargetMachine(
- theTriple, /*CPU=*/targetOpts.cpu,
- /*Features=*/featuresStr, llvm::TargetOptions(),
- /*Reloc::Model=*/CGOpts.getRelocationModel(),
- /*CodeModel::Model=*/std::nullopt, OptLevel));
- assert(tm && "Failed to create TargetMachine");
- return true;
-}
-
static std::unique_ptr<llvm::raw_pwrite_stream>
getOutputStream(CompilerInstance &ci, llvm::StringRef inFile,
BackendActionTy action) {
@@ -1020,6 +879,7 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
auto &diags = getInstance().getDiagnostics();
llvm::OptimizationLevel level = mapToLevel(opts);
+ llvm::TargetMachine *targetMachine = &getInstance().getTargetMachine();
// Create the analysis managers.
llvm::LoopAnalysisManager lam;
llvm::FunctionAnalysisManager fam;
@@ -1033,7 +893,7 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
llvm::StandardInstrumentations si(llvmModule->getContext(),
opts.DebugPassManager);
si.registerCallbacks(pic, &mam);
- llvm::PassBuilder pb(tm.get(), pto, pgoOpt, &pic);
+ llvm::PassBuilder pb(targetMachine, pto, pgoOpt, &pic);
// Attempt to load pass plugins and register their callbacks with PB.
for (auto &pluginFile : opts.LLVMPassPlugins) {
@@ -1299,9 +1159,8 @@ void CodeGenAction::executeAction() {
// Set the triple based on the targetmachine (this comes compiler invocation
// and the command-line target option if specified, or the default if not
// given on the command-line).
- if (!setUpTargetMachine())
- return;
- const std::string &theTriple = tm->getTargetTriple().str();
+ llvm::TargetMachine &targetMachine = ci.getTargetMachine();
+ const std::string &theTriple = targetMachine.getTargetTriple().str();
if (llvmModule->getTargetTriple() != theTriple) {
diags.Report(clang::diag::warn_fe_override_module) << theTriple;
@@ -1311,7 +1170,7 @@ void CodeGenAction::executeAction() {
// Note that this overwrites any datalayout stored in the LLVM-IR. This avoids
// an assert for incompatible data layout when the code-generation happens.
llvmModule->setTargetTriple(theTriple);
- llvmModule->setDataLayout(tm->createDataLayout());
+ llvmModule->setDataLayout(targetMachine.createDataLayout());
// Embed offload objects specified with -fembed-offload-object
if (!codeGenOpts.OffloadObjects.empty())
@@ -1361,7 +1220,7 @@ void CodeGenAction::executeAction() {
if (action == BackendActionTy::Backend_EmitAssembly ||
action == BackendActionTy::Backend_EmitObj) {
generateMachineCodeOrAssemblyImpl(
- diags, *tm, action, *llvmModule, codeGenOpts,
+ diags, targetMachine, action, *llvmModule, codeGenOpts,
ci.isOutputStreamNull() ? *os : ci.getOutputStream());
return;
}
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 1258e3b..7e64adc 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -44,6 +44,7 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/Support/DataLayout.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Transforms/Passes.h"
@@ -5089,7 +5090,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
fir::KindMapping &kindMap,
const Fortran::lower::LoweringOptions &loweringOptions,
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
- const Fortran::common::LanguageFeatureControl &languageFeatures)
+ const Fortran::common::LanguageFeatureControl &languageFeatures,
+ const llvm::DataLayout *dataLayout)
: semanticsContext{semanticsContext}, defaultKinds{defaultKinds},
intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics},
cooked{&cooked}, context{context}, kindMap{kindMap},
@@ -5145,4 +5147,6 @@ Fortran::lower::LoweringBridge::LoweringBridge(
assert(module.get() && "module was not created");
fir::setTargetTriple(*module.get(), triple);
fir::setKindMapping(*module.get(), kindMap);
+ if (dataLayout)
+ fir::support::setMLIRDataLayout(*module.get(), *dataLayout);
}
diff --git a/flang/lib/Optimizer/Support/CMakeLists.txt b/flang/lib/Optimizer/Support/CMakeLists.txt
index 2d03bc5..55f5718 100644
--- a/flang/lib/Optimizer/Support/CMakeLists.txt
+++ b/flang/lib/Optimizer/Support/CMakeLists.txt
@@ -2,6 +2,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
add_flang_library(FIRSupport
+ DataLayout.cpp
InitFIR.cpp
InternalNames.cpp
@@ -20,6 +21,7 @@ add_flang_library(FIRSupport
MLIROpenMPToLLVMIRTranslation
MLIRLLVMToLLVMIRTranslation
MLIRTargetLLVMIRExport
+ MLIRTargetLLVMIRImport
LINK_COMPONENTS
TargetParser
diff --git a/flang/lib/Optimizer/Support/DataLayout.cpp b/flang/lib/Optimizer/Support/DataLayout.cpp
new file mode 100644
index 0000000..5cd9c01
--- /dev/null
+++ b/flang/lib/Optimizer/Support/DataLayout.cpp
@@ -0,0 +1,47 @@
+//===-- Optimizer/Support/DataLayout.cpp ----------------------------------===//
+//
+// 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/Optimizer/Support/DataLayout.h"
+#include "flang/Optimizer/Dialect/Support/FIRContext.h"
+#include "flang/Optimizer/Support/FatalError.h"
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "mlir/Support/LLVM.h"
+#include "mlir/Target/LLVMIR/Import.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+
+void fir::support::setMLIRDataLayout(mlir::ModuleOp mlirModule,
+ const llvm::DataLayout &dl) {
+ mlir::MLIRContext *context = mlirModule.getContext();
+ mlirModule->setAttr(
+ mlir::LLVM::LLVMDialect::getDataLayoutAttrName(),
+ mlir::StringAttr::get(context, dl.getStringRepresentation()));
+ mlir::DataLayoutSpecInterface dlSpec = mlir::translateDataLayout(dl, context);
+ mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
+}
+
+void fir::support::setMLIRDataLayoutFromAttributes(mlir::ModuleOp mlirModule,
+ bool allowDefaultLayout) {
+ if (mlirModule.getDataLayoutSpec())
+ return; // Already set.
+ if (auto dataLayoutString = mlirModule->getAttrOfType<mlir::StringAttr>(
+ mlir::LLVM::LLVMDialect::getDataLayoutAttrName())) {
+ llvm::DataLayout llvmDataLayout(dataLayoutString);
+ fir::support::setMLIRDataLayout(mlirModule, llvmDataLayout);
+ return;
+ }
+ if (!allowDefaultLayout)
+ return;
+ llvm::DataLayout llvmDataLayout("");
+ fir::support::setMLIRDataLayout(mlirModule, llvmDataLayout);
+}