This is an archive of the discontinued LLVM Phabricator instance.

[Driver][RISCV] Adjust the priority between -mcpu, -mtune and -march
ClosedPublic

Authored by kito-cheng on Dec 27 2022, 6:02 AM.

Details

Summary

RISC-V supports -march, -mtune, and -mcpu: -march provides the
architecture extension information, -mtune provide the pipeline model, and
-mcpu provides both.

What's the priority among those options for now(w/o this patch)?

Pipeline model:

  • Take from -mtune if present.
  • Take from -mcpu if present
  • Use the default pipeline model: generic-rv32 or generic-rv64

Architecture extension has quite complicated behavior now:

  • Take union from -march and -mcpu if both are present.
  • Take from -march if present.
  • Take from -mcpu if present.
  • Implied from -mabi if present.
  • Use the default architecture depending on the target triple

We treat -mcpu/-mtune and -mcpu/-march differently, and it's
kind of counterintuitive: -march is explicitly specified but ignored.

This patch adjusts the priority between -mcpu/-march, letting it use
architecture extension information from -march if it's present.

So the priority of architecture extension information becomes:

  • Take from -march if present.
  • Take from -mcpu if present.
  • Implied from -mabi if present.
  • Use the default architecture depending on the target triple

And this also match what we implement in RISC-V GCC too.

Diff Detail

Event Timeline

kito-cheng created this revision.Dec 27 2022, 6:02 AM
kito-cheng requested review of this revision.Dec 27 2022, 6:02 AM

So if I read this correctly, the effect of this is that we never pass -target-cpu to the backend after this patch and will only pass -target-feature and -tune-cpu?

This doesn't seem correct

What's the priority among those options for now(w/o this patch)?

Pipeline model:

Take from -mtune if present.
Take from -mcpu if present
Use the default pipeline model: generic-rv32 or generic-rv64
Architecture extension:

Take from -mcpu if present.
Take from -march if present.
Use the default architecture depending on the target triple

The code in riscv::getRISCVArch prioritizes -march over -mcpu for architecture extensions for setting -target-features.

But the backend still applies extensions from -target-cpu via the tablegen features from RISCV.td.

So its not even a "priority", we end up with a union.

clang/lib/Driver/ToolChains/Clang.cpp
5457

I wonder if we should stop getCPUName from calling getRISCVTargetCPU instead? Have you audited all callers of getCPUName?

So if I read this correctly, the effect of this is that we never pass -target-cpu to the backend after this patch and will only pass -target-feature and -tune-cpu?

Yes, that's prevent us taking any extensions from -target-cpu, so always pass -target-feature and -tune-cpu only.

The code in riscv::getRISCVArch prioritizes -march over -mcpu for architecture extensions for setting -target-features.

But the backend still applies extensions from -target-cpu via the tablegen features from RISCV.td.

So its not even a "priority", we end up with a union.

Damm, you are right, that...even worth than I thought before, let me update the summary.

clang/lib/Driver/ToolChains/Clang.cpp
5457

That sounds a better way, that prevent us to auditing every caller of getCPUName.

Changes:

  • Stop calling getRISCVTargetCPU in getCPUName.
kito-cheng edited the summary of this revision. (Show Details)Dec 30 2022, 12:05 AM
kito-cheng marked an inline comment as done.
craig.topper added inline comments.Dec 30 2022, 12:24 AM
clang/lib/Driver/ToolChains/Clang.cpp
5457

I think we need to do the audit either way.

kito-cheng added inline comments.Jan 4 2023, 2:22 AM
clang/lib/Driver/ToolChains/Clang.cpp
5457

28 call site in clang, search by $ grep [^r]getCPUName * -R -n

$ grep [^r]getCPUName * -R -n
Reviewed and seems OK:

  • Clang::ConstructJob: lib/Driver/ToolChains/Clang.cpp:5438: getCPUName(D, HostArgs, *TC.getAuxTriple(), /*FromAs*/ false);
  • ClangAs::ConstructJob: lib/Driver/ToolChains/Clang.cpp:7880: std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ true);
  • -aux-target-cpu: lib/Driver/ToolChains/Clang.cpp:5480: std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ false);

Should fix:

  • tools::addLTOOptions: lib/Driver/ToolChains/CommonArgs.cpp:630: std::string CPU = getCPUName(D, Args, ToolChain.getTriple());

Should fix in future, because we don't really port that part for RISC-V:

  • lib/Driver/ToolChains/Flang.cpp:89: std::string CPU = getCPUName(D, Args, Triple);

x86 specific cpu_specific attribute:

  • include/clang/Basic/Attr.td:1136: IdentifierInfo *getCPUName(unsigned Index) const {
  • lib/CodeGen/CodeGenModule.cpp:1336: Out << getCPUSpecificMangling(CGM, Attr->getCPUName(CPUIndex)->getName());
  • lib/CodeGen/CodeGenModule.cpp:2202: SD->getCPUName(GD.getMultiVersionIndex())->getName());
  • lib/AST/ASTContext.cpp:13386: SD->getCPUName(GD.getMultiVersionIndex())->getName(), FeaturesTmp);

Target specific:

  • lib/Driver/ToolChains/AVR.cpp:372: if (getCPUName(D, Args, Triple).empty())
  • lib/Driver/ToolChains/AVR.cpp:445: std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
  • lib/Driver/ToolChains/Arch/Mips.cpp:453: return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))
  • lib/Driver/ToolChains/Arch/AArch64.cpp:623: std::string CPU = getCPUName(D, Args, Triple);
  • Sparc:
    • lib/Driver/ToolChains/OpenBSD.cpp:64: std::string CPU = getCPUName(D, Args, Triple);
    • lib/Driver/ToolChains/FreeBSD.cpp:103: std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
  • aarch64: lib/Driver/ToolChains/Gnu.cpp:461: std::string CPU = getCPUName(D, Args, Triple);
  • PPC: lib/Driver/ToolChains/Gnu.cpp:760: getCPUName(D, Args, getToolChain().getTriple())));
  • PPCLE: lib/Driver/ToolChains/Gnu.cpp:768: getCPUName(D, Args, getToolChain().getTriple())));
  • PPC64: lib/Driver/ToolChains/Gnu.cpp:776: getCPUName(D, Args, getToolChain().getTriple())));
  • PPC64LE: lib/Driver/ToolChains/Gnu.cpp:784: getCPUName(D, Args, getToolChain().getTriple())));
  • SPARC: lib/Driver/ToolChains/Gnu.cpp:819: std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
  • SPARCv9: lib/Driver/ToolChains/Gnu.cpp:827: std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
  • ARM: lib/Driver/ToolChains/Clang.cpp:1548: std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ false);
  • AArch64: lib/Driver/ToolChains/Fuchsia.cpp:92: std::string CPU = getCPUName(D, Args, Triple);
  • Sparc: lib/Driver/ToolChains/NetBSD.cpp:83: std::string CPU = getCPUName(D, Args, Triple);
  • Sparcv9: lib/Driver/ToolChains/NetBSD.cpp:91: std::string CPU = getCPUName(D, Args, Triple);

Declaration:

  • lib/Driver/ToolChains/CommonArgs.h:174:std::string getCPUName(const Driver &D, const llvm::opt::ArgList &Args,

Implement

  • lib/Driver/ToolChains/CommonArgs.cpp:363:std::string tools::getCPUName(const Driver &D, const ArgList &Args,
kito-cheng planned changes to this revision.Jan 9 2023, 7:48 AM
  • @craig.topper has suggested we could pass all extension with - or + to neutralize the effect of the -target-cpu, that's less intrusive way.
  • Add release note to mention the behavior change.

Changes:

  • Add release note to mention the behavior change for -march and -mcpu.
  • New way to implement this behavior, passing all supported extension with - or +, this way is less RISC-V specific logical around -mcpu.
Herald added a project: Restricted Project. · View Herald TranscriptJan 11 2023, 5:36 AM

Changes:

  • Trim unexpected change by clang-format
clang/test/Driver/riscv-cpus.c
12

Need to break this into two line since we'll add bunch of negative list of extension here.

clang/test/Driver/riscv-default-features.c
5 ↗(On Diff #488175)

Same reason here.

craig.topper added inline comments.Jan 11 2023, 9:32 AM
clang/docs/ReleaseNotes.rst
792 ↗(On Diff #488175)

back-end -> backend

clang/lib/Driver/ToolChains/Arch/RISCV.cpp
47

true -> /*AddAllExtensions*/true

llvm/lib/Support/RISCVISAInfo.cpp
14 ↗(On Diff #488175)

Why is this needed?

335 ↗(On Diff #488175)

AddAllExtension -> AddAllExtensions

MaskRay added a comment.EditedJan 11 2023, 10:25 AM

(Haven't looked carefully ) but the Pipeline model: matches AArch64 (ideal model in my view https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/compiler-flags-across-architectures-march-mtune-and-mcpu)
(I probably need to update my https://maskray.me/blog/2022-08-28-march-mcpu-mtune)

"Architecture extension has quite complicated behavior now:" looks too complex.

Take union from -march and -mcpu if both are present.

I'd like that we just take -march= and report an error if it is incompatible with -mcpu=

Changes:

  • Address Craig's comment.
kito-cheng marked 3 inline comments as done.Jan 12 2023, 8:14 AM

(I probably need to update my https://maskray.me/blog/2022-08-28-march-mcpu-mtune)

At least the behavior of RISC-V GCC need to update:

Architecture extension:

  • Take from -march if present.
  • Take from -mcpu if present.
  • Use the default architecture (TARGET_RISCV_DEFAULT_ARCH, set by --with-arch, implementation by spec here)

"Architecture extension has quite complicated behavior now:" looks too complex.
Take union from -march and -mcpu if both are present.

Yeah, and actually more like buggy behavior now, it seems like take from -march if both are given from the clang view, because the architecture test macro are only defined the part of -march, but the union behavior will performed by LLVM backend by -target-cpu option.


I'd like that we just take -march= and report an error if it is incompatible with -mcpu=

I would prefer using same * behavior as RISC-V GCC, one reason is RISC-V GCC implement that behavior since GCC 11 (and implemented at Oct. 2020).

  • Take from -march if present.
  • Take from -mcpu if present.
  • Implied from -mabi if present.
  • Use the default architecture depending on the target triple

* Okay, it's actually not same, it's just similar because GCC won't implied arch from -mabi.

llvm/lib/Support/RISCVISAInfo.cpp
14 ↗(On Diff #488175)

Added during my first attempt, apparently I forgot to clean this up.

This revision is now accepted and ready to land.Jan 12 2023, 11:10 AM
MaskRay added inline comments.Jan 12 2023, 1:22 PM
clang/lib/Driver/ToolChains/Arch/RISCV.cpp
47

The canonical comment is /*AddAllExtensions=*/true

clang/test/Driver/riscv-cpus.c
83

If the two features are adjacent, I suggest you place them one the same line.

MaskRay accepted this revision.Jan 12 2023, 4:16 PM
MaskRay added inline comments.
clang/test/Driver/riscv-march-mcpu-mtune.c
31

This NOT pattern isn't useful as -target-cpu has occurred.

llvm/lib/Support/RISCVISAInfo.cpp
333 ↗(On Diff #488656)

Use function_ref (in llvm::)

348 ↗(On Diff #488656)

auto const => RISCVSupportedExtension (optional const)

349 ↗(On Diff #488656)
for ...
  if (!Exts.count...)
    Features.push_back...
kito-cheng marked 6 inline comments as done.Jan 13 2023, 7:57 AM
kito-cheng added inline comments.
clang/test/Driver/riscv-cpus.c
83

It's not adjacent after this patch.

clang/test/Driver/riscv-march-mcpu-mtune.c
31

Thanks for catch this.

This revision was landed with ongoing or failed builds.Jan 13 2023, 7:58 AM
This revision was automatically updated to reflect the committed changes.
kito-cheng marked 2 inline comments as done.