Index: llvm/include/llvm/Support/AArch64TargetParser.def =================================================================== --- llvm/include/llvm/Support/AArch64TargetParser.def +++ llvm/include/llvm/Support/AArch64TargetParser.def @@ -166,6 +166,8 @@ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_PROFILE)) +AARCH64_CPU_NAME("a64fx", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_FP16 | AArch64::AEK_SVE)) // Invalid CPU AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID) #undef AARCH64_CPU_NAME Index: llvm/lib/Support/Host.cpp =================================================================== --- llvm/lib/Support/Host.cpp +++ llvm/lib/Support/Host.cpp @@ -219,6 +219,16 @@ } } + if (Implementer == "0x46") { // Fujitsu Ltd. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) { + if (Lines[I].startswith("CPU part")) { + return StringSwitch(Lines[I].substr(8).ltrim("\t :")) + .Case("0x001", "a64fx") + .Default("generic"); + } + } + } + if (Implementer == "0x48") // HiSilicon Technologies, Inc. // Look for the CPU part line. for (unsigned I = 0, E = Lines.size(); I != E; ++I) @@ -227,8 +237,8 @@ // values correspond to the "Part number" in the CP15/c0 register. The // contents are specified in the various processor manuals. return StringSwitch(Lines[I].substr(8).ltrim("\t :")) - .Case("0xd01", "tsv110") - .Default("generic"); + .Case("0xd01", "tsv110") + .Default("generic"); if (Implementer == "0x51") // Qualcomm Technologies, Inc. // Look for the CPU part line. Index: llvm/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/lib/Target/AArch64/AArch64.td +++ llvm/lib/Target/AArch64/AArch64.td @@ -563,6 +563,19 @@ FeatureSSBS ]>; +def ProcA64FX : SubtargetFeature<"a64fx", "ARMProcFamily", "A64FX", + "Fujitsu A64FX processors", [ + HasV8_2aOps, + FeatureFPARMv8, + FeatureNEON, + FeatureCrypto, + FeaturePerfMon, + FeatureFullFP16, + FeatureSVE, + FeaturePostRAScheduler, + FeatureComplxNum + ]>; + // Note that cyclone does not fuse AES instructions, but newer apple chips do // perform the fusion and cyclone is used by default when targetting apple OSes. def ProcAppleA7 : SubtargetFeature<"apple-a7", "ARMProcFamily", "AppleA7", @@ -901,6 +914,10 @@ // Alias for the latest Apple processor model supported by LLVM. def : ProcessorModel<"apple-latest", CycloneModel, [ProcAppleA13]>; +// Fujitsu A64FX +// FIXME: Scheduling model is not implemented yet. +def : ProcessorModel<"a64fx", NoSchedModel, [ProcA64FX]>; + //===----------------------------------------------------------------------===// // Assembly parser //===----------------------------------------------------------------------===// Index: llvm/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -38,6 +38,7 @@ public: enum ARMProcFamilyEnum : uint8_t { Others, + A64FX, AppleA7, AppleA10, AppleA11, Index: llvm/lib/Target/AArch64/AArch64Subtarget.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -88,6 +88,11 @@ case CortexA76: PrefFunctionLogAlignment = 4; break; + case A64FX: + CacheLineSize = 256; + PrefFunctionLogAlignment = 5; + PrefLoopLogAlignment = 5; + break; case AppleA7: case AppleA10: case AppleA11: Index: llvm/test/CodeGen/AArch64/cpus.ll =================================================================== --- llvm/test/CodeGen/AArch64/cpus.ll +++ llvm/test/CodeGen/AArch64/cpus.ll @@ -25,6 +25,7 @@ ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=thunderx2t99 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=tsv110 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=apple-latest 2>&1 | FileCheck %s +; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=a64fx 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=invalidcpu 2>&1 | FileCheck %s --check-prefix=INVALID ; CHECK-NOT: {{.*}} is not a recognized processor for this target Index: llvm/test/CodeGen/AArch64/preferred-function-alignment.ll =================================================================== --- llvm/test/CodeGen/AArch64/preferred-function-alignment.ll +++ llvm/test/CodeGen/AArch64/preferred-function-alignment.ll @@ -8,6 +8,7 @@ ; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=cortex-a73 < %s | FileCheck --check-prefixes=ALIGN4,CHECK %s ; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=cortex-a75 < %s | FileCheck --check-prefixes=ALIGN4,CHECK %s ; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=cortex-a76 < %s | FileCheck --check-prefixes=ALIGN4,CHECK %s +; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=a64fx < %s | FileCheck --check-prefixes=ALIGN5,CHECK %s ; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=cyclone < %s | FileCheck --check-prefixes=ALIGN2,CHECK %s ; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=falkor < %s | FileCheck --check-prefixes=ALIGN2,CHECK %s ; RUN: llc -mtriple=aarch64-unknown-linux -mcpu=kryo < %s | FileCheck --check-prefixes=ALIGN2,CHECK %s Index: llvm/unittests/Support/Host.cpp =================================================================== --- llvm/unittests/Support/Host.cpp +++ llvm/unittests/Support/Host.cpp @@ -249,6 +249,18 @@ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n" "CPU part : 0xd01"), "tsv110"); + const std::string A64FXProcCpuInfo = R"( +processor : 0 +BogoMIPS : 200.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve +CPU implementer : 0x46 +CPU architecture: 8 +CPU variant : 0x1 +CPU part : 0x001 +)"; + + // Verify A64FX. + EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo), "a64fx"); } #if defined(__APPLE__) || defined(_AIX) Index: llvm/unittests/Support/TargetParserTest.cpp =================================================================== --- llvm/unittests/Support/TargetParserTest.cpp +++ llvm/unittests/Support/TargetParserTest.cpp @@ -964,9 +964,15 @@ AArch64::AEK_RDM | AArch64::AEK_PROFILE | AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_DOTPROD, "8.2-A")); + EXPECT_TRUE(testAArch64CPU( + "a64fx", "armv8.2-a", "crypto-neon-fp-armv8", + AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_RAS | + AArch64::AEK_LSE | AArch64::AEK_SVE | AArch64::AEK_RDM, + "8.2-A")); } -static constexpr unsigned NumAArch64CPUArchs = 36; +static constexpr unsigned NumAArch64CPUArchs = 37; TEST(TargetParserTest, testAArch64CPUArchList) { SmallVector List; @@ -1107,6 +1113,12 @@ AArch64::ArchKind::INVALID, "fp16fml")); EXPECT_TRUE(testAArch64Extension("tsv110", AArch64::ArchKind::INVALID, "dotprod")); + EXPECT_TRUE(testAArch64Extension("a64fx", + AArch64::ArchKind::INVALID, "fp16")); + EXPECT_TRUE(testAArch64Extension("a64fx", + AArch64::ArchKind::INVALID, "sve")); + EXPECT_FALSE(testAArch64Extension("a64fx", + AArch64::ArchKind::INVALID, "sve2")); EXPECT_FALSE(testAArch64Extension( "generic", AArch64::ArchKind::ARMV8A, "ras"));