diff options
author | jeanPerier <jperier@nvidia.com> | 2023-12-06 14:20:06 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-06 14:20:06 +0100 |
commit | e59e848805f57bd52ebbb0f7f7d4d951e6af597c (patch) | |
tree | e83a8776a07bd467dc9d44547b1af660b2303f8d /flang/lib | |
parent | d77067d08a3f56dc2d0e6c95bd2852c943df743a (diff) | |
download | llvm-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.cpp | 134 | ||||
-rw-r--r-- | flang/lib/Frontend/CompilerInvocation.cpp | 23 | ||||
-rw-r--r-- | flang/lib/Frontend/FrontendActions.cpp | 177 | ||||
-rw-r--r-- | flang/lib/Lower/Bridge.cpp | 6 | ||||
-rw-r--r-- | flang/lib/Optimizer/Support/CMakeLists.txt | 2 | ||||
-rw-r--r-- | flang/lib/Optimizer/Support/DataLayout.cpp | 47 |
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); +} |