//===---- ScheduleDAGList.cpp - Implement a list scheduler for isel DAG ---===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Evan Cheng and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements bottom-up and top-down list schedulers, using standard
// algorithms. The basic approach uses a priority queue of available nodes to
// schedule. One at a time, nodes are taken from the priority queue (thus in
// priority order), checked for legality to schedule, and emitted if legal.
//
// Nodes may not be legal to schedule either due to structural hazards (e.g.
// pipeline or resource constraints) or because an input to the instruction has
// not completed execution.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sched"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include <climits>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#include "llvm/Support/CommandLine.h"
using namespace llvm;
namespace {
// TEMPORARY option to test a fix.
cl::opt<bool>
SchedIgnorStore("sched-ignore-store", cl::Hidden);
}
namespace {
Statistic<> NumNoops ("scheduler", "Number of noops inserted");
Statistic<> NumStalls("scheduler", "Number of pipeline stalls");
/// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or
/// a group of nodes flagged together.
struct SUnit {
SDNode *Node; // Representative node.
std::vector<SDNode*> FlaggedNodes; // All nodes flagged to Node.
// Preds/Succs - The SUnits before/after us in the graph. The boolean value
// is true if the edge is a token chain edge, false if it is a value edge.
std::set<std::pair<SUnit*,bool> > Preds; // All sunit predecessors.
std::set<std::pair<SUnit*,bool> > Succs; // All sunit successors.
short NumPredsLeft; // # of preds not scheduled.
short NumSuccsLeft; // # of succs not scheduled.
short NumChainPredsLeft; // # of chain preds not scheduled.
short NumChainSuccsLeft; // # of chain succs not scheduled.
bool isStore : 1; // Is a store.
bool isTwoAddress : 1; // Is a two-address instruction.
bool isDefNUseOperand : 1; // Is a def&use operand.
bool isPending : 1; // True once pending.
bool isAvailable : 1; // True once available.
bool isScheduled : 1; // True once scheduled.
unsigned short Latency; // Node latency.
unsigned CycleBound; // Upper/lower cycle to be scheduled at.
unsigned Cycle; // Once scheduled, the cycle of the op.
unsigned NodeNum; // Entry # of node in the node vector.
SUnit(SDNode *node, unsigned nodenum)
: Node(node), NumPredsLeft(0), NumSuccsLeft(0),
NumChainPredsLeft(0), NumChainSuccsLeft(0), isStore(false),
isTwoAddress(false), isDefNUseOperand(false),
isPending(false), isAvailable(false), isScheduled(false),
Latency(0), CycleBound(0), Cycle(0), NodeNum(nodenum) {}
void dump(const SelectionDAG *G) const;
void dumpAll(const SelectionDAG *G) const;
};
}
void SUnit::dump(const SelectionDAG *G) const {
std::cerr << "SU: ";
Node->dump(G);
std::cerr << "\n";
if (FlaggedNodes.size() != 0) {
for (unsigned i = 0, e = FlaggedNodes.size(); i != e; i++) {
std::cerr << " ";
FlaggedNodes[i]->dump(G);
std::cerr << "\n";
}
}
}
void SUnit::dumpAll(const SelectionDAG *G) const {
dump(G);
std::cerr << " # preds left : " << NumPredsLeft <<