Convert -enable-sched-cycles and -enable-sched-hazard to -disable
flags. They are still not enable in this revision.

Added TargetInstrInfo::isZeroCost() to fix a fundamental problem with
the scheduler's model of operand latency in the selection DAG.

Generalized unit tests to work with sched-cycles.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123969 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/lib/CodeGen/ScoreboardHazardRecognizer.cpp
index b00e0cd..e6d7ded 100644
--- a/lib/CodeGen/ScoreboardHazardRecognizer.cpp
+++ b/lib/CodeGen/ScoreboardHazardRecognizer.cpp
@@ -19,6 +19,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetInstrItineraries.h"
 
 using namespace llvm;
@@ -170,14 +171,17 @@
   if (!ItinData || ItinData->isEmpty())
     return;
 
-  ++IssueCount;
-
-  unsigned cycle = 0;
-
   // Use the itinerary for the underlying instruction to reserve FU's
   // in the scoreboard at the appropriate future cycles.
   const TargetInstrDesc *TID = DAG->getInstrDesc(SU);
   assert(TID && "The scheduler must filter non-machineinstrs");
+  if (DAG->TII->isZeroCost(TID->Opcode))
+    return;
+
+  ++IssueCount;
+
+  unsigned cycle = 0;
+
   unsigned idx = TID->getSchedClass();
   for (const InstrStage *IS = ItinData->beginStage(idx),
          *E = ItinData->endStage(idx); IS != E; ++IS) {
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 1a564f1..e43bcfd 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -66,10 +66,9 @@
                       "which tries to balance ILP and register pressure",
                       createILPListDAGScheduler);
 
-static cl::opt<bool> EnableSchedCycles(
-  "enable-sched-cycles",
-  cl::desc("Enable cycle-level precision during preRA scheduling"),
-  cl::init(false), cl::Hidden);
+static cl::opt<bool> DisableSchedCycles(
+  "disable-sched-cycles", cl::Hidden, cl::init(true),
+  cl::desc("Disable cycle-level precision during preRA scheduling"));
 
 namespace {
 //===----------------------------------------------------------------------===//
@@ -124,10 +123,10 @@
       Topo(SUnits) {
 
     const TargetMachine &tm = mf.getTarget();
-    if (EnableSchedCycles && OptLevel != CodeGenOpt::None)
-      HazardRec = tm.getInstrInfo()->CreateTargetHazardRecognizer(&tm, this);
-    else
+    if (DisableSchedCycles || !NeedLatency)
       HazardRec = new ScheduleHazardRecognizer();
+    else
+      HazardRec = tm.getInstrInfo()->CreateTargetHazardRecognizer(&tm, this);
   }
 
   ~ScheduleDAGRRList() {
@@ -168,7 +167,7 @@
 
 private:
   bool isReady(SUnit *SU) {
-    return !EnableSchedCycles || !AvailableQueue->hasReadyFilter() ||
+    return DisableSchedCycles || !AvailableQueue->hasReadyFilter() ||
       AvailableQueue->isReady(SU);
   }
 
@@ -237,7 +236,7 @@
         << " '" << BB->getName() << "' **********\n");
 
   CurCycle = 0;
-  MinAvailableCycle = EnableSchedCycles ? UINT_MAX : 0;
+  MinAvailableCycle = DisableSchedCycles ? 0 : UINT_MAX;
   NumLiveRegs = 0;
   LiveRegDefs.resize(TRI->getNumRegs(), NULL);
   LiveRegGens.resize(TRI->getNumRegs(), NULL);
@@ -350,7 +349,7 @@
 /// Check to see if any of the pending instructions are ready to issue.  If
 /// so, add them to the available queue.
 void ScheduleDAGRRList::ReleasePending() {
-  if (!EnableSchedCycles) {
+  if (DisableSchedCycles) {
     assert(PendingQueue.empty() && "pending instrs not allowed in this mode");
     return;
   }
@@ -385,7 +384,7 @@
     return;
 
   AvailableQueue->setCurCycle(NextCycle);
-  if (HazardRec->getMaxLookAhead() == 0) {
+  if (!HazardRec->isEnabled()) {
     // Bypass lots of virtual calls in case of long latency.
     CurCycle = NextCycle;
   }
@@ -405,7 +404,7 @@
 /// Move the scheduler state forward until the specified node's dependents are
 /// ready and can be scheduled with no resource conflicts.
 void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) {
-  if (!EnableSchedCycles)
+  if (DisableSchedCycles)
     return;
 
   unsigned ReadyCycle = isBottomUp ? SU->getHeight() : SU->getDepth();
@@ -440,7 +439,7 @@
 /// Record this SUnit in the HazardRecognizer.
 /// Does not update CurCycle.
 void ScheduleDAGRRList::EmitNode(SUnit *SU) {
-  if (!EnableSchedCycles || HazardRec->getMaxLookAhead() == 0)
+  if (!HazardRec->isEnabled())
     return;
 
   // Check for phys reg copy.
@@ -525,9 +524,9 @@
   // (1) No available instructions
   // (2) All pipelines full, so available instructions must have hazards.
   //
-  // If SchedCycles is disabled, count each inst as one cycle.
-  if (!EnableSchedCycles ||
-      AvailableQueue->empty() || HazardRec->atIssueLimit())
+  // If HazardRec is disabled, count each inst as one cycle.
+  if (!HazardRec->isEnabled() || HazardRec->atIssueLimit()
+      || AvailableQueue->empty())
     AdvanceToCycle(CurCycle + 1);
 }
 
@@ -585,7 +584,7 @@
   SU->setHeightDirty();
   SU->isScheduled = false;
   SU->isAvailable = true;
-  if (EnableSchedCycles && AvailableQueue->hasReadyFilter()) {
+  if (!DisableSchedCycles && AvailableQueue->hasReadyFilter()) {
     // Don't make available until backtracking is complete.
     SU->isPending = true;
     PendingQueue.push_back(SU);
@@ -2010,24 +2009,27 @@
   } else if (RStall)
     return -1;
 
-  // If either node is scheduling for latency, sort them by depth
+  // If either node is scheduling for latency, sort them by height/depth
   // and latency.
   if (!checkPref || (left->SchedulingPref == Sched::Latency ||
                      right->SchedulingPref == Sched::Latency)) {
-    int LDepth = (int)left->getDepth();
-    int RDepth = (int)right->getDepth();
-
-    if (EnableSchedCycles) {
-      if (LDepth != RDepth)
-        DEBUG(dbgs() << "  Comparing latency of SU (" << left->NodeNum
-              << ") depth " << LDepth << " vs SU (" << right->NodeNum
-              << ") depth " << RDepth << ")\n");
-        return LDepth < RDepth ? 1 : -1;
-    }
-    else {
+    if (DisableSchedCycles) {
       if (LHeight != RHeight)
         return LHeight > RHeight ? 1 : -1;
     }
+    else {
+      // If neither instruction stalls (!LStall && !RStall) then
+      // it's height is already covered so only its depth matters. We also reach
+      // this if both stall but have the same height.
+      unsigned LDepth = left->getDepth();
+      unsigned RDepth = right->getDepth();
+      if (LDepth != RDepth) {
+        DEBUG(dbgs() << "  Comparing latency of SU (" << left->NodeNum
+              << ") depth " << LDepth << " vs SU (" << right->NodeNum
+              << ") depth " << RDepth << "\n");
+        return LDepth < RDepth ? 1 : -1;
+      }
+    }
     if (left->Latency != right->Latency)
       return left->Latency > right->Latency ? 1 : -1;
   }
@@ -2068,7 +2070,7 @@
   if (LScratch != RScratch)
     return LScratch > RScratch;
 
-  if (EnableSchedCycles) {
+  if (!DisableSchedCycles) {
     int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ);
     if (result != 0)
       return result > 0;
diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp
index 787c271..15340a3 100644
--- a/lib/CodeGen/TargetInstrInfoImpl.cpp
+++ b/lib/CodeGen/TargetInstrInfoImpl.cpp
@@ -24,11 +24,16 @@
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
 #include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
+static cl::opt<bool> DisableHazardRecognizer(
+  "disable-sched-hazard", cl::Hidden, cl::init(false),
+  cl::desc("Disable hazard detection during preRA scheduling"));
+
 /// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything
 /// after it, replacing it with an unconditional branch to NewDest.
 void
@@ -421,7 +426,13 @@
   return false;
 }
 
-// Default implementation of CreateTargetPreRAHazardRecognizer.
+// Provide a global flag for disabling the PreRA hazard recognizer that targets
+// may choose to honor.
+bool TargetInstrInfoImpl::usePreRAHazardRecognizer() const {
+  return !DisableHazardRecognizer;
+}
+
+// Default implementation of CreateTargetRAHazardRecognizer.
 ScheduleHazardRecognizer *TargetInstrInfoImpl::
 CreateTargetHazardRecognizer(const TargetMachine *TM,
                              const ScheduleDAG *DAG) const {