Skip to content

Conversation

mcinally
Copy link
Contributor

Support -mcpu=native by querying the Host CPU Name.

Support -mcpu=native by querying the Host CPU Name.
@mcinally mcinally self-assigned this Sep 17, 2025
@mcinally mcinally added the mc label Sep 17, 2025
@llvmbot llvmbot added the llvm:mc Machine (object) code label Sep 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 17, 2025

@llvm/pr-subscribers-llvm-mc

Author: Cameron McInally (mcinally)

Changes

Support -mcpu=native by querying the Host CPU Name.


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

2 Files Affected:

  • (added) llvm/test/MC/AsmParser/native.s (+3)
  • (modified) llvm/tools/llvm-mc/llvm-mc.cpp (+4)
diff --git a/llvm/test/MC/AsmParser/native.s b/llvm/test/MC/AsmParser/native.s
new file mode 100644
index 0000000000000..b5228dfd77396
--- /dev/null
+++ b/llvm/test/MC/AsmParser/native.s
@@ -0,0 +1,3 @@
+# RUN: llvm-mc -filetype=obj -mcpu=native %s 2>&1 | FileCheck %s
+
+# CHECK-NOT: 'native' is not a recognized processor for this target (ignoring processor)
diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp
index 136cd69526a3c..cb38a04f249e1 100644
--- a/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -467,6 +467,10 @@ int main(int argc, char **argv) {
     FeaturesStr = Features.getString();
   }
 
+  // Replace -mcpu=native with Host CPU.
+  if (MCPU == "native")
+    MCPU = std::string(llvm::sys::getHostCPUName());
+
   std::unique_ptr<MCSubtargetInfo> STI(
       TheTarget->createMCSubtargetInfo(TheTriple, MCPU, FeaturesStr));
   assert(STI && "Unable to create subtarget info!");

// Replace -mcpu=native with Host CPU.
if (MCPU == "native")
MCPU = std::string(llvm::sys::getHostCPUName());

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need to pass call getHostCPUFeatures too and pass that information to MAttr?

I know on X86, getHostCPUName can return "haswell" on Pentium CPUs that don't support AVX2, but use the haswell microarchitecture. "haswell" implies AVX2. getHostCPUFeatures will return -avx2 for these CPUs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, that's a good point.

It doesn't look like X86 supports -mcpu= in Clang.

I do see that -march= is supported, but Clang just maps to llvm::sys::getHostCPUName(), like this patch, but with the obvious FIXME.

clang/lib/Driver/ToolChains/Arch/X86.cpp:

std::string x86::getX86TargetCPU(const Driver &D, const ArgList &Args,
                                 const llvm::Triple &Triple) {
  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
    StringRef CPU = A->getValue();
    if (CPU != "native")
      return std::string(CPU);

    // FIXME: Reject attempts to use -march=native unless the target matches
    // the host.
    CPU = llvm::sys::getHostCPUName();
    if (!CPU.empty() && CPU != "generic")
      return std::string(CPU);

I don't have a strong opinion here, but do have a strong opinion that MC needs to support -mcpu=native in some way. So whatever you suggest is fine with me.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Clang does use getHostCPUFeatures with -mcpu=native. I wrote the code originally. It's here.

void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,      
                               const ArgList &Args,                              
                               std::vector<StringRef> &Features) {               
  // Claim and report unsupported -mabi=. Note: we don't support "sysv_abi" or   
  // "ms_abi" as default function attributes.                                    
  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mabi_EQ)) {     
    StringRef DefaultAbi =                                                       
        (Triple.isOSWindows() || Triple.isUEFI()) ? "ms" : "sysv";               
    if (A->getValue() != DefaultAbi)                                             
      D.Diag(diag::err_drv_unsupported_opt_for_target)                           
          << A->getSpelling() << Triple.getTriple();                             
  }                                                                              
                                                                                 
  // If -march=native, autodetect the feature list.                              
  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {    
    if (StringRef(A->getValue()) == "native") {                                  
      for (auto &F : llvm::sys::getHostCPUFeatures())                            
        Features.push_back(                                                      
            Args.MakeArgString((F.second ? "+" : "-") + F.first()));             
    }                                                                            
  }  

Copy link
Collaborator

Choose a reason for hiding this comment

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

I do see that -march= is supported, but Clang just maps to llvm::sys::getHostCPUName(), like this patch, but with the obvious FIXME.

I think that fixme is maybe saying we shouldn't call getHostCPU if you explicitly pass --target=x86_64 on a non-x86 machine?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Clang does use getHostCPUFeatures with -mcpu=native. I wrote the code originally. It's here.

That's -march now. Maybe changed when -mcpu was deprecated on X86.

$ clang test.c -mcpu=native
clang: error: unsupported option '-mcpu=' for target 'x86_64-unknown-linux-gnu'

Copy link
Collaborator

Choose a reason for hiding this comment

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

Clang does use getHostCPUFeatures with -mcpu=native. I wrote the code originally. It's here.

That's -march now. Maybe changed when -mcpu was deprecated on X86.

$ clang test.c -mcpu=native
clang: error: unsupported option '-mcpu=' for target 'x86_64-unknown-linux-gnu'

Sorry I meant -march=native. For all intents and purpose -march on X86 is -mcpu. I've been on RISC-V for too long now so I my brain thinks -mcpu.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Latest patch addresses this. I think it's best to allow the command line -mattr's to override the default with native, but I don't feel strongly about it. Thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Latest patch addresses this. I think it's best to allow the command line -mattr's to override the default with native, but I don't feel strongly about it. Thoughts?

I agree.

@@ -0,0 +1,3 @@
# RUN: llvm-mc -filetype=obj -mcpu=native %s 2>&1 | FileCheck %s

# CHECK-NOT: 'native' is not a recognized processor for this target (ignoring processor)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is too specific for a not check. Better to verify the output is empty

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like FileCheck doesn't like an empty input file (really stderr piped to stdout):

FileCheck error: '<stdin>' is empty.

I could make the CHECK-NOT more narrow. Maybe something like:

# CHECK-NOT: native

Does that seem acceptable, @arsenm?

Copy link
Contributor

Choose a reason for hiding this comment

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

I know there's some trick to do this. I ran into this recently but forget what I did

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess checking native works though

Copy link
Contributor

Choose a reason for hiding this comment

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

--allow-empty

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in latest patch.

Also update negative check to look for no stderr output.
Copy link

github-actions bot commented Sep 18, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

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

LGTM

@mcinally mcinally merged commit 8009a5b into llvm:main Sep 19, 2025
9 checks passed
mcinally pushed a commit to mcinally/llvm-project that referenced this pull request Sep 19, 2025
llvm::sys::getHostCPUName() and llvm::sys::getHostCPUFeatures() appear to need
special cases for _WIN32 on X86 (similar to the existing _WIN32 on ARM special
cases) to restrict what CPUs and Features are available with that OS.

For now, limit this test to Linux systems only, as this test does not check
very much being that it is sensitve to the Host machine.

Originally llvm#159414.
@s-barannikov
Copy link
Contributor

s-barannikov commented Sep 19, 2025

I started seeing this error on a downstream CI:

# executed command: <...>/build/bin/FileCheck --allow-empty <...>/llvm/test/MC/AsmParser/native.s
# .---command stderr------------
# | <...>/llvm/test/MC/AsmParser/native.s:4:14: error: CHECK-NOT: excluded string found in input
# | # CHECK-NOT: {{.+}}
# |              ^
# | <stdin>:1:1: note: found here
# | 'cascadelake' is not a recognized processor for this target (ignoring processor)
# | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | 

My downstream target is not X86, so -mcpu=native can't work.
#159838 doesn't help with the issue since the CI is run on X86 Linux machine.
I have LLVM_DEFAULT_TARGET_TRIPLE set to my target triple and both my target and X86 in LLVM_TARGETS_TO_BUILD, if that matters.

@mcinally
Copy link
Contributor Author

My downstream target is not X86, so -mcpu=native can't work. #159838 doesn't help with the issue since the CI is run on X86 Linux machine. I have LLVM_DEFAULT_TARGET_TRIPLE set to my target triple and both my target and X86 in LLVM_TARGETS_TO_BUILD, if that matters.

Please help me understand what you're seeing. So you're cross-compiling for your target on a cascade lake Linux machine?

Could we check TripleName != sys::getDefaultTargetTriple() to determine if this is a cross-compile? Would that solve your problem?

@mcinally
Copy link
Contributor Author

The thinking there is that if we're cross-compiling, then we shouldn't be using -mcpu=native anyway.

@s-barannikov
Copy link
Contributor

s-barannikov commented Sep 19, 2025

Please help me understand what you're seeing. So you're cross-compiling for your target on a cascade lake Linux machine?

That's correct. I'm building a toolchain on an x86 machine, that will run on an x86 machine, and that will target a non-x86 architecture by default (unless overridden by clang --target or llvm-mc -triple).

Could we check TripleName != sys::getDefaultTargetTriple() to determine if this is a cross-compile? Would that solve your problem?

I'm not sure. What is TripleName here? I don't see this variable in the changes.

I don't think there is generic solution and we will have to specialize the test for some target(s). E.g.,

# REQUIRES: aarch64-registered-target
# RUN: llvm-mc -triple=aarch64 -mcpu=native ...

@s-barannikov
Copy link
Contributor

The thinking there is that if we're cross-compiling, then we shouldn't be using -mcpu=native anyway.

Yes, but that's what the test currently does :)

@mcinally
Copy link
Contributor Author

I don't think there is generic solution and we will have to specialize the test for some target(s). E.g.,

Yup, let's do that. I notice that Clang does similar for a -mcpu=native test. Patch incoming. I will add you as a reviewer.

mcinally pushed a commit to mcinally/llvm-project that referenced this pull request Sep 19, 2025
It's not possible to use `-mcpu=native` when the Target's Triple doesn't match
the Host's. Move this test to the AArch64 directory so that it isn't run while
cross-compiling.

Originally llvm#159414
mcinally added a commit that referenced this pull request Sep 20, 2025
It's not possible to use `-mcpu=native` when the Target's Triple doesn't
match the Host's. Move this test to the X86 directory so that it isn't
run while cross-compiling.

Originally #159414

---------

Co-authored-by: Cameron McInally <cmcinally@nvidia.com>
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 20, 2025

LLVM Buildbot has detected a new failure on builder llvm-nvptx-nvidia-ubuntu running on as-builder-7 while building llvm at step 6 "test-build-unified-tree-check-llvm".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/180/builds/25367

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-llvm) failure: test (failure)
******************** TEST 'LLVM :: MC/AsmParser/native.s' FAILED ********************
Exit Code: -11

Command Output (stdout):
--
# RUN: at line 1
/home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/build/bin/llvm-mc -filetype=obj -o /home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp -mcpu=native /home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/llvm-project/llvm/test/MC/AsmParser/native.s 2> /home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp.stderr
# executed command: /home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/build/bin/llvm-mc -filetype=obj -o /home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp -mcpu=native /home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/llvm-project/llvm/test/MC/AsmParser/native.s
# .---redirected output from '/home/buildbot/worker/as-builder-7/llvm-nvptx-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp.stderr'
# | 'icelake-server' is not a recognized processor for this target (ignoring processor)
# | '+prfchw' is not a recognized feature for this target (ignoring feature)
# | '-cldemote' is not a recognized feature for this target (ignoring feature)
# | '+avx' is not a recognized feature for this target (ignoring feature)
# | '+aes' is not a recognized feature for this target (ignoring feature)
# | '+sahf' is not a recognized feature for this target (ignoring feature)
# | '+pclmul' is not a recognized feature for this target (ignoring feature)
# | '-xop' is not a recognized feature for this target (ignoring feature)
# | '+crc32' is not a recognized feature for this target (ignoring feature)
# | '-amx-fp8' is not a recognized feature for this target (ignoring feature)
# | '+xsaves' is not a recognized feature for this target (ignoring feature)
# | '-avx512fp16' is not a recognized feature for this target (ignoring feature)
# | '-usermsr' is not a recognized feature for this target (ignoring feature)
# | '-sm4' is not a recognized feature for this target (ignoring feature
# | ...
# `---data was truncated--------
# note: command had no output on stdout or stderr
# error: command failed with exit status: -11

--

********************


@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 20, 2025

LLVM Buildbot has detected a new failure on builder llvm-nvptx64-nvidia-ubuntu running on as-builder-7 while building llvm at step 6 "test-build-unified-tree-check-llvm".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/160/builds/25227

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-llvm) failure: test (failure)
******************** TEST 'LLVM :: MC/AsmParser/native.s' FAILED ********************
Exit Code: -11

Command Output (stdout):
--
# RUN: at line 1
/home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/build/bin/llvm-mc -filetype=obj -o /home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp -mcpu=native /home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/llvm-project/llvm/test/MC/AsmParser/native.s 2> /home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp.stderr
# executed command: /home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/build/bin/llvm-mc -filetype=obj -o /home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp -mcpu=native /home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/llvm-project/llvm/test/MC/AsmParser/native.s
# .---redirected output from '/home/buildbot/worker/as-builder-7/llvm-nvptx64-nvidia-ubuntu/build/test/MC/AsmParser/Output/native.s.tmp.stderr'
# | 'icelake-server' is not a recognized processor for this target (ignoring processor)
# | '+prfchw' is not a recognized feature for this target (ignoring feature)
# | '-cldemote' is not a recognized feature for this target (ignoring feature)
# | '+avx' is not a recognized feature for this target (ignoring feature)
# | '+aes' is not a recognized feature for this target (ignoring feature)
# | '+sahf' is not a recognized feature for this target (ignoring feature)
# | '+pclmul' is not a recognized feature for this target (ignoring feature)
# | '-xop' is not a recognized feature for this target (ignoring feature)
# | '+crc32' is not a recognized feature for this target (ignoring feature)
# | '-amx-fp8' is not a recognized feature for this target (ignoring feature)
# | '+xsaves' is not a recognized feature for this target (ignoring feature)
# | '-avx512fp16' is not a recognized feature for this target (ignoring feature)
# | '-usermsr' is not a recognized feature for this target (ignoring feature)
# | '-sm4' is not a recognized feature for this target (ignoring feature
# | ...
# `---data was truncated--------
# note: command had no output on stdout or stderr
# error: command failed with exit status: -11

--

********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:mc Machine (object) code mc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants