aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/TargetParser/ARMTargetParser.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/TargetParser/ARMTargetParser.cpp
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'llvm/lib/TargetParser/ARMTargetParser.cpp')
-rw-r--r--llvm/lib/TargetParser/ARMTargetParser.cpp94
1 files changed, 78 insertions, 16 deletions
diff --git a/llvm/lib/TargetParser/ARMTargetParser.cpp b/llvm/lib/TargetParser/ARMTargetParser.cpp
index 785e9a4fe3fb..d09992441909 100644
--- a/llvm/lib/TargetParser/ARMTargetParser.cpp
+++ b/llvm/lib/TargetParser/ARMTargetParser.cpp
@@ -13,6 +13,8 @@
#include "llvm/TargetParser/ARMTargetParser.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/ARMTargetParserCommon.h"
#include "llvm/TargetParser/Triple.h"
#include <cctype>
@@ -364,26 +366,51 @@ StringRef ARM::getArchExtFeature(StringRef ArchExt) {
}
static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) {
+ if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE)
+ return ARM::FK_INVALID;
+
const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
// If the input FPU already supports double-precision, then there
// isn't any different FPU we can return here.
- //
- // The current available FPURestriction values are None (no
- // restriction), D16 (only 16 d-regs) and SP_D16 (16 d-regs
- // and single precision only); there's no value representing
- // SP restriction without D16. So this test just means 'is it
- // SP only?'.
- if (InputFPU.Restriction != ARM::FPURestriction::SP_D16)
+ if (ARM::isDoublePrecision(InputFPU.Restriction))
+ return InputFPUKind;
+
+ // Otherwise, look for an FPU entry with all the same fields, except
+ // that it supports double precision.
+ for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
+ if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
+ CandidateFPU.NeonSupport == InputFPU.NeonSupport &&
+ ARM::has32Regs(CandidateFPU.Restriction) ==
+ ARM::has32Regs(InputFPU.Restriction) &&
+ ARM::isDoublePrecision(CandidateFPU.Restriction)) {
+ return CandidateFPU.ID;
+ }
+ }
+
+ // nothing found
+ return ARM::FK_INVALID;
+}
+
+static ARM::FPUKind findSinglePrecisionFPU(ARM::FPUKind InputFPUKind) {
+ if (InputFPUKind == ARM::FK_INVALID || InputFPUKind == ARM::FK_NONE)
return ARM::FK_INVALID;
+ const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
+
+ // If the input FPU already is single-precision only, then there
+ // isn't any different FPU we can return here.
+ if (!ARM::isDoublePrecision(InputFPU.Restriction))
+ return InputFPUKind;
+
// Otherwise, look for an FPU entry with all the same fields, except
- // that SP_D16 has been replaced with just D16, representing adding
- // double precision and not changing anything else.
+ // that it does not support double precision.
for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
CandidateFPU.NeonSupport == InputFPU.NeonSupport &&
- CandidateFPU.Restriction == ARM::FPURestriction::D16) {
+ ARM::has32Regs(CandidateFPU.Restriction) ==
+ ARM::has32Regs(InputFPU.Restriction) &&
+ !ARM::isDoublePrecision(CandidateFPU.Restriction)) {
return CandidateFPU.ID;
}
}
@@ -418,20 +445,35 @@ bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
CPU = "generic";
if (ArchExt == "fp" || ArchExt == "fp.dp") {
+ const ARM::FPUKind DefaultFPU = getDefaultFPU(CPU, AK);
ARM::FPUKind FPUKind;
if (ArchExt == "fp.dp") {
+ const bool IsDP = ArgFPUKind != ARM::FK_INVALID &&
+ ArgFPUKind != ARM::FK_NONE &&
+ isDoublePrecision(getFPURestriction(ArgFPUKind));
if (Negated) {
- Features.push_back("-fp64");
- return true;
+ /* If there is no FPU selected yet, we still need to set ArgFPUKind, as
+ * leaving it as FK_INVALID, would cause default FPU to be selected
+ * later and that could be double precision one. */
+ if (ArgFPUKind != ARM::FK_INVALID && !IsDP)
+ return true;
+ FPUKind = findSinglePrecisionFPU(DefaultFPU);
+ if (FPUKind == ARM::FK_INVALID)
+ FPUKind = ARM::FK_NONE;
+ } else {
+ if (IsDP)
+ return true;
+ FPUKind = findDoublePrecisionFPU(DefaultFPU);
+ if (FPUKind == ARM::FK_INVALID)
+ return false;
}
- FPUKind = findDoublePrecisionFPU(getDefaultFPU(CPU, AK));
} else if (Negated) {
FPUKind = ARM::FK_NONE;
} else {
- FPUKind = getDefaultFPU(CPU, AK);
+ FPUKind = DefaultFPU;
}
ArgFPUKind = FPUKind;
- return ARM::getFPUFeatures(FPUKind, Features);
+ return true;
}
return StartingNumFeatures != Features.size();
}
@@ -517,6 +559,7 @@ StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
case Triple::GNUEABIHF:
case Triple::MuslEABI:
case Triple::MuslEABIHF:
+ case Triple::OpenHOS:
return "aapcs-linux";
case Triple::EABIHF:
case Triple::EABI:
@@ -524,7 +567,8 @@ StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
default:
if (TT.isOSNetBSD())
return "apcs-gnu";
- if (TT.isOSFreeBSD() || TT.isOSOpenBSD() || TT.isOHOSFamily())
+ if (TT.isOSFreeBSD() || TT.isOSOpenBSD() || TT.isOSHaiku() ||
+ TT.isOHOSFamily())
return "aapcs-linux";
return "aapcs";
}
@@ -540,6 +584,7 @@ StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) {
case llvm::Triple::FreeBSD:
case llvm::Triple::NetBSD:
case llvm::Triple::OpenBSD:
+ case llvm::Triple::Haiku:
if (!MArch.empty() && MArch == "v6")
return "arm1176jzf-s";
if (!MArch.empty() && MArch == "v7")
@@ -572,6 +617,8 @@ StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) {
// If no specific architecture version is requested, return the minimum CPU
// required by the OS and environment.
switch (Triple.getOS()) {
+ case llvm::Triple::Haiku:
+ return "arm1176jzf-s";
case llvm::Triple::NetBSD:
switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
@@ -598,3 +645,18 @@ StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) {
llvm_unreachable("invalid arch name");
}
+
+void ARM::PrintSupportedExtensions(StringMap<StringRef> DescMap) {
+ outs() << "All available -march extensions for ARM\n\n"
+ << " " << left_justify("Name", 20)
+ << (DescMap.empty() ? "\n" : "Description\n");
+ for (const auto &Ext : ARCHExtNames) {
+ // Extensions without a feature cannot be used with -march.
+ if (!Ext.Feature.empty()) {
+ std::string Description = DescMap[Ext.Name].str();
+ outs() << " "
+ << format(Description.empty() ? "%s\n" : "%-20s%s\n",
+ Ext.Name.str().c_str(), Description.c_str());
+ }
+ }
+}