forked from OSchip/llvm-project
- Added support for parsing HWDiv features using Target Parser.
- Architecture extensions are represented as a bitmap. Phabricator: http://reviews.llvm.org/D11457 llvm-svn: 243335
This commit is contained in:
parent
fe2c8b8015
commit
4ea707555a
|
@ -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<const char*> &Features);
|
||||
static bool getHWDivFeatures(unsigned HWDivKind,
|
||||
std::vector<const char*> &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);
|
||||
|
|
|
@ -113,13 +113,14 @@ struct {
|
|||
// FIXME: TableGen this.
|
||||
struct {
|
||||
const char *Name;
|
||||
ARM::ArchExtKind ID;
|
||||
unsigned ID;
|
||||
} ARCHExtNames[] = {
|
||||
{ "invalid", ARM::AEK_INVALID },
|
||||
{ "none", ARM::AEK_NONE },
|
||||
{ "crc", ARM::AEK_CRC },
|
||||
{ "crypto", ARM::AEK_CRYPTO },
|
||||
{ "fp", ARM::AEK_FP },
|
||||
{ "idiv", ARM::AEK_HWDIV },
|
||||
{ "idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV) },
|
||||
{ "mp", ARM::AEK_MP },
|
||||
{ "simd", ARM::AEK_SIMD },
|
||||
{ "sec", ARM::AEK_SEC },
|
||||
|
@ -130,6 +131,19 @@ struct {
|
|||
{ "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.
|
||||
// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
|
||||
|
@ -266,6 +280,25 @@ unsigned ARMTargetParser::getDefaultFPU(StringRef CPU) {
|
|||
return ARM::FK_INVALID;
|
||||
}
|
||||
|
||||
bool ARMTargetParser::getHWDivFeatures(unsigned HWDivKind,
|
||||
std::vector<const char *> &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<const char *> &Features) {
|
||||
|
||||
|
@ -372,9 +405,19 @@ unsigned ARMTargetParser::getArchAttr(unsigned ArchKind) {
|
|||
}
|
||||
|
||||
const char *ARMTargetParser::getArchExtName(unsigned ArchExtKind) {
|
||||
if (ArchExtKind >= ARM::AEK_LAST)
|
||||
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;
|
||||
return ARCHExtNames[ArchExtKind].Name;
|
||||
}
|
||||
|
||||
const char *ARMTargetParser::getDefaultCPU(StringRef Arch) {
|
||||
|
@ -394,6 +437,12 @@ const char *ARMTargetParser::getDefaultCPU(StringRef Arch) {
|
|||
// Parsers
|
||||
// ======================================================= //
|
||||
|
||||
StringRef ARMTargetParser::getHWDivSynonym(StringRef HWDiv) {
|
||||
return StringSwitch<StringRef>(HWDiv)
|
||||
.Case("thumb,arm", "arm,thumb")
|
||||
.Default(HWDiv);
|
||||
}
|
||||
|
||||
StringRef ARMTargetParser::getFPUSynonym(StringRef FPU) {
|
||||
return StringSwitch<StringRef>(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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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} },
|
||||
|
|
Loading…
Reference in New Issue