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/lib/Target/SubtargetFeature.cpp b/lib/Target/SubtargetFeature.cpp
index 4669e0f..598f029 100644
--- a/lib/Target/SubtargetFeature.cpp
+++ b/lib/Target/SubtargetFeature.cpp
@@ -199,6 +199,43 @@
   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 @@
     // 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 @@
            << "\n";
     }
   }
+
   return Bits;
 }
 
diff --git a/lib/Target/Target.td b/lib/Target/Target.td
index 938e4cd..f98c414 100644
--- a/lib/Target/Target.td
+++ b/lib/Target/Target.td
@@ -338,7 +338,8 @@
 //===----------------------------------------------------------------------===//
 // 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 @@
   // 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;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index 94e69f5..89cb749 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -18,24 +18,28 @@
 
 //===----------------------------------------------------------------------===//
 // 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.