Skip to content

Commit

Permalink
[Flang] Add code-object-version option (#72638)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
DominikAdamski committed Nov 29, 2023
1 parent ebeae22 commit 95943d2
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 21 deletions.
12 changes: 2 additions & 10 deletions clang/include/clang/Basic/TargetOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,9 @@ class TargetOptions {
/// \brief If enabled, allow AMDGPU unsafe floating point atomics.
bool AllowAMDGPUUnsafeFPAtomics = false;

/// \brief Enumeration value for AMDGPU code object version, which is the
/// code object version times 100.
enum CodeObjectVersionKind {
COV_None,
COV_2 = 200, // Unsupported.
COV_3 = 300, // Unsupported.
COV_4 = 400,
COV_5 = 500,
};
/// \brief Code object version for AMDGPU.
CodeObjectVersionKind CodeObjectVersion = CodeObjectVersionKind::COV_None;
llvm::CodeObjectVersionKind CodeObjectVersion =
llvm::CodeObjectVersionKind::COV_None;

/// \brief Enumeration values for AMDGPU printf lowering scheme
enum class AMDGPUPrintfKind {
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4721,9 +4721,9 @@ defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee",

def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group<m_Group>,
HelpText<"Specify code object ABI version. Defaults to 4. (AMDGPU only)">,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, FlangOption, CC1Option, FC1Option]>,
Values<"none,4,5">,
NormalizedValuesScope<"TargetOptions">,
NormalizedValuesScope<"llvm::CodeObjectVersionKind">,
NormalizedValues<["COV_None", "COV_4", "COV_5"]>,
MarshallingInfoEnum<TargetOpts<"CodeObjectVersion">, "COV_4">;

Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17588,7 +17588,7 @@ Value *EmitAMDGPUWorkGroupSize(CodeGenFunction &CGF, unsigned Index) {

auto Cov = CGF.getTarget().getTargetOpts().CodeObjectVersion;

if (Cov == clang::TargetOptions::COV_None) {
if (Cov == CodeObjectVersionKind::COV_None) {
StringRef Name = "__oclc_ABI_version";
auto *ABIVersionC = CGF.CGM.getModule().getNamedGlobal(Name);
if (!ABIVersionC)
Expand All @@ -17606,7 +17606,7 @@ Value *EmitAMDGPUWorkGroupSize(CodeGenFunction &CGF, unsigned Index) {

Value *IsCOV5 = CGF.Builder.CreateICmpSGE(
ABIVersion,
llvm::ConstantInt::get(CGF.Int32Ty, clang::TargetOptions::COV_5));
llvm::ConstantInt::get(CGF.Int32Ty, CodeObjectVersionKind::COV_5));

// Indexing the implicit kernarg segment.
Value *ImplicitGEP = CGF.Builder.CreateConstGEP1_32(
Expand All @@ -17621,7 +17621,7 @@ Value *EmitAMDGPUWorkGroupSize(CodeGenFunction &CGF, unsigned Index) {
Address(Result, CGF.Int16Ty, CharUnits::fromQuantity(2)));
} else {
Value *GEP = nullptr;
if (Cov == clang::TargetOptions::COV_5) {
if (Cov == CodeObjectVersionKind::COV_5) {
// Indexing the implicit kernarg segment.
GEP = CGF.Builder.CreateConstGEP1_32(
CGF.Int8Ty, EmitAMDGPUImplicitArgPtr(CGF), 12 + Index * 2);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ void CodeGenModule::Release() {
// Emit amdgpu_code_object_version module flag, which is code object version
// times 100.
if (getTarget().getTargetOpts().CodeObjectVersion !=
TargetOptions::COV_None) {
llvm::CodeObjectVersionKind::COV_None) {
getModule().addModuleFlag(llvm::Module::Error,
"amdgpu_code_object_version",
getTarget().getTargetOpts().CodeObjectVersion);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ void AMDGPUTargetCodeGenInfo::emitTargetGlobals(
return;

if (CGM.getTarget().getTargetOpts().CodeObjectVersion ==
clang::TargetOptions::COV_None)
llvm::CodeObjectVersionKind::COV_None)
return;

auto *Type = llvm::IntegerType::getIntNTy(CGM.getModule().getContext(), 32);
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
}
}

void Flang::AddAMDGPUTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (Arg *A = Args.getLastArg(options::OPT_mcode_object_version_EQ)) {
StringRef Val = A->getValue();
CmdArgs.push_back(Args.MakeArgString("-mcode-object-version=" + Val));
}
}

void Flang::addTargetOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
const ToolChain &TC = getToolChain();
Expand All @@ -300,6 +308,9 @@ void Flang::addTargetOptions(const ArgList &Args,

case llvm::Triple::r600:
case llvm::Triple::amdgcn:
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
AddAMDGPUTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::riscv64:
case llvm::Triple::x86_64:
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/ToolChains/Flang.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;

/// Add specific options for AMDGPU target.
///
/// \param [in] Args The list of input driver arguments
/// \param [out] CmdArgs The list of output command arguments
void AddAMDGPUTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;

/// Extract offload options from the driver arguments and add them to
/// the command arguments.
/// \param [in] C The current compilation for the driver invocation
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Frontend/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
RK_WithPattern, // Remark pattern specified via '-Rgroup=regexp'.
};

/// \brief Code object version for AMDGPU.
llvm::CodeObjectVersionKind CodeObjectVersion =
llvm::CodeObjectVersionKind::COV_4;

/// Optimization remark with an optional regular expression pattern.
struct OptRemark {
RemarkKind Kind = RemarkKind::RK_Missing;
Expand Down
11 changes: 11 additions & 0 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
71 changes: 67 additions & 4 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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();
Expand Down Expand Up @@ -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(),
Expand Down
9 changes: 9 additions & 0 deletions flang/test/Driver/code-object-version.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! REQUIRES: x86-registered-target, amdgpu-registered-target
! RUN: not %flang -target amdgcn-amd-amdhsa -target-cpu gfx908 -mcode-object-version=3 -S %s -o \
! RUN: /dev/null 2>&1 | FileCheck --check-prefix=INVALID_VERSION %s

! RUN: %flang -target x86_64-unknown-linux-gnu -mcode-object-version=3 -S %s -o \
! RUN: /dev/null 2>&1 | FileCheck --check-prefix=UNUSED_PARAM %s

! INVALID_VERSION: error: invalid integral value '3' in '-mcode-object-version=3'
! UNUSED_PARAM: warning: argument unused during compilation: '-mcode-object-version=3' [-Wunused-command-line-argument]
2 changes: 2 additions & 0 deletions flang/test/Driver/driver-help-hidden.f90
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
! CHECK-NEXT: -I <dir> Add directory to the end of the list of include search paths
! CHECK-NEXT: -L <dir> Add directory to library search path
! CHECK-NEXT: -march=<value> For a list of available architectures for the target use '-mcpu=help'
! CHECK-NEXT: -mcode-object-version=<value>
! CHECK-NEXT: Specify code object ABI version. Defaults to 4. (AMDGPU only)
! CHECK-NEXT: -mcpu=<value> For a list of available CPUs for the target use '-mcpu=help'
! CHECK-NEXT: -mllvm=<arg> Alias for -mllvm
! CHECK-NEXT: -mllvm <value> Additional arguments to forward to LLVM's option processing
Expand Down
4 changes: 4 additions & 0 deletions flang/test/Driver/driver-help.f90
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@
! HELP-NEXT: -I <dir> Add directory to the end of the list of include search paths
! HELP-NEXT: -L <dir> Add directory to library search path
! HELP-NEXT: -march=<value> For a list of available architectures for the target use '-mcpu=help'
! HELP-NEXT: -mcode-object-version=<value>
! HELP-NEXT: Specify code object ABI version. Defaults to 4. (AMDGPU only)
! HELP-NEXT: -mcpu=<value> For a list of available CPUs for the target use '-mcpu=help'
! HELP-NEXT: -mllvm=<arg> Alias for -mllvm
! HELP-NEXT: -mllvm <value> Additional arguments to forward to LLVM's option processing
Expand Down Expand Up @@ -232,6 +234,8 @@
! HELP-FC1-NEXT: -init-only Only execute frontend initialization
! HELP-FC1-NEXT: -I <dir> Add directory to the end of the list of include search paths
! HELP-FC1-NEXT: -load <dsopath> Load the named plugin (dynamic shared object)
! HELP-FC1-NEXT: -mcode-object-version=<value>
! HELP-FC1-NEXT: Specify code object ABI version. Defaults to 4. (AMDGPU only)
! HELP-FC1-NEXT: -menable-no-infs Allow optimization to assume there are no infinities.
! HELP-FC1-NEXT: -menable-no-nans Allow optimization to assume there are no NaNs.
! HELP-FC1-NEXT: -mllvm <value> Additional arguments to forward to LLVM's option processing
Expand Down
13 changes: 13 additions & 0 deletions flang/test/Lower/AMD/code-object-version.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
!REQUIRES: amdgpu-registered-target
!RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -target-cpu gfx908 %s -o - | FileCheck --check-prefix=COV_DEFAULT %s
!RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -mcode-object-version=none %s -o - | FileCheck --check-prefix=COV_NONE %s
!RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -mcode-object-version=4 %s -o - | FileCheck --check-prefix=COV_4 %s
!RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -mcode-object-version=5 %s -o - | FileCheck --check-prefix=COV_5 %s

!COV_DEFAULT: llvm.mlir.global weak_odr hidden local_unnamed_addr constant @__oclc_ABI_version(400 : i32) {addr_space = 4 : i32} : i32
!COV_NONE-NOT: llvm.mlir.global weak_odr hidden local_unnamed_addr constant @__oclc_ABI_version(400 : i32) {addr_space = 4 : i32} : i32
!COV_4: llvm.mlir.global weak_odr hidden local_unnamed_addr constant @__oclc_ABI_version(400 : i32) {addr_space = 4 : i32} : i32
!COV_5: llvm.mlir.global weak_odr hidden local_unnamed_addr constant @__oclc_ABI_version(500 : i32) {addr_space = 4 : i32} : i32
subroutine target_simple
end subroutine target_simple

10 changes: 10 additions & 0 deletions llvm/include/llvm/Target/TargetOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ namespace llvm {
Never,
};

/// \brief Enumeration value for AMDGPU code object version, which is the
/// code object version times 100.
enum CodeObjectVersionKind {
COV_None,
COV_2 = 200, // Unsupported.
COV_3 = 300, // Unsupported.
COV_4 = 400,
COV_5 = 500,
};

class TargetOptions {
public:
TargetOptions()
Expand Down

0 comments on commit 95943d2

Please sign in to comment.