Index: include/llvm/Support/TargetParser.h =================================================================== --- include/llvm/Support/TargetParser.h +++ include/llvm/Support/TargetParser.h @@ -178,6 +178,7 @@ static unsigned getFPUVersion(unsigned FPUKind); static unsigned getFPUNeonSupportLevel(unsigned FPUKind); static unsigned getFPURestriction(unsigned FPUKind); + static unsigned getFPUKind(StringRef CPU); // FIXME: This should be moved to TargetTuple once it exists static bool getFPUFeatures(unsigned FPUKind, std::vector &Features); Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -4055,6 +4055,7 @@ unsigned CRC : 1; unsigned Crypto : 1; + unsigned Unaligned : 1; // ACLE 6.5.1 Hardware floating point enum { @@ -4294,42 +4295,42 @@ // FIXME: This should be based on Arch attributes, not CPU names. void getDefaultFeatures(llvm::StringMap &Features) const override { - StringRef ArchName = getTriple().getArchName(); - unsigned ArchKind = llvm::ARMTargetParser::parseArch(ArchName); - bool IsV8 = (ArchKind == llvm::ARM::AK_ARMV8A || - ArchKind == llvm::ARM::AK_ARMV8_1A); - - if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore") - Features["vfp2"] = true; - else if (CPU == "cortex-a8" || CPU == "cortex-a9") { - Features["vfp3"] = true; - Features["neon"] = true; + unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU); + StringRef SubArch = llvm::ARMTargetParser::getSubArch(ArchKind); + unsigned ArchProfile = llvm::ARMTargetParser::parseArchProfile(SubArch); + unsigned ArchVersion = llvm::ARMTargetParser::parseArchVersion(SubArch); + + std::vector FPUFeatures; + unsigned FPUKind = llvm::ARMTargetParser::getFPUKind(CPU); + llvm::ARMTargetParser::getFPUFeatures(FPUKind, FPUFeatures); + + for (const char *Feature : FPUFeatures) { + if (Feature[0] == '+') + Features[Feature+1] = true; } - else if (CPU == "cortex-a5") { - Features["vfp4"] = true; - Features["neon"] = true; - } else if (CPU == "swift" || CPU == "cortex-a7" || - CPU == "cortex-a12" || CPU == "cortex-a15" || - CPU == "cortex-a17" || CPU == "krait") { - Features["vfp4"] = true; - Features["neon"] = true; - Features["hwdiv"] = true; - Features["hwdiv-arm"] = true; - } else if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" || - CPU == "cortex-a72") { - Features["fp-armv8"] = true; - Features["neon"] = true; - Features["hwdiv"] = true; - Features["hwdiv-arm"] = true; + + if (ArchVersion < 6 || + (ArchVersion == 6 && ArchProfile == llvm::ARM::PK_M)) + Features["unaligned"] = false; + else + Features["unaligned"] = true; + + if (ArchVersion >= 8) { Features["crc"] = true; - Features["crypto"] = true; - } else if (CPU == "cortex-r5" || CPU == "cortex-r7" || IsV8) { - Features["hwdiv"] = true; + // TargetParser implies that by +crypto + Features["neon"] = true; + } + + if (ArchVersion >= 8 || + CPU == "swift" || CPU == "krait" || CPU == "cortex-a7" || + CPU == "cortex-a12" || CPU == "cortex-a15" || CPU == "cortex-a17" || + CPU == "cortex-r5" || CPU == "cortex-r7") { + Features["hwdiv"] = true; Features["hwdiv-arm"] = true; - } else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" || - CPU == "sc300" || CPU == "cortex-r4" || CPU == "cortex-r4f") { - Features["hwdiv"] = true; } + else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" || + CPU == "cortex-r4" || CPU == "cortex-r4f" || CPU == "sc300") + Features["hwdiv"] = true; } bool handleTargetFeatures(std::vector &Features, @@ -4371,8 +4372,12 @@ CRC = 1; } else if (Feature == "+crypto") { Crypto = 1; + } else if (Feature == "+unaligned") { + Unaligned = 1; } else if (Feature == "+fp-only-sp") { HW_FP_remove |= HW_FP_DP | HW_FP_HP; + } else if (Feature == "+fp16") { + HW_FP |= HW_FP_HP; } } HW_FP &= ~HW_FP_remove; @@ -4393,6 +4398,11 @@ if (Feature != Features.end()) Features.erase(Feature); + const char *FeatureStr = Unaligned ? "+unaligned" : "-unaligned" ; + Feature = std::find(Features.begin(), Features.end(), FeatureStr); + if (Feature != Features.end()) + Features.erase(Feature); + return true; } Index: lib/Support/TargetParser.cpp =================================================================== --- lib/Support/TargetParser.cpp +++ lib/Support/TargetParser.cpp @@ -257,6 +257,65 @@ return FPUNames[FPUKind].Restriction; } +// FIXME it could be implemented as an extra column in the CPUNames table +unsigned ARMTargetParser::getFPUKind(StringRef CPU) { + unsigned ArchKind = parseCPUArch(CPU); + StringRef SubArch = getSubArch(ArchKind); + unsigned ArchVersion = parseArchVersion(SubArch); + + // based on SubArch + if (SubArch == "v5e") + return ARM::FK_VFPV2; + else if (SubArch == "v6m" || SubArch == "v6sm") + return ARM::FK_NONE; + + // based on ArchVersion + if (ArchVersion < 6) + return ARM::FK_NONE; + else if (ArchVersion == 6) + return ARM::FK_VFPV2; + else if (ArchVersion >= 8) + return ARM::FK_CRYPTO_NEON_FP_ARMV8; + + // based on CPUName + return StringSwitch(CPU) + .Cases("cortex-a5", "cortex-a7", "swift", "krait", + ARM::FK_NEON_VFPV4) + .Case ("cortex-a8", ARM::FK_NEON) + .Case ("cortex-a9", ARM::FK_NEON_FP16) + .Cases("cortex-a12", "cortex-a15", "cortex-a17", + ARM::FK_NEON_VFPV4) + .Cases("cortex-r4", "cortex-r5", "cortex-m4", + ARM::FK_NONE) + .Case ("cortex-r4f", ARM::FK_VFPV3_D16) + .Case ("cortex-r7", ARM::FK_VFPV3_D16_FP16) + .Case ("cortex-m7", ARM::FK_FPV5_D16) + .Default(ARM::FK_INVALID); + + /********************************************* + * CPU | FPU | NEON * + *-------------+----------------+------------* + * cortex-a5 | VFPV4_D16 | VFPV4 * + * cortex-a7 | VFPV4_D16 | VFPV4 * + * cortex-a8 | VFPV3 | VFPV3 * + * cortex-a9 | VFPV3_D16_FP16 | VFPV3_FP16 * + * cortex-a12 | 0 | VFPV4 * + * cortex-a15 | VFPV4_D16 | VFPV4 * + * cortex-a17 | 0 | VFPV4 * + * cortex-r4 | 0 | 0 * + * cortex-r4f | VFPV3_D16 | 0 * + * cortex-r5 | 0 | 0 * + * cortex-r5f | VFPV3_D16/XD | 0 *<--FIXME + * cortex-r7 | VFPV3_D16_FP16 | 0 * + * cortex-m4 | 0 | 0 * + * cortex-m4f | VFPV4_SP_D16 | 0 *<--FIXME + * cortex-m7 | FPV5(_SP)_D16 | 0 * + *-------------+----------------+------------* + * FIXME indicates missing CPUs from * + * CPUNames table * + *********************************************/ +} + bool ARMTargetParser::getFPUFeatures(unsigned FPUKind, std::vector &Features) { Index: test/CodeGen/arm-long-calls.c =================================================================== --- test/CodeGen/arm-long-calls.c +++ test/CodeGen/arm-long-calls.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple thumbv7-apple-ios5 -target-feature +long-calls -emit-llvm -o - %s | FileCheck -check-prefix=LONGCALL %s // RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=NOLONGCALL %s -// LONGCALL: attributes #0 = { {{.*}} "target-features"="+long-calls" -// NOLONGCALL-NOT: attributes #0 = { {{.*}} "target-features"="+long-calls" +// LONGCALL: attributes #0 = { {{.*}} "target-features"="{{.*}}+long-calls{{.*}}" +// NOLONGCALL-NOT: attributes #0 = { {{.*}} "target-features"="{{.*}}+long-calls{{.*}}" int foo1(int a) { return a; } Index: test/CodeGen/arm-target-features.c =================================================================== --- test/CodeGen/arm-target-features.c +++ test/CodeGen/arm-target-features.c @@ -1,10 +1,13 @@ // REQUIRES: arm-registered-target // RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a8 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3 -// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-a9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3 // CHECK-VFP3: "target-features"="+neon,+vfp3" +// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-a9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-FP16 +// CHECK-VFP3-FP16: "target-features"="+fp16,+neon,+vfp3" + + // RUN: %clang_cc1 -triple thumbv7-linux-gnueabihf -target-cpu cortex-a5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP4 // CHECK-VFP4: "target-features"="+neon,+vfp4" @@ -26,10 +29,22 @@ // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-DIV -// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-DIV // CHECK-DIV: "target-features"="+hwdiv,+hwdiv-arm" -// RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV + +// RUN: %clang_cc1 -triple armv7-linux-gnueabi -target-cpu cortex-r4f -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-THUMB-DIV +// CHECK-VFP3-D16-THUMB-DIV: "target-features"="+d16,+hwdiv,+vfp3" + + +// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP3-D16-FP16-DIV +// CHECK-VFP3-D16-FP16-DIV: "target-features"="+d16,+fp16,+hwdiv,+hwdiv-arm,+vfp3" + + +// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m7 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-VFP5-D16-THUMB-DIV +// CHECK-VFP5-D16-THUMB-DIV: "target-features"="+d16,+fp-armv8,+hwdiv" + + +// RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-r4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV // RUN: %clang_cc1 -triple thumbv7-linux-gnueabi -target-cpu cortex-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-THUMB-DIV // CHECK-THUMB-DIV: "target-features"="+hwdiv"