Add an "implies" field to features. This indicates that, if the current
authorBill Wendling <isanbard@gmail.com>
Fri, 4 May 2007 20:38:40 +0000 (20:38 +0000)
committerBill Wendling <isanbard@gmail.com>
Fri, 4 May 2007 20:38:40 +0000 (20:38 +0000)
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

include/llvm/Target/SubtargetFeature.h
lib/Target/SubtargetFeature.cpp
lib/Target/Target.td
lib/Target/X86/X86.td
utils/TableGen/SubtargetEmitter.cpp

index f6a83dfbdbf21d8ae6bbac8be5ba56762ebf7635..e809fc0a2cc199ad6f898aff2f3eaf6740061a09 100644 (file)
@@ -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 {
index 4669e0fdc3cfa45952c6913eb04c15ddd0b1bff5..598f02982b0e6079c75d8315dd9a6a56ff70b868 100644 (file)
@@ -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;
 }
 
index 938e4cdc8fbf72092257d0921f195a0337bdad29..f98c414d34cd349e6a36455ab9a748908352ce1a 100644 (file)
@@ -338,7 +338,8 @@ class Target {
 //===----------------------------------------------------------------------===//
 // SubtargetFeature - A characteristic of the chip set.
 //
-class SubtargetFeature<string n, string a,  string v, string d> {
+class SubtargetFeature<string n, string a,  string v, string d,
+                       list<SubtargetFeature> i = []> {
   // Name - Feature name.  Used by command line (-mattr=) to determine the
   // appropriate target chip.
   //
@@ -356,6 +357,11 @@ class SubtargetFeature<string n, string a,  string v, string d> {
   // 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<SubtargetFeature> Implies = i;
 }
 
 //===----------------------------------------------------------------------===//
index 94e69f5a36f68c7825ba96e212b92c6d3de0dc9c..89cb749d6461b257be2ad3925cbd53adcc55c6e2 100644 (file)
@@ -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.
index f6c7a44f347e7f531fcf388cdb1aa08e7538842d..fc913e69e125e41eb66691c64d17f851720eb5c0 100644 (file)
@@ -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<Record*> &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<Record*> FeatureList = 
+    const std::string &Name = Processor->getValueAsString("Name");
+    const std::vector<Record*> &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<Record*> StageList = ItinData->getValueAsListOfDefs("Stages");
+  const std::vector<Record*> &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<Record*> UnitList = Stage->getValueAsListOfDefs("Units");
+    const std::vector<Record*> &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";