mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Post RA scheduler changes. Introduce a hazard recognizer that uses the target schedule information to accurately model the pipeline. Update the scheduler to correctly handle multi-issue targets.
llvm-svn: 78563
This commit is contained in:
parent
0a08d1bb9c
commit
3245141543
@ -43,6 +43,11 @@ public:
|
||||
return NoHazard;
|
||||
}
|
||||
|
||||
/// Reset - This callback is invoked when a new block of
|
||||
/// instructions is about to be schedule. The hazard state should be
|
||||
/// set to an initialized state.
|
||||
virtual void Reset() {}
|
||||
|
||||
/// EmitInstruction - This callback is invoked when an instruction is
|
||||
/// emitted, to advance the hazard state.
|
||||
virtual void EmitInstruction(SUnit *) {}
|
||||
|
@ -20,9 +20,9 @@ namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Instruction stage - These values represent a step in the execution of an
|
||||
/// instruction. The latency represents the number of discrete time slots used
|
||||
/// need to complete the stage. Units represent the choice of functional units
|
||||
/// that can be used to complete the stage. Eg. IntUnit1, IntUnit2.
|
||||
/// instruction. The latency represents the number of discrete time slots
|
||||
/// needed to complete the stage. Units represent the choice of functional
|
||||
/// units that can be used to complete the stage. Eg. IntUnit1, IntUnit2.
|
||||
///
|
||||
struct InstrStage {
|
||||
unsigned Cycles; ///< Length of stage in machine cycles
|
||||
@ -84,7 +84,9 @@ struct InstrItineraryData {
|
||||
if (isEmpty())
|
||||
return 1;
|
||||
|
||||
// Just sum the cycle count for each stage.
|
||||
// Just sum the cycle count for each stage. The assumption is that all
|
||||
// inputs are consumed at the start of the first stage and that all
|
||||
// outputs are produced at the end of the last stage.
|
||||
unsigned Latency = 0;
|
||||
for (const InstrStage *IS = begin(ItinClassIndx), *E = end(ItinClassIndx);
|
||||
IS != E; ++IS)
|
||||
|
@ -6,6 +6,7 @@ add_llvm_library(LLVMCodeGen
|
||||
DwarfEHPrepare.cpp
|
||||
ELFCodeEmitter.cpp
|
||||
ELFWriter.cpp
|
||||
ExactHazardRecognizer.cpp
|
||||
GCMetadata.cpp
|
||||
GCMetadataPrinter.cpp
|
||||
GCStrategy.cpp
|
||||
|
149
lib/CodeGen/ExactHazardRecognizer.cpp
Normal file
149
lib/CodeGen/ExactHazardRecognizer.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
//===----- ExactHazardRecognizer.cpp - hazard recognizer -------- ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This implements a a hazard recognizer using the instructions itineraries
|
||||
// defined for the current target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "exact-hazards"
|
||||
#include "ExactHazardRecognizer.h"
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Target/TargetInstrItineraries.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
ExactHazardRecognizer::ExactHazardRecognizer(const InstrItineraryData &LItinData) :
|
||||
ScheduleHazardRecognizer(), ItinData(LItinData)
|
||||
{
|
||||
// Determine the maximum depth of any itinerary. This determines the
|
||||
// depth of the scoreboard. We always make the scoreboard at least 1
|
||||
// cycle deep to avoid dealing with the boundary condition.
|
||||
ScoreboardDepth = 1;
|
||||
if (!ItinData.isEmpty()) {
|
||||
for (unsigned idx = 0; ; ++idx) {
|
||||
// If the begin stage of an itinerary has 0 cycles and units,
|
||||
// then we have reached the end of the itineraries.
|
||||
const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
|
||||
if ((IS->Cycles == 0) && (IS->Units == 0))
|
||||
break;
|
||||
|
||||
unsigned ItinDepth = 0;
|
||||
for (; IS != E; ++IS)
|
||||
ItinDepth += IS->Cycles;
|
||||
|
||||
ScoreboardDepth = std::max(ScoreboardDepth, ItinDepth);
|
||||
}
|
||||
}
|
||||
|
||||
Scoreboard = new unsigned[ScoreboardDepth];
|
||||
ScoreboardHead = 0;
|
||||
|
||||
DOUT << "Using exact hazard recognizer: ScoreboardDepth = "
|
||||
<< ScoreboardDepth << '\n';
|
||||
}
|
||||
|
||||
ExactHazardRecognizer::~ExactHazardRecognizer() {
|
||||
delete Scoreboard;
|
||||
}
|
||||
|
||||
void ExactHazardRecognizer::Reset() {
|
||||
memset(Scoreboard, 0, ScoreboardDepth * sizeof(unsigned));
|
||||
ScoreboardHead = 0;
|
||||
}
|
||||
|
||||
unsigned ExactHazardRecognizer::getFutureIndex(unsigned offset) {
|
||||
return (ScoreboardHead + offset) % ScoreboardDepth;
|
||||
}
|
||||
|
||||
void ExactHazardRecognizer::dumpScoreboard() {
|
||||
DOUT << "Scoreboard:\n";
|
||||
|
||||
unsigned last = ScoreboardDepth - 1;
|
||||
while ((last > 0) && (Scoreboard[getFutureIndex(last)] == 0))
|
||||
last--;
|
||||
|
||||
for (unsigned i = 0; i <= last; i++) {
|
||||
unsigned FUs = Scoreboard[getFutureIndex(i)];
|
||||
DOUT << "\t";
|
||||
for (int j = 31; j >= 0; j--)
|
||||
DOUT << ((FUs & (1 << j)) ? '1' : '0');
|
||||
DOUT << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
ExactHazardRecognizer::HazardType ExactHazardRecognizer::getHazardType(SUnit *SU) {
|
||||
unsigned cycle = 0;
|
||||
|
||||
// Use the itinerary for the underlying instruction to check for
|
||||
// free FU's in the scoreboard at the appropriate future cycles.
|
||||
unsigned idx = SU->getInstr()->getDesc().getSchedClass();
|
||||
for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
|
||||
IS != E; ++IS) {
|
||||
// We must find one of the stage's units free for every cycle the
|
||||
// stage is occupied.
|
||||
for (unsigned int i = 0; i < IS->Cycles; ++i) {
|
||||
assert((cycle < ScoreboardDepth) && "Scoreboard depth exceeded!");
|
||||
|
||||
unsigned index = getFutureIndex(cycle);
|
||||
unsigned freeUnits = IS->Units & ~Scoreboard[index];
|
||||
if (!freeUnits) {
|
||||
DOUT << "*** Hazard in cycle " << cycle << ", ";
|
||||
DOUT << "SU(" << SU->NodeNum << "): ";
|
||||
DEBUG(SU->getInstr()->dump());
|
||||
return Hazard;
|
||||
}
|
||||
|
||||
++cycle;
|
||||
}
|
||||
}
|
||||
|
||||
return NoHazard;
|
||||
}
|
||||
|
||||
void ExactHazardRecognizer::EmitInstruction(SUnit *SU) {
|
||||
unsigned cycle = 0;
|
||||
|
||||
// Use the itinerary for the underlying instruction to reserve FU's
|
||||
// in the scoreboard at the appropriate future cycles.
|
||||
unsigned idx = SU->getInstr()->getDesc().getSchedClass();
|
||||
for (const InstrStage *IS = ItinData.begin(idx), *E = ItinData.end(idx);
|
||||
IS != E; ++IS) {
|
||||
// We must reserve one of the stage's units for every cycle the
|
||||
// stage is occupied.
|
||||
for (unsigned int i = 0; i < IS->Cycles; ++i) {
|
||||
assert((cycle < ScoreboardDepth) && "Scoreboard depth exceeded!");
|
||||
|
||||
unsigned index = getFutureIndex(cycle);
|
||||
unsigned freeUnits = IS->Units & ~Scoreboard[index];
|
||||
|
||||
// reduce to a single unit
|
||||
unsigned freeUnit = 0;
|
||||
do {
|
||||
freeUnit = freeUnits;
|
||||
freeUnits = freeUnit & (freeUnit - 1);
|
||||
} while (freeUnits);
|
||||
|
||||
assert(freeUnit && "No function unit available!");
|
||||
Scoreboard[index] |= freeUnit;
|
||||
++cycle;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(dumpScoreboard());
|
||||
}
|
||||
|
||||
void ExactHazardRecognizer::AdvanceCycle() {
|
||||
Scoreboard[ScoreboardHead] = 0;
|
||||
ScoreboardHead = getFutureIndex(1);
|
||||
}
|
||||
|
||||
} /* namespace llvm */
|
61
lib/CodeGen/ExactHazardRecognizer.h
Normal file
61
lib/CodeGen/ExactHazardRecognizer.h
Normal file
@ -0,0 +1,61 @@
|
||||
//=- llvm/CodeGen/ExactHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the ExactHazardRecognizer class, which
|
||||
// implements hazard-avoidance heuristics for scheduling, based on the
|
||||
// scheduling itineraries specified for the target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
|
||||
#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
|
||||
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/CodeGen/ScheduleDAG.h"
|
||||
#include "llvm/Target/TargetInstrItineraries.h"
|
||||
|
||||
namespace llvm {
|
||||
class ExactHazardRecognizer : public ScheduleHazardRecognizer {
|
||||
// Itinerary data for the target.
|
||||
const InstrItineraryData &ItinData;
|
||||
|
||||
// Scoreboard to track function unit usage. Scoreboard[0] is a
|
||||
// mask of the FUs in use in the cycle currently being
|
||||
// schedule. Scoreboard[1] is a mask for the next cycle. The
|
||||
// Scoreboard is used as a circular buffer with the current cycle
|
||||
// indicated by ScoreboardHead.
|
||||
unsigned *Scoreboard;
|
||||
|
||||
// The maximum number of cycles monitored by the Scoreboard. This
|
||||
// value is determined based on the target itineraries to ensure
|
||||
// that all hazards can be tracked.
|
||||
unsigned ScoreboardDepth;
|
||||
|
||||
// Indices into the Scoreboard that represent the current cycle.
|
||||
unsigned ScoreboardHead;
|
||||
|
||||
// Return the scoreboard index to use for 'offset' cycles in the
|
||||
// future. 'offset' of 0 returns ScoreboardHead.
|
||||
unsigned getFutureIndex(unsigned offset);
|
||||
|
||||
// Print the scoreboard.
|
||||
void dumpScoreboard();
|
||||
|
||||
public:
|
||||
ExactHazardRecognizer(const InstrItineraryData &ItinData);
|
||||
~ExactHazardRecognizer();
|
||||
|
||||
virtual HazardType getHazardType(SUnit *SU);
|
||||
virtual void Reset();
|
||||
virtual void EmitInstruction(SUnit *SU);
|
||||
virtual void AdvanceCycle();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -19,6 +19,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "post-RA-sched"
|
||||
#include "ExactHazardRecognizer.h"
|
||||
#include "SimpleHazardRecognizer.h"
|
||||
#include "ScheduleDAGInstrs.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/LatencyPriorityQueue.h"
|
||||
@ -49,8 +51,8 @@ EnableAntiDepBreaking("break-anti-dependencies",
|
||||
|
||||
static cl::opt<bool>
|
||||
EnablePostRAHazardAvoidance("avoid-hazards",
|
||||
cl::desc("Enable simple hazard-avoidance"),
|
||||
cl::init(true), cl::Hidden);
|
||||
cl::desc("Enable exact hazard avoidance"),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN PostRAScheduler : public MachineFunctionPass {
|
||||
@ -156,62 +158,6 @@ namespace {
|
||||
void ListScheduleTopDown();
|
||||
bool BreakAntiDependencies();
|
||||
};
|
||||
|
||||
/// SimpleHazardRecognizer - A *very* simple hazard recognizer. It uses
|
||||
/// a coarse classification and attempts to avoid that instructions of
|
||||
/// a given class aren't grouped too densely together.
|
||||
class SimpleHazardRecognizer : public ScheduleHazardRecognizer {
|
||||
/// Class - A simple classification for SUnits.
|
||||
enum Class {
|
||||
Other, Load, Store
|
||||
};
|
||||
|
||||
/// Window - The Class values of the most recently issued
|
||||
/// instructions.
|
||||
Class Window[8];
|
||||
|
||||
/// getClass - Classify the given SUnit.
|
||||
Class getClass(const SUnit *SU) {
|
||||
const MachineInstr *MI = SU->getInstr();
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
if (TID.mayLoad())
|
||||
return Load;
|
||||
if (TID.mayStore())
|
||||
return Store;
|
||||
return Other;
|
||||
}
|
||||
|
||||
/// Step - Rotate the existing entries in Window and insert the
|
||||
/// given class value in position as the most recent.
|
||||
void Step(Class C) {
|
||||
std::copy(Window+1, array_endof(Window), Window);
|
||||
Window[array_lengthof(Window)-1] = C;
|
||||
}
|
||||
|
||||
public:
|
||||
SimpleHazardRecognizer() : Window() {}
|
||||
|
||||
virtual HazardType getHazardType(SUnit *SU) {
|
||||
Class C = getClass(SU);
|
||||
if (C == Other)
|
||||
return NoHazard;
|
||||
unsigned Score = 0;
|
||||
for (unsigned i = 0; i != array_lengthof(Window); ++i)
|
||||
if (Window[i] == C)
|
||||
Score += i + 1;
|
||||
if (Score > array_lengthof(Window) * 2)
|
||||
return Hazard;
|
||||
return NoHazard;
|
||||
}
|
||||
|
||||
virtual void EmitInstruction(SUnit *SU) {
|
||||
Step(getClass(SU));
|
||||
}
|
||||
|
||||
virtual void AdvanceCycle() {
|
||||
Step(Other);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// isSchedulingBoundary - Test if the given instruction should be
|
||||
@ -241,9 +187,10 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
const MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
|
||||
const MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
|
||||
const InstrItineraryData &InstrItins = Fn.getTarget().getInstrItineraryData();
|
||||
ScheduleHazardRecognizer *HR = EnablePostRAHazardAvoidance ?
|
||||
new SimpleHazardRecognizer :
|
||||
new ScheduleHazardRecognizer();
|
||||
(ScheduleHazardRecognizer *)new ExactHazardRecognizer(InstrItins) :
|
||||
(ScheduleHazardRecognizer *)new SimpleHazardRecognizer();
|
||||
|
||||
SchedulePostRATDList Scheduler(Fn, MLI, MDT, HR);
|
||||
|
||||
@ -289,6 +236,9 @@ void SchedulePostRATDList::StartBlock(MachineBasicBlock *BB) {
|
||||
// Call the superclass.
|
||||
ScheduleDAGInstrs::StartBlock(BB);
|
||||
|
||||
// Reset the hazard recognizer.
|
||||
HazardRec->Reset();
|
||||
|
||||
// Clear out the register class data.
|
||||
std::fill(Classes, array_endof(Classes),
|
||||
static_cast<const TargetRegisterClass *>(0));
|
||||
@ -380,6 +330,9 @@ void SchedulePostRATDList::Schedule() {
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
|
||||
SUnits[su].dumpAll(this));
|
||||
|
||||
AvailableQueue.initNodes(SUnits);
|
||||
|
||||
ListScheduleTopDown();
|
||||
@ -872,13 +825,6 @@ void SchedulePostRATDList::ListScheduleTopDown() {
|
||||
MinDepth = PendingQueue[i]->getDepth();
|
||||
}
|
||||
|
||||
// If there are no instructions available, don't try to issue anything, and
|
||||
// don't advance the hazard recognizer.
|
||||
if (AvailableQueue.empty()) {
|
||||
CurCycle = MinDepth != ~0u ? MinDepth : CurCycle + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
SUnit *FoundSUnit = 0;
|
||||
|
||||
bool HasNoopHazards = false;
|
||||
@ -909,10 +855,14 @@ void SchedulePostRATDList::ListScheduleTopDown() {
|
||||
ScheduleNodeTopDown(FoundSUnit, CurCycle);
|
||||
HazardRec->EmitInstruction(FoundSUnit);
|
||||
|
||||
// If this is a pseudo-op node, we don't want to increment the current
|
||||
// cycle.
|
||||
if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops!
|
||||
++CurCycle;
|
||||
// If we are using the target-specific hazards, then don't
|
||||
// advance the cycle time just because we schedule a node. If
|
||||
// the target allows it we can schedule multiple nodes in the
|
||||
// same cycle.
|
||||
if (!EnablePostRAHazardAvoidance) {
|
||||
if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops!
|
||||
++CurCycle;
|
||||
}
|
||||
} else if (!HasNoopHazards) {
|
||||
// Otherwise, we have a pipeline stall, but no other problem, just advance
|
||||
// the current cycle and try again.
|
||||
|
@ -174,16 +174,20 @@ void ScheduleDAGInstrs::BuildSchedGraph() {
|
||||
assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!");
|
||||
std::vector<SUnit *> &UseList = Uses[Reg];
|
||||
std::vector<SUnit *> &DefList = Defs[Reg];
|
||||
// Optionally add output and anti dependencies.
|
||||
// TODO: Using a latency of 1 here assumes there's no cost for
|
||||
// reusing registers.
|
||||
// Optionally add output and anti dependencies. For anti
|
||||
// dependencies we use a latency of 0 because for a multi-issue
|
||||
// target we want to allow the defining instruction to issue
|
||||
// in the same cycle as the using instruction.
|
||||
// TODO: Using a latency of 1 here for output dependencies assumes
|
||||
// there's no cost for reusing registers.
|
||||
SDep::Kind Kind = MO.isUse() ? SDep::Anti : SDep::Output;
|
||||
unsigned AOLatency = (Kind == SDep::Anti) ? 0 : 1;
|
||||
for (unsigned i = 0, e = DefList.size(); i != e; ++i) {
|
||||
SUnit *DefSU = DefList[i];
|
||||
if (DefSU != SU &&
|
||||
(Kind != SDep::Output || !MO.isDead() ||
|
||||
!DefSU->getInstr()->registerDefIsDead(Reg)))
|
||||
DefSU->addPred(SDep(SU, Kind, /*Latency=*/1, /*Reg=*/Reg));
|
||||
DefSU->addPred(SDep(SU, Kind, AOLatency, /*Reg=*/Reg));
|
||||
}
|
||||
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) {
|
||||
std::vector<SUnit *> &DefList = Defs[*Alias];
|
||||
@ -192,7 +196,7 @@ void ScheduleDAGInstrs::BuildSchedGraph() {
|
||||
if (DefSU != SU &&
|
||||
(Kind != SDep::Output || !MO.isDead() ||
|
||||
!DefSU->getInstr()->registerDefIsDead(Reg)))
|
||||
DefSU->addPred(SDep(SU, Kind, /*Latency=*/1, /*Reg=*/ *Alias));
|
||||
DefSU->addPred(SDep(SU, Kind, AOLatency, /*Reg=*/ *Alias));
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,8 +403,7 @@ void ScheduleDAGInstrs::FinishBlock() {
|
||||
void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) {
|
||||
const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
|
||||
|
||||
// Compute the latency for the node. We use the sum of the latencies for
|
||||
// all nodes flagged together into this SUnit.
|
||||
// Compute the latency for the node.
|
||||
SU->Latency =
|
||||
InstrItins.getLatency(SU->getInstr()->getDesc().getSchedClass());
|
||||
|
||||
|
89
lib/CodeGen/SimpleHazardRecognizer.h
Normal file
89
lib/CodeGen/SimpleHazardRecognizer.h
Normal file
@ -0,0 +1,89 @@
|
||||
//=- llvm/CodeGen/SimpleHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the SimpleHazardRecognizer class, which
|
||||
// implements hazard-avoidance heuristics for scheduling, based on the
|
||||
// scheduling itineraries specified for the target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_SIMPLEHAZARDRECOGNIZER_H
|
||||
#define LLVM_CODEGEN_SIMPLEHAZARDRECOGNIZER_H
|
||||
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/CodeGen/ScheduleDAG.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
/// SimpleHazardRecognizer - A *very* simple hazard recognizer. It uses
|
||||
/// a coarse classification and attempts to avoid that instructions of
|
||||
/// a given class aren't grouped too densely together.
|
||||
class SimpleHazardRecognizer : public ScheduleHazardRecognizer {
|
||||
/// Class - A simple classification for SUnits.
|
||||
enum Class {
|
||||
Other, Load, Store
|
||||
};
|
||||
|
||||
/// Window - The Class values of the most recently issued
|
||||
/// instructions.
|
||||
Class Window[8];
|
||||
|
||||
/// getClass - Classify the given SUnit.
|
||||
Class getClass(const SUnit *SU) {
|
||||
const MachineInstr *MI = SU->getInstr();
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
if (TID.mayLoad())
|
||||
return Load;
|
||||
if (TID.mayStore())
|
||||
return Store;
|
||||
return Other;
|
||||
}
|
||||
|
||||
/// Step - Rotate the existing entries in Window and insert the
|
||||
/// given class value in position as the most recent.
|
||||
void Step(Class C) {
|
||||
std::copy(Window+1, array_endof(Window), Window);
|
||||
Window[array_lengthof(Window)-1] = C;
|
||||
}
|
||||
|
||||
public:
|
||||
SimpleHazardRecognizer() : Window() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
virtual HazardType getHazardType(SUnit *SU) {
|
||||
Class C = getClass(SU);
|
||||
if (C == Other)
|
||||
return NoHazard;
|
||||
unsigned Score = 0;
|
||||
for (unsigned i = 0; i != array_lengthof(Window); ++i)
|
||||
if (Window[i] == C)
|
||||
Score += i + 1;
|
||||
if (Score > array_lengthof(Window) * 2)
|
||||
return Hazard;
|
||||
return NoHazard;
|
||||
}
|
||||
|
||||
virtual void Reset() {
|
||||
for (unsigned i = 0; i != array_lengthof(Window); ++i)
|
||||
Window[i] = Other;
|
||||
}
|
||||
|
||||
virtual void EmitInstruction(SUnit *SU) {
|
||||
Step(getClass(SU));
|
||||
}
|
||||
|
||||
virtual void AdvanceCycle() {
|
||||
Step(Other);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user