Skip to content

Add -mcpu Extension Control Syntax for RISC-V Toolchain#139

Open
majin2020 wants to merge 1 commit intoriscv-non-isa:mainfrom
majin2020:main
Open

Add -mcpu Extension Control Syntax for RISC-V Toolchain#139
majin2020 wants to merge 1 commit intoriscv-non-isa:mainfrom
majin2020:main

Conversation

@majin2020
Copy link
Copy Markdown

Implementation Overview

This patch adds comprehensive -mcpu extension control syntax support to the RISC-V toolchain specification, following ARM GCC's mature design pattern.

Design References

Background and Motivation

In real-world RISC-V ecosystems, the same CPU IP core often exists in multiple hardware configuration variants:

  • Floating-point units: With F/D extensions vs without floating-point units
  • Vector units: With V extensions vs without vector units
  • Vector length: Configurable VLEN (e.g., 128b, 256b, 512b, etc.)
  • Other extensions: Optional components like Zicsr, Zifencei, compressed instructions, etc.

If we were to define separate CPU model names for every configuration combination, it would lead to exponential growth in CPU model names, creating a significant maintenance burden for toolchains and usability challenges for developers.

Key Features

1. Extension Control Syntax

  • Supports +extension / +noextension syntax to enable/disable specific RISC-V extensions
  • Rightmost precedence rule: conflicting modifiers are resolved right-to-left
  • Supports all standard and vendor-specific RISC-V extensions

2. Dependency Handling

  • Properly handles extension dependencies (e.g., D extension depends on F extension)
  • Automatically disables dependent extensions when base extensions are disabled

Problems Solved

  1. Model explosion problem: Avoids creating numerous duplicate CPU model definitions for different configurations of the same CPU IP
  2. Configuration flexibility: Users can precisely control processor extensions without being limited to predefined CPU models
  3. Hardware compatibility: Enables compilation for processor variants missing certain optional extensions

Usage Examples

# Disable floating-point extensions (for xt-c908 variants without FPU)
gcc -mcpu=xt-c908+nof

# Enable vector extensions (equivalent to xt-c908v, for variants with V unit)
gcc -mcpu=xt-c908+v+zvfh

# Conflict resolution (right-to-left precedence)
gcc -mcpu=xt-c908+nof+f  # F extension is ultimately enabled

# Multiple extension combinations (for specific VLEN configurations)
gcc -mcpu=xt-c908+v+zvl256b+zvfh

This implementation ensures full compatibility with existing GCC RISC-V backends while providing clear and accurate documentation guidance, effectively addressing the CPU model fragmentation issue in the RISC-V ecosystem.

@lenary
Copy link
Copy Markdown
Contributor

lenary commented Jan 14, 2026

I'm fairly against this proposal (but I know I'm one voice). We have a way of doing this already: provide the -march= explicitly and choose the tuning model with -mtune=. My understanding is this has been working clearly for users and vendors so far.

In particular I had problems with how arm and aarch64 both implement and use their -mcpu extension syntax:

  • there's no conflict tracking of the extensions -- so you can disable an extension that is required for a different extension you explicitly enable, and the resulting -march= is unclear and/or depends on the relative order of disabling/enabling.
  • vendors prefer to enable all "common" optional extensions ("for performance"), meaning in practice disabling extensions is more usual than enabling them, and so lots of docs are required because you have to teach some users that code produced with -mcpu=X won't work on their version of the X unit because they don't have a commonly configured unit.

I like that our march syntax is purely additive (you can only enable more extensions, there's no complex disable behaviour), and our mcpu syntax is also simple.

I don't think this "solves" a fragmentation issue, I think it just makes our toolchains harder to use.

I do see our march strings are getting longer and longer, which isn't great long term.

@majin2020
Copy link
Copy Markdown
Author

Thank you very much for your insightful and professional feedback! I strongly agree with your point: while aiming for flexibility—supporting both enabling and disabling features—we inevitably introduce usability complexity, particularly due to the lack of conflict tracking between extensions, as you highlighted. Although implementing such conflict detection may not be technically difficult, it can still cause confusion in practice.

In reality, what we typically need is additive configuration, not subtraction. The -mcpu usually represents a common baseline core, and features like vlen256, vlen512, or matrix are optional extensions layered on top of that baseline.

Therefore, I fully support an -mcpu syntax that does not allow disabling extensions (i.e., no +no-ext). My earlier mention of “subtraction” was only intended to facilitate discussion—it was not a proposal to actually support disabling features.

So I’d like to ask: do you still have concerns about a purely additive -mcpu extension mechanism?
Such an approach aims to address the explosion of CPU names caused by configurable feature combinations—by allowing users to start from a base CPU and add extensions as needed—while avoiding the pitfalls seen in ARM’s model.

BR

@lenary
Copy link
Copy Markdown
Contributor

lenary commented Feb 6, 2026

I personally don't have any problems with a purely additive extension mechanism.

I have found that vendors prefer to have -mcpu=core denote their "common" configuration for that core and not the "minimal" configuration, so I'm not sure it would be acceptable to others. The driving force behind that is benchmark numbers are (usually) better if one generates code for all the features in their core, and vendors want the best numbers with -mcpu=<core> because that's what most of their users will use, rather than the specific -mcpu for their exact core configuration.

@majin2020
Copy link
Copy Markdown
Author

I personally don't have any problems with a purely additive extension mechanism.

I have found that vendors prefer to have -mcpu=core denote their "common" configuration for that core and not the "minimal" configuration, so I'm not sure it would be acceptable to others. The driving force behind that is benchmark numbers are (usually) better if one generates code for all the features in their core, and vendors want the best numbers with -mcpu=<core> because that's what most of their users will use, rather than the specific -mcpu for their exact core configuration.

Hi,thanks for your feedback and suggestions!

I have completely removed the +noextension extension-disabling mechanism. The -mcpu extension control syntax is now purely additive, supporting only +extension to enable additional optional extensions.

Key changes made:

  1. Removed all extension-disabling capabilities: No longer supports +nof, +nod, or similar syntax
  2. Simplified the design: Avoids the complex conflict handling issues seen in the ARM model
  3. Clarified the use case: -mcpu=<core> uses the base configuration defined for the CPU, while +extension allows users to enable optional extensions that the CPU supports but are not included in the base configuration

Regarding your concern about vendor preferences, based on my understanding, what we typically need is a "minimal" baseline configuration for -mcpu=<core>, with optional features (like vlen256, vlen512, matrix, etc.) layered on top as needed. If other vendors have requirements for a "common" configuration approach, they can certainly bring it up for further discussion. For now, I believe the "minimal" configuration is sufficient.

This approach maintains backward compatibility while providing flexibility for scenarios requiring precise extension control, without the complexity of disabling extensions.

Do you have any other comments or suggestions on this purely additive design? Looking forward to your feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants