mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
Add capability to scheduler to commute nodes for profit.
If a two-address code whose first operand has uses below, it should be commuted when possible. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28230 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -91,7 +91,7 @@ namespace llvm {
|
|||||||
short NumChainPredsLeft; // # of chain preds not scheduled.
|
short NumChainPredsLeft; // # of chain preds not scheduled.
|
||||||
short NumChainSuccsLeft; // # of chain succs not scheduled.
|
short NumChainSuccsLeft; // # of chain succs not scheduled.
|
||||||
bool isTwoAddress : 1; // Is a two-address instruction.
|
bool isTwoAddress : 1; // Is a two-address instruction.
|
||||||
bool isDefNUseOperand : 1; // Is a def&use operand.
|
bool isCommutable : 1; // Is a commutable instruction.
|
||||||
bool isPending : 1; // True once pending.
|
bool isPending : 1; // True once pending.
|
||||||
bool isAvailable : 1; // True once available.
|
bool isAvailable : 1; // True once available.
|
||||||
bool isScheduled : 1; // True once scheduled.
|
bool isScheduled : 1; // True once scheduled.
|
||||||
@@ -105,7 +105,7 @@ namespace llvm {
|
|||||||
SUnit(SDNode *node, unsigned nodenum)
|
SUnit(SDNode *node, unsigned nodenum)
|
||||||
: Node(node), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
|
: Node(node), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
|
||||||
NumChainPredsLeft(0), NumChainSuccsLeft(0),
|
NumChainPredsLeft(0), NumChainSuccsLeft(0),
|
||||||
isTwoAddress(false), isDefNUseOperand(false),
|
isTwoAddress(false), isCommutable(false),
|
||||||
isPending(false), isAvailable(false), isScheduled(false),
|
isPending(false), isAvailable(false), isScheduled(false),
|
||||||
Latency(0), CycleBound(0), Cycle(0), Depth(0), Height(0),
|
Latency(0), CycleBound(0), Cycle(0), Depth(0), Height(0),
|
||||||
NodeNum(nodenum) {}
|
NodeNum(nodenum) {}
|
||||||
@@ -162,10 +162,11 @@ namespace llvm {
|
|||||||
const MRegisterInfo *MRI; // Target processor register info
|
const MRegisterInfo *MRI; // Target processor register info
|
||||||
SSARegMap *RegMap; // Virtual/real register map
|
SSARegMap *RegMap; // Virtual/real register map
|
||||||
MachineConstantPool *ConstPool; // Target constant pool
|
MachineConstantPool *ConstPool; // Target constant pool
|
||||||
std::vector<SUnit*> Sequence; // The schedule. Null SUnit*'s represent
|
std::vector<SUnit*> Sequence; // The schedule. Null SUnit*'s
|
||||||
// noop instructions.
|
// represent noop instructions.
|
||||||
std::map<SDNode*, SUnit*> SUnitMap; // SDNode to SUnit mapping (n -> 1).
|
std::map<SDNode*, SUnit*> SUnitMap; // SDNode to SUnit mapping (n -> 1).
|
||||||
std::vector<SUnit> SUnits; // The scheduling units.
|
std::vector<SUnit> SUnits; // The scheduling units.
|
||||||
|
std::set<SDNode*> CommuteSet; // Nodes the should be commuted.
|
||||||
|
|
||||||
ScheduleDAG(SelectionDAG &dag, MachineBasicBlock *bb,
|
ScheduleDAG(SelectionDAG &dag, MachineBasicBlock *bb,
|
||||||
const TargetMachine &tm)
|
const TargetMachine &tm)
|
||||||
|
@@ -165,6 +165,9 @@ public:
|
|||||||
bool isTwoAddrInstr(MachineOpCode Opcode) const {
|
bool isTwoAddrInstr(MachineOpCode Opcode) const {
|
||||||
return get(Opcode).Flags & M_2_ADDR_FLAG;
|
return get(Opcode).Flags & M_2_ADDR_FLAG;
|
||||||
}
|
}
|
||||||
|
bool isCommutableInstr(MachineOpCode Opcode) const {
|
||||||
|
return get(Opcode).Flags & M_COMMUTABLE;
|
||||||
|
}
|
||||||
bool isTerminatorInstr(unsigned Opcode) const {
|
bool isTerminatorInstr(unsigned Opcode) const {
|
||||||
return get(Opcode).Flags & M_TERMINATOR_FLAG;
|
return get(Opcode).Flags & M_TERMINATOR_FLAG;
|
||||||
}
|
}
|
||||||
|
@@ -120,13 +120,10 @@ void ScheduleDAG::BuildSchedUnits() {
|
|||||||
|
|
||||||
if (MainNode->isTargetOpcode()) {
|
if (MainNode->isTargetOpcode()) {
|
||||||
unsigned Opc = MainNode->getTargetOpcode();
|
unsigned Opc = MainNode->getTargetOpcode();
|
||||||
if (TII->isTwoAddrInstr(Opc)) {
|
if (TII->isTwoAddrInstr(Opc))
|
||||||
SU->isTwoAddress = true;
|
SU->isTwoAddress = true;
|
||||||
SDNode *OpN = MainNode->getOperand(0).Val;
|
if (TII->isCommutableInstr(Opc))
|
||||||
SUnit *OpSU = SUnitMap[OpN];
|
SU->isCommutable = true;
|
||||||
if (OpSU)
|
|
||||||
OpSU->isDefNUseOperand = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all predecessors and successors of the group.
|
// Find all predecessors and successors of the group.
|
||||||
@@ -391,7 +388,18 @@ void ScheduleDAG::EmitNode(SDNode *Node,
|
|||||||
// instruction as appropriate.
|
// instruction as appropriate.
|
||||||
for (unsigned i = 0; i != NodeOperands; ++i)
|
for (unsigned i = 0; i != NodeOperands; ++i)
|
||||||
AddOperand(MI, Node->getOperand(i), i+NumResults, &II, VRBaseMap);
|
AddOperand(MI, Node->getOperand(i), i+NumResults, &II, VRBaseMap);
|
||||||
|
|
||||||
|
// Commute node if it has been determined to be profitable.
|
||||||
|
if (CommuteSet.count(Node)) {
|
||||||
|
MachineInstr *NewMI = TII->commuteInstruction(MI);
|
||||||
|
if (NewMI == 0)
|
||||||
|
DEBUG(std::cerr << "Sched: COMMUTING FAILED!\n");
|
||||||
|
else {
|
||||||
|
DEBUG(std::cerr << "Sched: COMMUTED TO: " << *NewMI);
|
||||||
|
MI = NewMI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we have emitted all operands, emit this instruction itself.
|
// Now that we have emitted all operands, emit this instruction itself.
|
||||||
if ((II.Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION) == 0) {
|
if ((II.Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION) == 0) {
|
||||||
BB->insert(BB->end(), MI);
|
BB->insert(BB->end(), MI);
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
cl::opt<bool> SchedLowerDefNUse("sched-lower-defnuse", cl::Hidden);
|
cl::opt<bool> SchedCommuteNodes("sched-commute-nodes", cl::Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -70,6 +70,7 @@ private:
|
|||||||
void ScheduleNodeTopDown(SUnit *SU, unsigned& CurCycle);
|
void ScheduleNodeTopDown(SUnit *SU, unsigned& CurCycle);
|
||||||
void ListScheduleTopDown();
|
void ListScheduleTopDown();
|
||||||
void ListScheduleBottomUp();
|
void ListScheduleBottomUp();
|
||||||
|
void CommuteNodesToReducePressure();
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
@@ -95,6 +96,9 @@ void ScheduleDAGRRList::Schedule() {
|
|||||||
ListScheduleTopDown();
|
ListScheduleTopDown();
|
||||||
|
|
||||||
AvailableQueue->releaseState();
|
AvailableQueue->releaseState();
|
||||||
|
|
||||||
|
if (SchedCommuteNodes)
|
||||||
|
CommuteNodesToReducePressure();
|
||||||
|
|
||||||
DEBUG(std::cerr << "*** Final schedule ***\n");
|
DEBUG(std::cerr << "*** Final schedule ***\n");
|
||||||
DEBUG(dumpSchedule());
|
DEBUG(dumpSchedule());
|
||||||
@@ -104,6 +108,41 @@ void ScheduleDAGRRList::Schedule() {
|
|||||||
EmitSchedule();
|
EmitSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CommuteNodesToReducePressure - Is a node is two-address and commutable, and
|
||||||
|
/// it is not the last use of its first operand, add it to the CommuteSet if
|
||||||
|
/// possible. It will be commuted when it is translated to a MI.
|
||||||
|
void ScheduleDAGRRList::CommuteNodesToReducePressure() {
|
||||||
|
std::set<SUnit *> OperandSeen;
|
||||||
|
for (unsigned i = Sequence.size()-1; i != 0; --i) { // Ignore first node.
|
||||||
|
SUnit *SU = Sequence[i];
|
||||||
|
if (!SU) continue;
|
||||||
|
if (SU->isTwoAddress && SU->isCommutable) {
|
||||||
|
SDNode *OpN = SU->Node->getOperand(0).Val;
|
||||||
|
SUnit *OpSU = SUnitMap[OpN];
|
||||||
|
if (OpSU && OperandSeen.count(OpSU) == 1) {
|
||||||
|
// Ok, so SU is not the last use of OpSU, but SU is two-address so
|
||||||
|
// it will clobber OpSU. Try to commute it if possible.
|
||||||
|
bool DoCommute = true;
|
||||||
|
for (unsigned j = 1, e = SU->Node->getNumOperands(); j != e; ++j) {
|
||||||
|
OpN = SU->Node->getOperand(j).Val;
|
||||||
|
OpSU = SUnitMap[OpN];
|
||||||
|
if (OpSU && OperandSeen.count(OpSU) == 1) {
|
||||||
|
DoCommute = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DoCommute)
|
||||||
|
CommuteSet.insert(SU->Node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Preds.begin(),
|
||||||
|
E = SU->Preds.end(); I != E; ++I) {
|
||||||
|
if (!I->second)
|
||||||
|
OperandSeen.insert(I->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Bottom-Up Scheduling
|
// Bottom-Up Scheduling
|
||||||
@@ -436,8 +475,7 @@ namespace {
|
|||||||
void initNodes(const std::vector<SUnit> &sunits) {
|
void initNodes(const std::vector<SUnit> &sunits) {
|
||||||
SUnits = &sunits;
|
SUnits = &sunits;
|
||||||
// Add pseudo dependency edges for two-address nodes.
|
// Add pseudo dependency edges for two-address nodes.
|
||||||
if (SchedLowerDefNUse)
|
AddPseudoTwoAddrDeps();
|
||||||
AddPseudoTwoAddrDeps();
|
|
||||||
// Calculate node priorities.
|
// Calculate node priorities.
|
||||||
CalculatePriorities();
|
CalculatePriorities();
|
||||||
}
|
}
|
||||||
@@ -513,23 +551,6 @@ bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
|||||||
if (RIsFloater)
|
if (RIsFloater)
|
||||||
RBonus += 2;
|
RBonus += 2;
|
||||||
|
|
||||||
if (!SchedLowerDefNUse) {
|
|
||||||
// Special tie breaker: if two nodes share a operand, the one that use it
|
|
||||||
// as a def&use operand is preferred.
|
|
||||||
if (LIsTarget && RIsTarget) {
|
|
||||||
if (left->isTwoAddress && !right->isTwoAddress) {
|
|
||||||
SDNode *DUNode = left->Node->getOperand(0).Val;
|
|
||||||
if (DUNode->isOperand(right->Node))
|
|
||||||
LBonus += 2;
|
|
||||||
}
|
|
||||||
if (!left->isTwoAddress && right->isTwoAddress) {
|
|
||||||
SDNode *DUNode = right->Node->getOperand(0).Val;
|
|
||||||
if (DUNode->isOperand(left->Node))
|
|
||||||
RBonus += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LPriority+LBonus < RPriority+RBonus)
|
if (LPriority+LBonus < RPriority+RBonus)
|
||||||
return true;
|
return true;
|
||||||
else if (LPriority+LBonus == RPriority+RBonus)
|
else if (LPriority+LBonus == RPriority+RBonus)
|
||||||
@@ -602,16 +623,17 @@ void BURegReductionPriorityQueue<SF>::AddPseudoTwoAddrDeps() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (SU->isTwoAddress) {
|
if (SU->isTwoAddress) {
|
||||||
unsigned Depth = SU->Node->getNodeDepth();
|
|
||||||
SUnit *DUSU = getDefUsePredecessor(SU);
|
SUnit *DUSU = getDefUsePredecessor(SU);
|
||||||
if (!DUSU) continue;
|
if (!DUSU) continue;
|
||||||
|
|
||||||
for (std::set<std::pair<SUnit*, bool> >::iterator I = DUSU->Succs.begin(),
|
for (std::set<std::pair<SUnit*, bool> >::iterator I = DUSU->Succs.begin(),
|
||||||
E = DUSU->Succs.end(); I != E; ++I) {
|
E = DUSU->Succs.end(); I != E; ++I) {
|
||||||
|
if (I->second) continue;
|
||||||
SUnit *SuccSU = I->first;
|
SUnit *SuccSU = I->first;
|
||||||
if (SuccSU != SU && !canClobber(SuccSU, DUSU)) {
|
if (SuccSU != SU &&
|
||||||
if (SuccSU->Node->getNodeDepth() <= Depth+2 &&
|
(!canClobber(SuccSU, DUSU) ||
|
||||||
!isReachable(SuccSU, SU)) {
|
(SchedCommuteNodes && !SU->isCommutable && SuccSU->isCommutable))){
|
||||||
|
if (SuccSU->Depth <= SU->Depth+2 && !isReachable(SuccSU, SU)) {
|
||||||
DEBUG(std::cerr << "Adding an edge from SU # " << SU->NodeNum
|
DEBUG(std::cerr << "Adding an edge from SU # " << SU->NodeNum
|
||||||
<< " to SU #" << SuccSU->NodeNum << "\n");
|
<< " to SU #" << SuccSU->NodeNum << "\n");
|
||||||
if (SU->Preds.insert(std::make_pair(SuccSU, true)).second)
|
if (SU->Preds.insert(std::make_pair(SuccSU, true)).second)
|
||||||
|
Reference in New Issue
Block a user