diff options
| author | John Brawn <john.brawn@arm.com> | 2015-06-05 13:29:24 +0000 |
|---|---|---|
| committer | John Brawn <john.brawn@arm.com> | 2015-06-05 13:29:24 +0000 |
| commit | d03d22922dee3bdb039c5926c49c4e1e5da5a734 (patch) | |
| tree | dc155b9c744601a5608f6e646ee70ab7c15e0457 /llvm/lib | |
| parent | 6f2b88a39838fa46b222e506c9407f1cc31feeb3 (diff) | |
| download | bcm5719-llvm-d03d22922dee3bdb039c5926c49c4e1e5da5a734.tar.gz bcm5719-llvm-d03d22922dee3bdb039c5926c49c4e1e5da5a734.zip | |
[ARM] Add knowledge of FPU subtarget features to TargetParser
Add getFPUFeatures to TargetParser, which gets the list of subtarget features
that are enabled/disabled for each FPU, and use it when handling the .fpu
directive.
No functional change in this commit, though clang will start behaving
differently once it starts using this.
Differential Revision: http://reviews.llvm.org/D10237
llvm-svn: 239150
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/MC/MCSubtargetInfo.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/MC/SubtargetFeature.cpp | 55 | ||||
| -rw-r--r-- | llvm/lib/Support/TargetParser.cpp | 125 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 72 |
4 files changed, 153 insertions, 104 deletions
diff --git a/llvm/lib/MC/MCSubtargetInfo.cpp b/llvm/lib/MC/MCSubtargetInfo.cpp index 6abdd3acbc5..7954a02d83b 100644 --- a/llvm/lib/MC/MCSubtargetInfo.cpp +++ b/llvm/lib/MC/MCSubtargetInfo.cpp @@ -81,6 +81,11 @@ FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef FS) { return FeatureBits; } +FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) { + SubtargetFeatures Features; + FeatureBits = Features.ApplyFeatureFlag(FeatureBits, FS, ProcFeatures); + return FeatureBits; +} MCSchedModel MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { diff --git a/llvm/lib/MC/SubtargetFeature.cpp b/llvm/lib/MC/SubtargetFeature.cpp index e976a508bc2..76574e987cb 100644 --- a/llvm/lib/MC/SubtargetFeature.cpp +++ b/llvm/lib/MC/SubtargetFeature.cpp @@ -190,6 +190,38 @@ SubtargetFeatures::ToggleFeature(FeatureBitset Bits, StringRef Feature, return Bits; } +FeatureBitset +SubtargetFeatures::ApplyFeatureFlag(FeatureBitset Bits, StringRef Feature, + ArrayRef<SubtargetFeatureKV> FeatureTable) { + + assert(hasFlag(Feature)); + + // Find feature in table. + const SubtargetFeatureKV *FeatureEntry = + Find(StripFlag(Feature), FeatureTable); + // If there is a match + if (FeatureEntry) { + // Enable/disable feature in bits + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable); + } + } else { + errs() << "'" << Feature + << "' is not a recognized feature for this target" + << " (ignoring feature)\n"; + } + + return Bits; +} + /// getFeatureBits - Get feature bits a CPU. /// @@ -245,28 +277,7 @@ SubtargetFeatures::getFeatureBits(StringRef CPU, if (Feature == "+help") Help(CPUTable, FeatureTable); - // Find feature in table. - const SubtargetFeatureKV *FeatureEntry = - Find(StripFlag(Feature), FeatureTable); - // If there is a match - if (FeatureEntry) { - // Enable/disable feature in bits - if (isEnabled(Feature)) { - Bits |= FeatureEntry->Value; - - // For each feature that this implies, set it. - SetImpliedBits(Bits, FeatureEntry, FeatureTable); - } else { - Bits &= ~FeatureEntry->Value; - - // For each feature that implies this, clear it. - ClearImpliedBits(Bits, FeatureEntry, FeatureTable); - } - } else { - errs() << "'" << Feature - << "' is not a recognized feature for this target" - << " (ignoring feature)\n"; - } + Bits = ApplyFeatureFlag(Bits, Feature, FeatureTable); } return Bits; diff --git a/llvm/lib/Support/TargetParser.cpp b/llvm/lib/Support/TargetParser.cpp index 9e81763603f..c2f521f323c 100644 --- a/llvm/lib/Support/TargetParser.cpp +++ b/llvm/lib/Support/TargetParser.cpp @@ -22,27 +22,33 @@ using namespace llvm; namespace { -// List of canonical FPU names (use getFPUSynonym). +// List of canonical FPU names (use getFPUSynonym) and which architectural +// features they correspond to (use getFPUFeatures). // FIXME: TableGen this. struct { const char * Name; ARM::FPUKind ID; + unsigned FPUVersion; //< Corresponds directly to the FP arch version number. + ARM::NeonSupportLevel NeonSupport; + ARM::FPURestriction Restriction; } FPUNames[] = { - { "invalid", ARM::FK_INVALID }, - { "vfp", ARM::FK_VFP }, - { "vfpv2", ARM::FK_VFPV2 }, - { "vfpv3", ARM::FK_VFPV3 }, - { "vfpv3-d16", ARM::FK_VFPV3_D16 }, - { "vfpv4", ARM::FK_VFPV4 }, - { "vfpv4-d16", ARM::FK_VFPV4_D16 }, - { "fpv5-d16", ARM::FK_FPV5_D16 }, - { "fp-armv8", ARM::FK_FP_ARMV8 }, - { "neon", ARM::FK_NEON }, - { "neon-vfpv4", ARM::FK_NEON_VFPV4 }, - { "neon-fp-armv8", ARM::FK_NEON_FP_ARMV8 }, - { "crypto-neon-fp-armv8", ARM::FK_CRYPTO_NEON_FP_ARMV8 }, - { "softvfp", ARM::FK_SOFTVFP } + { "invalid", ARM::FK_INVALID, 0, ARM::NS_None, ARM::FR_None}, + { "vfp", ARM::FK_VFP, 2, ARM::NS_None, ARM::FR_None}, + { "vfpv2", ARM::FK_VFPV2, 2, ARM::NS_None, ARM::FR_None}, + { "vfpv3", ARM::FK_VFPV3, 3, ARM::NS_None, ARM::FR_None}, + { "vfpv3-d16", ARM::FK_VFPV3_D16, 3, ARM::NS_None, ARM::FR_D16}, + { "vfpv4", ARM::FK_VFPV4, 4, ARM::NS_None, ARM::FR_None}, + { "vfpv4-d16", ARM::FK_VFPV4_D16, 4, ARM::NS_None, ARM::FR_D16}, + { "fpv5-d16", ARM::FK_FPV5_D16, 5, ARM::NS_None, ARM::FR_D16}, + { "fp-armv8", ARM::FK_FP_ARMV8, 5, ARM::NS_None, ARM::FR_None}, + { "neon", ARM::FK_NEON, 3, ARM::NS_Neon, ARM::FR_None}, + { "neon-vfpv4", ARM::FK_NEON_VFPV4, 4, ARM::NS_Neon, ARM::FR_None}, + { "neon-fp-armv8", ARM::FK_NEON_FP_ARMV8, 5, ARM::NS_Neon, ARM::FR_None}, + { "crypto-neon-fp-armv8", + ARM::FK_CRYPTO_NEON_FP_ARMV8, 5, ARM::NS_Crypto, ARM::FR_None}, + { "softvfp", ARM::FK_SOFTVFP, 0, ARM::NS_None, ARM::FR_None}, }; + // List of canonical arch names (use getArchSynonym). // This table also provides the build attribute fields for CPU arch // and Arch ID, according to the Addenda to the ARM ABI, chapters @@ -226,6 +232,95 @@ const char *ARMTargetParser::getFPUName(unsigned FPUKind) { return FPUNames[FPUKind].Name; } +unsigned ARMTargetParser::getFPUVersion(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return 0; + return FPUNames[FPUKind].FPUVersion; +} + +unsigned getFPUNeonSupportLevel(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return 0; + return FPUNames[FPUKind].NeonSupport; +} + +unsigned getFPURestriction(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return 0; + return FPUNames[FPUKind].Restriction; +} + +bool ARMTargetParser::getFPUFeatures(unsigned FPUKind, + std::vector<const char *> &Features) { + + if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) + return false; + + // fp-only-sp and d16 subtarget features are independent of each other, so we + // must enable/disable both. + switch (FPUNames[FPUKind].Restriction) { + case ARM::FR_SP_D16: + Features.push_back("+fp-only-sp"); + Features.push_back("+d16"); + break; + case ARM::FR_D16: + Features.push_back("-fp-only-sp"); + Features.push_back("+d16"); + break; + case ARM::FR_None: + Features.push_back("-fp-only-sp"); + Features.push_back("-d16"); + break; + } + + // FPU version subtarget features are inclusive of lower-numbered ones, so + // enable the one corresponding to this version and disable all that are + // higher. + switch (FPUNames[FPUKind].FPUVersion) { + case 5: + Features.push_back("+fp-armv8"); + break; + case 4: + Features.push_back("+vfp4"); + Features.push_back("-fp-armv8"); + break; + case 3: + Features.push_back("+vfp3"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + case 2: + Features.push_back("+vfp2"); + Features.push_back("-vfp3"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + case 0: + Features.push_back("-vfp2"); + Features.push_back("-vfp3"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + } + + // crypto includes neon, so we handle this similarly to FPU version. + switch (FPUNames[FPUKind].NeonSupport) { + case ARM::NS_Crypto: + Features.push_back("+crypto"); + break; + case ARM::NS_Neon: + Features.push_back("+neon"); + Features.push_back("-crypto"); + break; + case ARM::NS_None: + Features.push_back("-neon"); + Features.push_back("-crypto"); + break; + } + + return true; +} + const char *ARMTargetParser::getArchName(unsigned ArchKind) { if (ArchKind >= ARM::AK_LAST) return nullptr; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f965cb5400d..c7287abaac5 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -9181,60 +9181,6 @@ bool ARMAsmParser::parseDirectiveCPU(SMLoc L) { return false; } - -// FIXME: This is duplicated in getARMFPUFeatures() in -// tools/clang/lib/Driver/Tools.cpp -static const struct { - const unsigned ID; - const FeatureBitset Enabled; - const FeatureBitset Disabled; -} FPUs[] = { - {/* ID */ ARM::FK_VFP, - /* Enabled */ {ARM::FeatureVFP2}, - /* Disabled */ {ARM::FeatureNEON}}, - {/* ID */ ARM::FK_VFPV2, - /* Enabled */ {ARM::FeatureVFP2}, - /* Disabled */ {ARM::FeatureNEON}}, - {/* ID */ ARM::FK_VFPV3, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3}, - /* Disabled */ {ARM::FeatureNEON, ARM::FeatureD16}}, - {/* ID */ ARM::FK_VFPV3_D16, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureD16}, - /* Disabled */ {ARM::FeatureNEON}}, - {/* ID */ ARM::FK_VFPV4, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4}, - /* Disabled */ {ARM::FeatureNEON, ARM::FeatureD16}}, - {/* ID */ ARM::FK_VFPV4_D16, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4, - ARM::FeatureD16}, - /* Disabled */ {ARM::FeatureNEON}}, - {/* ID */ ARM::FK_FPV5_D16, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4, - ARM::FeatureFPARMv8, ARM::FeatureD16}, - /* Disabled */ {ARM::FeatureNEON, ARM::FeatureCrypto}}, - {/* ID */ ARM::FK_FP_ARMV8, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4, - ARM::FeatureFPARMv8}, - /* Disabled */ {ARM::FeatureNEON, ARM::FeatureCrypto, ARM::FeatureD16}}, - {/* ID */ ARM::FK_NEON, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureNEON}, - /* Disabled */ {ARM::FeatureD16}}, - {/* ID */ ARM::FK_NEON_VFPV4, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4, - ARM::FeatureNEON}, - /* Disabled */ {ARM::FeatureD16}}, - {/* ID */ ARM::FK_NEON_FP_ARMV8, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4, - ARM::FeatureFPARMv8, ARM::FeatureNEON}, - /* Disabled */ {ARM::FeatureCrypto, ARM::FeatureD16}}, - {/* ID */ ARM::FK_CRYPTO_NEON_FP_ARMV8, - /* Enabled */ {ARM::FeatureVFP2, ARM::FeatureVFP3, ARM::FeatureVFP4, - ARM::FeatureFPARMv8, ARM::FeatureNEON, - ARM::FeatureCrypto}, - /* Disabled */ {ARM::FeatureD16}}, - {ARM::FK_SOFTVFP, {}, {}}, -}; - /// parseDirectiveFPU /// ::= .fpu str bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { @@ -9242,23 +9188,15 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { StringRef FPU = getParser().parseStringToEndOfStatement().trim(); unsigned ID = ARMTargetParser::parseFPU(FPU); - - if (ID == ARM::FK_INVALID) { + std::vector<const char *> Features; + if (!ARMTargetParser::getFPUFeatures(ID, Features)) { Error(FPUNameLoc, "Unknown FPU name"); return false; } - for (const auto &Entry : FPUs) { - if (Entry.ID != ID) - continue; - - // Need to toggle features that should be on but are off and that - // should off but are on. - FeatureBitset Toggle = (Entry.Enabled & ~STI.getFeatureBits()) | - (Entry.Disabled & STI.getFeatureBits()); - setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle))); - break; - } + for (auto Feature : Features) + STI.ApplyFeatureFlag(Feature); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); getTargetStreamer().emitFPU(ID); return false; |

