Author: Usman Nadeem Date: 2022-12-02T09:37:53-08:00 New Revision: 3951a73490df0f3dd307e8ea6aa52d2776259a4c
URL: https://github.com/llvm/llvm-project/commit/3951a73490df0f3dd307e8ea6aa52d2776259a4c DIFF: https://github.com/llvm/llvm-project/commit/3951a73490df0f3dd307e8ea6aa52d2776259a4c.diff LOG: [Flang][Driver] Handle target CPU and features This patch: - Adds target-feature and target-cpu to FC1Options. - Moves getTargetFeatures() from Clang.cpp to CommonArgs.cpp. - Processes target cpu and features in the flang driver. Right now features are only added for AArch64/x86 because I only did basic testing on them but it should generally work for others as well. Option handling is similar to clang. - Adds appropriate structures in TargetOptions and passes them to the target machine. What's missing: - Adding the CPU info and the features as attributes in the LLVM IR module. - Processing target specific flags, e.g. SVE vector bits for AArch64, ABI etc. Differential Revision: https://reviews.llvm.org/D137995 Change-Id: Ib081a74ea98617674845518a5d2754edba596418 Added: flang/test/Driver/target-cpu-features.f90 Modified: clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Driver/ToolChains/CommonArgs.h clang/lib/Driver/ToolChains/Flang.cpp clang/lib/Driver/ToolChains/Flang.h flang/include/flang/Frontend/TargetOptions.h flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Frontend/FrontendActions.cpp flang/test/Driver/driver-help.f90 Removed: ################################################################################ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 8da5e25bd38d0..a76c753a08aaa 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5076,15 +5076,9 @@ def emit_fir : Flag<["-"], "emit-fir">, Alias<emit_mlir>; let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { -def target_cpu : Separate<["-"], "target-cpu">, - HelpText<"Target a specific cpu type">, - MarshallingInfoString<TargetOpts<"CPU">>; def tune_cpu : Separate<["-"], "tune-cpu">, HelpText<"Tune for a specific cpu type">, MarshallingInfoString<TargetOpts<"TuneCPU">>; -def target_feature : Separate<["-"], "target-feature">, - HelpText<"Target specific attributes">, - MarshallingInfoStringVector<TargetOpts<"FeaturesAsWritten">>; def target_abi : Separate<["-"], "target-abi">, HelpText<"Target a particular ABI type">, MarshallingInfoString<TargetOpts<"ABI">>; @@ -5111,6 +5105,12 @@ def darwin_target_variant_triple : Separate<["-"], "darwin-target-variant-triple let Flags = [CC1Option, CC1AsOption, FC1Option, NoDriverOption] in { +def target_cpu : Separate<["-"], "target-cpu">, + HelpText<"Target a specific cpu type">, + MarshallingInfoString<TargetOpts<"CPU">>; +def target_feature : Separate<["-"], "target-feature">, + HelpText<"Target specific attributes">, + MarshallingInfoStringVector<TargetOpts<"FeaturesAsWritten">>; def triple : Separate<["-"], "triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">, MarshallingInfoString<TargetOpts<"Triple">, "llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple())">, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index d8ece4ee7a9f3..16130982eb8c5 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -292,98 +292,6 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args, } } -static void getWebAssemblyTargetFeatures(const ArgList &Args, - std::vector<StringRef> &Features) { - handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); -} - -static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args, ArgStringList &CmdArgs, - bool ForAS, bool IsAux = false) { - std::vector<StringRef> Features; - switch (Triple.getArch()) { - default: - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - mips::getMIPSTargetFeatures(D, Triple, Args, Features); - break; - - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS); - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppcle: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - ppc::getPPCTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: - riscv::getRISCVTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::systemz: - systemz::getSystemZTargetFeatures(D, Args, Features); - break; - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - x86::getX86TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::hexagon: - hexagon::getHexagonTargetFeatures(D, Args, Features); - break; - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - getWebAssemblyTargetFeatures(Args, Features); - break; - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); - break; - case llvm::Triple::r600: - case llvm::Triple::amdgcn: - amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::m68k: - m68k::getM68kTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::msp430: - msp430::getMSP430TargetFeatures(D, Args, Features); - break; - case llvm::Triple::ve: - ve::getVETargetFeatures(D, Args, Features); - break; - case llvm::Triple::csky: - csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features); - break; - case llvm::Triple::loongarch32: - case llvm::Triple::loongarch64: - loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features); - break; - } - - for (auto Feature : unifyTargetFeatures(Features)) { - CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature"); - CmdArgs.push_back(Feature.data()); - } -} - static bool shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, const llvm::Triple &Triple) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index cbdb51fe9d688..47f09732f95af 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -9,6 +9,8 @@ #include "CommonArgs.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" +#include "Arch/CSKY.h" +#include "Arch/LoongArch.h" #include "Arch/M68k.h" #include "Arch/Mips.h" #include "Arch/PPC.h" @@ -19,6 +21,7 @@ #include "Arch/X86.h" #include "HIPAMD.h" #include "Hexagon.h" +#include "MSP430.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" @@ -470,6 +473,96 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args, } } +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector<StringRef> &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); +} + +void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, + bool ForAS, bool IsAux) { + std::vector<StringRef> Features; + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + mips::getMIPSTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS); + break; + case llvm::Triple::ppc: + case llvm::Triple::ppcle: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + ppc::getPPCTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + riscv::getRISCVTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::systemz: + systemz::getSystemZTargetFeatures(D, Args, Features); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: + case llvm::Triple::aarch64_be: + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + x86::getX86TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::hexagon: + hexagon::getHexagonTargetFeatures(D, Args, Features); + break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + getWebAssemblyTargetFeatures(Args, Features); + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + sparc::getSparcTargetFeatures(D, Args, Features); + break; + case llvm::Triple::r600: + case llvm::Triple::amdgcn: + amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::nvptx: + case llvm::Triple::nvptx64: + NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::m68k: + m68k::getM68kTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::msp430: + msp430::getMSP430TargetFeatures(D, Args, Features); + break; + case llvm::Triple::ve: + ve::getVETargetFeatures(D, Args, Features); + break; + case llvm::Triple::csky: + csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features); + break; + case llvm::Triple::loongarch32: + case llvm::Triple::loongarch64: + loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features); + break; + } + + for (auto Feature : unifyTargetFeatures(Features)) { + CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature"); + CmdArgs.push_back(Feature.data()); + } +} + llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) { Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ); if (!LtoJobsArg) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 1d2284e99321a..d44d9214c08bc 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -174,6 +174,11 @@ void AddTargetFeature(const llvm::opt::ArgList &Args, std::string getCPUName(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &T, bool FromAs = false); +void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, bool ForAS, + bool IsAux = false); + /// Iterate \p Args and convert -mxxx to +xxx and -mno-xxx to -xxx and /// append it to \p Features. /// diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 588fabd560009..b2b08f960842e 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -80,6 +80,32 @@ void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const { } } +void Flang::addTargetOptions(const ArgList &Args, + ArgStringList &CmdArgs) const { + const ToolChain &TC = getToolChain(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); + const Driver &D = TC.getDriver(); + + std::string CPU = getCPUName(D, Args, Triple); + if (!CPU.empty()) { + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(Args.MakeArgString(CPU)); + } + + // Add the target features. + switch (TC.getArch()) { + default: + break; + case llvm::Triple::aarch64: + [[fallthrough]]; + case llvm::Triple::x86_64: + getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); + break; + } + + // TODO: Add target specific flags, ABI, mtune option etc. +} + static void addFloatingPointOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) { StringRef FPContract; @@ -243,6 +269,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, // Floating point related options addFloatingPointOptions(D, Args, CmdArgs); + // Add target args, features, etc. + addTargetOptions(Args, CmdArgs); + // Add other compile options addOtherOptions(Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h index de72ac3601f96..4c85c602e2673 100644 --- a/clang/lib/Driver/ToolChains/Flang.h +++ b/clang/lib/Driver/ToolChains/Flang.h @@ -48,6 +48,14 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool { void addPicOptions(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// Extract target options from the driver arguments and add them to + /// the command arguments. + /// + /// \param [in] Args The list of input driver arguments + /// \param [out] CmdArgs The list of output command arguments + void addTargetOptions(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; + /// Extract other compilation options from the driver arguments and add them /// to the command arguments. /// diff --git a/flang/include/flang/Frontend/TargetOptions.h b/flang/include/flang/Frontend/TargetOptions.h index 84371be23d665..170509fac8995 100644 --- a/flang/include/flang/Frontend/TargetOptions.h +++ b/flang/include/flang/Frontend/TargetOptions.h @@ -22,18 +22,18 @@ namespace Fortran::frontend { -/// Options for controlling the target. Currently this is just a placeholder. -/// In the future, we will use this to specify various target options that -/// will affect the generated code e.g.: -/// * CPU to tune the code for -/// * available CPU/hardware extensions -/// * target specific features to enable/disable -/// * options for accelerators (e.g. GPUs) -/// * (...) +/// Options for controlling the target. class TargetOptions { public: /// The name of the target triple to compile for. std::string triple; + + /// If given, the name of the target CPU to generate code for. + std::string cpu; + + /// The list of target specific features to enable or disable, as written on + /// the command line. + std::vector<std::string> featuresAsWritten; }; } // end namespace Fortran::frontend diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index b8f4ad7326428..e24d816383808 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -171,6 +171,14 @@ static void parseTargetArgs(TargetOptions &opts, llvm::opt::ArgList &args) { if (const llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_triple)) opts.triple = a->getValue(); + + if (const llvm::opt::Arg *a = + args.getLastArg(clang::driver::options::OPT_target_cpu)) + opts.cpu = a->getValue(); + + for (const llvm::opt::Arg *currentArg : + args.filtered(clang::driver::options::OPT_target_feature)) + opts.featuresAsWritten.emplace_back(currentArg->getValue()); } // Tweak the frontend configuration based on the frontend action diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 990cb76f6915c..82d472dd8fd2f 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -591,7 +591,8 @@ getCGOptLevel(const Fortran::frontend::CodeGenOptions &opts) { void CodeGenAction::setUpTargetMachine() { CompilerInstance &ci = this->getInstance(); - const std::string &theTriple = ci.getInvocation().getTargetOpts().triple; + const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts(); + const std::string &theTriple = targetOpts.triple; // Create `Target` std::string error; @@ -602,9 +603,11 @@ void CodeGenAction::setUpTargetMachine() { // Create `TargetMachine` const auto &CGOpts = ci.getInvocation().getCodeGenOpts(); llvm::CodeGenOpt::Level OptLevel = getCGOptLevel(CGOpts); + std::string featuresStr = llvm::join(targetOpts.featuresAsWritten.begin(), + targetOpts.featuresAsWritten.end(), ","); tm.reset(theTarget->createTargetMachine( - theTriple, /*CPU=*/"", - /*Features=*/"", llvm::TargetOptions(), + theTriple, /*CPU=*/targetOpts.cpu, + /*Features=*/featuresStr, llvm::TargetOptions(), /*Reloc::Model=*/CGOpts.getRelocationModel(), /*CodeModel::Model=*/llvm::None, OptLevel)); assert(tm && "Failed to create TargetMachine"); diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index 4f04b85440399..d54ed7b288bc5 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -156,6 +156,8 @@ ! HELP-FC1-NEXT: -P Disable linemarker output in -E mode ! HELP-FC1-NEXT: -std=<value> Language standard to compile for ! HELP-FC1-NEXT: -S Only run preprocess and compilation steps +! HELP-FC1-NEXT: -target-cpu <value> Target a specific cpu type +! HELP-FC1-NEXT: -target-feature <value> Target specific attributes ! HELP-FC1-NEXT: -test-io Run the InputOuputTest action. Use for development and testing only. ! HELP-FC1-NEXT: -triple <value> Specify target triple (e.g. i686-apple-darwin9) ! HELP-FC1-NEXT: -U <macro> Undefine macro <macro> diff --git a/flang/test/Driver/target-cpu-features.f90 b/flang/test/Driver/target-cpu-features.f90 new file mode 100644 index 0000000000000..985a13de75952 --- /dev/null +++ b/flang/test/Driver/target-cpu-features.f90 @@ -0,0 +1,56 @@ +! REQUIRES: aarch64-registered-target, x86-registered-target + +! Test that -mcpu/march are used and that the -target-cpu and -target-features +! are also added to the fc1 command. + +! RUN: %flang --target=aarch64-linux-gnu -mcpu=cortex-a57 -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-A57 + +! RUN: %flang --target=aarch64-linux-gnu -mcpu=cortex-a76 -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-A76 + +! RUN: %flang --target=aarch64-linux-gnu -march=armv9 -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-ARMV9 + +! Negative test. ARM cpu with x86 target. +! RUN: %flang --target=x86_64-linux-gnu -mcpu=cortex-a57 -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-NO-A57 + +! RUN: %flang --target=x86_64-linux-gnu -march=skylake -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-SKYLAKE + +! RUN: %flang --target=x86_64h-linux-gnu -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-X86_64H + + +! Test that invalid cpu and features are ignored. + +! RUN: %flang_fc1 -triple aarch64-linux-gnu -target-cpu supercpu \ +! RUN: -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-CPU + +! RUN: %flang_fc1 -triple aarch64-linux-gnu -target-feature +superspeed \ +! RUN: -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FEATURE + + +! CHECK-A57: "-fc1" "-triple" "aarch64-unknown-linux-gnu" +! CHECK-A57-SAME: "-target-cpu" "cortex-a57" "-target-feature" "+v8a" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+sha2" "-target-feature" "+aes" + +! CHECK-A76: "-fc1" "-triple" "aarch64-unknown-linux-gnu" +! CHECK-A76-SAME: "-target-cpu" "cortex-a76" "-target-feature" "+v8.2a" "-target-feature" "+crc" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+crypto" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+ssbs" "-target-feature" "+sha2" "-target-feature" "+aes" + +! CHECK-ARMV9: "-fc1" "-triple" "aarch64-unknown-linux-gnu" +! CHECK-ARMV9-SAME: "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9a" "-target-feature" "+sve" "-target-feature" "+sve2" + +! CHECK-NO-A57: "-fc1" "-triple" "x86_64-unknown-linux-gnu" +! CHECK-NO-A57-NOT: cortex-a57 +! CHECK-NO-A57-SAME: "-target-cpu" "x86-64" +! CHECK-NO-A57-NOT: cortex-a57 + +! CHECK-SKYLAKE: "-fc1" "-triple" "x86_64-unknown-linux-gnu" +! CHECK-SKYLAKE-SAME: "-target-cpu" "skylake" + +! CHECK-X86_64H: "-fc1" "-triple" "x86_64h-unknown-linux-gnu" +! CHECK-X86_64H-SAME: "-target-cpu" "x86-64" "-target-feature" "-rdrnd" "-target-feature" "-aes" "-target-feature" "-pclmul" "-target-feature" "-rtm" "-target-feature" "-fsgsbase" + +! CHECK-INVALID-CPU: 'supercpu' is not a recognized processor for this target (ignoring processor) +! CHECK-INVALID-FEATURE: '+superspeed' is not a recognized feature for this target (ignoring feature) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits