diff options
author | Dominik Adamski <dominik.adamski@amd.com> | 2023-11-28 19:57:36 +0100 |
---|---|---|
committer | Dominik Adamski <dominik.adamski@amd.com> | 2023-11-29 03:01:01 -0600 |
commit | 95943d2fab7e6f8dcea216df2d56a0512201b467 (patch) | |
tree | 340b052fdc9f726ff8c2c2929515e1fd8bbc4cd3 /flang/lib/Frontend | |
parent | ebeae22cdebc1db62a0264cf8f5179d079ff3262 (diff) | |
download | llvm-95943d2fab7e6f8dcea216df2d56a0512201b467.zip llvm-95943d2fab7e6f8dcea216df2d56a0512201b467.tar.gz llvm-95943d2fab7e6f8dcea216df2d56a0512201b467.tar.bz2 |
[Flang] Add code-object-version option (#72638)
Information about code object version can be configured by the user for
AMD GPU target and it needs to be placed in LLVM IR generated by Flang.
Information about code object version in MLIR generated by the parser
can be reused by other tools. There is no need to specify extra flags if
we want to invoke MLIR tools (like fir-opt) separately.
Changes in comparison to a8ac93:
* added information about required targets for test
flang/test/Driver/driver-help.f90
Diffstat (limited to 'flang/lib/Frontend')
-rw-r--r-- | flang/lib/Frontend/CompilerInvocation.cpp | 11 | ||||
-rw-r--r-- | flang/lib/Frontend/FrontendActions.cpp | 71 |
2 files changed, 78 insertions, 4 deletions
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 1c09ae9..0dc11ab 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -268,6 +268,17 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, opts.PrepareForThinLTO = true; } + if (const llvm::opt::Arg *a = args.getLastArg( + clang::driver::options::OPT_mcode_object_version_EQ)) { + llvm::StringRef s = a->getValue(); + if (s == "5") + opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_5; + if (s == "4") + opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_4; + if (s == "none") + opts.CodeObjectVersion = llvm::CodeObjectVersionKind::COV_None; + } + // -f[no-]save-optimization-record[=<format>] if (const llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_opt_record_file)) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index f573ac8..6663548 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -244,8 +244,7 @@ static void setMLIRDataLayout(mlir::ModuleOp &mlirModule, mlirModule->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec); } -static void addDepdendentLibs(mlir::ModuleOp &mlirModule, - CompilerInstance &ci) { +static void addDependentLibs(mlir::ModuleOp &mlirModule, CompilerInstance &ci) { const std::vector<std::string> &libs = ci.getInvocation().getCodeGenOpts().DependentLibs; if (libs.empty()) { @@ -264,6 +263,68 @@ static void addDepdendentLibs(mlir::ModuleOp &mlirModule, } } +// Add to MLIR code target specific items which are dependent on target +// configuration specified by the user. +// Clang equivalent function: AMDGPUTargetCodeGenInfo::emitTargetGlobals +static void addAMDGPUSpecificMLIRItems(mlir::ModuleOp &mlirModule, + CompilerInstance &ci) { + const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts(); + const llvm::Triple triple(targetOpts.triple); + const llvm::StringRef codeObjectVersionGlobalOpName = "__oclc_ABI_version"; + + // TODO: Share address spaces enumeration between Clang and Flang. + // Currently this enumeration is defined in Clang specific class + // defined in file: clang/lib/Basic/Targets/AMDGPU.h . + // and we need to move it to LLVM directory. + const int constantAddressSpace = 4; + + if (!triple.isAMDGPU()) { + return; + } + const CodeGenOptions &codeGenOpts = ci.getInvocation().getCodeGenOpts(); + if (codeGenOpts.CodeObjectVersion == llvm::CodeObjectVersionKind::COV_None) { + return; + } + + mlir::ConversionPatternRewriter builder(mlirModule.getContext()); + unsigned oclcABIVERsion = codeGenOpts.CodeObjectVersion; + auto int32Type = builder.getI32Type(); + + std::optional<mlir::LLVM::GlobalOp> originalGV; + + mlirModule.walk([&originalGV, codeObjectVersionGlobalOpName]( + mlir::LLVM::GlobalOp globalOp) { + if (globalOp.getName() == codeObjectVersionGlobalOpName) + originalGV = globalOp; + }); + if (originalGV.has_value()) { + mlir::LLVM::GlobalOp originalGVOp = originalGV.value(); + if (originalGVOp.getLinkage() != mlir::LLVM::Linkage::External) { + return; + } + // Update the variable if it is already present in MLIR but it was marked + // as external linkage variable + originalGVOp.setLinkage(mlir::LLVM::Linkage::WeakODR); + originalGVOp.setValueAttr( + builder.getIntegerAttr(int32Type, oclcABIVERsion)); + originalGVOp.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Local); + originalGVOp.setAddrSpace(constantAddressSpace); + originalGVOp.setVisibility_(mlir::LLVM::Visibility::Hidden); + return; + } + + mlir::LLVM::GlobalOp covInfo = builder.create<mlir::LLVM::GlobalOp>( + /* Location */ mlirModule.getLoc(), /* Type */ int32Type, + /* IsConstant */ true, /* Linkage */ mlir::LLVM::Linkage::WeakODR, + /* Name */ codeObjectVersionGlobalOpName, + /* Value */ builder.getIntegerAttr(int32Type, oclcABIVERsion)); + covInfo.setUnnamedAddr(mlir::LLVM::UnnamedAddr::Local); + covInfo.setAddrSpace(constantAddressSpace); + covInfo.setVisibility_(mlir::LLVM::Visibility::Hidden); + builder.setInsertionPointToStart(mlirModule.getBody()); + builder.insert(covInfo); +} + bool CodeGenAction::beginSourceFileAction() { llvmCtx = std::make_unique<llvm::LLVMContext>(); CompilerInstance &ci = this->getInstance(); @@ -365,8 +426,10 @@ bool CodeGenAction::beginSourceFileAction() { Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()}; lb.lower(parseTree, ci.getInvocation().getSemanticsContext()); - // Add dependent libraries - addDepdendentLibs(*mlirModule, ci); + // Add target specific items like dependent libraries, target specific + // constants etc. + addDependentLibs(*mlirModule, ci); + addAMDGPUSpecificMLIRItems(*mlirModule, ci); // run the default passes. mlir::PassManager pm((*mlirModule)->getName(), |