From: Bill Wendling Date: Fri, 4 May 2007 20:38:40 +0000 (+0000) Subject: Add an "implies" field to features. This indicates that, if the current X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4222d806faae71ecc794cfdaa873817873c2f3d8;p=oota-llvm.git Add an "implies" field to features. This indicates that, if the current feature is set, then the features in the implied list should be set also. The opposite is also enforced: if a feature in the implied list isn't set, then the feature that owns that implies list shouldn't be set either. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36756 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h index f6a83dfbdbf..e809fc0a2cc 100644 --- a/include/llvm/Target/SubtargetFeature.h +++ b/include/llvm/Target/SubtargetFeature.h @@ -34,6 +34,7 @@ struct SubtargetFeatureKV { const char *Key; // K-V key string const char *Desc; // Help descriptor uint32_t Value; // K-V integer value + uint32_t Implies; // K-V bit mask // Compare routine for std binary search bool operator<(const SubtargetFeatureKV &S) const { diff --git a/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp index 4669e0fdc3c..598f02982b0 100644 --- a/lib/Target/SubtargetFeature.cpp +++ b/lib/Target/SubtargetFeature.cpp @@ -199,6 +199,43 @@ void SubtargetFeatures::setCPUIfNone(const std::string &String) { if (Features[0].empty()) setCPU(String); } +/// SetImpliedBits - For each feature that is (transitively) implied by this +/// feature, set it. +/// +static +void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FeatureEntry->Implies & FE.Value) { + Bits |= FE.Value; + SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} + +/// ClearImpliedBits - For each feature that (transitively) implies this +/// feature, clear it. +/// +static +void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize) { + for (size_t i = 0; i < FeatureTableSize; ++i) { + const SubtargetFeatureKV &FE = FeatureTable[i]; + + if (FeatureEntry->Value == FE.Value) continue; + + if (FE.Implies & FeatureEntry->Value) { + Bits &= ~FE.Value; + ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize); + } + } +} /// getBits - Get feature bits. /// @@ -251,8 +288,17 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, // If there is a match if (FeatureEntry) { // Enable/disable feature in bits - if (isEnabled(Feature)) Bits |= FeatureEntry->Value; - else Bits &= ~FeatureEntry->Value; + if (isEnabled(Feature)) { + Bits |= FeatureEntry->Value; + + // For each feature that this implies, set it. + SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } else { + Bits &= ~FeatureEntry->Value; + + // For each feature that implies this, clear it. + ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize); + } } else { cerr << "'" << Feature << "' is not a recognized feature for this target" @@ -260,6 +306,7 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable, << "\n"; } } + return Bits; } diff --git a/lib/Target/Target.td b/lib/Target/Target.td index 938e4cdc8fb..f98c414d34c 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -338,7 +338,8 @@ class Target { //===----------------------------------------------------------------------===// // SubtargetFeature - A characteristic of the chip set. // -class SubtargetFeature { +class SubtargetFeature i = []> { // Name - Feature name. Used by command line (-mattr=) to determine the // appropriate target chip. // @@ -356,6 +357,11 @@ class SubtargetFeature { // information. // string Desc = d; + + // Implies - Features that this feature implies are present. If one of those + // features isn't set, then this one shouldn't be set either. + // + list Implies = i; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 94e69f5a36f..89cb749d646 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -18,24 +18,28 @@ include "../Target.td" //===----------------------------------------------------------------------===// // X86 Subtarget features. -// +//===----------------------------------------------------------------------===// -def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", - "Support 64-bit instructions">; -def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", - "Enable MMX instructions">; -def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", - "Enable SSE instructions">; -def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", - "Enable SSE2 instructions">; -def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", - "Enable SSE3 instructions">; -def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", - "Enable SSSE3 instructions">; -def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions">; -def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", - "Enable 3DNow! Athlon instructions">; +def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", + "Support 64-bit instructions">; +def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX", + "Enable MMX instructions">; +def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", + "Enable SSE instructions", + [FeatureMMX]>; +def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", + "Enable SSE2 instructions", + [FeatureSSE1]>; +def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3", + "Enable SSE3 instructions", + [FeatureSSE2]>; +def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3", + "Enable SSSE3 instructions", + [FeatureSSE3]>; +def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", + "Enable 3DNow! instructions">; +def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", + "Enable 3DNow! Athlon instructions">; //===----------------------------------------------------------------------===// // X86 processors supported. diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index f6c7a44f347..fc913e69e12 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -56,8 +56,7 @@ void SubtargetEmitter::Enumeration(std::ostream &OS, Record *Def = DefList[i]; // Get and emit name - std::string Name = Def->getName(); - OS << " " << Name; + OS << " " << Def->getName(); // If bit flags then emit expression (1 << i) if (isBits) OS << " = " << " 1 << " << i; @@ -73,8 +72,8 @@ void SubtargetEmitter::Enumeration(std::ostream &OS, } // -// FeatureKeyValues - Emit data of all the subtarget features. Used by command -// line. +// FeatureKeyValues - Emit data of all the subtarget features. Used by the +// command line. // void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { // Gather and sort all the features @@ -91,18 +90,31 @@ void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) { // Next feature Record *Feature = FeatureList[i]; - std::string Name = Feature->getName(); - std::string CommandLineName = Feature->getValueAsString("Name"); - std::string Desc = Feature->getValueAsString("Desc"); + const std::string &Name = Feature->getName(); + const std::string &CommandLineName = Feature->getValueAsString("Name"); + const std::string &Desc = Feature->getValueAsString("Desc"); if (CommandLineName.empty()) continue; - // Emit as { "feature", "decription", feactureEnum } + // Emit as { "feature", "decription", feactureEnum, i1 | i2 | ... | in } OS << " { " << "\"" << CommandLineName << "\", " << "\"" << Desc << "\", " - << Name - << " }"; + << Name << ", "; + + const std::vector &ImpliesList = + Feature->getValueAsListOfDefs("Implies"); + + if (ImpliesList.empty()) { + OS << "0"; + } else { + for (unsigned j = 0, M = ImpliesList.size(); j < M;) { + OS << ImpliesList[j]->getName(); + if (++j < M) OS << " | "; + } + } + + OS << " }"; // Depending on 'if more in the list' emit comma if ((i + 1) < N) OS << ","; @@ -138,8 +150,8 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { // Next processor Record *Processor = ProcessorList[i]; - std::string Name = Processor->getValueAsString("Name"); - std::vector FeatureList = + const std::string &Name = Processor->getValueAsString("Name"); + const std::vector &FeatureList = Processor->getValueAsListOfDefs("Features"); // Emit as { "cpu", "description", f1 | f2 | ... fn }, @@ -151,14 +163,13 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) { OS << "0"; } else { for (unsigned j = 0, M = FeatureList.size(); j < M;) { - Record *Feature = FeatureList[j]; - std::string Name = Feature->getName(); - OS << Name; + OS << FeatureList[j]->getName(); if (++j < M) OS << " | "; } } - OS << " }"; + // The "0" is for the "implies" section of this data structure. + OS << ", 0 }"; // Depending on 'if more in the list' emit comma if (++i < N) OS << ","; @@ -190,11 +201,10 @@ unsigned SubtargetEmitter::CollectAllItinClasses(std::ostream &OS, unsigned N = ItinClassList.size(); for (unsigned i = 0; i < N; i++) { // Next itinerary class - Record *ItinClass = ItinClassList[i]; + const Record *ItinClass = ItinClassList[i]; // Get name of itinerary class - std::string Name = ItinClass->getName(); // Assign itinerary class a unique number - ItinClassesMap[Name] = i; + ItinClassesMap[ItinClass->getName()] = i; } // Emit size of table @@ -214,28 +224,26 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData, std::string &ItinString, unsigned &NStages) { // Get states list - std::vector StageList = ItinData->getValueAsListOfDefs("Stages"); + const std::vector &StageList = + ItinData->getValueAsListOfDefs("Stages"); // For each stage unsigned N = NStages = StageList.size(); for (unsigned i = 0; i < N;) { // Next stage - Record *Stage = StageList[i]; + const Record *Stage = StageList[i]; // Form string as ,{ cycles, u1 | u2 | ... | un } int Cycles = Stage->getValueAsInt("Cycles"); ItinString += " { " + itostr(Cycles) + ", "; // Get unit list - std::vector UnitList = Stage->getValueAsListOfDefs("Units"); + const std::vector &UnitList = Stage->getValueAsListOfDefs("Units"); // For each unit for (unsigned j = 0, M = UnitList.size(); j < M;) { - // Next unit - Record *Unit = UnitList[j]; - // Add name and bitwise or - ItinString += Unit->getName(); + ItinString += UnitList[j]->getName(); if (++j < M) ItinString += " | "; } @@ -271,7 +279,7 @@ void SubtargetEmitter::EmitStageData(std::ostream &OS, Record *Proc = ProcItinList[i]; // Get processor itinerary name - std::string Name = Proc->getName(); + const std::string &Name = Proc->getName(); // Skip default if (Name == "NoItineraries") continue; @@ -308,7 +316,7 @@ void SubtargetEmitter::EmitStageData(std::ostream &OS, InstrItinerary Intinerary = { Find, Find + NStages }; // Locate where to inject into processor itinerary table - std::string Name = ItinData->getValueAsDef("TheClass")->getName(); + const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); Find = ItinClassesMap[Name]; // Inject - empty slots will be 0, 0 @@ -347,7 +355,7 @@ void SubtargetEmitter::EmitProcessorData(std::ostream &OS, Record *Itin = Itins[i]; // Get processor itinerary name - std::string Name = Itin->getName(); + const std::string &Name = Itin->getName(); // Skip default if (Name == "NoItineraries") continue; @@ -398,8 +406,9 @@ void SubtargetEmitter::EmitProcessorLookup(std::ostream &OS) { // Next processor Record *Processor = ProcessorList[i]; - std::string Name = Processor->getValueAsString("Name"); - std::string ProcItin = Processor->getValueAsDef("ProcItin")->getName(); + const std::string &Name = Processor->getValueAsString("Name"); + const std::string &ProcItin = + Processor->getValueAsDef("ProcItin")->getName(); // Emit as { "cpu", procinit }, OS << " { " @@ -456,33 +465,32 @@ void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) { std::sort(Features.begin(), Features.end(), LessRecord()); OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" - "// subtarget options.\n" - "void llvm::"; + << "// subtarget options.\n" + << "void llvm::"; OS << Target; OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" - " const std::string &CPU) {\n" - " SubtargetFeatures Features(FS);\n" - " Features.setCPUIfNone(CPU);\n" - " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" - " FeatureKV, FeatureKVSize);\n"; - + << " const std::string &CPU) {\n" + << " SubtargetFeatures Features(FS);\n" + << " Features.setCPUIfNone(CPU);\n" + << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" + << " FeatureKV, FeatureKVSize);\n"; + for (unsigned i = 0; i < Features.size(); i++) { // Next record Record *R = Features[i]; - std::string Instance = R->getName(); - std::string Name = R->getValueAsString("Name"); - std::string Value = R->getValueAsString("Value"); - std::string Attribute = R->getValueAsString("Attribute"); + const std::string &Instance = R->getName(); + const std::string &Value = R->getValueAsString("Value"); + const std::string &Attribute = R->getValueAsString("Attribute"); OS << " if ((Bits & " << Instance << ") != 0) " << Attribute << " = " << Value << ";\n"; } - + if (HasItineraries) { OS << "\n" << " InstrItinerary *Itinerary = (InstrItinerary *)" - "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" - " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; + << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" + << " InstrItins = InstrItineraryData(Stages, Itinerary);\n"; } OS << "}\n";