Skip to content

[RISCV] Add ability to list extensions enabled for a target #98207

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/docs/CommandGuide/clang.rst
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@ number of cross compilers, or may only support a native target.
allowed to generate instructions that are valid on i486 and later processors,
but which may not exist on earlier ones.

.. option:: --print-enabled-extensions

Prints the list of extensions that are enabled for the target specified by the
combination of `--target`, `-march`, and `-mcpu` values. Currently, this
option is only supported on AArch64 and RISC-V. On RISC-V, this option also
prints out the ISA string of enabled extensions.

Code Generation Options
~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5730,7 +5730,7 @@ def print_supported_extensions : Flag<["-", "--"], "print-supported-extensions">
def print_enabled_extensions : Flag<["-", "--"], "print-enabled-extensions">,
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Print the extensions enabled by the given target and -march/-mcpu options."
" (AArch64 only)">,
" (AArch64 and RISC-V only)">,
MarshallingInfoFlag<FrontendOpts<"PrintEnabledExtensions">>;
def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>;
def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4367,6 +4367,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
return;
}
if (Opt == options::OPT_print_enabled_extensions &&
!C.getDefaultToolChain().getTriple().isRISCV() &&
!C.getDefaultToolChain().getTriple().isAArch64()) {
C.getDriver().Diag(diag::err_opt_not_valid_on_target)
<< "--print-enabled-extensions";
Expand Down
13 changes: 10 additions & 3 deletions clang/tools/driver/cc1_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static int PrintSupportedExtensions(std::string TargetStr) {
DescMap.insert({feature.Key, feature.Desc});

if (MachineTriple.isRISCV())
llvm::riscvExtensionsHelp(DescMap);
llvm::RISCVISAInfo::printSupportedExtensions(DescMap);
else if (MachineTriple.isAArch64())
llvm::AArch64::PrintSupportedExtensions();
else if (MachineTriple.isARM())
Expand Down Expand Up @@ -190,13 +190,20 @@ static int PrintEnabledExtensions(const TargetOptions& TargetOpts) {
for (const llvm::SubtargetFeatureKV &feature : Features)
EnabledFeatureNames.insert(feature.Key);

if (!MachineTriple.isAArch64()) {
if (MachineTriple.isAArch64())
llvm::AArch64::printEnabledExtensions(EnabledFeatureNames);
else if (MachineTriple.isRISCV()) {
llvm::StringMap<llvm::StringRef> DescMap;
for (const llvm::SubtargetFeatureKV &feature : Features)
DescMap.insert({feature.Key, feature.Desc});
llvm::RISCVISAInfo::printEnabledExtensions(MachineTriple.isArch64Bit(),
EnabledFeatureNames, DescMap);
} else {
// The option was already checked in Driver::HandleImmediateArgs,
// so we do not expect to get here if we are not a supported architecture.
assert(0 && "Unhandled triple for --print-enabled-extensions option.");
return 1;
}
llvm::AArch64::printEnabledExtensions(EnabledFeatureNames);

return 0;
}
Expand Down
7 changes: 6 additions & 1 deletion llvm/include/llvm/TargetParser/RISCVISAInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
#include "llvm/Support/RISCVISAUtils.h"

#include <map>
#include <set>
#include <string>
#include <vector>

namespace llvm {
void riscvExtensionsHelp(StringMap<StringRef> DescMap);

class RISCVISAInfo {
public:
Expand Down Expand Up @@ -75,6 +75,11 @@ class RISCVISAInfo {
unsigned MinorVersion);
static std::string getTargetFeatureForExtension(StringRef Ext);

static void printSupportedExtensions(StringMap<StringRef> &DescMap);
static void printEnabledExtensions(bool IsRV64,
std::set<StringRef> &EnabledFeatureNames,
StringMap<StringRef> &DescMap);

private:
RISCVISAInfo(unsigned XLen) : XLen(XLen) {}

Expand Down
42 changes: 40 additions & 2 deletions llvm/lib/TargetParser/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ static void PrintExtension(StringRef Name, StringRef Version,
<< Description << "\n";
}

void llvm::riscvExtensionsHelp(StringMap<StringRef> DescMap) {

void RISCVISAInfo::printSupportedExtensions(StringMap<StringRef> &DescMap) {
outs() << "All available -march extensions for RISC-V\n\n";
PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));

Expand Down Expand Up @@ -116,6 +115,45 @@ void llvm::riscvExtensionsHelp(StringMap<StringRef> DescMap) {
"For example, clang -march=rv32i_v1p0\n";
}

void RISCVISAInfo::printEnabledExtensions(
bool IsRV64, std::set<StringRef> &EnabledFeatureNames,
StringMap<StringRef> &DescMap) {
outs() << "Extensions enabled for the given RISC-V target\n\n";
PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));

RISCVISAUtils::OrderedExtensionMap FullExtMap;
RISCVISAUtils::OrderedExtensionMap ExtMap;
for (const auto &E : SupportedExtensions)
if (EnabledFeatureNames.count(E.Name) != 0) {
FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
}
for (const auto &E : ExtMap) {
std::string Version =
std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
PrintExtension(E.first, Version, DescMap[E.first]);
}

outs() << "\nExperimental extensions\n";
ExtMap.clear();
for (const auto &E : SupportedExperimentalExtensions) {
StringRef Name(E.Name);
if (EnabledFeatureNames.count("experimental-" + Name.str()) != 0) {
FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
}
}
for (const auto &E : ExtMap) {
std::string Version =
std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor);
PrintExtension(E.first, Version, DescMap["experimental-" + E.first]);
}

unsigned XLen = IsRV64 ? 64 : 32;
if (auto ISAString = RISCVISAInfo::createFromExtMap(XLen, FullExtMap))
outs() << "\nISA String: " << ISAString.get()->toString();
}

static bool stripExperimentalPrefix(StringRef &Ext) {
return Ext.consume_front("experimental-");
}
Expand Down
31 changes: 30 additions & 1 deletion llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1060,11 +1060,40 @@ For example, clang -march=rv32i_v1p0)";

outs().flush();
testing::internal::CaptureStdout();
riscvExtensionsHelp(DummyMap);
RISCVISAInfo::printSupportedExtensions(DummyMap);
outs().flush();

std::string CapturedOutput = testing::internal::GetCapturedStdout();
EXPECT_TRUE([](std::string &Captured, std::string &Expected) {
return Captured.find(Expected) != std::string::npos;
}(CapturedOutput, ExpectedOutput));
}

TEST(TargetParserTest, RISCVPrintEnabledExtensions) {
// clang-format off
std::string ExpectedOutput =
R"(Extensions enabled for the given RISC-V target

Name Version Description
i 2.1 'I' (Base Integer Instruction Set)

Experimental extensions
zicfilp 0.4 'Zicfilp' (Landing pad)

ISA String: rv64i2p1_zicfilp0p4_zicsr2p0)";
// clang-format on

StringMap<StringRef> DescMap;
DescMap["i"] = "'I' (Base Integer Instruction Set)";
DescMap["experimental-zicfilp"] = "'Zicfilp' (Landing pad)";
std::set<StringRef> EnabledExtensions = {"i", "experimental-zicfilp"};

outs().flush();
testing::internal::CaptureStdout();
RISCVISAInfo::printEnabledExtensions(/*IsRV64=*/true, EnabledExtensions,
DescMap);
outs().flush();
std::string CapturedOutput = testing::internal::GetCapturedStdout();

EXPECT_EQ(CapturedOutput, ExpectedOutput);
}
Loading