[AArch64] Add all predecessor archs in target info

A given function is compatible with all previous arch versions.
To avoid compering values of the attribute this logic adds all predecessor
architecture values.

Reviewed By: dmgreen, DavidSpickett

Differential Revision: https://reviews.llvm.org/D134353
This commit is contained in:
Daniel Kiss 2022-09-27 10:22:20 +02:00
parent 97dfa53626
commit 712de9d171
7 changed files with 161 additions and 13 deletions

View File

@ -529,6 +529,22 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name, bool Enabled) const {
Features[Name] = Enabled;
llvm::AArch64::ArchKind AK = llvm::AArch64::getSubArchArchKind(Name);
// Add all previous architecture versions.
// In case of v9.x the v8.x counterparts are added too.
if ("9" == getArchVersionString(AK))
for (llvm::AArch64::ArchKind I = llvm::AArch64::convertV9toV8(AK);
I != llvm::AArch64::ArchKind::INVALID; --I)
Features[llvm::AArch64::getSubArch(I)] = Enabled;
for (llvm::AArch64::ArchKind I = --AK; I != llvm::AArch64::ArchKind::INVALID;
--I)
Features[llvm::AArch64::getSubArch(I)] = Enabled;
}
bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
FPU = FPUMode;
@ -620,31 +636,32 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasSM4 = true;
if (Feature == "+strict-align")
HasUnaligned = false;
if (Feature == "+v8a")
// All predecessor archs are added but select the latest one for ArchKind.
if (Feature == "+v8a" && ArchKind < llvm::AArch64::ArchKind::ARMV8A)
ArchKind = llvm::AArch64::ArchKind::ARMV8A;
if (Feature == "+v8.1a")
if (Feature == "+v8.1a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_1A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
if (Feature == "+v8.2a")
if (Feature == "+v8.2a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_2A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
if (Feature == "+v8.3a")
if (Feature == "+v8.3a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_3A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
if (Feature == "+v8.4a")
if (Feature == "+v8.4a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_4A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
if (Feature == "+v8.5a")
if (Feature == "+v8.5a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_5A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
if (Feature == "+v8.6a")
if (Feature == "+v8.6a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_6A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
if (Feature == "+v8.7a")
if (Feature == "+v8.7a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_7A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_7A;
if (Feature == "+v8.8a")
if (Feature == "+v8.8a" && ArchKind < llvm::AArch64::ArchKind::ARMV8_8A)
ArchKind = llvm::AArch64::ArchKind::ARMV8_8A;
if (Feature == "+v9a")
if (Feature == "+v9a" && ArchKind < llvm::AArch64::ArchKind::ARMV9A)
ArchKind = llvm::AArch64::ArchKind::ARMV9A;
if (Feature == "+v9.1a")
if (Feature == "+v9.1a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_1A)
ArchKind = llvm::AArch64::ArchKind::ARMV9_1A;
if (Feature == "+v9.2a")
if (Feature == "+v9.2a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_2A)
ArchKind = llvm::AArch64::ArchKind::ARMV9_2A;
if (Feature == "+v9.3a")
if (Feature == "+v9.3a" && ArchKind < llvm::AArch64::ArchKind::ARMV9_3A)
ArchKind = llvm::AArch64::ArchKind::ARMV9_3A;
if (Feature == "+v8r")
ArchKind = llvm::AArch64::ArchKind::ARMV8R;

View File

@ -114,6 +114,8 @@ public:
getVScaleRange(const LangOptions &LangOpts) const override;
bool hasFeature(StringRef Feature) const override;
void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
bool Enabled) const override;
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;

View File

@ -0,0 +1,71 @@
// REQUIRES: aarch64-registered-target
// RUN: %clang -target aarch64-none-linux -march=armv9.3-a -o %t -c %s 2>&1 | FileCheck --allow-empty %s
// Successor targets should be ableto call predecessor target functions.
__attribute__((__always_inline__,target("v8a")))
int armv80(int i) {
return i + 42;
}
__attribute__((__always_inline__,target("v8.1a")))
int armv81(int i) {
return armv80(i);
}
__attribute__((__always_inline__,target("v8.2a")))
int armv82(int i) {
return armv81(i);
}
__attribute__((__always_inline__,target("v8.3a")))
int armv83(int i) {
return armv82(i);
}
__attribute__((__always_inline__,target("v8.4a")))
int armv84(int i) {
return armv83(i);
}
__attribute__((__always_inline__,target("v8.5a")))
int armv85(int i) {
return armv84(i);
}
__attribute__((__always_inline__,target("v8.6a")))
int armv86(int i) {
return armv85(i);
}
__attribute__((__always_inline__,target("v8.7a")))
int armv87(int i) {
return armv86(i);
}
__attribute__((__always_inline__,target("v8.8a")))
int armv88(int i) {
return armv87(i);
}
__attribute__((__always_inline__,target("v9a")))
int armv9(int i) {
return armv85(i);
}
__attribute__((__always_inline__,target("v9.1a")))
int armv91(int i) {
return armv9(i);
}
__attribute__((__always_inline__,target("v9.2a")))
int armv92(int i) {
return armv91(i);
}
__attribute__((__always_inline__,target("v9.3a")))
int armv93(int i) {
return armv92(i);
}
// CHECK-NOT: always_inline function {{.*}} requires target feature {{.*}}, but would be inlined into function {{.*}} that is compiled without support for {{.*}}
// CHECK-NOT: {{.*}} is not a recognized feature for this target

View File

@ -15,6 +15,8 @@
#ifndef AARCH64_ARCH
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)
#endif
// NOTE: The order and the grouping of the elements matter to make ArchKind iterable.
// List is organised as armv8a -> armv8n-a, armv9a -> armv9m-a and armv8-r.
AARCH64_ARCH("invalid", INVALID, "", "",
ARMBuildAttrs::CPUArch::v8_A, FK_NONE, AArch64::AEK_NONE)
AARCH64_ARCH("armv8-a", ARMV8A, "8-A", "v8a", ARMBuildAttrs::CPUArch::v8_A,

View File

@ -113,6 +113,17 @@ const ArchKind ArchKinds[] = {
#include "AArch64TargetParser.def"
};
inline ArchKind &operator--(ArchKind &Kind) {
if ((Kind == ArchKind::INVALID) || (Kind == ArchKind::ARMV8A) ||
(Kind == ArchKind::ARMV9A) || (Kind == ArchKind::ARMV8R))
Kind = ArchKind::INVALID;
else {
unsigned KindAsInteger = static_cast<unsigned>(Kind);
Kind = static_cast<ArchKind>(--KindAsInteger);
}
return Kind;
}
// FIXME: These should be moved to TargetTuple once it exists
bool getExtensionFeatures(uint64_t Extensions,
std::vector<StringRef> &Features);
@ -124,12 +135,14 @@ StringRef getCPUAttr(ArchKind AK);
StringRef getSubArch(ArchKind AK);
StringRef getArchExtName(unsigned ArchExtKind);
StringRef getArchExtFeature(StringRef ArchExt);
ArchKind convertV9toV8(ArchKind AK);
// Information by Name
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK);
StringRef getDefaultCPU(StringRef Arch);
ArchKind getCPUArchKind(StringRef CPU);
ArchKind getSubArchArchKind(StringRef SubArch);
// Parser
ArchKind parseArch(StringRef Arch);

View File

@ -59,6 +59,15 @@ AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) {
.Default(ArchKind::INVALID);
}
AArch64::ArchKind AArch64::getSubArchArchKind(StringRef SubArch) {
return StringSwitch<AArch64::ArchKind>(SubArch)
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \
ARCH_BASE_EXT) \
.Case(SUB_ARCH, ArchKind::ID)
#include "../../include/llvm/Support/AArch64TargetParser.def"
.Default(ArchKind::INVALID);
}
bool AArch64::getExtensionFeatures(uint64_t Extensions,
std::vector<StringRef> &Features) {
if (Extensions == AArch64::AEK_INVALID)
@ -123,6 +132,19 @@ StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
return StringRef();
}
AArch64::ArchKind AArch64::convertV9toV8(AArch64::ArchKind AK) {
if (AK == AArch64::ArchKind::INVALID)
return AK;
if (AK < AArch64::ArchKind::ARMV9A)
return AK;
if (AK >= AArch64::ArchKind::ARMV8R)
return AArch64::ArchKind::INVALID;
unsigned AK_v8 = static_cast<unsigned>(AArch64::ArchKind::ARMV8_5A);
AK_v8 += static_cast<unsigned>(AK) -
static_cast<unsigned>(AArch64::ArchKind::ARMV9A);
return static_cast<AArch64::ArchKind>(AK_v8);
}
StringRef AArch64::getDefaultCPU(StringRef Arch) {
ArchKind AK = parseArch(Arch);
if (AK == ArchKind::INVALID)

View File

@ -1584,6 +1584,27 @@ TEST(TargetParserTest, AArch64ArchFeatures) {
}
}
TEST(TargetParserTest, AArch64ArchV9toV8Conversion) {
for (auto AK : AArch64::ArchKinds) {
if (AK == AArch64::ArchKind::INVALID)
EXPECT_EQ(AK, AArch64::convertV9toV8(AK));
else if (AK < AArch64::ArchKind::ARMV9A)
EXPECT_EQ(AK, AArch64::convertV9toV8(AK));
else if (AK >= AArch64::ArchKind::ARMV8R)
EXPECT_EQ(AArch64::ArchKind::INVALID, AArch64::convertV9toV8(AK));
else
EXPECT_TRUE(AArch64::convertV9toV8(AK) < AArch64::ArchKind::ARMV9A);
}
EXPECT_EQ(AArch64::ArchKind::ARMV8_5A,
AArch64::convertV9toV8(AArch64::ArchKind::ARMV9A));
EXPECT_EQ(AArch64::ArchKind::ARMV8_6A,
AArch64::convertV9toV8(AArch64::ArchKind::ARMV9_1A));
EXPECT_EQ(AArch64::ArchKind::ARMV8_7A,
AArch64::convertV9toV8(AArch64::ArchKind::ARMV9_2A));
EXPECT_EQ(AArch64::ArchKind::ARMV8_8A,
AArch64::convertV9toV8(AArch64::ArchKind::ARMV9_3A));
}
TEST(TargetParserTest, AArch64ArchExtFeature) {
const char *ArchExt[][4] = {
{"crc", "nocrc", "+crc", "-crc"},