Add support for building a ScheduleDAG from MachineInstrs. This is currently
authorDan Gohman <gohman@apple.com>
Fri, 14 Nov 2008 21:47:58 +0000 (21:47 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 14 Nov 2008 21:47:58 +0000 (21:47 +0000)
fairly conservative; it doesn't do alias-analysis queries and it doesn't
attempt to break anti-dependencies.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59324 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/ScheduleDAG.h
lib/CodeGen/SelectionDAG/ScheduleDAG.cpp

index 8445432e8ebdda46e378e92ffc54a751b84c9d47..7c32205163ae4616be72113b903d55ba9a2707ee 100644 (file)
@@ -439,6 +439,11 @@ namespace llvm {
     /// and if it has live ins that need to be copied into vregs, emit the
     /// copies into the top of the block.
     void EmitLiveInCopies(MachineBasicBlock *MBB);
+
+    /// BuildSchedUnitsFromMBB - Build SUnits from the MachineBasicBlock.
+    /// This SUnit graph is similar to the pre-regalloc SUnit graph, but represents
+    /// MachineInstrs directly instead of SDNodes.
+    void BuildSchedUnitsFromMBB();
   };
 
   /// createBURRListDAGScheduler - This creates a bottom up register usage
index 6d6b9c7c0f0c95b476b9d335d8abca393260d063..3fb25159ea89c09093d82d5fae858f50d33502aa 100644 (file)
@@ -72,6 +72,13 @@ SUnit *ScheduleDAG::Clone(SUnit *Old) {
 /// This SUnit graph is similar to the SelectionDAG, but represents flagged
 /// together nodes with a single SUnit.
 void ScheduleDAG::BuildSchedUnits() {
+  // For post-regalloc scheduling, build the SUnits from the MachineInstrs
+  // in the MachineBasicBlock.
+  if (!DAG) {
+    BuildSchedUnitsFromMBB();
+    return;
+  }
+
   // Reserve entries in the vector for each of the SUnits we are creating.  This
   // ensure that reallocation of the vector won't happen, so SUnit*'s won't get
   // invalidated.
@@ -185,6 +192,83 @@ void ScheduleDAG::BuildSchedUnits() {
   }
 }
 
+void ScheduleDAG::BuildSchedUnitsFromMBB() {
+  SUnits.clear();
+  SUnits.reserve(BB->size());
+
+  std::vector<SUnit *> PendingLoads;
+  SUnit *Terminator = 0;
+  SUnit *Chain = 0;
+  SUnit *Defs[TargetRegisterInfo::FirstVirtualRegister] = {};
+  std::vector<SUnit *> Uses[TargetRegisterInfo::FirstVirtualRegister] = {};
+  int Cost = 1; // FIXME
+
+  for (MachineBasicBlock::iterator MII = BB->end(), MIE = BB->begin();
+       MII != MIE; --MII) {
+    MachineInstr *MI = prior(MII);
+    SUnit *SU = NewSUnit(MI);
+
+    for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) {
+      const MachineOperand &MO = MI->getOperand(j);
+      if (!MO.isReg()) continue;
+      unsigned Reg = MO.getReg();
+      if (Reg == 0) continue;
+
+      assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!");
+      std::vector<SUnit *> &UseList = Uses[Reg];
+      SUnit *&Def = Defs[Reg];
+      // Optionally add output and anti dependences
+      if (Def && Def != SU)
+        Def->addPred(SU, /*isCtrl=*/true, /*isSpecial=*/false,
+                     /*PhyReg=*/Reg, Cost);
+      for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
+        SUnit *&Def = Defs[*Alias];
+        if (Def && Def != SU)
+          Def->addPred(SU, /*isCtrl=*/true, /*isSpecial=*/false,
+                       /*PhyReg=*/*Alias, Cost);
+      }
+
+      if (MO.isDef()) {
+        // Add any data dependencies.
+        for (unsigned i = 0, e = UseList.size(); i != e; ++i)
+          if (UseList[i] != SU)
+            UseList[i]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false,
+                                /*PhysReg=*/Reg, Cost);
+        for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
+          std::vector<SUnit *> &UseList = Uses[*Alias];
+          for (unsigned i = 0, e = UseList.size(); i != e; ++i)
+            if (UseList[i] != SU)
+              UseList[i]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false,
+                                  /*PhysReg=*/*Alias, Cost);
+        }
+
+        UseList.clear();
+        Def = SU;
+      } else {
+        UseList.push_back(SU);
+      }
+    }
+    bool False = false;
+    bool True = true;
+    if (!MI->isSafeToMove(TII, False)) {
+      if (Chain)
+        Chain->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+      for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k)
+        PendingLoads[k]->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+      PendingLoads.clear();
+      Chain = SU;
+    } else if (!MI->isSafeToMove(TII, True)) {
+      if (Chain)
+        Chain->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+      PendingLoads.push_back(SU);
+    }
+    if (Terminator && SU->Succs.empty())
+      Terminator->addPred(SU, /*isCtrl=*/false, /*isSpecial=*/false);
+    if (MI->getDesc().isTerminator())
+      Terminator = SU;
+  }
+}
+
 void ScheduleDAG::ComputeLatency(SUnit *SU) {
   const InstrItineraryData &InstrItins = TM.getInstrItineraryData();