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/tools | |
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/tools')
-rw-r--r-- | flang/tools/bbc/CMakeLists.txt | 3 | ||||
-rw-r--r-- | flang/tools/bbc/bbc.cpp | 69 | ||||
-rw-r--r-- | flang/tools/f18/CMakeLists.txt | 11 | ||||
-rw-r--r-- | flang/tools/tco/tco.cpp | 14 |
4 files changed, 74 insertions, 23 deletions
diff --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt index cbae4ec..f21fa3b 100644 --- a/flang/tools/bbc/CMakeLists.txt +++ b/flang/tools/bbc/CMakeLists.txt @@ -1,5 +1,8 @@ set(LLVM_LINK_COMPONENTS Passes +AllTargetsCodeGens +AllTargetsDescs +AllTargetsInfos TargetParser ) diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp index 0c35d5c..0122cf3 100644 --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -16,6 +16,7 @@ #include "flang/Common/Fortran-features.h" #include "flang/Common/OpenMP-features.h" +#include "flang/Common/Version.h" #include "flang/Common/default-kinds.h" #include "flang/Lower/Bridge.h" #include "flang/Lower/PFTBuilder.h" @@ -39,6 +40,7 @@ #include "flang/Semantics/semantics.h" #include "flang/Semantics/unparse-with-symbols.h" #include "flang/Tools/CrossToolHelpers.h" +#include "flang/Tools/TargetSetup.h" #include "flang/Version.inc" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/AsmState.h" @@ -50,6 +52,7 @@ #include "mlir/Pass/PassRegistry.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include "mlir/Transforms/Passes.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorOr.h" @@ -63,6 +66,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" #include "llvm/TargetParser/Triple.h" +#include <memory> //===----------------------------------------------------------------------===// // Some basic command-line options @@ -202,6 +206,10 @@ static llvm::cl::opt<bool> enableCUDA("fcuda", static llvm::cl::opt<bool> fixedForm("ffixed-form", llvm::cl::desc("enable fixed form"), llvm::cl::init(false)); +static llvm::cl::opt<std::string> + targetTripleOverride("target", + llvm::cl::desc("Override host target triple"), + llvm::cl::init("")); #define FLANG_EXCLUDE_CODEGEN #include "flang/Tools/CLOptions.inc" @@ -221,6 +229,27 @@ static void registerAllPasses() { fir::registerOptTransformPasses(); } +/// Create a target machine that is at least sufficient to get data-layout +/// information required by flang semantics and lowering. Note that it may not +/// contain all the CPU feature information to get optimized assembly generation +/// from LLVM IR. Drivers that needs to generate assembly from LLVM IR should +/// create a target machine according to their specific options. +static std::unique_ptr<llvm::TargetMachine> +createTargetMachine(llvm::StringRef targetTriple, std::string &error) { + std::string triple{targetTriple}; + if (triple.empty()) + triple = llvm::sys::getDefaultTargetTriple(); + + const llvm::Target *theTarget = + llvm::TargetRegistry::lookupTarget(triple, error); + if (!theTarget) + return nullptr; + return std::unique_ptr<llvm::TargetMachine>{ + theTarget->createTargetMachine(triple, /*CPU=*/"", + /*Features=*/"", llvm::TargetOptions(), + /*Reloc::Model=*/std::nullopt)}; +} + //===----------------------------------------------------------------------===// // Translate Fortran input to FIR, a dialect of MLIR. //===----------------------------------------------------------------------===// @@ -229,7 +258,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR( std::string path, Fortran::parser::Options options, const ProgramName &programPrefix, Fortran::semantics::SemanticsContext &semanticsContext, - const mlir::PassPipelineCLParser &passPipeline) { + const mlir::PassPipelineCLParser &passPipeline, + const llvm::TargetMachine &targetMachine) { // prep for prescan and parse Fortran::parser::Parsing parsing{semanticsContext.allCookedSources()}; @@ -295,6 +325,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR( auto &defKinds = semanticsContext.defaultKinds(); fir::KindMapping kindMap( &ctx, llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)}); + const llvm::DataLayout &dataLayout = targetMachine.createDataLayout(); + std::string targetTriple = targetMachine.getTargetTriple().normalize(); // Use default lowering options for bbc. Fortran::lower::LoweringOptions loweringOptions{}; loweringOptions.setPolymorphicTypeImpl(enablePolymorphic); @@ -302,8 +334,9 @@ static mlir::LogicalResult convertFortranSourceToMLIR( loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR); auto burnside = Fortran::lower::LoweringBridge::create( ctx, semanticsContext, defKinds, semanticsContext.intrinsics(), - semanticsContext.targetCharacteristics(), parsing.allCooked(), "", - kindMap, loweringOptions, {}, semanticsContext.languageFeatures()); + semanticsContext.targetCharacteristics(), parsing.allCooked(), + targetTriple, kindMap, loweringOptions, {}, + semanticsContext.languageFeatures(), &dataLayout); burnside.lower(parseTree, semanticsContext); mlir::ModuleOp mlirModule = burnside.getModule(); if (enableOpenMP) { @@ -388,6 +421,8 @@ static mlir::LogicalResult convertFortranSourceToMLIR( int main(int argc, char **argv) { [[maybe_unused]] llvm::InitLLVM y(argc, argv); + llvm::InitializeAllTargets(); + llvm::InitializeAllTargetMCs(); registerAllPasses(); mlir::registerMLIRContextCLOptions(); @@ -453,17 +488,21 @@ int main(int argc, char **argv) { .set_warnOnNonstandardUsage(warnStdViolation) .set_warningsAreErrors(warnIsError); - llvm::Triple targetTriple{llvm::Triple( - llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))}; - // FIXME: Handle real(3) ? - if (targetTriple.getArch() != llvm::Triple::ArchType::x86 && - targetTriple.getArch() != llvm::Triple::ArchType::x86_64) { - semanticsContext.targetCharacteristics().DisableType( - Fortran::common::TypeCategory::Real, /*kind=*/10); + std::string error; + // Create host target machine. + std::unique_ptr<llvm::TargetMachine> targetMachine = + createTargetMachine(targetTripleOverride, error); + if (!targetMachine) { + llvm::errs() << "failed to create target machine: " << error << "\n"; + return mlir::failed(mlir::failure()); } - if (targetTriple.isPPC()) - semanticsContext.targetCharacteristics().set_isPPC(true); - - return mlir::failed(convertFortranSourceToMLIR( - inputFilename, options, programPrefix, semanticsContext, passPipe)); + std::string compilerVersion = Fortran::common::getFlangToolFullVersion("bbc"); + std::string compilerOptions = ""; + Fortran::tools::setUpTargetCharacteristics( + semanticsContext.targetCharacteristics(), *targetMachine, compilerVersion, + compilerOptions); + + return mlir::failed( + convertFortranSourceToMLIR(inputFilename, options, programPrefix, + semanticsContext, passPipe, *targetMachine)); } diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index 270124b..ba6c664 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -49,9 +49,14 @@ if (NOT CMAKE_CROSSCOMPILING) # The module contains PPC vector types that needs the PPC target. set(opts "") - if(${filename} STREQUAL "__ppc_intrinsics" OR - ${filename} STREQUAL "mma") - set(opts "--target=ppc64le") + if(${filename} STREQUAL "__ppc_intrinsics" OR + ${filename} STREQUAL "mma") + if (PowerPC IN_LIST LLVM_TARGETS_TO_BUILD) + set(opts "--target=ppc64le") + else() + # Do not compile PPC module if the target is not available. + continue() + endif() endif() add_custom_command(OUTPUT ${base}.mod diff --git a/flang/tools/tco/tco.cpp b/flang/tools/tco/tco.cpp index a649535..d5f5cd0 100644 --- a/flang/tools/tco/tco.cpp +++ b/flang/tools/tco/tco.cpp @@ -14,6 +14,7 @@ #include "flang/Optimizer/CodeGen/CodeGen.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/InternalNames.h" #include "flang/Optimizer/Transforms/Passes.h" @@ -61,9 +62,8 @@ static cl::opt<bool> codeGenLLVM( #include "flang/Tools/CLOptions.inc" -static void printModuleBody(mlir::ModuleOp mod, raw_ostream &output) { - for (auto &op : *mod.getBody()) - output << op << '\n'; +static void printModule(mlir::ModuleOp mod, raw_ostream &output) { + output << mod << '\n'; } // compile a .fir file @@ -104,6 +104,10 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) { fir::KindMapping kindMap{&context}; fir::setTargetTriple(*owningRef, targetTriple); fir::setKindMapping(*owningRef, kindMap); + // tco is a testing tool, so it will happily use the target independent + // data layout if none is on the module. + fir::support::setMLIRDataLayoutFromAttributes(*owningRef, + /*allowDefaultLayout=*/true); mlir::PassManager pm((*owningRef)->getName(), mlir::OpPassManager::Nesting::Implicit); pm.enableVerifier(/*verifyPasses=*/true); @@ -135,13 +139,13 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) { if (mlir::succeeded(pm.run(*owningRef))) { // passes ran successfully, so keep the output if ((emitFir || passPipeline.hasAnyOccurrences()) && !codeGenLLVM) - printModuleBody(*owningRef, out.os()); + printModule(*owningRef, out.os()); out.keep(); return mlir::success(); } // pass manager failed - printModuleBody(*owningRef, errs()); + printModule(*owningRef, errs()); errs() << "\n\nFAILED: " << inputFilename << '\n'; return mlir::failure(); } |