aboutsummaryrefslogtreecommitdiff
path: root/flang/tools
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/tools
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/tools')
-rw-r--r--flang/tools/bbc/CMakeLists.txt3
-rw-r--r--flang/tools/bbc/bbc.cpp69
-rw-r--r--flang/tools/f18/CMakeLists.txt11
-rw-r--r--flang/tools/tco/tco.cpp14
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();
}