[clang] [flang] [flang][Driver] Support -print-supported-cpus and associated aliases (PR #117199)

Tarun Prabhu via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 21 09:47:49 PST 2024


https://github.com/tarunprabhu created https://github.com/llvm/llvm-project/pull/117199

The aliases are -mcpu=help and -mtune=help. There is still an issue with the output which prints an example line that references clang. That is not fixed here because it is printed in llvm/MC/SubtargetInfo.cpp. Some more thought is needed to determine how best to handle this.

Fixes #117010

----------------------
Notes for reviewers: The corresponding test in `clang/test/Driver/print-supported-cpus.c` tests two different architectures in the same file. This has been split into two separate tests here to allow the test to be run in cases where only one of the targets has been built.

>From a7d176ed8c7aa9d22944600a301fb690b845935d Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun.prabhu at gmail.com>
Date: Thu, 21 Nov 2024 09:53:49 -0700
Subject: [PATCH] [flang][Driver] Support -print-supported-cpus and associated
 aliases

The aliases are -mcpu=help and -mtune=help. There is still an issue with the
output which prints an example line that references clang. That is not fixed
here because it is printed in llvm/MC/SubtargetInfo.cpp. Some more thought is
needed to determine how best to handle this.

Fixes #117010
---
 clang/include/clang/Driver/Options.td         |  8 ++++---
 clang/lib/Driver/Driver.cpp                   |  7 +++---
 clang/lib/Driver/ToolChains/Flang.cpp         | 18 +++++++++++---
 .../include/flang/Frontend/FrontendOptions.h  |  6 ++++-
 flang/lib/Frontend/CompilerInvocation.cpp     |  2 ++
 .../Driver/print-supported-cpus-aarch64.f90   | 23 ++++++++++++++++++
 .../test/Driver/print-supported-cpus-x86.f90  | 22 +++++++++++++++++
 flang/tools/flang-driver/fc1_main.cpp         | 24 +++++++++++++++++++
 8 files changed, 100 insertions(+), 10 deletions(-)
 create mode 100644 flang/test/Driver/print-supported-cpus-aarch64.f90
 create mode 100644 flang/test/Driver/print-supported-cpus-x86.f90

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 5167c3c39e315a..9850bdf459fbe5 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5886,7 +5886,7 @@ def darwin_target_variant : Separate<["-"], "darwin-target-variant">,
   HelpText<"Generate code for an additional runtime variant of the deployment target">;
 def print_supported_cpus : Flag<["-", "--"], "print-supported-cpus">,
   Group<CompileOnly_Group>,
-  Visibility<[ClangOption, CC1Option, CLOption]>,
+  Visibility<[ClangOption, CC1Option, CLOption, FlangOption, FC1Option]>,
   HelpText<"Print supported cpu models for the given target (if target is not specified,"
            " it will print the supported cpus for the default target)">,
   MarshallingInfoFlag<FrontendOpts<"PrintSupportedCPUs">>;
@@ -5899,8 +5899,10 @@ def print_enabled_extensions : Flag<["-", "--"], "print-enabled-extensions">,
   HelpText<"Print the extensions enabled by the given target and -march/-mcpu options."
            " (AArch64 and RISC-V only)">,
   MarshallingInfoFlag<FrontendOpts<"PrintEnabledExtensions">>;
-def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>;
-def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>;
+def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>,
+  Visibility<[ClangOption, CC1Option, CLOption, FlangOption, FC1Option]>;
+def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>,
+  Visibility<[ClangOption, CC1Option, CLOption, FlangOption, FC1Option]>;
 def time : Flag<["-"], "time">,
   HelpText<"Time individual commands">;
 def traditional_cpp : Flag<["-", "--"], "traditional-cpp">,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a0f4329e36136b..ad14b5c9b6dc80 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -4417,7 +4417,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
 
       // Use the -mcpu=? flag as the dummy input to cc1.
       Actions.clear();
-      Action *InputAc = C.MakeAction<InputAction>(*A, types::TY_C);
+      Action *InputAc = C.MakeAction<InputAction>(
+          *A, IsFlangMode() ? types::TY_Fortran : types::TY_C);
       Actions.push_back(
           C.MakeAction<PrecompileJobAction>(InputAc, types::TY_Nothing));
       for (auto &I : Inputs)
@@ -6621,8 +6622,8 @@ bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
     return false;
 
   // And say "no" if this is not a kind of action flang understands.
-  if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) &&
-      !isa<BackendJobAction>(JA))
+  if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
+      !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
     return false;
 
   return true;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 11070c23c75f4a..8db7c4aa5ebe93 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -747,6 +747,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   } else if (isa<AssembleJobAction>(JA)) {
     CmdArgs.push_back("-emit-obj");
+  } else if (isa<PrecompileJobAction>(JA)) {
+    // The Precompile job action is only needed for options such as -mcpu=help.
+    // Those will already have been handled by the fc1 driver.
   } else {
     assert(false && "Unexpected action class for Flang tool.");
   }
@@ -911,8 +914,6 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(Output.getFilename());
   }
 
-  assert(Input.isFilename() && "Invalid input.");
-
   if (Args.getLastArg(options::OPT_save_temps_EQ))
     Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
 
@@ -932,7 +933,18 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  CmdArgs.push_back(Input.getFilename());
+  // The input could be Ty_Nothing when "querying" options such as -mcpu=help
+  // are used.
+  ArrayRef<InputInfo> FrontendInputs = Input;
+  if (Input.isNothing())
+    FrontendInputs = {};
+
+  for (const InputInfo &Input : FrontendInputs) {
+    if (Input.isFilename())
+      CmdArgs.push_back(Input.getFilename());
+    else
+      Input.getInputArg().renderAsInput(Args, CmdArgs);
+  }
 
   const char *Exec = Args.MakeArgString(D.GetProgramPath("flang", TC));
   C.addCommand(std::make_unique<Command>(JA, *this,
diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index 82ca99672ec610..a48234d79ad2f5 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -236,7 +236,8 @@ class FrontendInputFile {
 struct FrontendOptions {
   FrontendOptions()
       : showHelp(false), showVersion(false), instrumentedParse(false),
-        showColors(false), needProvenanceRangeToCharBlockMappings(false) {}
+        showColors(false), printSupportedCPUs(false),
+        needProvenanceRangeToCharBlockMappings(false) {}
 
   /// Show the -help text.
   unsigned showHelp : 1;
@@ -250,6 +251,9 @@ struct FrontendOptions {
   /// Enable color diagnostics.
   unsigned showColors : 1;
 
+  /// print the supported cpus for the current target
+  unsigned printSupportedCPUs : 1;
+
   /// Enable Provenance to character-stream mapping. Allows e.g. IDEs to find
   /// symbols based on source-code location. This is not needed in regular
   /// compilation.
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 1214a2ea6bf1f3..0b79c95eade0d3 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -634,6 +634,8 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
   opts.outputFile = args.getLastArgValue(clang::driver::options::OPT_o);
   opts.showHelp = args.hasArg(clang::driver::options::OPT_help);
   opts.showVersion = args.hasArg(clang::driver::options::OPT_version);
+  opts.printSupportedCPUs =
+      args.hasArg(clang::driver::options::OPT_print_supported_cpus);
 
   // Get the input kind (from the value passed via `-x`)
   InputKind dashX(Language::Unknown);
diff --git a/flang/test/Driver/print-supported-cpus-aarch64.f90 b/flang/test/Driver/print-supported-cpus-aarch64.f90
new file mode 100644
index 00000000000000..284440d6d0f4df
--- /dev/null
+++ b/flang/test/Driver/print-supported-cpus-aarch64.f90
@@ -0,0 +1,23 @@
+! Test --print-supported-cpus and associated aliases, -mcpu=help and
+! -mtune=help on AArch64.
+
+! REQUIRES: aarch64-registered-target
+
+! RUN: %flang --target=aarch64-unknown-linux-gnu --print-supported-cpus 2>&1 | \
+! RUN:   FileCheck %s
+! RUN: %flang --target=aarch64-unknown-linux-gnu -mcpu=help 2>&1 | \
+! RUN:   FileCheck %s
+! RUN: %flang --target=aarch64-unknown-linux-gnu -mtune=help 2>&1 | \
+! RUN:   FileCheck %s
+
+! CHECK-NOT: warning: argument unused during compilation
+
+! CHECK: Target: aarch64-unknown-linux-gnu
+! CHECK: cortex-a73
+! CHECK: cortex-a75
+
+! TODO: This is a line that is printed at the end of the output. The full line
+! also includes an example that references clang. That needs to be fixed and a
+! a check added here to make sure that it references flang, not clang.
+
+! CHECK: Use -mcpu or -mtune to specify the target's processor.
diff --git a/flang/test/Driver/print-supported-cpus-x86.f90 b/flang/test/Driver/print-supported-cpus-x86.f90
new file mode 100644
index 00000000000000..ad0e25ea15c7c8
--- /dev/null
+++ b/flang/test/Driver/print-supported-cpus-x86.f90
@@ -0,0 +1,22 @@
+! Test --print-supported-cpus and associated aliases, -mcpu=help and
+! -mtune=help on X86.
+
+! REQUIRES: x86-registered-target
+
+! RUN: %flang --target=x86_64-unknown-linux-gnu --print-supported-cpus 2>&1 | \
+! RUN:   FileCheck %s
+! RUN: %flang --target=x86_64-unknown-linux-gnu -mcpu=help 2>&1 | \
+! RUN:   FileCheck %s
+! RUN: %flang --target=x86_64-unknown-linux-gnu -mtune=help 2>&1 | \
+! RUN:   FileCheck %s
+
+! CHECK-NOT: warning: argument unused during compilation
+
+! CHECK: Target: x86_64-unknown-linux-gnu
+! CHECK: corei7
+
+! TODO: This is a line that is printed at the end of the output. The full line
+! also includes an example that references clang. That needs to be fixed and a
+! a check added here to make sure that it references flang, not clang.
+
+! CHECK: Use -mcpu or -mtune to specify the target's processor.
diff --git a/flang/tools/flang-driver/fc1_main.cpp b/flang/tools/flang-driver/fc1_main.cpp
index b5b062aaac2671..561a0dd5524e37 100644
--- a/flang/tools/flang-driver/fc1_main.cpp
+++ b/flang/tools/flang-driver/fc1_main.cpp
@@ -21,15 +21,35 @@
 #include "flang/Frontend/TextDiagnosticBuffer.h"
 #include "flang/FrontendTool/Utils.h"
 #include "clang/Driver/DriverDiagnostic.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
 
 #include <cstdio>
 
 using namespace Fortran::frontend;
 
+/// Print supported cpus of the given target.
+static int printSupportedCPUs(llvm::StringRef triple) {
+  std::string error;
+  const llvm::Target *target =
+      llvm::TargetRegistry::lookupTarget(triple, error);
+  if (!target) {
+    llvm::errs() << error;
+    return 1;
+  }
+
+  // the target machine will handle the mcpu printing
+  llvm::TargetOptions targetOpts;
+  std::unique_ptr<llvm::TargetMachine> targetMachine(
+      target->createTargetMachine(triple, "", "+cpuhelp", targetOpts,
+                                  std::nullopt));
+  return 0;
+}
+
 int fc1_main(llvm::ArrayRef<const char *> argv, const char *argv0) {
   // Create CompilerInstance
   std::unique_ptr<CompilerInstance> flang(new CompilerInstance());
@@ -58,6 +78,10 @@ int fc1_main(llvm::ArrayRef<const char *> argv, const char *argv0) {
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllAsmPrinters();
 
+  // --print-supported-cpus takes priority over the actual compilation.
+  if (flang->getFrontendOpts().printSupportedCPUs)
+    return printSupportedCPUs(flang->getInvocation().getTargetOpts().triple);
+
   diagsBuffer->flushDiagnostics(flang->getDiagnostics());
 
   if (!success)



More information about the cfe-commits mailing list