//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sched"
-#include "llvm/CodeGen/MachinePassRegistry.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Visibility.h"
+#include "llvm/Support/Compiler.h"
#include <algorithm>
-#include <iostream>
using namespace llvm;
-
namespace {
static RegisterScheduler
/// ResourceTally - Manages the use of resources over time intervals. Each
/// item (slot) in the tally vector represents the resources used at a given
/// moment. A bit set to 1 indicates that a resource is in use, otherwise
-/// available. An assumption is made that the tally is large enough to schedule
+/// available. An assumption is made that the tally is large enough to schedule
/// all current instructions (asserts otherwise.)
///
template<class T>
// Tally iterator
/// SlotsAvailable - Returns true if all units are available.
- ///
+ ///
bool SlotsAvailable(Iter Begin, unsigned N, unsigned ResourceSet,
- unsigned &Resource) {
+ unsigned &Resource) {
assert(N && "Must check availability with N != 0");
// Determine end of interval
Iter End = Begin + N;
Resource = 0;
return false;
}
-
- /// RetrySlot - Finds a good candidate slot to retry search.
+
+ /// RetrySlot - Finds a good candidate slot to retry search.
Iter RetrySlot(Iter Begin, unsigned N, unsigned ResourceSet) {
assert(N && "Must check availability with N != 0");
// Determine end of interval
Iter End = Begin + N;
assert(End <= Tally.end() && "Tally is not large enough for schedule");
-
- while (Begin != End--) {
- // Clear units in use
- ResourceSet &= ~*End;
- // If no units left then we should go no further
- if (!ResourceSet) return End + 1;
- }
- // Made it all the way through
- return Begin;
- }
+
+ while (Begin != End--) {
+ // Clear units in use
+ ResourceSet &= ~*End;
+ // If no units left then we should go no further
+ if (!ResourceSet) return End + 1;
+ }
+ // Made it all the way through
+ return Begin;
+ }
/// FindAndReserveStages - Return true if the stages can be completed. If
/// so mark as busy.
// Try at cursor, if successful return position.
if (FindAndReserveStages(Cursor, StageBegin, StageEnd)) return Cursor;
// Locate a better position
- Cursor = RetrySlot(Cursor + 1, StageBegin->Cycles, StageBegin->Units);
+ Cursor = RetrySlot(Cursor + 1, StageBegin->Cycles, StageBegin->Units);
}
}
// FindAndReserve - Locate an ideal slot for the specified stages and mark
// as busy.
unsigned FindAndReserve(unsigned Slot, InstrStage *StageBegin,
- InstrStage *StageEnd) {
- // Where to begin
- Iter Begin = Tally.begin() + Slot;
- // Find a free slot
- Iter Where = FindSlots(Begin, StageBegin, StageEnd);
- // Distance is slot number
- unsigned Final = Where - Tally.begin();
+ InstrStage *StageEnd) {
+ // Where to begin
+ Iter Begin = Tally.begin() + Slot;
+ // Find a free slot
+ Iter Where = FindSlots(Begin, StageBegin, StageEnd);
+ // Distance is slot number
+ unsigned Final = Where - Tally.begin();
return Final;
}
/// print - Print ordering to specified output stream.
///
void print(std::ostream &O) const;
+ void print(std::ostream *O) const { if (O) print(*O); }
void dump(const char *tag) const;
/// printNI - Print node info.
///
void printNI(std::ostream &O, NodeInfo *NI) const;
+ void printNI(std::ostream *O, NodeInfo *NI) const { if (O) printNI(*O, NI); }
/// printChanges - Hilight changes in order caused by scheduling.
///
RSLoadStore = 0x0C000000, // Two load store units
RSBranch = 0x02000000 // One branch unit
};
-static InstrStage CallStage = { CallLatency, RSBranch };
static InstrStage LoadStage = { 5, RSLoadStore };
static InstrStage StoreStage = { 2, RSLoadStore };
static InstrStage IntStage = { 2, RSInteger };
}
void ScheduleDAGSimple::dump(const char *tag) const {
- std::cerr << tag; dump();
+ cerr << tag; dump();
}
void ScheduleDAGSimple::dump() const {
- print(std::cerr);
+ print(cerr);
}
/// EmitAll - Emit all nodes in schedule sorted order.
///
void ScheduleDAGSimple::EmitAll() {
- std::map<SDNode*, unsigned> VRBaseMap;
+ // If this is the first basic block in the function, and if it has live ins
+ // that need to be copied into vregs, emit the copies into the top of the
+ // block before emitting the code for the block.
+ MachineFunction &MF = DAG.getMachineFunction();
+ if (&MF.front() == BB && MF.livein_begin() != MF.livein_end()) {
+ for (MachineFunction::livein_iterator LI = MF.livein_begin(),
+ E = MF.livein_end(); LI != E; ++LI)
+ if (LI->second)
+ MRI->copyRegToReg(*MF.begin(), MF.begin()->end(), LI->second,
+ LI->first, RegMap->getRegClass(LI->second));
+ }
+
+ DenseMap<SDNode*, unsigned> VRBaseMap;
// For each node in the ordering
for (unsigned i = 0, N = Ordering.size(); i < N; i++) {
}
if (i < N) {
- std::cerr << Index << ". New Ordering\n";
+ cerr << Index << ". New Ordering\n";
for (i = 0; i < N; i++) {
NodeInfo *NI = Ordering[i];
- std::cerr << " " << NI->Preorder << ". ";
- printNI(std::cerr, NI);
- std::cerr << "\n";
+ cerr << " " << NI->Preorder << ". ";
+ printNI(cerr, NI);
+ cerr << "\n";
if (NI->isGroupDominator()) {
NodeGroup *Group = NI->Group;
for (NIIterator NII = Group->group_begin(), E = Group->group_end();
NII != E; NII++) {
- std::cerr << " ";
- printNI(std::cerr, *NII);
- std::cerr << "\n";
+ cerr << " ";
+ printNI(cerr, *NII);
+ cerr << "\n";
}
}
}
} else {
- std::cerr << Index << ". No Changes\n";
+ cerr << Index << ". No Changes\n";
}
#endif
}
/// createSimpleDAGScheduler - This creates a simple two pass instruction
/// scheduler using instruction itinerary.
-llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(SelectionDAG *DAG,
+llvm::ScheduleDAG* llvm::createSimpleDAGScheduler(SelectionDAGISel *IS,
+ SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(false, false, *DAG, BB, DAG->getTarget());
}
/// createNoItinsDAGScheduler - This creates a simple two pass instruction
/// scheduler without using instruction itinerary.
-llvm::ScheduleDAG* llvm::createNoItinsDAGScheduler(SelectionDAG *DAG,
+llvm::ScheduleDAG* llvm::createNoItinsDAGScheduler(SelectionDAGISel *IS,
+ SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(false, true, *DAG, BB, DAG->getTarget());
}
/// createBFS_DAGScheduler - This creates a simple breadth first instruction
/// scheduler.
-llvm::ScheduleDAG* llvm::createBFS_DAGScheduler(SelectionDAG *DAG,
+llvm::ScheduleDAG* llvm::createBFS_DAGScheduler(SelectionDAGISel *IS,
+ SelectionDAG *DAG,
MachineBasicBlock *BB) {
return new ScheduleDAGSimple(true, false, *DAG, BB, DAG->getTarget());
}