mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-03 05:41:42 +00:00
Add a really faster pre-RA scheduler (-pre-RA-sched=linearize). It doesn't use
any scheduling heuristics nor does it build up any scheduling data structure that other heuristics use. It essentially linearize by doing a DFA walk but it does handle glues correctly. IMPORTANT: it probably can't handle all the physical register dependencies so it's not suitable for x86. It also doesn't deal with dbg_value nodes right now so it's definitely is still WIP. rdar://12474515 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166122 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9aa6e0a134
commit
d4f759696d
@ -102,6 +102,11 @@ ScheduleDAGSDNodes *createVLIWDAGScheduler(SelectionDAGISel *IS,
|
|||||||
ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS,
|
ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS,
|
||||||
CodeGenOpt::Level OptLevel);
|
CodeGenOpt::Level OptLevel);
|
||||||
|
|
||||||
|
/// createDAGLinearizer - This creates a "no-scheduling" scheduler which
|
||||||
|
/// linearize the DAG using topological order.
|
||||||
|
ScheduleDAGSDNodes *createDAGLinearizer(SelectionDAGISel *IS,
|
||||||
|
CodeGenOpt::Level OptLevel);
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#define DEBUG_TYPE "pre-RA-sched"
|
#define DEBUG_TYPE "pre-RA-sched"
|
||||||
#include "ScheduleDAGSDNodes.h"
|
#include "ScheduleDAGSDNodes.h"
|
||||||
|
#include "InstrEmitter.h"
|
||||||
#include "llvm/InlineAsm.h"
|
#include "llvm/InlineAsm.h"
|
||||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||||
@ -34,6 +35,10 @@ STATISTIC(NumPRCopies, "Number of physical copies");
|
|||||||
static RegisterScheduler
|
static RegisterScheduler
|
||||||
fastDAGScheduler("fast", "Fast suboptimal list scheduling",
|
fastDAGScheduler("fast", "Fast suboptimal list scheduling",
|
||||||
createFastDAGScheduler);
|
createFastDAGScheduler);
|
||||||
|
static RegisterScheduler
|
||||||
|
linearizeDAGScheduler("linearize", "Linearize DAG, no scheduling",
|
||||||
|
createDAGLinearizer);
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// FastPriorityQueue - A degenerate priority queue that considers
|
/// FastPriorityQueue - A degenerate priority queue that considers
|
||||||
@ -629,6 +634,153 @@ void ScheduleDAGFast::ListScheduleBottomUp() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// ScheduleDAGLinearize - No scheduling scheduler, it simply linearize the
|
||||||
|
// DAG in topological order.
|
||||||
|
// IMPORTANT: this may not work for targets with phyreg dependency.
|
||||||
|
//
|
||||||
|
class ScheduleDAGLinearize : public ScheduleDAGSDNodes {
|
||||||
|
public:
|
||||||
|
ScheduleDAGLinearize(MachineFunction &mf) : ScheduleDAGSDNodes(mf) {}
|
||||||
|
|
||||||
|
void Schedule();
|
||||||
|
|
||||||
|
MachineBasicBlock *EmitSchedule(MachineBasicBlock::iterator &InsertPos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SDNode*> Sequence;
|
||||||
|
DenseMap<SDNode*, SDNode*> GluedMap; // Cache glue to its user
|
||||||
|
|
||||||
|
void ScheduleNode(SDNode *N);
|
||||||
|
};
|
||||||
|
|
||||||
|
void ScheduleDAGLinearize::ScheduleNode(SDNode *N) {
|
||||||
|
if (N->getNodeId() != 0)
|
||||||
|
llvm_unreachable(0);
|
||||||
|
|
||||||
|
if (!N->isMachineOpcode() &&
|
||||||
|
(N->getOpcode() == ISD::EntryToken || isPassiveNode(N)))
|
||||||
|
// These nodes do not need to be translated into MIs.
|
||||||
|
return;
|
||||||
|
|
||||||
|
DEBUG(dbgs() << "\n*** Scheduling: ");
|
||||||
|
DEBUG(N->dump(DAG));
|
||||||
|
Sequence.push_back(N);
|
||||||
|
|
||||||
|
unsigned NumOps = N->getNumOperands();
|
||||||
|
if (unsigned NumLeft = NumOps) {
|
||||||
|
SDNode *GluedOpN = 0;
|
||||||
|
do {
|
||||||
|
const SDValue &Op = N->getOperand(NumLeft-1);
|
||||||
|
SDNode *OpN = Op.getNode();
|
||||||
|
|
||||||
|
if (NumLeft == NumOps && Op.getValueType() == MVT::Glue) {
|
||||||
|
// Schedule glue operand right above N.
|
||||||
|
GluedOpN = OpN;
|
||||||
|
assert(OpN->getNodeId() != 0 && "Glue operand not ready?");
|
||||||
|
OpN->setNodeId(0);
|
||||||
|
ScheduleNode(OpN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OpN == GluedOpN)
|
||||||
|
// Glue operand is already scheduled.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DenseMap<SDNode*, SDNode*>::iterator DI = GluedMap.find(OpN);
|
||||||
|
if (DI != GluedMap.end() && DI->second != N)
|
||||||
|
// Users of glues are counted against the glued users.
|
||||||
|
OpN = DI->second;
|
||||||
|
|
||||||
|
unsigned Degree = OpN->getNodeId();
|
||||||
|
assert(Degree > 0 && "Predecessor over-released!");
|
||||||
|
OpN->setNodeId(--Degree);
|
||||||
|
if (Degree == 0)
|
||||||
|
ScheduleNode(OpN);
|
||||||
|
} while (--NumLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// findGluedUser - Find the representative use of a glue value by walking
|
||||||
|
/// the use chain.
|
||||||
|
static SDNode *findGluedUser(SDNode *N) {
|
||||||
|
while (SDNode *Glued = N->getGluedUser())
|
||||||
|
N = Glued;
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScheduleDAGLinearize::Schedule() {
|
||||||
|
DEBUG(dbgs() << "********** DAG Linearization **********\n");
|
||||||
|
|
||||||
|
SmallVector<SDNode*, 8> Glues;
|
||||||
|
unsigned DAGSize = 0;
|
||||||
|
for (SelectionDAG::allnodes_iterator I = DAG->allnodes_begin(),
|
||||||
|
E = DAG->allnodes_end(); I != E; ++I) {
|
||||||
|
SDNode *N = I;
|
||||||
|
|
||||||
|
// Use node id to record degree.
|
||||||
|
unsigned Degree = N->use_size();
|
||||||
|
N->setNodeId(Degree);
|
||||||
|
unsigned NumVals = N->getNumValues();
|
||||||
|
if (NumVals && N->getValueType(NumVals-1) == MVT::Glue &&
|
||||||
|
N->hasAnyUseOfValue(NumVals-1)) {
|
||||||
|
SDNode *User = findGluedUser(N);
|
||||||
|
if (User) {
|
||||||
|
Glues.push_back(N);
|
||||||
|
GluedMap.insert(std::make_pair(N, User));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (N->isMachineOpcode() ||
|
||||||
|
(N->getOpcode() != ISD::EntryToken && !isPassiveNode(N)))
|
||||||
|
++DAGSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = Glues.size(); i != e; ++i) {
|
||||||
|
SDNode *Glue = Glues[i];
|
||||||
|
SDNode *GUser = GluedMap[Glue];
|
||||||
|
unsigned Degree = Glue->getNodeId();
|
||||||
|
unsigned UDegree = GUser->getNodeId();
|
||||||
|
|
||||||
|
// Glue user must be scheduled together with the glue operand. So other
|
||||||
|
// users of the glue operand must be treated as its users.
|
||||||
|
SDNode *ImmGUser = Glue->getGluedUser();
|
||||||
|
for (SDNode::use_iterator ui = Glue->use_begin(), ue = Glue->use_end();
|
||||||
|
ui != ue; ++ui)
|
||||||
|
if (*ui == ImmGUser)
|
||||||
|
--Degree;
|
||||||
|
GUser->setNodeId(UDegree + Degree);
|
||||||
|
Glue->setNodeId(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequence.reserve(DAGSize);
|
||||||
|
ScheduleNode(DAG->getRoot().getNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineBasicBlock*
|
||||||
|
ScheduleDAGLinearize::EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
|
||||||
|
InstrEmitter Emitter(BB, InsertPos);
|
||||||
|
DenseMap<SDValue, unsigned> VRBaseMap;
|
||||||
|
|
||||||
|
DEBUG({
|
||||||
|
dbgs() << "\n*** Final schedule ***\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
// FIXME: Handle dbg_values.
|
||||||
|
unsigned NumNodes = Sequence.size();
|
||||||
|
for (unsigned i = 0; i != NumNodes; ++i) {
|
||||||
|
SDNode *N = Sequence[NumNodes-i-1];
|
||||||
|
DEBUG(N->dump(DAG));
|
||||||
|
Emitter.EmitNode(N, false, false, VRBaseMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(dbgs() << '\n');
|
||||||
|
|
||||||
|
InsertPos = Emitter.getInsertPos();
|
||||||
|
return Emitter.getBlock();
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Public Constructor Functions
|
// Public Constructor Functions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -637,3 +789,8 @@ llvm::ScheduleDAGSDNodes *
|
|||||||
llvm::createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
|
llvm::createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) {
|
||||||
return new ScheduleDAGFast(*IS->MF);
|
return new ScheduleDAGFast(*IS->MF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::ScheduleDAGSDNodes *
|
||||||
|
llvm::createDAGLinearizer(SelectionDAGISel *IS, CodeGenOpt::Level) {
|
||||||
|
return new ScheduleDAGLinearize(*IS->MF);
|
||||||
|
}
|
||||||
|
@ -831,8 +831,7 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SmallVector<SDNode *, 4> GluedNodes;
|
SmallVector<SDNode *, 4> GluedNodes;
|
||||||
for (SDNode *N = SU->getNode()->getGluedNode(); N;
|
for (SDNode *N = SU->getNode()->getGluedNode(); N; N = N->getGluedNode())
|
||||||
N = N->getGluedNode())
|
|
||||||
GluedNodes.push_back(N);
|
GluedNodes.push_back(N);
|
||||||
while (!GluedNodes.empty()) {
|
while (!GluedNodes.empty()) {
|
||||||
SDNode *N = GluedNodes.back();
|
SDNode *N = GluedNodes.back();
|
||||||
|
@ -114,7 +114,8 @@ namespace llvm {
|
|||||||
/// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock
|
/// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock
|
||||||
/// according to the order specified in Sequence.
|
/// according to the order specified in Sequence.
|
||||||
///
|
///
|
||||||
MachineBasicBlock *EmitSchedule(MachineBasicBlock::iterator &InsertPos);
|
virtual MachineBasicBlock*
|
||||||
|
EmitSchedule(MachineBasicBlock::iterator &InsertPos);
|
||||||
|
|
||||||
virtual void dumpNode(const SUnit *SU) const;
|
virtual void dumpNode(const SUnit *SU) const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user