summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2016-07-18 14:52:13 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2016-07-18 14:52:13 +0000
commit3467e9d0a93db2d0a997168d2231d6860b010784 (patch)
treeeafeb1133dfa780f2a2560db262bf0b5dab94a25 /llvm/lib
parentab1b926bb9033018ace8d1dbe780ac954659a94b (diff)
downloadbcm5719-llvm-3467e9d0a93db2d0a997168d2231d6860b010784.tar.gz
bcm5719-llvm-3467e9d0a93db2d0a997168d2231d6860b010784.zip
[Hexagon] HexagonMachineScheduler should account for resources
The machine scheduler needs to account for available resources more accurately in order to avoid scheduling an instruction that forces a new packet to be created. This occurs in two ways: First, an instruction without an available resource may have a large priority due to other metrics and be scheduled when there are other instructions with available resources. Second, an instruction with a non-zero latency may become available prematurely. In both these cases, we attempt change the priority in order to allow a better instruction to be scheduled. Patch by Brendon Cahoon. llvm-svn: 275793
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp88
1 files changed, 78 insertions, 10 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp b/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp
index 2e7a46fe2d6..5e275f0975d 100644
--- a/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonMachineScheduler.cpp
@@ -18,12 +18,20 @@
#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include "llvm/IR/Function.h"
+static cl::opt<bool> IgnoreBBRegPressure("ignore-bb-reg-pressure",
+ cl::Hidden, cl::ZeroOrMore, cl::init(false));
+
static cl::opt<bool> SchedPredsCloser("sched-preds-closer",
cl::Hidden, cl::ZeroOrMore, cl::init(true));
static cl::opt<bool> SchedRetvalOptimization("sched-retval-optimization",
cl::Hidden, cl::ZeroOrMore, cl::init(true));
+// Check if the scheduler should penalize instructions that are available to
+// early due to a zero-latency dependence.
+static cl::opt<bool> CheckEarlyAvail("check-early-avail", cl::Hidden,
+ cl::ZeroOrMore, cl::init(true));
+
using namespace llvm;
#define DEBUG_TYPE "misched"
@@ -573,15 +581,23 @@ int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
// If resources are available for it, multiply the
// chance of scheduling.
- if (Top.ResourceModel->isResourceAvailable(SU))
+ if (Top.ResourceModel->isResourceAvailable(SU)) {
ResCount <<= FactorOne;
+ ResCount += PriorityThree;
+ DEBUG(if (verbose) dbgs() << "A|");
+ } else
+ DEBUG(if (verbose) dbgs() << " |");
} else {
ResCount += (SU->getDepth() * ScaleTwo);
// If resources are available for it, multiply the
// chance of scheduling.
- if (Bot.ResourceModel->isResourceAvailable(SU))
+ if (Bot.ResourceModel->isResourceAvailable(SU)) {
ResCount <<= FactorOne;
+ ResCount += PriorityThree;
+ DEBUG(if (verbose) dbgs() << "A|");
+ } else
+ DEBUG(if (verbose) dbgs() << " |");
}
unsigned NumNodesBlocking = 0;
@@ -590,23 +606,35 @@ int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
// Look at all of the successors of this node.
// Count the number of nodes that
// this node is the sole unscheduled node for.
- for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
- I != E; ++I)
- if (getSingleUnscheduledPred(I->getSUnit()) == SU)
+ for (const SDep &SI : SU->Succs)
+ if (getSingleUnscheduledPred(SI.getSUnit()) == SU)
++NumNodesBlocking;
} else {
// How many unscheduled predecessors block this node?
- for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
- I != E; ++I)
- if (getSingleUnscheduledSucc(I->getSUnit()) == SU)
+ for (const SDep &PI : SU->Preds)
+ if (getSingleUnscheduledSucc(PI.getSUnit()) == SU)
++NumNodesBlocking;
}
ResCount += (NumNodesBlocking * ScaleTwo);
// Factor in reg pressure as a heuristic.
- ResCount -= (Delta.Excess.getUnitInc()*PriorityTwo);
- ResCount -= (Delta.CriticalMax.getUnitInc()*PriorityTwo);
+ if (!IgnoreBBRegPressure) {
+ // Decrease priority by the amount that register pressure exceeds the limit.
+ ResCount -= (Delta.Excess.getUnitInc()*PriorityOne);
+ // Decrease priority if register pressure exceeds the limit.
+ ResCount -= (Delta.CriticalMax.getUnitInc()*PriorityOne);
+ // Decrease priority slightly if register pressure would increase over the
+ // current maximum.
+ ResCount -= (Delta.CurrentMax.getUnitInc()*PriorityTwo);
+ DEBUG(if (verbose) {
+ dbgs() << "RP " << Delta.Excess.getUnitInc() << "/"
+ << Delta.CriticalMax.getUnitInc() <<"/"
+ << Delta.CurrentMax.getUnitInc() << ")|";
+ });
+ }
+ // Give a little extra priority to a .cur instruction if there is a resource
+ // available for it.
auto &QST = DAG->MF.getSubtarget<HexagonSubtarget>();
auto &QII = *QST.getInstrInfo();
@@ -660,6 +688,46 @@ int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
}
}
+ // If the instruction has a non-zero latency dependence with an instruction in
+ // the current packet, then it should not be scheduled yet. The case occurs
+ // when the dependent instruction is scheduled in a new packet, so the
+ // scheduler updates the current cycle and pending instructions become
+ // available.
+ if (CheckEarlyAvail) {
+ if (Q.getID() == TopQID) {
+ for (const auto &PI : SU->Preds) {
+ if (PI.getLatency() > 0 &&
+ Top.ResourceModel->isInPacket(PI.getSUnit())) {
+ ResCount -= PriorityOne;
+ DEBUG(if (verbose) dbgs() << "D|");
+ }
+ }
+ } else {
+ for (const auto &SI : SU->Succs) {
+ if (SI.getLatency() > 0 &&
+ Bot.ResourceModel->isInPacket(SI.getSUnit())) {
+ ResCount -= PriorityOne;
+ DEBUG(if (verbose) dbgs() << "D|");
+ }
+ }
+ }
+ }
+
+ // Give less preference to an instruction that will cause a stall with
+ // an instruction in the previous packet.
+ if (QII.isV60VectorInstruction(Instr)) {
+ // Check for stalls in the previous packet.
+ if (Q.getID() == TopQID) {
+ for (auto J : Top.ResourceModel->OldPacket)
+ if (QII.producesStall(J->getInstr(), Instr))
+ ResCount -= PriorityOne;
+ } else {
+ for (auto J : Bot.ResourceModel->OldPacket)
+ if (QII.producesStall(Instr, J->getInstr()))
+ ResCount -= PriorityOne;
+ }
+ }
+
DEBUG(if (verbose) dbgs() << " Total(" << ResCount << ")");
return ResCount;
OpenPOWER on IntegriCloud