Initial support for different kinds of FU reservation.
authorAnton Korobeynikov <asl@math.spbu.ru>
Wed, 7 Apr 2010 18:19:32 +0000 (18:19 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Wed, 7 Apr 2010 18:19:32 +0000 (18:19 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100645 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetInstrItineraries.h
include/llvm/Target/TargetSchedule.td
lib/CodeGen/ExactHazardRecognizer.cpp
lib/CodeGen/ExactHazardRecognizer.h
utils/TableGen/SubtargetEmitter.cpp

index 420fa94ce76bc97f7a14ad7e50cd2ef2129bc065..3dfa8bc10bfecd82e892d184843a6ad4f6624317 100644 (file)
@@ -47,10 +47,24 @@ namespace llvm {
 ///      indicate that the instruction requires multiple stages at the
 ///      same time.
 ///
+/// FU reservation can be of two different kinds:
+///  - FUs which instruction actually requires
+///  - FUs which instruction just reserves. Reserved unit is not available for
+///    execution of other instruction. However, several instructions can reserve
+///    the same unit several times.
+/// Such two types of units reservation is used to model instruction domain
+/// change stalls, FUs using the same resource (e.g. same register file), etc.
+
 struct InstrStage {
+  enum ReservationKinds {
+    Required = 0,
+    Reserved = 1
+  };
+
   unsigned Cycles_;  ///< Length of stage in machine cycles
   unsigned Units_;   ///< Choice of functional units
-  int NextCycles_;   ///< Number of machine cycles to next stage 
+  int NextCycles_;   ///< Number of machine cycles to next stage
+  ReservationKinds Kind_; ///< Kind of the FU reservation
 
   /// getCycles - returns the number of cycles the stage is occupied
   unsigned getCycles() const {
@@ -62,6 +76,10 @@ struct InstrStage {
     return Units_;
   }
 
+  ReservationKinds getReservationKind() const {
+    return Kind_;
+  }
+
   /// getNextCycles - returns the number of cycles from the start of
   /// this stage to the start of the next stage in the itinerary
   unsigned getNextCycles() const {
index dcc09921d9943d9aa0ba0f43ba7e8bc54b7332f0..bbf43dec58acc3f13f68ce9e330fee0a1302e396 100644 (file)
 //  
 class FuncUnit;
 
+class ReservationKind<bits<1> val> {
+  bits<1> Value = val;
+}
+
+def Required : ReservationKind<0>;
+def Reserved : ReservationKind<1>;
+
 //===----------------------------------------------------------------------===//
 // Instruction stage - These values represent a non-pipelined step in
 // the execution of an instruction.  Cycles represents the number of
@@ -36,10 +43,12 @@ class FuncUnit;
 //   InstrStage<1, [FU_x, FU_y]>     - TimeInc defaults to Cycles
 //   InstrStage<1, [FU_x, FU_y], 0>  - TimeInc explicit
 //
-class InstrStage<int cycles, list<FuncUnit> units, int timeinc = -1> {
+class InstrStage<int cycles, list<FuncUnit> units,
+                 int timeinc = -1, ReservationKind kind = Required> {
   int Cycles          = cycles;       // length of stage in machine cycles
   list<FuncUnit> Units = units;       // choice of functional units
   int TimeInc         = timeinc;      // cycles till start of next stage
+  int Kind            = kind.Value;   // kind of FU reservation
 }
 
 //===----------------------------------------------------------------------===//
index 52908edefc880cc580d4ad2e44a4beb62c78c02e..af5f2892c2f07f2f1a56321e96688b4037688308 100644 (file)
@@ -45,14 +45,16 @@ ExactHazardRecognizer(const InstrItineraryData &LItinData) :
     }
   }
 
-  Scoreboard.reset(ScoreboardDepth);
+  ReservedScoreboard.reset(ScoreboardDepth);
+  RequiredScoreboard.reset(ScoreboardDepth);
 
   DEBUG(dbgs() << "Using exact hazard recognizer: ScoreboardDepth = " 
                << ScoreboardDepth << '\n');
 }
 
 void ExactHazardRecognizer::Reset() {
-  Scoreboard.reset();
+  RequiredScoreboard.reset();
+  ReservedScoreboard.reset();
 }
 
 void ExactHazardRecognizer::ScoreBoard::dump() const {
@@ -86,10 +88,23 @@ ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU
     // stage is occupied. FIXME it would be more accurate to find the
     // same unit free in all the cycles.
     for (unsigned int i = 0; i < IS->getCycles(); ++i) {
-      assert(((cycle + i) < Scoreboard.getDepth()) &&
+      assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
              "Scoreboard depth exceeded!");
 
-      unsigned freeUnits = IS->getUnits() & ~Scoreboard[cycle + i];
+      unsigned freeUnits = IS->getUnits();
+      switch (IS->getReservationKind()) {
+      default:
+       assert(0 && "Invalid FU reservation");
+      case InstrStage::Required:
+        // Required FUs conflict with both reserved and required ones
+        freeUnits &= ~ReservedScoreboard[cycle + i];
+        // FALLTHROUGH
+      case InstrStage::Reserved:
+        // Reserved FUs can conflict only with required ones.
+        freeUnits &= ~RequiredScoreboard[cycle + i];
+        break;
+      }
+
       if (!freeUnits) {
         DEBUG(dbgs() << "*** Hazard in cycle " << (cycle + i) << ", ");
         DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
@@ -114,16 +129,28 @@ void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {
   // Use the itinerary for the underlying instruction to reserve FU's
   // in the scoreboard at the appropriate future cycles.
   unsigned idx = SU->getInstr()->getDesc().getSchedClass();
-  for (const InstrStage *IS = ItinData.beginStage(idx), 
+  for (const InstrStage *IS = ItinData.beginStage(idx),
          *E = ItinData.endStage(idx); IS != E; ++IS) {
     // We must reserve one of the stage's units for every cycle the
     // stage is occupied. FIXME it would be more accurate to reserve
     // the same unit free in all the cycles.
     for (unsigned int i = 0; i < IS->getCycles(); ++i) {
-      assert(((cycle + i) < Scoreboard.getDepth()) &&
+      assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
              "Scoreboard depth exceeded!");
 
-      unsigned freeUnits = IS->getUnits() & ~Scoreboard[cycle + i];
+      unsigned freeUnits = IS->getUnits();
+      switch (IS->getReservationKind()) {
+      default:
+       assert(0 && "Invalid FU reservation");
+      case InstrStage::Required:
+        // Required FUs conflict with both reserved and required ones
+        freeUnits &= ~ReservedScoreboard[cycle + i];
+        // FALLTHROUGH
+      case InstrStage::Reserved:
+        // Reserved FUs can conflict only with required ones.
+        freeUnits &= ~RequiredScoreboard[cycle + i];
+        break;
+      }
 
       // reduce to a single unit
       unsigned freeUnit = 0;
@@ -133,17 +160,21 @@ void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {
       } while (freeUnits);
 
       assert(freeUnit && "No function unit available!");
-      Scoreboard[cycle + i] |= freeUnit;
+      if (IS->getReservationKind() == InstrStage::Required)
+        RequiredScoreboard[cycle + i] |= freeUnit;
+      else
+        ReservedScoreboard[cycle + i] |= freeUnit;
     }
 
     // Advance the cycle to the next stage.
     cycle += IS->getNextCycles();
   }
 
-  DEBUG(Scoreboard.dump());
+  DEBUG(ReservedScoreboard.dump());
+  DEBUG(RequiredScoreboard.dump());
 }
 
 void ExactHazardRecognizer::AdvanceCycle() {
-  Scoreboard[0] = 0;
-  Scoreboard.advance();
+  ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
+  RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
 }
index 50fe024d978a2c47220eabecde02f3820856a638..91c81a970fa5b0d832c559145547850097846f78 100644 (file)
@@ -70,7 +70,8 @@ namespace llvm {
     // Itinerary data for the target.
     const InstrItineraryData &ItinData;
 
-    ScoreBoard Scoreboard;
+    ScoreBoard ReservedScoreboard;
+    ScoreBoard RequiredScoreboard;
 
   public:
     ExactHazardRecognizer(const InstrItineraryData &ItinData);
index 9ac652f79935446915fe646a975b206aff70acf4..fb86a704c47c01e39156f23dcfe44b8f97c42ec5 100644 (file)
@@ -216,7 +216,7 @@ void SubtargetEmitter::FormItineraryStageString(Record *ItinData,
     // Next stage
     const Record *Stage = StageList[i];
   
-    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc }
+    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
     int Cycles = Stage->getValueAsInt("Cycles");
     ItinString += "  { " + itostr(Cycles) + ", ";
     
@@ -233,6 +233,9 @@ void SubtargetEmitter::FormItineraryStageString(Record *ItinData,
     int TimeInc = Stage->getValueAsInt("TimeInc");
     ItinString += ", " + itostr(TimeInc);
 
+    int Kind = Stage->getValueAsInt("Kind");
+    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
+
     // Close off stage
     ItinString += " }";
     if (++i < N) ItinString += ", ";
@@ -278,7 +281,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
 
   // Begin stages table
   std::string StageTable = "static const llvm::InstrStage Stages[] = {\n";
-  StageTable += "  { 0, 0, 0 }, // No itinerary\n";
+  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
         
   // Begin operand cycle table
   std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
@@ -367,7 +370,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
   }
   
   // Closing stage
-  StageTable += "  { 0, 0, 0 } // End itinerary\n";
+  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
   StageTable += "};\n";
 
   // Closing operand cycles