Skip to content

[flang][Driver] Support -print-supported-cpus and associated aliases #117199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 22, 2024

Conversation

tarunprabhu
Copy link
Contributor

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' flang:driver flang Flang issues not falling into any other category labels Nov 21, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2024

@llvm/pr-subscribers-flang-driver

@llvm/pr-subscribers-clang-driver

Author: Tarun Prabhu (tarunprabhu)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/117199.diff

8 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+5-3)
  • (modified) clang/lib/Driver/Driver.cpp (+4-3)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+15-3)
  • (modified) flang/include/flang/Frontend/FrontendOptions.h (+5-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2)
  • (added) flang/test/Driver/print-supported-cpus-aarch64.f90 (+23)
  • (added) flang/test/Driver/print-supported-cpus-x86.f90 (+22)
  • (modified) flang/tools/flang-driver/fc1_main.cpp (+24)
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)

@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2024

@llvm/pr-subscribers-clang

Author: Tarun Prabhu (tarunprabhu)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/117199.diff

8 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+5-3)
  • (modified) clang/lib/Driver/Driver.cpp (+4-3)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+15-3)
  • (modified) flang/include/flang/Frontend/FrontendOptions.h (+5-1)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+2)
  • (added) flang/test/Driver/print-supported-cpus-aarch64.f90 (+23)
  • (added) flang/test/Driver/print-supported-cpus-x86.f90 (+22)
  • (modified) flang/tools/flang-driver/fc1_main.cpp (+24)
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)

@banach-space
Copy link
Contributor

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.

Wouldn't something like this work:

! RUN: %if aarch64-registered-target %{ %flang_fc1 -emit-fir -triple aarch64-unknown-linux-gnu -target-cpu aarch64 %s -o - | FileCheck %s --check-prefixes=ALL,ARMCPU %}
! RUN: %if aarch64-registered-target %{ %flang_fc1 -emit-fir -triple aarch64-unknown-linux-gnu -tune-cpu neoverse-n1 %s -o - | FileCheck %s --check-prefixes=ALL,ARMTUNE %}
! RUN: %if aarch64-registered-target %{ %flang_fc1 -emit-fir -triple aarch64-unknown-linux-gnu -target-cpu aarch64 -tune-cpu neoverse-n1 %s -o - | FileCheck %s --check-prefixes=ALL,ARMBOTH %}

?

Copy link
Contributor

@banach-space banach-space left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, makes sense. From what I can tell, the behaviour is consistent with Clang (i.e. -print-supported-cpus invalidates any other action flags).

Just a couple of smallish comments/suggestions

Comment on lines 5902 to 5905
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]>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to extract these to some documented block, similar to

//===----------------------------------------------------------------------===//
// Optimisation remark options
//===----------------------------------------------------------------------===//
let Visibility = [ClangOption, CC1Option, FC1Option, FlangOption] in {
def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>,
HelpText<"Report transformations performed by optimization passes whose "
"name matches the given POSIX regular expression">;
def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group<R_value_Group>,
HelpText<"Report missed transformations by optimization passes whose "
"name matches the given POSIX regular expression">;
def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_value_Group>,
HelpText<"Report transformation analysis from optimization passes whose "
"name matches the given POSIX regular expression">;
def R_Joined : Joined<["-"], "R">, Group<R_Group>,
Visibility<[ClangOption, CLOption, DXCOption]>,
MetaVarName<"<remark>">, HelpText<"Enable the specified remark">;
} // let Visibility = [ClangOption, CC1Option, FC1Option, FlangOption]
.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea. I have moved the options into such a block. I have begun adding support for -print-supported-extensions and -print-enabled-extensions as well which can eventually be added to the block.

Comment on lines +4420 to +4421
Action *InputAc = C.MakeAction<InputAction>(
*A, IsFlangMode() ? types::TY_Fortran : types::TY_C);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually needed.

The -mcpu=help argument is used as a "dummy input" (there is a comment a few lines above that says as much).
The input action created here eventually gets used in ShouldUseFlangCompiler which checks if the input type is accepted by flang. flang does not accept inputs of type TY_C (even if they are "dummies"). If ShouldUseFlangCompiler returns false, a cc1 command line is created - which is, obviously, not correct.

@tarunprabhu
Copy link
Contributor Author

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.

Wouldn't something like this work:

Ah! I keep forgetting that that is now possible. Updated the tests to do that.

Copy link
Contributor

@banach-space banach-space left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, my final comment is nit - feel free to ignore. Thanks!

Comment on lines 39 to 41
! 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] I would add that bit with clang invocation. Once this is fixed, the test will fail and we will know that we don't need to write a new test (sometimes less is more)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I added that to the test and updated the comment. It will fail when llvm/MCSubtargetInfo is fixed.

Tarun Prabhu added 5 commits November 22, 2024 09:11
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 llvm#117010
- Move the options into a commented block. The -print-supported-extensions and
  related options can be moved into this block in a future PR.

- Combine the tests for the different architectures into a single file.
…xed so it

does not always print clang in the footer of the output.
@tarunprabhu tarunprabhu force-pushed the support-print-supported-cpus branch from 194a31a to 7a12ecc Compare November 22, 2024 17:41
@tarunprabhu tarunprabhu merged commit 23d7a6c into llvm:main Nov 22, 2024
8 checks passed
@tarunprabhu tarunprabhu deleted the support-print-supported-cpus branch November 22, 2024 18:57
@jplehr
Copy link
Contributor

jplehr commented Nov 25, 2024

I believe this results in tests failures on our bot: https://lab.llvm.org/staging/#/builders/105/builds/9796 (and a few others)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category flang:driver flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[flang] -mcpu=help does not work with flang
5 participants