https://github.com/Leporacanthicus updated https://github.com/llvm/llvm-project/pull/95411
>From 0ef4b61d0429517b92f7b6de7fa52c516f3a1468 Mon Sep 17 00:00:00 2001 From: David Truby <david.tr...@arm.com> Date: Thu, 13 Jun 2024 14:01:36 +0000 Subject: [PATCH 1/3] [flang] Implement -mcmodel flag This patch implements the -mcmodel flag from clang, allowing the Code Model to be changed for the LLVM module. The same set of mcmodel flags are accepted as in clang and the same Code Model attributes are added to the LLVM module for those flags. --- clang/include/clang/Driver/Options.td | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 76 +---------------- clang/lib/Driver/ToolChains/CommonArgs.cpp | 81 +++++++++++++++++++ clang/lib/Driver/ToolChains/CommonArgs.h | 4 + clang/lib/Driver/ToolChains/Flang.cpp | 5 ++ .../include/flang/Frontend/CodeGenOptions.def | 1 + flang/lib/Frontend/CompilerInvocation.cpp | 21 +++++ flang/lib/Frontend/FrontendActions.cpp | 3 + flang/test/Driver/mcmodel.f90 | 44 ++++++++++ flang/test/Lower/mcmodel.f90 | 16 ++++ 10 files changed, 177 insertions(+), 76 deletions(-) create mode 100644 flang/test/Driver/mcmodel.f90 create mode 100644 flang/test/Lower/mcmodel.f90 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 9f7904dd94b94..4087d3b95cc39 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4600,7 +4600,7 @@ def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group<m_Group>, NormalizedValuesScope<"CodeGenOptions">, NormalizedValues<["IAD_ATT", "IAD_Intel"]>, MarshallingInfoEnum<CodeGenOpts<"InlineAsmDialect">, "IAD_ATT">; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>; def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group<m_Group>, Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1f8591537b6c8..0447581128cd1 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5908,81 +5908,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind()); - if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { - StringRef CM = A->getValue(); - bool Ok = false; - if (Triple.isOSAIX() && CM == "medium") - CM = "large"; - if (Triple.isAArch64(64)) { - Ok = CM == "tiny" || CM == "small" || CM == "large"; - if (CM == "large" && !Triple.isOSBinFormatMachO() && - RelocationModel != llvm::Reloc::Static) - D.Diag(diag::err_drv_argument_only_allowed_with) - << A->getAsString(Args) << "-fno-pic"; - } else if (Triple.isLoongArch()) { - if (CM == "extreme" && - Args.hasFlagNoClaim(options::OPT_fplt, options::OPT_fno_plt, false)) - D.Diag(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << "-fplt"; - Ok = CM == "normal" || CM == "medium" || CM == "extreme"; - // Convert to LLVM recognizable names. - if (Ok) - CM = llvm::StringSwitch<StringRef>(CM) - .Case("normal", "small") - .Case("extreme", "large") - .Default(CM); - } else if (Triple.isPPC64() || Triple.isOSAIX()) { - Ok = CM == "small" || CM == "medium" || CM == "large"; - } else if (Triple.isRISCV()) { - if (CM == "medlow") - CM = "small"; - else if (CM == "medany") - CM = "medium"; - Ok = CM == "small" || CM == "medium"; - } else if (Triple.getArch() == llvm::Triple::x86_64) { - Ok = llvm::is_contained({"small", "kernel", "medium", "large", "tiny"}, - CM); - } else if (Triple.isNVPTX() || Triple.isAMDGPU() || Triple.isSPIRV()) { - // NVPTX/AMDGPU/SPIRV does not care about the code model and will accept - // whatever works for the host. - Ok = true; - } else if (Triple.isSPARC64()) { - if (CM == "medlow") - CM = "small"; - else if (CM == "medmid") - CM = "medium"; - else if (CM == "medany") - CM = "large"; - Ok = CM == "small" || CM == "medium" || CM == "large"; - } - if (Ok) { - CmdArgs.push_back(Args.MakeArgString("-mcmodel=" + CM)); - } else { - D.Diag(diag::err_drv_unsupported_option_argument_for_target) - << A->getSpelling() << CM << TripleStr; - } - } - - if (Triple.getArch() == llvm::Triple::x86_64) { - bool IsMediumCM = false; - bool IsLargeCM = false; - if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { - IsMediumCM = StringRef(A->getValue()) == "medium"; - IsLargeCM = StringRef(A->getValue()) == "large"; - } - if (Arg *A = Args.getLastArg(options::OPT_mlarge_data_threshold_EQ)) { - if (!IsMediumCM && !IsLargeCM) { - D.Diag(diag::warn_drv_large_data_threshold_invalid_code_model) - << A->getOption().getRenderName(); - } else { - A->render(Args, CmdArgs); - } - } else if (IsMediumCM) { - CmdArgs.push_back("-mlarge-data-threshold=65536"); - } else if (IsLargeCM) { - CmdArgs.push_back("-mlarge-data-threshold=0"); - } - } + addMCModel(D, Args, Triple, RelocationModel, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_mtls_size_EQ)) { StringRef Value = A->getValue(); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 2a4c1369f5a73..a33975e14c541 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2823,3 +2823,84 @@ void tools::addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs, CmdArgs.push_back( TCArgs.MakeArgString(Twine("-compression-level=") + Arg->getValue())); } + +void tools::addMCModel(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &Triple, + const llvm::Reloc::Model &RelocationModel, + llvm::opt::ArgStringList &CmdArgs) { + if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { + StringRef CM = A->getValue(); + bool Ok = false; + if (Triple.isOSAIX() && CM == "medium") + CM = "large"; + if (Triple.isAArch64(64)) { + Ok = CM == "tiny" || CM == "small" || CM == "large"; + if (CM == "large" && !Triple.isOSBinFormatMachO() && + RelocationModel != llvm::Reloc::Static) + D.Diag(diag::err_drv_argument_only_allowed_with) + << A->getAsString(Args) << "-fno-pic"; + } else if (Triple.isLoongArch()) { + if (CM == "extreme" && + Args.hasFlagNoClaim(options::OPT_fplt, options::OPT_fno_plt, false)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "-fplt"; + Ok = CM == "normal" || CM == "medium" || CM == "extreme"; + // Convert to LLVM recognizable names. + if (Ok) + CM = llvm::StringSwitch<StringRef>(CM) + .Case("normal", "small") + .Case("extreme", "large") + .Default(CM); + } else if (Triple.isPPC64() || Triple.isOSAIX()) { + Ok = CM == "small" || CM == "medium" || CM == "large"; + } else if (Triple.isRISCV()) { + if (CM == "medlow") + CM = "small"; + else if (CM == "medany") + CM = "medium"; + Ok = CM == "small" || CM == "medium"; + } else if (Triple.getArch() == llvm::Triple::x86_64) { + Ok = llvm::is_contained({"small", "kernel", "medium", "large", "tiny"}, + CM); + } else if (Triple.isNVPTX() || Triple.isAMDGPU() || Triple.isSPIRV()) { + // NVPTX/AMDGPU/SPIRV does not care about the code model and will accept + // whatever works for the host. + Ok = true; + } else if (Triple.isSPARC64()) { + if (CM == "medlow") + CM = "small"; + else if (CM == "medmid") + CM = "medium"; + else if (CM == "medany") + CM = "large"; + Ok = CM == "small" || CM == "medium" || CM == "large"; + } + if (Ok) { + CmdArgs.push_back(Args.MakeArgString("-mcmodel=" + CM)); + } else { + D.Diag(diag::err_drv_unsupported_option_argument_for_target) + << A->getSpelling() << CM << Triple.getTriple(); + } + } + + if (Triple.getArch() == llvm::Triple::x86_64) { + bool IsMediumCM = false; + bool IsLargeCM = false; + if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) { + IsMediumCM = StringRef(A->getValue()) == "medium"; + IsLargeCM = StringRef(A->getValue()) == "large"; + } + if (Arg *A = Args.getLastArg(options::OPT_mlarge_data_threshold_EQ)) { + if (!IsMediumCM && !IsLargeCM) { + D.Diag(diag::warn_drv_large_data_threshold_invalid_code_model) + << A->getOption().getRenderName(); + } else { + A->render(Args, CmdArgs); + } + } else if (IsMediumCM) { + CmdArgs.push_back("-mlarge-data-threshold=65536"); + } else if (IsLargeCM) { + CmdArgs.push_back("-mlarge-data-threshold=0"); + } + } +} diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 5581905db3114..52818ecde924b 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -223,6 +223,10 @@ void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC, const llvm::Triple &Triple); void addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs, llvm::opt::ArgStringList &CmdArgs); +void addMCModel(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &Triple, + const llvm::Reloc::Model &RelocationModel, + llvm::opt::ArgStringList &CmdArgs); } // end namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 42b45dba2bd31..962a6c2c6b298 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -735,6 +735,11 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, // Add target args, features, etc. addTargetOptions(Args, CmdArgs); + llvm::Reloc::Model RelocationModel = + std::get<0>(ParsePICArgs(getToolChain(), Args)); + // Add MCModel information + addMCModel(D, Args, Triple, RelocationModel, CmdArgs); + // Add Codegen options addCodegenOptions(Args, CmdArgs); diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def index 9d03ec88a56b8..5d364e6655b99 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.def +++ b/flang/include/flang/Frontend/CodeGenOptions.def @@ -39,6 +39,7 @@ ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///< ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) ///< Level of debug info to generate ENUM_CODEGENOPT(VecLib, llvm::driver::VectorLibrary, 3, llvm::driver::VectorLibrary::NoLibrary) ///< Vector functions library to use ENUM_CODEGENOPT(FramePointer, llvm::FramePointerKind, 2, llvm::FramePointerKind::None) ///< Enable the usage of frame pointers +ENUM_CODEGENOPT(CodeModel, llvm::CodeModel::Model, 5, llvm::CodeModel::Model::Small) #undef CODEGENOPT #undef ENUM_CODEGENOPT diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index f64a939b785ef..5c27088ec3890 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -32,6 +32,7 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Path.h" @@ -381,6 +382,26 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, opts.IsPIE = 1; } + // -mcmodel option. + if (const llvm::opt::Arg *a = + args.getLastArg(clang::driver::options::OPT_mcmodel_EQ)) { + llvm::StringRef modelName = a->getValue(); + auto codeModel = + llvm::StringSwitch<std::optional<llvm::CodeModel::Model>>(modelName) + .Case("tiny", llvm::CodeModel::Model::Tiny) + .Case("small", llvm::CodeModel::Model::Small) + .Case("kernel", llvm::CodeModel::Model::Kernel) + .Case("medium", llvm::CodeModel::Model::Medium) + .Case("large", llvm::CodeModel::Model::Large) + .Default(std::nullopt); + + if (codeModel.has_value()) + opts.setCodeModel(*codeModel); + else + diags.Report(clang::diag::err_drv_invalid_value) + << a->getAsString(args) << modelName; + } + // This option is compatible with -f[no-]underscoring in gfortran. if (args.hasFlag(clang::driver::options::OPT_fno_underscoring, clang::driver::options::OPT_funderscoring, false)) { diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index b1b6391f1439c..b5c1792850fe3 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -861,6 +861,9 @@ void CodeGenAction::generateLLVMIR() { llvmModule->setPIELevel( static_cast<llvm::PIELevel::Level>(opts.PICLevel)); } + + // Set mcmodel level LLVM module flags + llvmModule->setCodeModel(opts.getCodeModel()); } static std::unique_ptr<llvm::raw_pwrite_stream> diff --git a/flang/test/Driver/mcmodel.f90 b/flang/test/Driver/mcmodel.f90 new file mode 100644 index 0000000000000..12d90ece2f24f --- /dev/null +++ b/flang/test/Driver/mcmodel.f90 @@ -0,0 +1,44 @@ +! RUN: not %flang -### -c --target=i686 -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=ERR-MEDIUM %s +! RUN: %flang --target=x86_64 -### -c -mcmodel=tiny %s 2>&1 | FileCheck --check-prefix=TINY %s +! RUN: %flang --target=x86_64 -### -c -mcmodel=small %s 2>&1 | FileCheck --check-prefix=SMALL %s +! RUN: %flang --target=x86_64 -### -S -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=KERNEL %s +! RUN: %flang --target=x86_64 -### -c -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=MEDIUM %s +! RUN: %flang --target=x86_64 -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=LARGE %s +! RUN: not %flang -### -c --target=powerpc-linux-gnu -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=ERR-MEDIUM %s +! RUN: %flang --target=powerpc-unknown-aix -### -S -mcmodel=small %s 2>&1 | FileCheck --check-prefix=SMALL %s +! RUN: %flang --target=powerpc-unknown-aix -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=LARGE %s +! RUN: %flang --target=powerpc-unknown-aix -### -S -mcmodel=medium %s 2> %t.log +! RUN: FileCheck --check-prefix=AIX-MCMEDIUM-OVERRIDE %s < %t.log +! RUN: not %flang -### -c -mcmodel=lager %s 2>&1 | FileCheck --check-prefix=INVALID %s +! RUN: %flang --target=aarch64 -### -S -mcmodel=large -fno-pic %s 2>&1 | FileCheck --check-prefix=LARGE %s +! RUN: %flang --target=aarch64-apple-macosx -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=LARGE %s +! RUN: not %flang --target=aarch64 -### -S -mcmodel=large -fpic %s 2>&1 | FileCheck --check-prefix=AARCH64-PIC-LARGE %s +! RUN: not %flang -### -c --target=aarch64 -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=ERR-MEDIUM %s +! RUN: not %flang -### -c --target=aarch64 -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=ERR-KERNEL %s +! RUN: not %flang --target=aarch64_32-linux -### -S -mcmodel=small %s 2>&1 | FileCheck --check-prefix=ERR-AARCH64_32 %s +! RUN: %flang --target=loongarch64 -### -S -mcmodel=normal %s 2>&1 | FileCheck --check-prefix=SMALL %s +! RUN: %flang --target=loongarch64 -### -S -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=MEDIUM %s +! RUN: %flang --target=loongarch64 -### -S -mcmodel=extreme %s 2>&1 | FileCheck --check-prefix=LARGE %s +! RUN: not %flang --target=loongarch64 -### -S -mcmodel=tiny %s 2>&1 | FileCheck --check-prefix=ERR-TINY %s +! RUN: not %flang --target=loongarch64 -### -S -mcmodel=small %s 2>&1 | FileCheck --check-prefix=ERR-SMALL %s +! RUN: not %flang --target=loongarch64 -### -S -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=ERR-KERNEL %s +! RUN: not %flang --target=loongarch64 -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=ERR-LARGE %s + +! TINY: "-mcmodel=tiny" +! SMALL: "-mcmodel=small" +! KERNEL: "-mcmodel=kernel" +! MEDIUM: "-mcmodel=medium" +! LARGE: "-mcmodel=large" +! AIX-MCMEDIUM-OVERRIDE: "-mcmodel=large" + +! INVALID: error: unsupported argument 'lager' to option '-mcmodel=' for target '{{.*}}' + +! ERR-TINY: error: unsupported argument 'tiny' to option '-mcmodel=' for target '{{.*}}' +! ERR-SMALL: error: unsupported argument 'small' to option '-mcmodel=' for target '{{.*}}' +! ERR-MEDIUM: error: unsupported argument 'medium' to option '-mcmodel=' for target '{{.*}}' +! ERR-KERNEL: error: unsupported argument 'kernel' to option '-mcmodel=' for target '{{.*}}' +! ERR-LARGE: error: unsupported argument 'large' to option '-mcmodel=' for target '{{.*}}' + +! AARCH64-PIC-LARGE: error: invalid argument '-mcmodel=large' only allowed with '-fno-pic' +! ERR-AARCH64_32: error: unsupported argument 'small' to option '-mcmodel=' for target 'aarch64_32-unknown-linux' + diff --git a/flang/test/Lower/mcmodel.f90 b/flang/test/Lower/mcmodel.f90 new file mode 100644 index 0000000000000..dd9eb145f5e2a --- /dev/null +++ b/flang/test/Lower/mcmodel.f90 @@ -0,0 +1,16 @@ +! RUN: %flang_fc1 -triple aarch64 -emit-llvm -mcmodel=tiny %s -o - | FileCheck %s -check-prefix=CHECK-TINY +! RUN: %flang_fc1 -emit-llvm -mcmodel=small %s -o - | FileCheck %s -check-prefix=CHECK-SMALL +! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcmodel=kernel %s -o - | FileCheck %s -check-prefix=CHECK-KERNEL +! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-llvm -mcmodel=medium %s -o - | FileCheck %s -check-prefix=CHECK-MEDIUM +! RUN: %flang_fc1 -emit-llvm -mcmodel=large %s -o - | FileCheck %s -check-prefix=CHECK-LARGE + +! CHECK-TINY: !llvm.module.flags = !{{{.*}}} +! CHECK-TINY: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 0} +! CHECK-SMALL: !llvm.module.flags = !{{{.*}}} +! CHECK-SMALL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 1} +! CHECK-KERNEL: !llvm.module.flags = !{{{.*}}} +! CHECK-KERNEL: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 2} +! CHECK-MEDIUM: !llvm.module.flags = !{{{.*}}} +! CHECK-MEDIUM: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 3} +! CHECK-LARGE: !llvm.module.flags = !{{{.*}}} +! CHECK-LARGE: !{{[0-9]+}} = !{i32 1, !"Code Model", i32 4} >From 77ca6312a09340f6368459964e446cb00e0b55f0 Mon Sep 17 00:00:00 2001 From: Mats Petersson <mats.peters...@arm.com> Date: Fri, 28 Jun 2024 19:10:27 +0100 Subject: [PATCH 2/3] Add new flag -mlarge-data-threshold --- clang/include/clang/Driver/Options.td | 2 +- flang/include/flang/Frontend/CodeGenOptions.h | 4 ++++ flang/lib/Frontend/CompilerInvocation.cpp | 9 +++++++++ flang/lib/Frontend/FrontendActions.cpp | 1 + flang/test/Driver/large-data-threshold.f90 | 18 ++++++++++++++++++ 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 flang/test/Driver/large-data-threshold.f90 diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4087d3b95cc39..54659fb6ae27c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4603,7 +4603,7 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>; def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group<m_Group>, - Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>, + Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option,FlangOption, FC1Option]>, MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "0">; def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group<m_Group>, Visibility<[ClangOption, CC1Option]>, diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index 918192abae724..5cba2deb91ffb 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -129,6 +129,10 @@ class CodeGenOptions : public CodeGenOptionsBase { /// transformation. OptRemark OptimizationRemarkAnalysis; + /// The code model-specific large data threshold to use + /// (-mlarge-data-threshold). + uint64_t LargeDataThreshold; + // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) #define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 5c27088ec3890..e9281672e7269 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -402,6 +402,15 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, << a->getAsString(args) << modelName; } + if (const llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_mlarge_data_threshold_EQ)) { + uint64_t LDT; + if (llvm::StringRef(arg->getValue()).getAsInteger(/*Radix=*/10, LDT)) { + diags.Report(clang::diag::err_drv_invalid_value) + << arg->getSpelling() << arg->getValue(); + } + opts.LargeDataThreshold = LDT; + } + // This option is compatible with -f[no-]underscoring in gfortran. if (args.hasFlag(clang::driver::options::OPT_fno_underscoring, clang::driver::options::OPT_funderscoring, false)) { diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index b5c1792850fe3..e45e9ece7adb0 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -864,6 +864,7 @@ void CodeGenAction::generateLLVMIR() { // Set mcmodel level LLVM module flags llvmModule->setCodeModel(opts.getCodeModel()); + llvmModule->setLargeDataThreshold(opts.LargeDataThreshold); } static std::unique_ptr<llvm::raw_pwrite_stream> diff --git a/flang/test/Driver/large-data-threshold.f90 b/flang/test/Driver/large-data-threshold.f90 new file mode 100644 index 0000000000000..ac6f78713f62c --- /dev/null +++ b/flang/test/Driver/large-data-threshold.f90 @@ -0,0 +1,18 @@ +! RUN: %flang -### -c --target=x86_64 -mcmodel=large -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s +! RUN: %flang -### -c --target=x86_64 -mcmodel=large -mlarge-data-threshold=59000 %s 2>&1 | FileCheck %s --check-prefix=CHECK-59000 +! RUN: %flang -### -c --target=x86_64 -mcmodel=large -mlarge-data-threshold=1048576 %s 2>&1 | FileCheck %s --check-prefix=CHECK-1M +! RUN: not %flang -c --target=x86_64 -mcmodel=large -mlarge-data-threshold=nonsense %s 2>&1 | FileCheck %s --check-prefix=INVALID +! RUN: %flang -### -c --target=x86_64 -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s --check-prefix=NO-MCMODEL +! RUN: %flang -### -c --target=x86_64 -mcmodel=small -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s --check-prefix=NO-MCMODEL +! RUN: not %flang -### -c --target=aarch64 -mcmodel=small -mlarge-data-threshold=32768 %s 2>&1 | FileCheck %s --check-prefix=NOT-SUPPORTED + + +! CHECK: "{{.*}}/flang-new" "-fc1" +! CHECK-SAME: "-mlarge-data-threshold=32768" +! CHECK-59000: "{{.*}}/flang-new" "-fc1" +! CHECK-59000-SAME: "-mlarge-data-threshold=59000" +! CHECK-1M: "{{.*}}/flang-new" "-fc1" +! CHECK-1M-SAME: "-mlarge-data-threshold=1048576" +! NO-MCMODEL: 'mlarge-data-threshold=' only applies to medium and large code models +! INVALID: error: invalid value 'nonsense' in '-mlarge-data-threshold=' +! NOT-SUPPORTED: error: unsupported option '-mlarge-data-threshold=' for target 'aarch64' >From af77a86ecc2d2895b51887cc4705aaec768a765c Mon Sep 17 00:00:00 2001 From: Mats Petersson <mats.peters...@arm.com> Date: Fri, 28 Jun 2024 21:26:32 +0100 Subject: [PATCH 3/3] Make everything work --- .../include/flang/Frontend/CodeGenOptions.def | 1 - flang/include/flang/Frontend/CodeGenOptions.h | 5 +++++ flang/lib/Frontend/CodeGenOptions.cpp | 11 ++++++++++ flang/lib/Frontend/CompilerInstance.cpp | 10 ++++++++- flang/lib/Frontend/CompilerInvocation.cpp | 11 ++-------- flang/lib/Frontend/FrontendActions.cpp | 12 +++++++++-- flang/test/Lower/large-data-threshold.f90 | 21 +++++++++++++++++++ 7 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 flang/test/Lower/large-data-threshold.f90 diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def index 5d364e6655b99..9d03ec88a56b8 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.def +++ b/flang/include/flang/Frontend/CodeGenOptions.def @@ -39,7 +39,6 @@ ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///< ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) ///< Level of debug info to generate ENUM_CODEGENOPT(VecLib, llvm::driver::VectorLibrary, 3, llvm::driver::VectorLibrary::NoLibrary) ///< Vector functions library to use ENUM_CODEGENOPT(FramePointer, llvm::FramePointerKind, 2, llvm::FramePointerKind::None) ///< Enable the usage of frame pointers -ENUM_CODEGENOPT(CodeModel, llvm::CodeModel::Model, 5, llvm::CodeModel::Model::Small) #undef CODEGENOPT #undef ENUM_CODEGENOPT diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index 5cba2deb91ffb..d8a806b44a821 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -129,6 +129,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// transformation. OptRemark OptimizationRemarkAnalysis; + /// The code model to use (-mcmodel). + std::string CodeModel; + /// The code model-specific large data threshold to use /// (-mlarge-data-threshold). uint64_t LargeDataThreshold; @@ -143,6 +146,8 @@ class CodeGenOptions : public CodeGenOptionsBase { CodeGenOptions(); }; +std::optional<llvm::CodeModel::Model> getCodeModel(llvm::StringRef string); + } // end namespace Fortran::frontend #endif // FORTRAN_FRONTEND_CODEGENOPTIONS_H diff --git a/flang/lib/Frontend/CodeGenOptions.cpp b/flang/lib/Frontend/CodeGenOptions.cpp index a7947182decce..8a9d3c27c8bc3 100644 --- a/flang/lib/Frontend/CodeGenOptions.cpp +++ b/flang/lib/Frontend/CodeGenOptions.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "flang/Frontend/CodeGenOptions.h" +#include <optional> #include <string.h> namespace Fortran::frontend { @@ -21,4 +22,14 @@ CodeGenOptions::CodeGenOptions() { #include "flang/Frontend/CodeGenOptions.def" } +std::optional<llvm::CodeModel::Model> getCodeModel(llvm::StringRef string) { + return llvm::StringSwitch<std::optional<llvm::CodeModel::Model>>(string) + .Case("tiny", llvm::CodeModel::Model::Tiny) + .Case("small", llvm::CodeModel::Model::Small) + .Case("kernel", llvm::CodeModel::Model::Kernel) + .Case("medium", llvm::CodeModel::Model::Medium) + .Case("large", llvm::CodeModel::Model::Large) + .Default(std::nullopt); +} + } // end namespace Fortran::frontend diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp index c78137346640a..27c36b7f84d89 100644 --- a/flang/lib/Frontend/CompilerInstance.cpp +++ b/flang/lib/Frontend/CompilerInstance.cpp @@ -321,11 +321,19 @@ bool CompilerInstance::setUpTargetMachine() { assert(OptLevelOrNone && "Invalid optimization level!"); llvm::CodeGenOptLevel OptLevel = *OptLevelOrNone; std::string featuresStr = getTargetFeatures(); + std::optional<llvm::CodeModel::Model> cm = getCodeModel(CGOpts.CodeModel); targetMachine.reset(theTarget->createTargetMachine( theTriple, /*CPU=*/targetOpts.cpu, /*Features=*/featuresStr, llvm::TargetOptions(), /*Reloc::Model=*/CGOpts.getRelocationModel(), - /*CodeModel::Model=*/std::nullopt, OptLevel)); + /*CodeModel::Model=*/cm, OptLevel)); assert(targetMachine && "Failed to create TargetMachine"); + if (cm.has_value()) { + const llvm::Triple triple(theTriple); + if ((cm == llvm::CodeModel::Medium || cm == llvm::CodeModel::Large) && + triple.getArch() == llvm::Triple::x86_64) { + targetMachine->setLargeDataThreshold(CGOpts.LargeDataThreshold); + } + } return true; } diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index e9281672e7269..2fd2ac3244a17 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -386,17 +386,10 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, if (const llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_mcmodel_EQ)) { llvm::StringRef modelName = a->getValue(); - auto codeModel = - llvm::StringSwitch<std::optional<llvm::CodeModel::Model>>(modelName) - .Case("tiny", llvm::CodeModel::Model::Tiny) - .Case("small", llvm::CodeModel::Model::Small) - .Case("kernel", llvm::CodeModel::Model::Kernel) - .Case("medium", llvm::CodeModel::Model::Medium) - .Case("large", llvm::CodeModel::Model::Large) - .Default(std::nullopt); + std::optional<llvm::CodeModel::Model> codeModel = getCodeModel(modelName); if (codeModel.has_value()) - opts.setCodeModel(*codeModel); + opts.CodeModel = modelName; else diags.Report(clang::diag::err_drv_invalid_value) << a->getAsString(args) << modelName; diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index e45e9ece7adb0..23f92b6c3a4ea 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -863,8 +863,15 @@ void CodeGenAction::generateLLVMIR() { } // Set mcmodel level LLVM module flags - llvmModule->setCodeModel(opts.getCodeModel()); - llvmModule->setLargeDataThreshold(opts.LargeDataThreshold); + std::optional<llvm::CodeModel::Model> cm = getCodeModel(opts.CodeModel); + if (cm.has_value()) { + const llvm::Triple triple(ci.getInvocation().getTargetOpts().triple); + llvmModule->setCodeModel(*cm); + if ((cm == llvm::CodeModel::Medium || cm == llvm::CodeModel::Large) && + triple.getArch() == llvm::Triple::x86_64) { + llvmModule->setLargeDataThreshold(opts.LargeDataThreshold); + } + } } static std::unique_ptr<llvm::raw_pwrite_stream> @@ -1229,6 +1236,7 @@ void CodeGenAction::executeAction() { // and the command-line target option if specified, or the default if not // given on the command-line). llvm::TargetMachine &targetMachine = ci.getTargetMachine(); + const std::string &theTriple = targetMachine.getTargetTriple().str(); if (llvmModule->getTargetTriple() != theTriple) { diff --git a/flang/test/Lower/large-data-threshold.f90 b/flang/test/Lower/large-data-threshold.f90 new file mode 100644 index 0000000000000..51ddd429d770a --- /dev/null +++ b/flang/test/Lower/large-data-threshold.f90 @@ -0,0 +1,21 @@ +! REQUIRES: x86-registered-target + +! RUN: %flang_fc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=medium | FileCheck %s --check-prefix=IR-DEFAULT +! RUN: %flang_fc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=medium -mlarge-data-threshold=200 | FileCheck %s --check-prefix=IR-CUSTOM +! RUN: %flang_fc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=large -mlarge-data-threshold=200 | FileCheck %s --check-prefix=IR-CUSTOM +! RUN: %flang_fc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - -mcmodel=small -mlarge-data-threshold=200 | FileCheck %s --check-prefix=IR-SMALL +! RUN: %flang_fc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=200 | FileCheck %s --check-prefix=ASM-SMALL +! RUN: %flang_fc1 -triple x86_64-unknown-unknown -S %s -o - -mcmodel=medium -mlarge-data-threshold=2 | FileCheck %s --check-prefix=ASM-LARGE + +! IR-DEFAULT: !{i32 1, !"Large Data Threshold", i64 0} +! IR-CUSTOM: !{i32 1, !"Large Data Threshold", i64 200} +! IR-SMALL-NOT: !"Large Data Threshold" + +! ASM-SMALL-NOT: movabsq +! ASM-LARGE: movabsq + +function f + integer :: f + integer, save :: i + f = i +end function f _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits