From 10da90aaf3e7c679cd36733c81ad07d9d5d8cf55 Mon Sep 17 00:00:00 2001 From: Alexandros Lamprineas Date: Mon, 27 Jul 2015 22:26:59 +0000 Subject: [PATCH] - Added support for parsing HWDiv features using Target Parser. - Architecture extensions are represented as a bitmap. Phabricator: http://reviews.llvm.org/D11457 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243335 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/TargetParser.h | 36 +++++---- lib/Support/TargetParser.cpp | 94 ++++++++++++++++++----- lib/Target/ARM/ARMAsmPrinter.cpp | 2 +- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 4 +- 4 files changed, 100 insertions(+), 36 deletions(-) diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h index 526ee4a1fcf..e6017bec23e 100644 --- a/include/llvm/Support/TargetParser.h +++ b/include/llvm/Support/TargetParser.h @@ -122,22 +122,23 @@ namespace ARM { // Arch extension modifiers for CPUs. enum ArchExtKind { - AEK_INVALID = 0, - AEK_CRC, - AEK_CRYPTO, - AEK_FP, - AEK_HWDIV, - AEK_MP, - AEK_SIMD, - AEK_SEC, - AEK_VIRT, + AEK_INVALID = 0x0, + AEK_NONE = 0x1, + AEK_CRC = 0x2, + AEK_CRYPTO = 0x4, + AEK_FP = 0x8, + AEK_HWDIV = 0x10, + AEK_HWDIVARM = 0x20, + AEK_MP = 0x40, + AEK_SIMD = 0x80, + AEK_SEC = 0x100, + AEK_VIRT = 0x200, // Unsupported extensions. - AEK_OS, - AEK_IWMMXT, - AEK_IWMMXT2, - AEK_MAVERICK, - AEK_XSCALE, - AEK_LAST + AEK_OS = 0x8000000, + AEK_IWMMXT = 0x10000000, + AEK_IWMMXT2 = 0x20000000, + AEK_MAVERICK = 0x40000000, + AEK_XSCALE = 0x80000000, }; // ISA kinds. @@ -167,6 +168,7 @@ namespace ARM { // Target Parsers, one per architecture. class ARMTargetParser { + static StringRef getHWDivSynonym(StringRef HWDiv); static StringRef getFPUSynonym(StringRef FPU); static StringRef getArchSynonym(StringRef Arch); @@ -182,14 +184,18 @@ public: // FIXME: This should be moved to TargetTuple once it exists static bool getFPUFeatures(unsigned FPUKind, std::vector &Features); + static bool getHWDivFeatures(unsigned HWDivKind, + std::vector &Features); static const char * getArchName(unsigned ArchKind); static unsigned getArchAttr(unsigned ArchKind); static const char * getCPUAttr(unsigned ArchKind); static const char * getSubArch(unsigned ArchKind); static const char * getArchExtName(unsigned ArchExtKind); + static const char * getHWDivName(unsigned HWDivKind); static const char * getDefaultCPU(StringRef Arch); // Parser + static unsigned parseHWDiv(StringRef HWDiv); static unsigned parseFPU(StringRef FPU); static unsigned parseArch(StringRef Arch); static unsigned parseArchExt(StringRef ArchExt); diff --git a/lib/Support/TargetParser.cpp b/lib/Support/TargetParser.cpp index 315e0f793ad..6d43f252eaf 100644 --- a/lib/Support/TargetParser.cpp +++ b/lib/Support/TargetParser.cpp @@ -113,22 +113,36 @@ struct { // FIXME: TableGen this. struct { const char *Name; - ARM::ArchExtKind ID; + unsigned ID; } ARCHExtNames[] = { - { "invalid", ARM::AEK_INVALID }, - { "crc", ARM::AEK_CRC }, - { "crypto", ARM::AEK_CRYPTO }, - { "fp", ARM::AEK_FP }, - { "idiv", ARM::AEK_HWDIV }, - { "mp", ARM::AEK_MP }, - { "simd", ARM::AEK_SIMD }, - { "sec", ARM::AEK_SEC }, - { "virt", ARM::AEK_VIRT }, - { "os", ARM::AEK_OS }, - { "iwmmxt", ARM::AEK_IWMMXT }, - { "iwmmxt2", ARM::AEK_IWMMXT2 }, - { "maverick", ARM::AEK_MAVERICK }, - { "xscale", ARM::AEK_XSCALE } + { "invalid", ARM::AEK_INVALID }, + { "none", ARM::AEK_NONE }, + { "crc", ARM::AEK_CRC }, + { "crypto", ARM::AEK_CRYPTO }, + { "fp", ARM::AEK_FP }, + { "idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV) }, + { "mp", ARM::AEK_MP }, + { "simd", ARM::AEK_SIMD }, + { "sec", ARM::AEK_SEC }, + { "virt", ARM::AEK_VIRT }, + { "os", ARM::AEK_OS }, + { "iwmmxt", ARM::AEK_IWMMXT }, + { "iwmmxt2", ARM::AEK_IWMMXT2 }, + { "maverick", ARM::AEK_MAVERICK }, + { "xscale", ARM::AEK_XSCALE } +}; +// List of HWDiv names (use getHWDivSynonym) and which architectural +// features they correspond to (use getHWDivFeatures). +// FIXME: TableGen this. +struct { + const char *Name; + unsigned ID; +} HWDivNames[] = { + { "invalid", ARM::AEK_INVALID }, + { "none", ARM::AEK_NONE }, + { "thumb", ARM::AEK_HWDIV }, + { "arm", ARM::AEK_HWDIVARM }, + { "arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV) } }; // List of CPU names and their arches. // The same CPU can have multiple arches and can be default on multiple arches. @@ -266,6 +280,25 @@ unsigned ARMTargetParser::getDefaultFPU(StringRef CPU) { return ARM::FK_INVALID; } +bool ARMTargetParser::getHWDivFeatures(unsigned HWDivKind, + std::vector &Features) { + + if (HWDivKind == ARM::AEK_INVALID) + return false; + + if (HWDivKind & ARM::AEK_HWDIVARM) + Features.push_back("+hwdiv-arm"); + else + Features.push_back("-hwdiv-arm"); + + if (HWDivKind & ARM::AEK_HWDIV) + Features.push_back("+hwdiv"); + else + Features.push_back("-hwdiv"); + + return true; +} + bool ARMTargetParser::getFPUFeatures(unsigned FPUKind, std::vector &Features) { @@ -372,9 +405,19 @@ unsigned ARMTargetParser::getArchAttr(unsigned ArchKind) { } const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) { - if (ArchExtKind >= ARM::AEK_LAST) - return nullptr; - return ARCHExtNames[ArchExtKind].Name; + for (const auto AE : ARCHExtNames) { + if (ArchExtKind == AE.ID) + return AE.Name; + } + return nullptr; +} + +const char *ARMTargetParser::getHWDivName(unsigned HWDivKind) { + for (const auto D : HWDivNames) { + if (HWDivKind == D.ID) + return D.Name; + } + return nullptr; } const char *ARMTargetParser::getDefaultCPU(StringRef Arch) { @@ -394,6 +437,12 @@ const char *ARMTargetParser::getDefaultCPU(StringRef Arch) { // Parsers // ======================================================= // +StringRef ARMTargetParser::getHWDivSynonym(StringRef HWDiv) { + return StringSwitch(HWDiv) + .Case("thumb,arm", "arm,thumb") + .Default(HWDiv); +} + StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) { return StringSwitch(FPU) .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported @@ -477,6 +526,15 @@ StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) { return A; } +unsigned ARMTargetParser::parseHWDiv(StringRef HWDiv) { + StringRef Syn = getHWDivSynonym(HWDiv); + for (const auto D : HWDivNames) { + if (Syn == D.Name) + return D.ID; + } + return ARM::AEK_INVALID; +} + unsigned ARMTargetParser::parseFPU(StringRef FPU) { StringRef Syn = getFPUSynonym(FPU); for (const auto F : FPUNames) { diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 7f982eeabb9..f5f12472437 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -578,7 +578,7 @@ void ARMAsmPrinter::emitAttributes() { // We consider krait as a "cortex-a9" + hwdiv CPU // Enable hwdiv through ".arch_extension idiv" if (STI.hasDivide() || STI.hasDivideInARMMode()) - ATS.emitArchExtension(ARM::AEK_HWDIV); + ATS.emitArchExtension(ARM::AEK_HWDIV | ARM::AEK_HWDIVARM); } else ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); } diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 8cc5a57a5e6..6d8377178e6 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -9971,7 +9971,7 @@ extern "C" void LLVMInitializeARMAsmParser() { // when we start to table-generate them, and we can use the ARM // flags below, that were generated by table-gen. static const struct { - const ARM::ArchExtKind Kind; + const unsigned Kind; const unsigned ArchCheck; const FeatureBitset Features; } Extensions[] = { @@ -9979,7 +9979,7 @@ static const struct { { ARM::AEK_CRYPTO, Feature_HasV8, {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} }, { ARM::AEK_FP, Feature_HasV8, {ARM::FeatureFPARMv8} }, - { ARM::AEK_HWDIV, Feature_HasV7 | Feature_IsNotMClass, + { (ARM::AEK_HWDIV | ARM::AEK_HWDIVARM), Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureHWDiv, ARM::FeatureHWDivARM} }, { ARM::AEK_MP, Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} }, { ARM::AEK_SIMD, Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} }, -- 2.34.1