[llvm-branch-commits] [llvm-branch] r164517 - in /llvm/branches/R600: include/llvm/Target/TargetSchedule.td utils/TableGen/CodeGenSchedule.cpp utils/TableGen/CodeGenSchedule.h utils/TableGen/SubtargetEmitter.cpp

Tom Stellard thomas.stellard at amd.com
Mon Sep 24 08:53:48 PDT 2012


Author: tstellar
Date: Mon Sep 24 10:52:10 2012
New Revision: 164517

URL: http://llvm.org/viewvc/llvm-project?rev=164517&view=rev
Log:
Machine Model (-schedmodel only). Added SchedAliases.

Allow subtargets to tie SchedReadWrite types to processor specific
sequences or variants.

Modified:
    llvm/branches/R600/include/llvm/Target/TargetSchedule.td
    llvm/branches/R600/utils/TableGen/CodeGenSchedule.cpp
    llvm/branches/R600/utils/TableGen/CodeGenSchedule.h
    llvm/branches/R600/utils/TableGen/SubtargetEmitter.cpp

Modified: llvm/branches/R600/include/llvm/Target/TargetSchedule.td
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/R600/include/llvm/Target/TargetSchedule.td?rev=164517&r1=164516&r2=164517&view=diff
==============================================================================
--- llvm/branches/R600/include/llvm/Target/TargetSchedule.td (original)
+++ llvm/branches/R600/include/llvm/Target/TargetSchedule.td Mon Sep 24 10:52:10 2012
@@ -101,6 +101,10 @@
 // cycle that the instruction issues in-order, forcing an interlock
 // with subsequent instructions that require the same resource until
 // the number of ResourceCyles specified in WriteRes expire.
+//
+// SchedModel ties these units to a processor for any stand-alone defs
+// of this class. Instances of subclass ProcResource will be automatically
+// attached to a processor, so SchedModel is not needed.
 class ProcResourceUnits<ProcResourceKind kind, int num> {
   ProcResourceKind Kind = kind;
   int NumUnits = num;
@@ -152,12 +156,17 @@
 // If the final write in this sequence is a SchedWriteVariant marked
 // Variadic, then the list of prior writes are distributed across all
 // operands after resolving the predicate for the final write.
+//
+// SchedModel silences warnings but is ignored.
 class WriteSequence<list<SchedWrite> writes, int rep = 1> : SchedWrite {
   list<SchedWrite> Writes = writes;
   int Repeat = rep;
+  SchedMachineModel SchedModel = ?;
 }
 
 // Define values common to WriteRes and SchedWriteRes.
+//
+// SchedModel ties these resources to a processor.
 class ProcWriteResources<list<ProcResourceKind> resources> {
   list<ProcResourceKind> ProcResources = resources;
   list<int> ResourceCycles = [];
@@ -217,12 +226,15 @@
   ProcWriteResources<resources>;
 
 // Define values common to ReadAdvance and SchedReadAdvance.
+//
+// SchedModel ties these resources to a processor.
 class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> {
   int Cycles = cycles;
   list<SchedWrite> ValidWrites = writes;
   // Allow a processor to mark some scheduling classes as unsupported
   // for stronger verification.
   bit Unsupported = 0;
+  SchedMachineModel SchedModel = ?;
 }
 
 // A processor may define a ReadAdvance associated with a SchedRead
@@ -237,7 +249,6 @@
 // to issue earlier relative to the writer.
 class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = []>
   : ProcReadAdvance<cycles, writes> {
-  SchedMachineModel SchedModel = ?;
   SchedRead ReadType = read;
 }
 
@@ -261,6 +272,8 @@
 // particular MachineInstr. The code snippet is used as an
 // if-statement's expression. Available variables are MI, SchedModel,
 // and anything defined in a PredicateProlog.
+//
+// SchedModel silences warnings but is ignored.
 class SchedPredicate<code pred> {
   SchedMachineModel SchedModel = ?;
   code Predicate = pred;
@@ -281,6 +294,7 @@
   list<SchedReadWrite> Selected = selected;
 }
 
+// SchedModel silences warnings but is ignored.
 class SchedVariant<list<SchedVar> variants> {
   list<SchedVar> Variants = variants;
   bit Variadic = 0;
@@ -309,6 +323,8 @@
 
 // Map a set of opcodes to a list of SchedReadWrite types. This allows
 // the subtarget to easily override specific operations.
+//
+// SchedModel ties this opcode mapping to a processor.
 class InstRW<list<SchedReadWrite> rw, list<Instruction> instrs> {
   list<SchedReadWrite> OperandReadWrites = rw;
   list<Instruction> Instrs = instrs;
@@ -318,8 +334,23 @@
 // Map a set of itinerary classes to SchedReadWrite resources. This is
 // used to bootstrap a target (e.g. ARM) when itineraries already
 // exist and changing InstrInfo is undesirable.
+//
+// SchedModel ties this ItineraryClass mapping to a processor.
 class ItinRW<list<SchedReadWrite> rw, list<InstrItinClass> iic> {
   list<InstrItinClass> MatchedItinClasses = iic;
   list<SchedReadWrite> OperandReadWrites = rw;
   SchedMachineModel SchedModel = ?;
 }
+
+// Alias a target-defined SchedReadWrite to a processor specific
+// SchedReadWrite. This allows a subtarget to easily map a
+// SchedReadWrite type onto a WriteSequence, SchedWriteVariant, or
+// SchedReadVariant.
+//
+// SchedModel will usually be provided by surrounding let statement
+// and ties this SchedAlias mapping to a processor.
+class SchedAlias<SchedReadWrite match, SchedReadWrite alias> {
+  SchedReadWrite MatchRW = match;
+  SchedReadWrite AliasRW = alias;
+  SchedMachineModel SchedModel = ?;
+}

Modified: llvm/branches/R600/utils/TableGen/CodeGenSchedule.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/R600/utils/TableGen/CodeGenSchedule.cpp?rev=164517&r1=164516&r2=164517&view=diff
==============================================================================
--- llvm/branches/R600/utils/TableGen/CodeGenSchedule.cpp (original)
+++ llvm/branches/R600/utils/TableGen/CodeGenSchedule.cpp Mon Sep 24 10:52:10 2012
@@ -61,7 +61,7 @@
   collectSchedClasses();
 
   // Find instruction itineraries for each processor. Sort and populate
-  // CodeGenProcMode::ItinDefList. (Cycle-to-cycle itineraries). This requires
+  // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
   // all itinerary classes to be discovered.
   collectProcItins();
 
@@ -204,6 +204,25 @@
       }
     }
   }
+  // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
+  // for the loop below that initializes Alias vectors.
+  RecVec AliasDefs = Records.getAllDerivedDefinitions("SchedAlias");
+  std::sort(AliasDefs.begin(), AliasDefs.end(), LessRecord());
+  for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {
+    Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
+    Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
+    if (MatchDef->isSubClassOf("SchedWrite")) {
+      if (!AliasDef->isSubClassOf("SchedWrite"))
+        throw TGError((*AI)->getLoc(), "SchedWrite Alias must be SchedWrite");
+      scanSchedRW(AliasDef, SWDefs, RWSet);
+    }
+    else {
+      assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
+      if (!AliasDef->isSubClassOf("SchedRead"))
+        throw TGError((*AI)->getLoc(), "SchedRead Alias must be SchedRead");
+      scanSchedRW(AliasDef, SRDefs, RWSet);
+    }
+  }
   // Sort and add the SchedReadWrites directly referenced by instructions or
   // itinerary resources. Index reads and writes in separate domains.
   std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
@@ -224,6 +243,16 @@
     findRWs(WI->TheDef->getValueAsListOfDefs("Writes"), WI->Sequence,
             /*IsRead=*/false);
   }
+  // Initialize Aliases vectors.
+  for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {
+    Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
+    getSchedRW(AliasDef).IsAlias = true;
+    Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
+    CodeGenSchedRW &RW = getSchedRW(MatchDef);
+    if (RW.IsAlias)
+      throw TGError((*AI)->getLoc(), "Cannot Alias an Alias");
+    RW.Aliases.push_back(*AI);
+  }
   DEBUG(
     for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) {
       dbgs() << WIdx << ": ";
@@ -412,7 +441,7 @@
     IdxVec ProcIndices(1, 0);
     addSchedClass(Writes, Reads, ProcIndices);
   }
-  // Create classes for InstReadWrite defs.
+  // Create classes for InstRW defs.
   RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
   std::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord());
   for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI)
@@ -766,6 +795,17 @@
 }
 
 namespace {
+// Helper for substituteVariantOperand.
+struct TransVariant {
+  Record *VariantDef;
+  unsigned RWIdx;       // Index of this variant's matched type.
+  unsigned ProcIdx;     // Processor model index or zero for any.
+  unsigned TransVecIdx; // Index into PredTransitions::TransVec.
+
+  TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
+    VariantDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
+};
+
 // Associate a predicate with the SchedReadWrite that it guards.
 // RWIdx is the index of the read/write variant.
 struct PredCheck {
@@ -782,6 +822,7 @@
   SmallVector<PredCheck, 4> PredTerm;
   SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
   SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
+  SmallVector<unsigned, 4> ProcIndices;
 };
 
 // Encapsulate a set of partially constructed transitions.
@@ -805,8 +846,7 @@
 
 private:
   bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
-  void pushVariant(unsigned SchedRW, Record *Variant, PredTransition &Trans,
-                   bool IsRead);
+  void pushVariant(const TransVariant &VInfo, bool IsRead);
 };
 } // anonymous
 
@@ -838,16 +878,26 @@
   return false;
 }
 
-// Push the Reads/Writes selected by this variant onto the given PredTransition.
-void PredTransitions::pushVariant(unsigned RWIdx, Record *Variant,
-                                  PredTransition &Trans, bool IsRead) {
-  Trans.PredTerm.push_back(
-    PredCheck(IsRead, RWIdx, Variant->getValueAsDef("Predicate")));
-  RecVec SelectedDefs = Variant->getValueAsListOfDefs("Selected");
+// Push the Reads/Writes selected by this variant onto the PredTransition
+// specified by VInfo.
+void PredTransitions::
+pushVariant(const TransVariant &VInfo, bool IsRead) {
+
+  PredTransition &Trans = TransVec[VInfo.TransVecIdx];
+
+  Record *PredDef = VInfo.VariantDef->getValueAsDef("Predicate");
+  Trans.PredTerm.push_back(PredCheck(IsRead, VInfo.RWIdx,PredDef));
+
+  // If this operand transition is reached through a processor-specific alias,
+  // then the whole transition is specific to this processor.
+  if (VInfo.ProcIdx != 0)
+    Trans.ProcIndices.assign(1, VInfo.ProcIdx);
+
+  RecVec SelectedDefs = VInfo.VariantDef->getValueAsListOfDefs("Selected");
   IdxVec SelectedRWs;
   SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
 
-  const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(RWIdx, IsRead);
+  const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
 
   SmallVectorImpl<SmallVector<unsigned,4> > &RWSequences = IsRead
     ? Trans.ReadSequences : Trans.WriteSequences;
@@ -889,9 +939,48 @@
   }
 }
 
+static bool hasAliasedVariants(const CodeGenSchedRW &RW,
+                               CodeGenSchedModels &SchedModels) {
+  if (RW.HasVariants)
+    return true;
+
+  for (RecIter I = RW.Aliases.begin(), E = RW.Aliases.end(); I != E; ++I) {
+    if (SchedModels.getSchedRW((*I)->getValueAsDef("AliasRW")).HasVariants)
+      return true;
+  }
+  return false;
+}
+
+static bool hasVariant(ArrayRef<PredTransition> Transitions,
+                       CodeGenSchedModels &SchedModels) {
+  for (ArrayRef<PredTransition>::iterator
+         PTI = Transitions.begin(), PTE = Transitions.end();
+       PTI != PTE; ++PTI) {
+    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+           WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end();
+         WSI != WSE; ++WSI) {
+      for (SmallVectorImpl<unsigned>::const_iterator
+             WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
+        if (hasAliasedVariants(SchedModels.getSchedWrite(*WI), SchedModels))
+          return true;
+      }
+    }
+    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
+           RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end();
+         RSI != RSE; ++RSI) {
+      for (SmallVectorImpl<unsigned>::const_iterator
+             RI = RSI->begin(), RE = RSI->end(); RI != RE; ++RI) {
+        if (hasAliasedVariants(SchedModels.getSchedRead(*RI), SchedModels))
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
 // RWSeq is a sequence of all Reads or all Writes for the next read or write
 // operand. StartIdx is an index into TransVec where partial results
-// starts. RWSeq must be applied to all tranistions between StartIdx and the end
+// starts. RWSeq must be applied to all transitions between StartIdx and the end
 // of TransVec.
 void PredTransitions::substituteVariantOperand(
   const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
@@ -906,7 +995,7 @@
     for (unsigned TransIdx = StartIdx, TransEnd = TransVec.size();
          TransIdx != TransEnd; ++TransIdx) {
       // In the common case, push RW onto the current operand's sequence.
-      if (!SchedRW.HasVariants) {
+      if (!hasAliasedVariants(SchedRW, SchedModels)) {
         if (IsRead)
           TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
         else
@@ -914,28 +1003,74 @@
         continue;
       }
       // Distribute this partial PredTransition across intersecting variants.
-      RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
-      std::vector<std::pair<Record*,unsigned> > IntersectingVariants;
-      for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) {
-        Record *PredDef = (*VI)->getValueAsDef("Predicate");
+      RecVec Variants;
+      if (SchedRW.HasVariants)
+        Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
+      IdxVec VarRWIds(Variants.size(), *RWI);
+      IdxVec VarProcModels(Variants.size(), 0);
+      for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+           AI != AE; ++AI) {
+        unsigned AIdx;
+        const CodeGenSchedRW &AliasRW =
+          SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"), AIdx);
+        if (!AliasRW.HasVariants)
+          continue;
+
+        RecVec AliasVars = AliasRW.TheDef->getValueAsListOfDefs("Variants");
+        Variants.insert(Variants.end(), AliasVars.begin(), AliasVars.end());
+
+        VarRWIds.resize(Variants.size(), AIdx);
+
+        Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+        VarProcModels.resize(Variants.size(),
+                             SchedModels.getProcModel(ModelDef).Index);
+      }
+      std::vector<TransVariant> IntersectingVariants;
+      for (unsigned VIdx = 0, VEnd = Variants.size(); VIdx != VEnd; ++VIdx) {
+        Record *PredDef = Variants[VIdx]->getValueAsDef("Predicate");
+
+        // Don't expand variants if the processor models don't intersect.
+        // A zero processor index means any processor.
+        SmallVector<unsigned, 4> &ProcIndices = TransVec[TransIdx].ProcIndices;
+        if (ProcIndices[0] != 0 && VarProcModels[VIdx] != 0) {
+          unsigned Cnt = std::count(ProcIndices.begin(), ProcIndices.end(),
+                                    VarProcModels[VIdx]);
+          if (!Cnt)
+            continue;
+          if (Cnt > 1) {
+            const CodeGenProcModel &PM =
+              *(SchedModels.procModelBegin() + VarProcModels[VIdx]);
+            throw TGError(Variants[VIdx]->getLoc(), "Multiple variants defined "
+                          "for processor " + PM.ModelName +
+                          " Ensure only one SchedAlias exists per RW.");
+          }
+        }
         if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
           continue;
-        if (IntersectingVariants.empty())
+        if (IntersectingVariants.empty()) {
           // The first variant builds on the existing transition.
-          IntersectingVariants.push_back(std::make_pair(*VI, TransIdx));
+          IntersectingVariants.push_back(
+            TransVariant(Variants[VIdx], VarRWIds[VIdx], VarProcModels[VIdx],
+                         TransIdx));
+        }
         else {
           // Push another copy of the current transition for more variants.
           IntersectingVariants.push_back(
-            std::make_pair(*VI, TransVec.size()));
+            TransVariant(Variants[VIdx], VarRWIds[VIdx], VarProcModels[VIdx],
+                         TransVec.size()));
           TransVec.push_back(TransVec[TransIdx]);
         }
       }
+      if (IntersectingVariants.empty())
+        throw TGError(SchedRW.TheDef->getLoc(), "No variant of this type has a "
+                      "matching predicate on any processor ");
       // Now expand each variant on top of its copy of the transition.
-      for (std::vector<std::pair<Record*, unsigned> >::const_iterator
+      for (std::vector<TransVariant>::const_iterator
              IVI = IntersectingVariants.begin(),
              IVE = IntersectingVariants.end();
-           IVI != IVE; ++IVI)
-        pushVariant(*RWI, IVI->first, TransVec[IVI->second], IsRead);
+           IVI != IVE; ++IVI) {
+        pushVariant(*IVI, IsRead);
+      }
     }
   }
 }
@@ -952,6 +1087,7 @@
   unsigned StartIdx = TransVec.size();
   TransVec.resize(TransVec.size() + 1);
   TransVec.back().PredTerm = Trans.PredTerm;
+  TransVec.back().ProcIndices = Trans.ProcIndices;
 
   // Visit each original write sequence.
   for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
@@ -977,37 +1113,9 @@
   }
 }
 
-static bool hasVariant(ArrayRef<PredTransition> Transitions,
-                       CodeGenSchedModels &SchedModels) {
-  for (ArrayRef<PredTransition>::iterator
-         PTI = Transitions.begin(), PTE = Transitions.end();
-       PTI != PTE; ++PTI) {
-    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
-           WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end();
-         WSI != WSE; ++WSI) {
-      for (SmallVectorImpl<unsigned>::const_iterator
-             WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
-        if (SchedModels.getSchedWrite(*WI).HasVariants)
-          return true;
-      }
-    }
-    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
-           RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end();
-         RSI != RSE; ++RSI) {
-      for (SmallVectorImpl<unsigned>::const_iterator
-             RI = RSI->begin(), RE = RSI->end(); RI != RE; ++RI) {
-        if (SchedModels.getSchedRead(*RI).HasVariants)
-          return true;
-      }
-    }
-  }
-  return false;
-}
-
 // Create a new SchedClass for each variant found by inferFromRW. Pass
-// ProcIndices by copy to avoid referencing anything from SchedClasses.
 static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
-                                 unsigned FromClassIdx, IdxVec ProcIndices,
+                                 unsigned FromClassIdx,
                                  CodeGenSchedModels &SchedModels) {
   // For each PredTransition, create a new CodeGenSchedTransition, which usually
   // requires creating a new SchedClass.
@@ -1025,10 +1133,11 @@
     for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
            RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end();
          RSI != RSE; ++RSI) {
-      // Create a new write representing the expanded sequence.
+      // Create a new read representing the expanded sequence.
       OperReadsVariant.push_back(
         SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true));
     }
+    IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end());
     CodeGenSchedTransition SCTrans;
     SCTrans.ToClassIdx =
       SchedModels.addSchedClass(OperWritesVariant, OperReadsVariant,
@@ -1047,18 +1156,22 @@
   }
 }
 
-/// Find each variant write that OperWrites or OperaReads refers to and create a
-/// new SchedClass for each variant.
+// Create new SchedClasses for the given ReadWrite list. If any of the
+// ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
+// of the ReadWrite list, following Aliases if necessary.
 void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
                                      const IdxVec &OperReads,
                                      unsigned FromClassIdx,
                                      const IdxVec &ProcIndices) {
-  DEBUG(dbgs() << "INFERRW Writes: ");
+  DEBUG(dbgs() << "INFER RW: ");
 
   // Create a seed transition with an empty PredTerm and the expanded sequences
   // of SchedWrites for the current SchedClass.
   std::vector<PredTransition> LastTransitions;
   LastTransitions.resize(1);
+  LastTransitions.back().ProcIndices.append(ProcIndices.begin(),
+                                            ProcIndices.end());
+
   for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) {
     IdxVec WriteSeq;
     expandRWSequence(*I, WriteSeq, /*IsRead=*/false);
@@ -1100,7 +1213,7 @@
 
   // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
   // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
-  inferFromTransitions(LastTransitions, FromClassIdx, ProcIndices, *this);
+  inferFromTransitions(LastTransitions, FromClassIdx, *this);
 }
 
 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
@@ -1200,6 +1313,15 @@
         addWriteRes(SchedRW.TheDef, *PI);
       }
     }
+    for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+         AI != AE; ++AI) {
+      const CodeGenSchedRW &AliasRW =
+        getSchedRW((*AI)->getValueAsDef("AliasRW"));
+      if (AliasRW.TheDef && AliasRW.TheDef->isSubClassOf("SchedWriteRes")) {
+        Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+        addWriteRes(AliasRW.TheDef, getProcModel(ModelDef).Index);
+      }
+    }
   }
   for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) {
     const CodeGenSchedRW &SchedRW = getSchedRW(*RI, /*IsRead=*/true);
@@ -1209,6 +1331,15 @@
         addReadAdvance(SchedRW.TheDef, *PI);
       }
     }
+    for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+         AI != AE; ++AI) {
+      const CodeGenSchedRW &AliasRW =
+        getSchedRW((*AI)->getValueAsDef("AliasRW"));
+      if (AliasRW.TheDef && AliasRW.TheDef->isSubClassOf("SchedReadAdvance")) {
+        Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+        addReadAdvance(AliasRW.TheDef, getProcModel(ModelDef).Index);
+      }
+    }
   }
 }
 
@@ -1265,6 +1396,8 @@
 
 // Add resources for a SchedWrite to this processor if they don't exist.
 void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
+  assert(PIdx && "don't add resources to an invalid Processor model");
+
   RecVec &WRDefs = ProcModels[PIdx].WriteResDefs;
   RecIter WRI = std::find(WRDefs.begin(), WRDefs.end(), ProcWriteResDef);
   if (WRI != WRDefs.end())

Modified: llvm/branches/R600/utils/TableGen/CodeGenSchedule.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/R600/utils/TableGen/CodeGenSchedule.h?rev=164517&r1=164516&r2=164517&view=diff
==============================================================================
--- llvm/branches/R600/utils/TableGen/CodeGenSchedule.h (original)
+++ llvm/branches/R600/utils/TableGen/CodeGenSchedule.h Mon Sep 24 10:52:10 2012
@@ -45,14 +45,16 @@
 struct CodeGenSchedRW {
   std::string Name;
   Record *TheDef;
+  bool IsAlias;
   bool HasVariants;
   bool IsVariadic;
   bool IsSequence;
   IdxVec Sequence;
+  RecVec Aliases;
 
-  CodeGenSchedRW(): TheDef(0), HasVariants(false), IsVariadic(false),
-                    IsSequence(false) {}
-  CodeGenSchedRW(Record *Def): TheDef(Def), IsVariadic(false) {
+  CodeGenSchedRW(): TheDef(0), IsAlias(false), HasVariants(false),
+                    IsVariadic(false), IsSequence(false) {}
+  CodeGenSchedRW(Record *Def): TheDef(Def), IsAlias(false), IsVariadic(false) {
     Name = Def->getName();
     HasVariants = Def->isSubClassOf("SchedVariant");
     if (HasVariants)
@@ -65,8 +67,8 @@
   }
 
   CodeGenSchedRW(const IdxVec &Seq, const std::string &Name):
-    Name(Name), TheDef(0), HasVariants(false), IsVariadic(false),
-    IsSequence(true), Sequence(Seq) {
+    Name(Name), TheDef(0), IsAlias(false), HasVariants(false),
+    IsVariadic(false), IsSequence(true), Sequence(Seq) {
     assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
   }
 
@@ -75,6 +77,7 @@
     assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
     assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
     assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
+    assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");
     return TheDef || !Sequence.empty();
   }
 
@@ -125,8 +128,10 @@
 
   std::vector<CodeGenSchedTransition> Transitions;
 
-  // InstReadWrite records associated with this class. Any Instrs that the
-  // definitions refer to that are not mapped to this class should be ignored.
+  // InstRW records associated with this class. These records may refer to an
+  // Instruction no longer mapped to this class by InstrClassMap. These
+  // Instructions should be ignored by this class because they have been split
+  // off to join another inferred class.
   RecVec InstRWs;
 
   CodeGenSchedClass(): ItinClassDef(0) {}
@@ -229,7 +234,7 @@
   unsigned NumInstrSchedClasses;
 
   // Map Instruction to SchedClass index. Only for Instructions mentioned in
-  // OpReadWrites.
+  // InstRW records.
   typedef DenseMap<Record*, unsigned> InstClassMapTy;
   InstClassMapTy InstrClassMap;
 
@@ -281,6 +286,16 @@
   const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
     return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
   }
+  CodeGenSchedRW &getSchedRW(Record *Def, unsigned &Idx) {
+    bool IsRead = Def->isSubClassOf("SchedRead");
+    Idx = getSchedRWIdx(Def, IsRead);
+    return const_cast<CodeGenSchedRW&>(
+      IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
+  }
+  CodeGenSchedRW &getSchedRW(Record *Def) {
+    unsigned Idx;
+    return getSchedRW(Def, Idx);
+  }
 
   unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
 

Modified: llvm/branches/R600/utils/TableGen/SubtargetEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/R600/utils/TableGen/SubtargetEmitter.cpp?rev=164517&r1=164516&r2=164517&view=diff
==============================================================================
--- llvm/branches/R600/utils/TableGen/SubtargetEmitter.cpp (original)
+++ llvm/branches/R600/utils/TableGen/SubtargetEmitter.cpp Mon Sep 24 10:52:10 2012
@@ -81,9 +81,10 @@
                          char Separator);
   void EmitProcessorResources(const CodeGenProcModel &ProcModel,
                               raw_ostream &OS);
-  Record *FindWriteResources(Record *WriteDef,
+  Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
                              const CodeGenProcModel &ProcModel);
-  Record *FindReadAdvance(Record *ReadDef, const CodeGenProcModel &ProcModel);
+  Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
+                          const CodeGenProcModel &ProcModel);
   void GenSchedClassTables(const CodeGenProcModel &ProcModel,
                            SchedClassTables &SchedTables);
   void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
@@ -654,48 +655,107 @@
 // Find the WriteRes Record that defines processor resources for this
 // SchedWrite.
 Record *SubtargetEmitter::FindWriteResources(
-  Record *WriteDef, const CodeGenProcModel &ProcModel) {
+  const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
 
   // Check if the SchedWrite is already subtarget-specific and directly
   // specifies a set of processor resources.
-  if (WriteDef->isSubClassOf("SchedWriteRes"))
-    return WriteDef;
+  if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
+    return SchedWrite.TheDef;
+
+  // Check this processor's list of aliases for SchedWrite.
+  Record *AliasDef = 0;
+  for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
+       AI != AE; ++AI) {
+    const CodeGenSchedRW &AliasRW =
+      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+    Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+    if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
+      continue;
+    if (AliasDef)
+      throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+                    "defined for processor " + ProcModel.ModelName +
+                    " Ensure only one SchedAlias exists per RW.");
+    AliasDef = AliasRW.TheDef;
+  }
+  if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
+    return AliasDef;
 
   // Check this processor's list of write resources.
+  Record *ResDef = 0;
   for (RecIter WRI = ProcModel.WriteResDefs.begin(),
          WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
     if (!(*WRI)->isSubClassOf("WriteRes"))
       continue;
-    if (WriteDef == (*WRI)->getValueAsDef("WriteType"))
-      return *WRI;
+    if (AliasDef == (*WRI)->getValueAsDef("WriteType")
+        || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
+      if (ResDef) {
+        throw TGError((*WRI)->getLoc(), "Resources are defined for both "
+                      "SchedWrite and its alias on processor " +
+                      ProcModel.ModelName);
+      }
+      ResDef = *WRI;
+    }
   }
-  throw TGError(ProcModel.ModelDef->getLoc(),
-                std::string("Processor does not define resources for ")
-                + WriteDef->getName());
+  // TODO: If ProcModel has a base model (previous generation processor),
+  // then call FindWriteResources recursively with that model here.
+  if (!ResDef) {
+    throw TGError(ProcModel.ModelDef->getLoc(),
+                  std::string("Processor does not define resources for ")
+                  + SchedWrite.TheDef->getName());
+  }
+  return ResDef;
 }
 
 /// Find the ReadAdvance record for the given SchedRead on this processor or
 /// return NULL.
-Record *SubtargetEmitter::FindReadAdvance(Record *ReadDef,
+Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
                                           const CodeGenProcModel &ProcModel) {
   // Check for SchedReads that directly specify a ReadAdvance.
-  if (ReadDef->isSubClassOf("SchedReadAdvance"))
-    return ReadDef;
+  if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
+    return SchedRead.TheDef;
+
+  // Check this processor's list of aliases for SchedRead.
+  Record *AliasDef = 0;
+  for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
+       AI != AE; ++AI) {
+    const CodeGenSchedRW &AliasRW =
+      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+    Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+    if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
+      continue;
+    if (AliasDef)
+      throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+                    "defined for processor " + ProcModel.ModelName +
+                    " Ensure only one SchedAlias exists per RW.");
+    AliasDef = AliasRW.TheDef;
+  }
+  if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
+    return AliasDef;
 
   // Check this processor's ReadAdvanceList.
+  Record *ResDef = 0;
   for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
          RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
     if (!(*RAI)->isSubClassOf("ReadAdvance"))
       continue;
-    if (ReadDef == (*RAI)->getValueAsDef("ReadType"))
-      return *RAI;
+    if (AliasDef == (*RAI)->getValueAsDef("ReadType")
+        || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
+      if (ResDef) {
+        throw TGError((*RAI)->getLoc(), "Resources are defined for both "
+                      "SchedRead and its alias on processor " +
+                      ProcModel.ModelName);
+      }
+      ResDef = *RAI;
+    }
   }
-  if (ReadDef->getName() != "ReadDefault") {
+  // TODO: If ProcModel has a base model (previous generation processor),
+  // then call FindReadAdvance recursively with that model here.
+  if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
     throw TGError(ProcModel.ModelDef->getLoc(),
                   std::string("Processor does not define resources for ")
-                  + ReadDef->getName());
+                  + SchedRead.TheDef->getName());
   }
-  return NULL;
+  return ResDef;
 }
 
 // Generate the SchedClass table for this processor and update global
@@ -797,8 +857,8 @@
       for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
            WSI != WSE; ++WSI) {
 
-        Record *WriteDef = SchedModels.getSchedWrite(*WSI).TheDef;
-        Record *WriteRes = FindWriteResources(WriteDef, ProcModel);
+        Record *WriteRes =
+          FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
 
         // Mark the parent class as invalid for unsupported write types.
         if (WriteRes->getValueAsBit("Unsupported")) {
@@ -832,8 +892,8 @@
     // Entries must be sorted first by UseIdx then by WriteResourceID.
     for (unsigned UseIdx = 0, EndIdx = Reads.size();
          UseIdx != EndIdx; ++UseIdx) {
-      Record *ReadDef = SchedModels.getSchedRead(Reads[UseIdx]).TheDef;
-      Record *ReadAdvance = FindReadAdvance(ReadDef, ProcModel);
+      Record *ReadAdvance =
+        FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
       if (!ReadAdvance)
         continue;
 





More information about the llvm-branch-commits mailing list