Index: include/llvm/Support/AArch64TargetParser.def =================================================================== --- include/llvm/Support/AArch64TargetParser.def +++ include/llvm/Support/AArch64TargetParser.def @@ -70,6 +70,8 @@ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) AARCH64_CPU_NAME("vulcan", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false, (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("xgene1", AK_ARMV8A, FK_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_FP)) // Invalid CPU AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID) #undef AARCH64_CPU_NAME Index: include/llvm/Support/ARMTargetParser.def =================================================================== --- include/llvm/Support/ARMTargetParser.def +++ include/llvm/Support/ARMTargetParser.def @@ -233,6 +233,8 @@ ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("xgene1", AK_ARMV8A, FK_NEON_FP_ARMV8, false, ARM::AEK_CRC | + ARM::AEK_FP | ARM::AEK_SIMD) // Non-standard Arch names. ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE) ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE) Index: include/llvm/Support/TargetParser.h =================================================================== --- include/llvm/Support/TargetParser.h +++ include/llvm/Support/TargetParser.h @@ -162,7 +162,7 @@ AEK_SIMD = 0x10, AEK_FP16 = 0x20, AEK_PROFILE = 0x40, - AEK_RAS = 0x80 + AEK_RAS = 0x80, }; StringRef getCanonicalArchName(StringRef Arch); Index: lib/Support/Host.cpp =================================================================== --- lib/Support/Host.cpp +++ lib/Support/Host.cpp @@ -1095,6 +1095,58 @@ return "generic"; } +#elif defined(__linux__) && defined(__aarch64__) +StringRef sys::getHostCPUName() { + // The cpuid register on arm is not accessible from user space. On Linux, + // it is exposed through the /proc/cpuinfo file. + + // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line + // in all cases. + char buffer[1024]; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return "generic"; + + StringRef Str(buffer, CPUInfoSize); + + SmallVector Lines; + Str.split(Lines, "\n"); + + // Look for the CPU implementer line. + StringRef Implementer; + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU implementer")) + Implementer = Lines[I].substr(15).ltrim("\t :"); + + if (Implementer == "0x41") // ARM Ltd. + // Look for the CPU part line. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU part")) + // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The + // 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("0xd03", "cortex-a53") + .Case("0xd07", "cortex-a57") + .Case("0xd08", "cortex-a72") + .Case("0xd09", "cortex-a73") + .Default("generic"); + + + + if (Implementer == "0x50") // Applied Micro Circuits Corporation (APM). + // Look for the CPU part line. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU part")) + // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The + // 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("0x000", "xgene1") + .Default("generic"); + + return "generic"; +} #elif defined(__linux__) && defined(__s390x__) StringRef sys::getHostCPUName() { // STIDP is a privileged operation, so use /proc/cpuinfo instead. Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -254,6 +254,14 @@ FeaturePredictableSelectIsExpensive, HasV8_1aOps]>; +def ProcXGene1 : SubtargetFeature<"xgene1", "ARMProcFamily", "XGene1", + "AppliedMicro (APM) X-Gene-1 processors", [ + FeatureCRC, + FeatureFPARMv8, + FeatureNEON, + FeaturePerfMon + ]>; + def : ProcessorModel<"generic", NoSchedModel, [ FeatureCRC, FeatureFPARMv8, @@ -274,6 +282,8 @@ def : ProcessorModel<"exynos-m2", ExynosM1Model, [ProcExynosM1]>; def : ProcessorModel<"kryo", KryoModel, [ProcKryo]>; def : ProcessorModel<"vulcan", VulcanModel, [ProcVulcan]>; +// FIXME: X-Gene-1 is currently modelled as generic schedule. +def : ProcessorModel<"xgene1", NoSchedModel, [ProcXGene1]>; //===----------------------------------------------------------------------===// // Assembly parser Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -44,7 +44,8 @@ Cyclone, ExynosM1, Kryo, - Vulcan + Vulcan, + XGene1 }; protected: Index: lib/Target/AArch64/AArch64Subtarget.cpp =================================================================== --- lib/Target/AArch64/AArch64Subtarget.cpp +++ lib/Target/AArch64/AArch64Subtarget.cpp @@ -81,6 +81,7 @@ case CortexA53: break; case CortexA72: break; case CortexA73: break; + case XGene1: break; case Others: break; } } Index: lib/Target/ARM/ARM.td =================================================================== --- lib/Target/ARM/ARM.td +++ lib/Target/ARM/ARM.td @@ -804,6 +804,11 @@ FeatureCrypto, FeatureCRC]>; +def : ProcNoItin<"xgene1", [ARMv8a, ProcXGene1, + FeatureHWDiv, + FeatureHWDivARM, + FeatureCRC]>; + //===----------------------------------------------------------------------===// // Register File Description //===----------------------------------------------------------------------===// Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -45,7 +45,7 @@ Others, CortexA5, CortexA7, CortexA8, CortexA9, CortexA12, CortexA15, CortexA17, CortexR4, CortexR4F, CortexR5, CortexR7, CortexM3, CortexA32, CortexA35, CortexA53, CortexA57, CortexA72, CortexA73, - Krait, Swift, ExynosM1 + Krait, Swift, ExynosM1, XGene1 }; enum ARMProcClassEnum { None, AClass, RClass, MClass Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -233,6 +233,7 @@ case CortexA57: case CortexA72: case CortexA73: + case XGene1: case CortexR4: case CortexR4F: case CortexR5: Index: unittests/Support/TargetParserTest.cpp =================================================================== --- unittests/Support/TargetParserTest.cpp +++ unittests/Support/TargetParserTest.cpp @@ -545,7 +545,8 @@ const char *CPU[] = {"cortex-a35", "cortex-a53", "cortex-a57", "cortex-a72", "cortex-a73", "cyclone", "exynos-m1", "exynos-m2", "kryo", - "vulcan"}; + "vulcan", + "xgene1"}; for (const auto &AArch64CPUName : kAArch64CPUNames) EXPECT_TRUE(contains(CPU, AArch64CPUName.Name)