TCE  1.20
Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
BypassingBUBasicBlockScheduler Class Reference

#include <BypassingBUBasicBlockScheduler.hh>

Inheritance diagram for BypassingBUBasicBlockScheduler:
Inheritance graph
Collaboration diagram for BypassingBUBasicBlockScheduler:
Collaboration graph

Public Types

enum  TempRegCopyLocation { TempRegNotAllowed, TempRegBefore, TempRegAfter }
 

Public Member Functions

 BypassingBUBasicBlockScheduler (InterPassData &data, SoftwareBypasser *bypasser=NULL, CopyingDelaySlotFiller *delaySlotFiller=NULL, RegisterRenamer *registerRenamer=NULL)
 
virtual ~BypassingBUBasicBlockScheduler ()
 
virtual void handleDDG (DataDependenceGraph &ddg, SimpleResourceManager &rm, const TTAMachine::Machine &targetMachine)
 
virtual std::string shortDescription () const
 
virtual std::string longDescription () const
 
virtual MoveNodeSelectorcreateSelector (TTAProgram::BasicBlock &bb, const TTAMachine::Machine &machine)
 
void scheduleOperation (MoveNodeGroup &mng, MoveNodeSelector &selector)
 
- Public Member Functions inherited from BasicBlockScheduler
 BasicBlockScheduler (InterPassData &data, SoftwareBypasser *bypasser=NULL, CopyingDelaySlotFiller *delaySlotFiller=NULL, RegisterRenamer *registerRenamer=NULL)
 
virtual ~BasicBlockScheduler ()
 
- Public Member Functions inherited from BBSchedulerController
 BBSchedulerController (InterPassData &data, SoftwareBypasser *bypasser=NULL, CopyingDelaySlotFiller *delaySlotFiller=NULL, DataDependenceGraph *bigDDG=NULL)
 
virtual ~BBSchedulerController ()
 
virtual void handleBasicBlock (TTAProgram::BasicBlock &bb, const TTAMachine::Machine &targetMachine, TTAProgram::InstructionReferenceManager &irm, BasicBlockNode *bbn=NULL)
 
virtual void handleControlFlowGraph (ControlFlowGraph &cfg, const TTAMachine::Machine &targetMachine)
 
virtual void handleProcedure (TTAProgram::Procedure &procedure, const TTAMachine::Machine &targetMachine)
 
virtual void handleProgram (TTAProgram::Program &program, const TTAMachine::Machine &targetMachine)
 
virtual void executeDDGPass (TTAProgram::BasicBlock &bb, const TTAMachine::Machine &targetMachine, TTAProgram::InstructionReferenceManager &irm, std::vector< DDGPass *> ddgPasses, BasicBlockNode *bbn=NULL)
 
virtual void handleCFGDDG (ControlFlowGraph &cfg, DataDependenceGraph &ddg, const TTAMachine::Machine &targetMachine)
 
- Public Member Functions inherited from BasicBlockPass
 BasicBlockPass (InterPassData &data)
 
virtual ~BasicBlockPass ()
 
virtual bool executeLoopPass (TTAProgram::BasicBlock &bb, const TTAMachine::Machine &targetMachine, TTAProgram::InstructionReferenceManager &irm, std::vector< DDGPass *> ddgPasses, BasicBlockNode *bbn=NULL)
 
virtual DataDependenceGraphBuilderddgBuilder ()
 
- Public Member Functions inherited from SchedulerPass
 SchedulerPass (InterPassData &data)
 
virtual ~SchedulerPass ()
 
InterPassDatainterPassData ()
 
- Public Member Functions inherited from ControlFlowGraphPass
 ControlFlowGraphPass (InterPassData &data)
 
virtual ~ControlFlowGraphPass ()
 
void executeBasicBlockPass (ControlFlowGraph &cfg, const TTAMachine::Machine &targetMachine, BasicBlockPass &bbPass)
 
- Public Member Functions inherited from ProcedurePass
 ProcedurePass (InterPassData &data)
 
virtual ~ProcedurePass ()
 
- Public Member Functions inherited from ProgramPass
 ProgramPass (InterPassData &data)
 
virtual ~ProgramPass ()
 
- Public Member Functions inherited from DDGPass
 DDGPass (InterPassData &data)
 
virtual ~DDGPass ()
 

Private Member Functions

bool renameSourceIfNotConnected (MoveNode &moveNode, int latestCycle)
 
void finalizeOperation (MoveNodeSelector &selector)
 
bool scheduleOperation (ProgramOperation &po, int &latestCycle, bool allowTempRegCopies)
 
bool scheduleResults (ProgramOperation &po, int latestCycle, bool allowTempRegCopies)
 
bool scheduleMoveUB (MoveNode &mn, int earlistCycle, int latestCycle)
 
bool scheduleMoveBU (MoveNode &mn, int earlistCycle, int latestCycle, TempRegCopyLocation t)
 
int bypassNode (MoveNode &node, int maxHopCount)
 
std::pair< MoveNode *, int > findBypassSource (MoveNode &node, int maxHopCount)
 
bool bypassAndScheduleNode (MoveNode &node, MoveNode *trigger, int latestCycle, bool allowRegCopies)
 
bool bypassAndScheduleOperands (ProgramOperation &po, MoveNode *trigger, int latestCycle, bool allowRegCopies)
 
bool scheduleOperandOrTrigger (MoveNode &operand, MoveNode *trigger, int latestCycle, bool allowRegCopies)
 
void unscheduleResults (ProgramOperation &po)
 
void unscheduleOperands (ProgramOperation &po)
 
void unschedule (MoveNode &mn)
 
void undoBypass (MoveNode &mn)
 
void undoBypassAndUnschedule (MoveNode &mn)
 
void unscheduleOperation (ProgramOperation &po)
 
std::pair< int, int > operandCycleLimits (MoveNode &mn, MoveNode *trigger)
 
int lastOperandCycle (const ProgramOperation &po)
 
MoveNodecreateTempRegCopy (MoveNode &mn, bool after)
 
void createAntidepsFromUnscheduledRegCopies (MoveNode &copyNode, MoveNode &mn, TTAProgram::Terminal &terminalRegister)
 
std::set< TTAMachine::RegisterFile *, TTAMachine::MachinePart::ComparatorpossibleTempRegRFs (const MoveNode &mn, bool tempRegAfter)
 
void clearCaches ()
 

Private Attributes

std::map< MoveNode *, MoveNode *, MoveNode::ComparatorbypassSources_
 
std::map< MoveNode *, MoveNode *, MoveNode::ComparatorremovedBypassSources_
 
std::set< MoveNode *, MoveNode::ComparatorremovedNodes_
 
std::set< MoveNode *, MoveNode::ComparatorpendingBypassSources_
 
std::set< MoveNode *, MoveNode::ComparatorscheduledMoves_
 
std::map< MoveNode *, MoveNode *, MoveNode::ComparatorregCopiesBefore_
 
std::map< MoveNode *, MoveNode *, MoveNode::ComparatorregCopiesAfter_
 
bool killDeadResults_
 
bool renameRegisters_
 
int endCycle_
 

Additional Inherited Members

- Static Public Member Functions inherited from BasicBlockPass
static void copyRMToBB (SimpleResourceManager &rm, TTAProgram::BasicBlock &bb, const TTAMachine::Machine &targetMachine, TTAProgram::InstructionReferenceManager &irm, int lastCycle=-1)
 
- Static Public Member Functions inherited from ProcedurePass
static void copyCfgToProcedure (TTAProgram::Procedure &procedure, ControlFlowGraph &cfg)
 
static void executeControlFlowGraphPass (TTAProgram::Procedure &procedure, const TTAMachine::Machine &targetmachine, ControlFlowGraphPass &cfgp)
 
- Static Public Member Functions inherited from ProgramPass
static void executeProcedurePass (TTAProgram::Program &program, const TTAMachine::Machine &targetMachine, ProcedurePass &procedurePass)
 
- Protected Member Functions inherited from BasicBlockScheduler
void scheduleRRMove (MoveNode &moveNode)
 
void scheduleOperation (MoveNodeGroup &moves)
 
int scheduleOperandWrites (int &cycle, MoveNodeGroup &moves)
 
bool scheduleResultReads (MoveNodeGroup &moves)
 
void scheduleMove (MoveNode &move, int earliestCycle)
 
void scheduleRRTempMoves (MoveNode &regToRegMove, MoveNode &firstMove, int lastUse)
 
void scheduleInputOperandTempMoves (MoveNode &operandMove, MoveNode &operandWrite)
 
void unschedule (MoveNode &moveNode)
 
void unscheduleInputOperandTempMoves (MoveNode &operandMove)
 
void scheduleResultReadTempMoves (MoveNode &resultMove, MoveNode &resultRead, int lastUse)
 
void unscheduleResultReadTempMoves (MoveNode &resultMove)
 
void notifyScheduled (MoveNodeGroup &moves, MoveNodeSelector &selector)
 
void ddgSnapshot (DataDependenceGraph &ddg, const std::string &name, DataDependenceGraph::DumpFileFormat format, bool final, bool resetCounter=false) const
 
MoveNodesucceedingTempMove (MoveNode &current)
 
int getTriggerOperand (const Operation &operation, const TTAMachine::Machine &machine)
 
bool tryToSwitchInputs (ProgramOperation &op)
 
MoveNodefindTrigger (ProgramOperation &po)
 
MoveNodefindTriggerFromUnit (ProgramOperation &po, TTAMachine::Unit &unit)
 
- Protected Member Functions inherited from BBSchedulerController
virtual DataDependenceGraphcreateDDGFromBB (TTAProgram::BasicBlock &bb, const TTAMachine::Machine &mach)
 
- Protected Member Functions inherited from BasicBlockPass
void ddgSnapshot (DataDependenceGraph *ddg, std::string &name, DataDependenceGraph::DumpFileFormat format, bool final)
 
- Protected Attributes inherited from BasicBlockScheduler
const TTAMachine::MachinetargetMachine_
 The target machine we are scheduling the program against. More...
 
DataDependenceGraphddg_
 DDG of the currently scheduled BB. More...
 
SimpleResourceManagerrm_
 Resource Manager of the currently scheduled BB. More...
 
std::map< const MoveNode *, DataDependenceGraph::NodeSetscheduledTempMoves_
 Stores the MoveNodes that were scheduled as temp moves during scheduling of the operand move. More...
 
SoftwareBypassersoftwareBypasser_
 The software bypasser to use to bypass registers when possible. More...
 
RegisterRenamerrenamer_
 
int bypassedCount_
 
int deadResults_
 
LLVMTCECmdLineOptionsoptions_
 

Detailed Description

A class that implements the functionality of a bottom up basic block scheduler.

Schedules the program one basic block at a time. Does not fill delay slots if they couldn't be filled with the basic block's contents itself (no instruction importing).

Definition at line 74 of file BypassingBUBasicBlockScheduler.hh.

Member Enumeration Documentation

◆ TempRegCopyLocation

Constructor & Destructor Documentation

◆ BypassingBUBasicBlockScheduler()

BypassingBUBasicBlockScheduler::BypassingBUBasicBlockScheduler ( InterPassData data,
SoftwareBypasser bypasser = NULL,
CopyingDelaySlotFiller delaySlotFiller = NULL,
RegisterRenamer renamer = NULL 
)

Constructs the basic block scheduler.

Parameters
dataInterpass data
bypasserHelper module implementing software bypassing. Not used.
delaySlotFillerHelper module implementing jump delay slot filling
registerRenamerHelper module implementing register renaming

Definition at line 110 of file BypassingBUBasicBlockScheduler.cc.

References Application::cmdLineOptions(), SchedulerCmdLineOptions::killDeadResults(), killDeadResults_, BasicBlockScheduler::options_, SchedulerCmdLineOptions::renameRegisters(), and renameRegisters_.

114  :
115  BasicBlockScheduler(data, bypasser, delaySlotFiller, renamer),
116  killDeadResults_(false), renameRegisters_(false) {
117 
118  CmdLineOptions *cmdLineOptions = Application::cmdLineOptions();
119  options_ = dynamic_cast<LLVMTCECmdLineOptions*>(cmdLineOptions);
120  if (options_ != NULL) {
123  }
124 }
virtual bool killDeadResults() const
static CmdLineOptions * cmdLineOptions()
Definition: Application.cc:346
LLVMTCECmdLineOptions * options_
BasicBlockScheduler(InterPassData &data, SoftwareBypasser *bypasser=NULL, CopyingDelaySlotFiller *delaySlotFiller=NULL, RegisterRenamer *registerRenamer=NULL)
Here is the call graph for this function:

◆ ~BypassingBUBasicBlockScheduler()

BypassingBUBasicBlockScheduler::~BypassingBUBasicBlockScheduler ( )
virtual

Destructor.

Definition at line 129 of file BypassingBUBasicBlockScheduler.cc.

129  {
130 }

Member Function Documentation

◆ bypassAndScheduleNode()

bool BypassingBUBasicBlockScheduler::bypassAndScheduleNode ( MoveNode node,
MoveNode trigger,
int  latestCycle,
bool  allowRegCopies 
)
private

Tries to schedule an (input) node, bypassing if possible

Definition at line 856 of file BypassingBUBasicBlockScheduler.cc.

References bypassNode(), MoveNode::isSourceOperation(), scheduleOperandOrTrigger(), scheduleOperation(), MoveNode::sourceOperation(), MoveNode::toString(), and undoBypass().

Referenced by bypassAndScheduleOperands(), and scheduleOperation().

857  {
858  // TODO: DDG does not yet support bypass over multiply nodes
859  int bypassHopCount = 1; //INT_MAX;
860  while (bypassHopCount >= 0) {
861  bypassHopCount = bypassNode(node, bypassHopCount);
862  if (bypassHopCount > 0) {
863  std::cerr << "\tBypassed node: " << node.toString() << std::endl;
864  if (node.isSourceOperation()) {
865  // take a copy of latestCycle because scheduleOperation
866  // may modify it
867  int lc = latestCycle;
868  if (scheduleOperation(node.sourceOperation(), lc, false)) {
869  return true;
870  } else {
871  // scheduling bypassed op failed.
872  // revert bypass, and try with smaller bypass ho count.
873  undoBypass(node);
874  bypassHopCount--;
875  continue;
876  }
877  } else {
878  // schedule individual input, not bypassed from op.
879  // bypassed from reg write?
881  node, trigger, latestCycle, allowRegCopies)) {
882  return true;
883  } else {
884  std::cerr << "Bypassed operand failed.. trying smaller "
885  << " hop count." <<
886  node.toString() << std::endl;
887 
888  // scheduling bypassed op failed.
889  // revert bypass, and try with smaller bypass ho count.
890  undoBypass(node);
891  bypassHopCount--;
892  continue;
893  }
894  }
895  }
896  // not bypassed.
897  std::cerr << "\tDid not bypass: " << node.toString() << std::endl;
899  node, trigger, latestCycle, allowRegCopies)) {
900  return true;
901  } else {
902  return false;
903  }
904  }
905  // for some reason went out from the loop. fail
906  return false;
907 }
bool scheduleOperandOrTrigger(MoveNode &operand, MoveNode *trigger, int latestCycle, bool allowRegCopies)
void scheduleOperation(MoveNodeGroup &mng, MoveNodeSelector &selector)
bool isSourceOperation() const
Definition: MoveNode.cc:157
int bypassNode(MoveNode &node, int maxHopCount)
std::string toString() const
Definition: MoveNode.cc:492
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:402
Here is the call graph for this function:

◆ bypassAndScheduleOperands()

bool BypassingBUBasicBlockScheduler::bypassAndScheduleOperands ( ProgramOperation po,
MoveNode trigger,
int  latestCycle,
bool  allowRegCopies 
)
private

Schedule all operands of an operation, (but no trigger), trying t bypass them.

Definition at line 914 of file BypassingBUBasicBlockScheduler.cc.

References assert, bypassAndScheduleNode(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), MoveNode::isScheduled(), and undoBypassAndUnschedule().

Referenced by scheduleOperation().

916  {
917 
918  for (int i = 0; i < po.inputMoveCount(); i++) {
919  MoveNode& operand = po.inputMove(i);
920  if (trigger != &operand) {
922  operand, trigger, latestCycle, allowRegCopies)) {
923  for (; i >= 0; i++) {
925  return false;
926  }
927  }
928  } else {
929  assert(operand.isScheduled());
930  }
931  }
932  return true;
933 }
int inputMoveCount() const
MoveNode & inputMove(int index) const
bool bypassAndScheduleNode(MoveNode &node, MoveNode *trigger, int latestCycle, bool allowRegCopies)
#define assert(condition)
Definition: Application.hh:80
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ bypassNode()

int BypassingBUBasicBlockScheduler::bypassNode ( MoveNode node,
int  maxHopCount 
)
private

Bypasses a node.

Parameters
maxHopCountmaximum amount or registers to skip while bypassing. 1 == bypass from move which produced the value, 0 == do not bypass.
Returns
the amount of moves saved by this bypass

Definition at line 761 of file BypassingBUBasicBlockScheduler.cc.

References bypassSources_, BasicBlockScheduler::ddg_, findBypassSource(), DataDependenceGraph::guardsAllowBypass(), killDeadResults_, DataDependenceGraph::mergeAndKeep(), pendingBypassSources_, regCopiesBefore_, and DataDependenceGraph::resultUsed().

Referenced by bypassAndScheduleNode().

761  {
762  std::cerr << "\t\tIncoming hopcount: " << maxHopCount << std::endl;
763  std::pair<MoveNode*,int> bypassSource =
764  findBypassSource(node, maxHopCount);
765  if (bypassSource.second == 0) {
766  std::cerr << "\t\thopcount 0" << std::endl;
767  return 0;
768  }
769 
770  // do not bypass from already scheduled moves.
771  if (bypassSource.first->isScheduled()) {
772  std::cerr << "\t\tbypassource scheduled" << std::endl;
773  return 0;
774  }
775 /*
776  ddg_->writeToDotFile("bypass_source_scheduled.dot");
777  throw Exception(__FILE__, __LINE__,__func__,
778  "Bypass souce already scheduled! " +
779  bypassSource.first->toString());
780  }
781 */
782 
783  if (!ddg_->guardsAllowBypass(*bypassSource.first, node)) {
784  std::cerr << "\t\tguardsnotallowbypass" << std::endl;
785  return 0;
786  }
787 
788 // std::cerr << "\t\tMerging." << std::endl;
789 // ddg_->writeToDotFile("merging.dot");
790  if (!ddg_->mergeAndKeep(*bypassSource.first,node)) {
791 
792  std::cerr << "Merge fail." << std::endl;
793  return 0;
794  }
795 
796  std::cerr << "Merged." << std::endl;
797 
798  bypassSources_[&node] = bypassSource.first;
799 
800  // TODO: DRE seems to slow things down!
801  if (killDeadResults_) {
802  if (!ddg_->resultUsed(*bypassSource.first)) {
803  std::cerr << "Could remove source:" <<
804  bypassSource.first->toString() << std::endl;
805  pendingBypassSources_.insert(bypassSource.first);
806  }
807  // bypassing own regcopy away? what if 2?
808  if (regCopiesBefore_[&node] == bypassSource.first) {
809  MoveNode* rgBefore = regCopiesBefore_[bypassSource.first];
810  if (rgBefore != NULL) {
811  regCopiesBefore_[&node] = rgBefore;
812  }
813  }
814  }
815 
816  return bypassSource.second;
817 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
bool guardsAllowBypass(const MoveNode &defNode, const MoveNode &useNode)
bool mergeAndKeep(MoveNode &resultNode, MoveNode &userNode)
std::pair< MoveNode *, int > findBypassSource(MoveNode &node, int maxHopCount)
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > bypassSources_
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
std::set< MoveNode *, MoveNode::Comparator > pendingBypassSources_
bool resultUsed(MoveNode &resultNode)
Here is the call graph for this function:

◆ clearCaches()

void BypassingBUBasicBlockScheduler::clearCaches ( )
private

Cleanups some bookkeeping. This should not be needed

Definition at line 1132 of file BypassingBUBasicBlockScheduler.cc.

References assert, bypassSources_, BasicBlockScheduler::ddg_, pendingBypassSources_, regCopiesAfter_, regCopiesBefore_, removedNodes_, BoostGraph< GraphNode, GraphEdge >::removeNode(), and BoostGraph< GraphNode, GraphEdge >::rootGraph().

Referenced by handleDDG().

1132  {
1133  bypassSources_.clear();
1134  for (DataDependenceGraph::NodeSet::iterator i = removedNodes_.begin();
1135  i != removedNodes_.end(); i++) {
1136  if (ddg_->rootGraph() != ddg_) {
1137  if ((**i).isScheduled()) {
1138  std::cerr << "DRE'd move: " << (**i).toString() <<
1139  " is Scheduled! " << std::endl;
1140  }
1141  assert(!(**i).isScheduled());
1142  ddg_->rootGraph()->removeNode(**i);
1143  }
1144  delete *i;
1145  }
1146  removedNodes_.clear();
1147  pendingBypassSources_.clear();
1148 
1149  regCopiesBefore_.clear();
1150  regCopiesAfter_.clear();
1151 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
std::set< MoveNode *, MoveNode::Comparator > removedNodes_
virtual void removeNode(Node &node)
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > bypassSources_
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesAfter_
BoostGraph * rootGraph()
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
#define assert(condition)
Definition: Application.hh:80
std::set< MoveNode *, MoveNode::Comparator > pendingBypassSources_
Here is the call graph for this function:

◆ createAntidepsFromUnscheduledRegCopies()

void BypassingBUBasicBlockScheduler::createAntidepsFromUnscheduledRegCopies ( MoveNode copyNode,
MoveNode mn,
TTAProgram::Terminal terminalRegister 
)
private

Creste register antideps from unscheduled temp reg copies to the just created one.

This is needed when temp reg copies are "created on wrong order", for example if some operation is attempted to first schedule some FU, later to some another

Definition at line 1282 of file BypassingBUBasicBlockScheduler.cc.

References DataDependenceGraph::connectOrDeleteEdge(), BasicBlockScheduler::ddg_, DataDependenceEdge::DEP_WAR, DataDependenceEdge::DEP_WAW, DataDependenceEdge::EDGE_REGISTER, regCopiesBefore_, and DisassemblyRegister::registerName().

Referenced by createTempRegCopy().

1284  {
1285  TCEString reg = DisassemblyRegister::registerName(terminalRegister);
1286 
1287  for (std::map<MoveNode*, MoveNode*, MoveNode::Comparator>::iterator i =
1288  regCopiesBefore_.begin(); i != regCopiesBefore_.end(); i++) {
1289  // found non-scheduled move having regcopies..
1290  if (!i->first->isScheduled() && i->first != &mn) {
1291  if (i->first->isSourceVariable()) {
1293  i->first->move().source());
1294  if (reg1 == reg) {
1295  DataDependenceEdge* edgeWar =
1296  new DataDependenceEdge(
1299  ddg_->connectOrDeleteEdge(*i->first, copyNode, edgeWar);
1300 
1301  DataDependenceEdge* edgeWaw =
1302  new DataDependenceEdge(
1305  ddg_->connectOrDeleteEdge(*i->second, copyNode, edgeWaw);
1306  }
1307  }
1308  }
1309  }
1310 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
bool connectOrDeleteEdge(const MoveNode &tailNode, const MoveNode &headNode, DataDependenceEdge *edge)
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
static TCEString registerName(const TTAMachine::RegisterFile &rf, int index, char delim='.')
Here is the call graph for this function:

◆ createSelector()

virtual MoveNodeSelector* BypassingBUBasicBlockScheduler::createSelector ( TTAProgram::BasicBlock bb,
const TTAMachine::Machine machine 
)
inlinevirtual

Reimplemented from BasicBlockScheduler.

Definition at line 96 of file BypassingBUBasicBlockScheduler.hh.

References BasicBlockPass::ddgBuilder().

97  {
98  return new BUMoveNodeSelector(bb, machine);
99  }
Here is the call graph for this function:

◆ createTempRegCopy()

MoveNode * BypassingBUBasicBlockScheduler::createTempRegCopy ( MoveNode mn,
bool  after 
)
private

Creates a temp reg copy for given move.

Does not necessarily create all required temp reg copies, so this may be needed to be called recursively to get all required copies.

: Smarted logic to select the register to use

Parameters
mnmovenode to be splitted
afterset to true if temp reg is the last of the nodes, false if first
Returns
the created tempregcopy

Definition at line 1213 of file BypassingBUBasicBlockScheduler.cc.

References TTAProgram::AnnotatedInstructionElement::addAnnotation(), DataDependenceGraph::addNode(), TTAProgram::ProgramAnnotation::ANN_CONNECTIVITY_MOVE, TTAProgram::ProgramAnnotation::ANN_STACKFRAME_PROCEDURE_RETURN, TTAProgram::Move::copy(), createAntidepsFromUnscheduledRegCopies(), BasicBlockScheduler::ddg_, TTAMachine::RegisterFile::firstReadPort(), TTAMachine::RegisterFile::firstWritePort(), RegisterCopyAdder::fixDDGEdgesInTempReg(), DataDependenceGraph::getBasicBlockNode(), TTAProgram::Move::isReturn(), MoveNode::move(), possibleTempRegRFs(), TTAProgram::AnnotatedInstructionElement::setAnnotation(), TTAProgram::Move::setDestination(), TTAProgram::Move::setSource(), TTAMachine::BaseRegisterFile::size(), TTAProgram::Move::toString(), and MoveNode::toString().

Referenced by scheduleMoveBU().

1213  {
1214 
1215  // before splitting, annotate the possible return move so we can still
1216  // detect a procedure return in simulator
1217  if (mn.move().isReturn()) {
1218  TTAProgram::ProgramAnnotation annotation(
1220  mn.move().setAnnotation(annotation);
1221  }
1222 
1223  std::set<TTAMachine::RegisterFile*, TTAMachine::MachinePart::Comparator>
1224  rfs = possibleTempRegRFs(mn, after);
1225 
1226  TTAMachine::RegisterFile* rf = *rfs.rbegin();
1227 
1228  int lastRegisterIndex = rf->size()-1;
1229  TTAMachine::Port* dstRFPort = rf->firstWritePort();
1230  TTAMachine::Port* srcRFPort = rf->firstReadPort();
1231 
1232  TTAProgram::TerminalRegister* tempWrite =
1233  new TTAProgram::TerminalRegister(*dstRFPort, lastRegisterIndex);
1234 
1235  TTAProgram::TerminalRegister* tempRead =
1236  new TTAProgram::TerminalRegister(*srcRFPort, lastRegisterIndex);
1237 
1238  TTAProgram::ProgramAnnotation connMoveAnnotation(
1240 
1241  TTAProgram::Move* copyMove = mn.move().copy();
1242  MoveNode* copyNode = new MoveNode(copyMove);
1244  ddg_->addNode(*copyNode,bbn);
1245  copyMove->addAnnotation(connMoveAnnotation);
1246 
1247  if (after) {
1248  std::cerr << "Creating temp move after: " << mn.toString() << " ";
1249  copyMove->setSource(tempRead);
1250  mn.move().setDestination(tempWrite);
1252  *ddg_, mn, &mn, copyNode, rf, lastRegisterIndex, bbn, true);
1253  std::cerr << " Moves after split: " << mn.toString() << " and " <<
1254  copyMove->toString() << std::endl;
1255 
1256 
1257  } else {
1258  std::cerr << "Creating temp move before: " << mn.toString();
1259  copyMove->setDestination(tempWrite);
1260  mn.move().setSource(tempRead);
1261 
1263  *ddg_, mn, copyNode, &mn, rf, lastRegisterIndex, bbn, true);
1264 
1265  std::cerr << "Moves after split: " << copyMove->toString()
1266  << " and "<< mn.toString() << std::endl;
1267 
1268  createAntidepsFromUnscheduledRegCopies(*copyNode, mn, *tempWrite);
1269  }
1270 
1271  return copyNode;
1272 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
void setAnnotation(const ProgramAnnotation &annotation)
void setDestination(Terminal *dst)
Definition: Move.cc:319
void createAntidepsFromUnscheduledRegCopies(MoveNode &copyNode, MoveNode &mn, TTAProgram::Terminal &terminalRegister)
bool isReturn() const
Definition: Move.cc:245
Move * copy() const
Definition: Move.cc:399
const BasicBlockNode & getBasicBlockNode(const MoveNode &mn) const
void addNode(MoveNode &moveNode)
std::string toString() const
Definition: MoveNode.cc:492
virtual int size() const
static void fixDDGEdgesInTempReg(DataDependenceGraph &ddg, MoveNode &originalMove, MoveNode *firstMove, MoveNode *lastMove, const TTAMachine::RegisterFile *lastRF, int lastRegisterIndex, BasicBlockNode &currentBBNode, bool bottomUpScheduling)
void addAnnotation(const ProgramAnnotation &annotation)
A reg to reg move that was added because of missing connectivity between the original target and dest...
std::string toString() const
Definition: Move.cc:422
TTAProgram::Move & move()
std::set< TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > possibleTempRegRFs(const MoveNode &mn, bool tempRegAfter)
void setSource(Terminal *src)
Definition: Move.cc:298
Here is the call graph for this function:

◆ finalizeOperation()

void BypassingBUBasicBlockScheduler::finalizeOperation ( MoveNodeSelector selector)
private

Definition at line 312 of file BypassingBUBasicBlockScheduler.cc.

References assert, bypassSources_, BasicBlockScheduler::ddg_, BoostGraph< GraphNode, GraphEdge >::dropNode(), MoveNodeSelector::mightBeReady(), MoveNodeSelector::notifyScheduled(), pendingBypassSources_, BoostGraph< GraphNode, GraphEdge >::predecessors(), regCopiesAfter_, regCopiesBefore_, removedNodes_, BoostGraph< GraphNode, GraphEdge >::rootGraph(), and scheduledMoves_.

Referenced by handleDDG(), and scheduleOperation().

312  {
313 
314  for (std::map<MoveNode*, MoveNode*, MoveNode::Comparator>::iterator i =
315  bypassSources_.begin(); i != bypassSources_.end(); i++) {
316  // only notify if no DRE'd
317  if (i->second != NULL && pendingBypassSources_.find(i->second)
318  == pendingBypassSources_.end()) {
319  selector.mightBeReady(*i->second);
320  }
321  }
322 
323  bypassSources_.clear();
324 
325  for (std::set<MoveNode*, MoveNode::Comparator>::iterator i =
326  pendingBypassSources_.begin(); i != pendingBypassSources_.end();
327  i++) {
328  MoveNode* node = *i;
329 
330  // this may lead to extra raw edges.
331  static_cast<DataDependenceGraph*>(ddg_->rootGraph())->
332  copyDepsOver(*node, true, true);
333 
334  std::cerr << "DRE killing node: " << (**i).toString() << std::endl;
336  ddg_->dropNode(*node);
337  removedNodes_.insert(node);
338  for (DataDependenceGraph::NodeSet::iterator i =
339  preds.begin(); i != preds.end(); i++) {
340  selector.mightBeReady(**i);
341  }
342  }
343  pendingBypassSources_.clear();
344 
345  for (std::set<MoveNode*, MoveNode::Comparator>::iterator i =
346  scheduledMoves_.begin(); i != scheduledMoves_.end();
347  i++) {
348  assert((**i).isScheduled());
349  selector.notifyScheduled(**i);
350  }
351  scheduledMoves_.clear();
352 
353  regCopiesBefore_.clear();
354  regCopiesAfter_.clear();
355 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
std::set< MoveNode *, MoveNode::Comparator > removedNodes_
virtual void notifyScheduled(MoveNode &node)=0
std::set< MoveNode *, typename MoveNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > bypassSources_
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesAfter_
BoostGraph * rootGraph()
virtual void dropNode(Node &node)
std::set< MoveNode *, MoveNode::Comparator > scheduledMoves_
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
#define assert(condition)
Definition: Application.hh:80
std::set< MoveNode *, MoveNode::Comparator > pendingBypassSources_
virtual void mightBeReady(MoveNode &node)=0
Here is the call graph for this function:

◆ findBypassSource()

std::pair< MoveNode *, int > BypassingBUBasicBlockScheduler::findBypassSource ( MoveNode node,
int  maxHopCount 
)
private

Finds a source where from to bypass.

Goes ddg backwards and checks for connectivity.

Returns
pair of source of bypass and amount of regs skipped by the bypass.

Definition at line 827 of file BypassingBUBasicBlockScheduler.cc.

References MachineConnectivityCheck::canSourceWriteToAnyDestinationPort(), BasicBlockScheduler::ddg_, MachineConnectivityCheck::findPossibleDestinationPorts(), DataDependenceGraph::onlyRegisterRawSource(), and BasicBlockScheduler::targetMachine_.

Referenced by bypassNode().

828  {
829  std::set<const TTAMachine::Port*>
830  destinationPorts =
832  *targetMachine_, node);
833 
834  MoveNode* n = &node;
835  MoveNode* okSource = NULL;
836  int hops = 0;
837  for (int i = 0; i < maxHopCount; i++) {
838  MoveNode* rrSource = ddg_->onlyRegisterRawSource(*n);
839  if (rrSource == NULL) {
840  break;
841  }
842  n = rrSource;
844  *n, destinationPorts)) {
845  okSource = n;
846  hops = i+1;
847  }
848  }
849  return std::pair<MoveNode*,int>(okSource, hops);
850 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
const TTAMachine::Machine * targetMachine_
The target machine we are scheduling the program against.
MoveNode * onlyRegisterRawSource(const MoveNode &mn) const
static int canSourceWriteToAnyDestinationPort(const MoveNode &src, std::set< const TTAMachine::Port *> &ports)
static std::set< const TTAMachine::Port * > findPossibleDestinationPorts(const TTAMachine::Machine &mach, const MoveNode &node)
Here is the call graph for this function:

◆ handleDDG()

void BypassingBUBasicBlockScheduler::handleDDG ( DataDependenceGraph ddg,
SimpleResourceManager rm,
const TTAMachine::Machine targetMachine 
)
virtual

Schedules a piece of code in a DDG

Parameters
ddgThe ddg containing the code
rmResource manager that is to be used.
targetMachineThe target machine.
Exceptions
Exceptionseveral TCE exceptions can be thrown in case of a scheduling error.

Reimplemented from BasicBlockScheduler.

Definition at line 141 of file BypassingBUBasicBlockScheduler.cc.

References __func__, abortWithError, BUMoveNodeSelector::candidates(), clearCaches(), BasicBlockScheduler::ddg_, BasicBlockScheduler::ddgSnapshot(), debugLog, DataDependenceGraph::DUMP_DOT, DataDependenceGraph::DUMP_XML, LLVMTCECmdLineOptions::dumpDDGsDot(), LLVMTCECmdLineOptions::dumpDDGsXML(), endCycle_, finalizeOperation(), RegisterCopyAdder::findTempRegisters(), RegisterRenamer::initialize(), SchedulerPass::interPassData(), MoveNode::isMove(), MoveNode::isOperationMove(), MoveNodeGroup::isScheduled(), MoveNodeGroup::node(), BoostGraph< GraphNode, GraphEdge >::node(), MoveNodeGroup::nodeCount(), BoostGraph< GraphNode, GraphEdge >::nodeCount(), BasicBlockScheduler::options_, BasicBlockScheduler::renamer_, BasicBlockScheduler::rm_, DataDependenceGraph::scheduledNodeCount(), scheduleMoveBU(), scheduleOperation(), SimpleResourceManager::setMaxCycle(), RegisterRenamer::setSelector(), BasicBlockScheduler::targetMachine_, TempRegBefore, MoveNode::toString(), and GraphBase< GraphNode, GraphEdge >::writeToDotFile().

143  {
144  if (!BasicBlockPass::interPassData().hasDatum("SCRATCH_REGISTERS")) {
146  targetMachine, BasicBlockPass::interPassData());
147  }
148 
149  ddg_ = &ddg;
150  targetMachine_ = &targetMachine;
151 
152  if (renamer_ != NULL) {
153  renamer_->initialize(ddg);
154  }
155 
156  if (options_ != NULL && options_->dumpDDGsDot()) {
157  ddgSnapshot(
158  ddg, std::string("0"), DataDependenceGraph::DUMP_DOT, false);
159  }
160 
161  if (options_ != NULL && options_->dumpDDGsXML()) {
162  ddgSnapshot(
163  ddg, std::string("0"), DataDependenceGraph::DUMP_XML, false);
164  }
165 
166  // empty need not to be scheduled
167  if (ddg.nodeCount() == 0 ||
168  (ddg.nodeCount() == 1 && !ddg.node(0).isMove())) {
169  return;
170  }
171  // TODO: Magic number! Provide better heuristics.
172  // INT_MAX/2 won't work on trunk due to multithreading injecting empty
173  // instructions into the beginning of basic block.
174  // Remove magic 1000 once the sparse implementation of RM vectors works.
175 //endCycle_ = (ddg.nodeCount() < 1000) ? ddg.nodeCount() + 200 : 1000;
176  endCycle_ = (int)(ddg.nodeCount()*1.3 + 150);
177  BUMoveNodeSelector selector(ddg, targetMachine);
178 
179  // scheduling pipeline resources after last cycle may cause problems.
180  // make RM to check for those
182 
183 
184  // register selector to renamer for notfications.
185  if (renamer_ != NULL) {
186  renamer_->setSelector(&selector);
187  }
188 
189  rm_ = &rm;
190 
191  MoveNodeGroup moves = selector.candidates();
192  while (moves.nodeCount() > 0) {
193  MoveNode& firstMove = moves.node(0);
194  if (firstMove.isOperationMove()) {
195  scheduleOperation(moves, selector);
196  } else {
197  std::cerr << "Individual move: " << firstMove.toString()
198  << std::endl;
199  scheduleMoveBU(firstMove, 0, endCycle_, TempRegBefore);
200  finalizeOperation(selector);
201  }
202  if (!moves.isScheduled()) {
203  std::string message = " Move(s) did not get scheduled: ";
204  for (int i = 0; i < moves.nodeCount(); i++) {
205  message += moves.node(i).toString() + " ";
206  }
207  ddg.writeToDotFile("failed_bb.dot");
208  throw ModuleRunTimeError(__FILE__,__LINE__,__func__, message);
209  }
210  moves = selector.candidates();
211  }
212 
213  clearCaches();
214 
215  if (ddg.nodeCount() != ddg.scheduledNodeCount()) {
216  debugLog("All moves in the DDG didn't get scheduled.");
217  ddg.writeToDotFile("failed_bb.dot");
218  abortWithError("Should not happen!");
219  }
220 
221  if (options_ != NULL && options_->dumpDDGsDot()) {
222  std::string wtf = "0";
223  ddgSnapshot(
224  ddg, wtf, DataDependenceGraph::DUMP_DOT, true);
225  }
226 
227  if (options_ != NULL && options_->dumpDDGsXML()) {
228  ddgSnapshot(
229  ddg, std::string("0"), DataDependenceGraph::DUMP_XML, true);
230  }
231 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
RegisterRenamer * renamer_
void scheduleOperation(MoveNodeGroup &mng, MoveNodeSelector &selector)
void setMaxCycle(unsigned int maxCycle)
bool isOperationMove() const
Definition: MoveNode.cc:214
#define __func__
Definition: Application.hh:67
const TTAMachine::Machine * targetMachine_
The target machine we are scheduling the program against.
void finalizeOperation(MoveNodeSelector &selector)
bool isScheduled() const
virtual bool dumpDDGsXML() const
int nodeCount() const
virtual bool dumpDDGsDot() const
#define debugLog(text)
Definition: Application.hh:87
Node & node(const int index) const
virtual void writeToDotFile(const TCEString &fileName) const
std::string toString() const
Definition: MoveNode.cc:492
InterPassData & interPassData()
int nodeCount() const
void ddgSnapshot(DataDependenceGraph &ddg, const std::string &name, DataDependenceGraph::DumpFileFormat format, bool final, bool resetCounter=false) const
static void findTempRegisters(const TTAMachine::Machine &machine, InterPassData &ipd)
bool isMove() const
SimpleResourceManager * rm_
Resource Manager of the currently scheduled BB.
void setSelector(MoveNodeSelector *selector)
LLVMTCECmdLineOptions * options_
void initialize(DataDependenceGraph &ddg)
#define abortWithError(message)
Definition: Application.hh:72
MoveNode & node(int index) const
bool scheduleMoveBU(MoveNode &mn, int earlistCycle, int latestCycle, TempRegCopyLocation t)
Here is the call graph for this function:

◆ lastOperandCycle()

int BypassingBUBasicBlockScheduler::lastOperandCycle ( const ProgramOperation po)
private

find the highest cycle some operand of an operation is scheduled.

: move this to ProgramOperation class?

Definition at line 997 of file BypassingBUBasicBlockScheduler.cc.

References MoveNode::cycle(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), and MoveNode::isScheduled().

Referenced by operandCycleLimits().

998  {
999  int res = -1;
1000  for (int i = 0; i < po.inputMoveCount(); i++) {
1001  const MoveNode& mn = po.inputMove(i);
1002  if (mn.isScheduled()) {
1003  if (mn.cycle() > res) {
1004  res = mn.cycle();
1005  }
1006  }
1007  }
1008  return res;
1009 }
int inputMoveCount() const
MoveNode & inputMove(int index) const
int cycle() const
Definition: MoveNode.cc:365
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ longDescription()

std::string BypassingBUBasicBlockScheduler::longDescription ( ) const
virtual

Optional longer description of the pass.

This description can include usage instructions, details of choice of algorithmic details, etc.

Returns
The description as a string.

Reimplemented from BasicBlockScheduler.

Definition at line 305 of file BypassingBUBasicBlockScheduler.cc.

305  {
306  return
307  "Bottom-up list basic block scheduler that first tries to bypass"
308  " and only then assign moves,and recursively schedules bypass sources";
309 }

◆ operandCycleLimits()

std::pair< int, int > BypassingBUBasicBlockScheduler::operandCycleLimits ( MoveNode mn,
MoveNode trigger 
)
private

Calculates the range where operand can be scheduled, based on results and other operands.

Definition at line 957 of file BypassingBUBasicBlockScheduler.cc.

References assert, MoveNode::cycle(), MoveNode::destinationOperation(), endCycle_, BasicBlockScheduler::findTrigger(), MoveNode::isDestinationOperation(), MoveNode::isScheduled(), lastOperandCycle(), and MoveNode::latestTriggerWriteCycle().

Referenced by scheduleOperandOrTrigger(), and scheduleResults().

958  {
959  int minn = 0;
960  int maxx = endCycle_;
963  if (po.areOutputsAssigned()) {
964  maxx = std::min(mn.latestTriggerWriteCycle(), (int)endCycle_);
965  } else {
966  maxx = -1;
967  }
968  if (po.isAnyInputAssigned()) {
969  // if trigger now known, find it.
970  if (trigger == NULL) {
971  trigger = findTrigger(po);
972  }
973  if (trigger != NULL) {
974  if (trigger == &mn) {
975  // this is trigger. limit min to last operand.
976  minn = std::max(lastOperandCycle(po), 0);
977  } else {
978  // this is not trigger.
979  if (trigger->isScheduled()) {
980  maxx = trigger->cycle();
981  }
982  }
983  } else {
984  // TODO: what to do if cannot find trigger? fail?
985  return std::pair<int,int>(INT_MAX, -1);
986  }
987  }
988  return std::pair<int,int>(minn, maxx);
989 }
int lastOperandCycle(const ProgramOperation &po)
int latestTriggerWriteCycle() const
Definition: MoveNode.cc:593
ProgramOperation & destinationOperation(unsigned int index=0) const
bool isDestinationOperation() const
int cycle() const
Definition: MoveNode.cc:365
MoveNode * findTrigger(ProgramOperation &po)
#define assert(condition)
Definition: Application.hh:80
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ possibleTempRegRFs()

std::set< TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > BypassingBUBasicBlockScheduler::possibleTempRegRFs ( const MoveNode mn,
bool  tempRegAfter 
)
private

Find possible temp reg RF's for connectivity of given register.

This only gives the register files that for the "next register in the temp reg chain", not the whole chain

Definition at line 1319 of file BypassingBUBasicBlockScheduler.cc.

References __func__, MachineConnectivityCheck::canAnyPortWriteToDestination(), MachineConnectivityCheck::canSourceWriteToAnyDestinationPort(), InterPassData::datum(), MachineConnectivityCheck::findReadPorts(), MachineConnectivityCheck::findWritePorts(), TTAProgram::MoveGuard::guard(), TTAProgram::Move::guard(), SchedulerPass::interPassData(), MachineConnectivityCheck::isConnected(), TTAProgram::Move::isUnconditional(), and MoveNode::move().

Referenced by createTempRegCopy().

1320  {
1321 
1322  std::set<TTAMachine::RegisterFile*, TTAMachine::MachinePart::Comparator>
1323  result;
1324 
1325  std::map<int, int> rfDistanceFromSource;
1326  std::map<int, int> rfDistanceFromDestination;
1327 
1328  typedef SimpleInterPassDatum<
1329  std::vector<std::pair<TTAMachine::RegisterFile*, int> > >
1330  TempRegData;
1331 
1332  std::string srDatumName = "SCRATCH_REGISTERS";
1333  if (!BasicBlockPass::interPassData().hasDatum(srDatumName) ||
1334  (dynamic_cast<TempRegData&>(
1335  BasicBlockPass::interPassData().datum(srDatumName))).size() == 0)
1336  throw IllegalProgram(
1337  __FILE__, __LINE__, __func__,
1338  "No scratch registers available for temporary moves.");
1339 
1340  const TempRegData& tempRegs =
1341  dynamic_cast<TempRegData&>(
1342  BasicBlockPass::interPassData().datum(srDatumName));
1343 
1344 
1345  for (unsigned int i = 0; i < tempRegs.size(); i++) {
1346  rfDistanceFromSource[i] = INT_MAX;
1347  rfDistanceFromDestination[i] = INT_MAX;
1348  }
1349 
1350 
1351  for (unsigned int i = 0; i < tempRegs.size(); i++) {
1352  TTAMachine::RegisterFile* rf = tempRegs[i].first;
1353  std::set<const TTAMachine::Port*> readPorts =
1355  std::set<const TTAMachine::Port*> writePorts =
1357  bool srcOk = false;
1359  mn, writePorts)) {
1360  rfDistanceFromSource[i] = 1;
1361  srcOk = true;
1362  }
1363 
1365  readPorts, mn)) {
1366  rfDistanceFromDestination[i] = 1;
1367  if (srcOk) {
1368  // this RF does it!
1369  result.insert(rf);
1370  }
1371  }
1372  }
1373 
1374  // modified check to avoid 4ever loop in case of broken machine
1375  bool modified = true;
1376  if (!tempRegAfter) {
1377  while (result.empty() && modified) {
1378  int shortest = INT_MAX;
1379  modified = false;
1380  for (unsigned int i = 0; i < tempRegs.size(); i++) {
1381  int srcDist = rfDistanceFromSource[i];
1382  if (srcDist != INT_MAX) {
1383  TTAMachine::RegisterFile* rfSrc = tempRegs[i].first;
1384  for (unsigned int j = 0; j < tempRegs.size(); j++) {
1385  if (rfDistanceFromSource[j] > srcDist + 1) {
1386  TTAMachine::RegisterFile* rfDest = tempRegs[j].first;
1387  // ignore rf's which are not wide enough
1389  *rfSrc, *rfDest,
1390  (mn.move().isUnconditional() ? NULL :
1391  &mn.move().guard().guard()))) {
1392  rfDistanceFromSource[j] = srcDist + 1;
1393  modified = true;
1394  if (rfDistanceFromDestination[j] == 1) {
1395  int dist = srcDist + 2;
1396  if (dist < shortest) {
1397  result.clear();
1398  shortest = dist;
1399  }
1400  if (dist == shortest) {
1401  result.insert(rfDest);
1402  }
1403  }
1404  }
1405  }
1406  }
1407  }
1408  }
1409  }
1410  return result;
1411  } else {
1412  while (result.empty() && modified) {
1413  int shortest = INT_MAX;
1414  modified = false;
1415  for (unsigned int i = 0; i < tempRegs.size(); i++) {
1416  int dstDist = rfDistanceFromDestination[i];
1417  if (dstDist != INT_MAX) {
1418  TTAMachine::RegisterFile* rfDst = tempRegs[i].first;
1419  for (unsigned int j = 0; j < tempRegs.size(); j++) {
1420  if (rfDistanceFromDestination[j] > dstDist + 1) {
1421  TTAMachine::RegisterFile* rfSrc = tempRegs[j].first;
1423  *rfDst, *rfSrc,
1424  (mn.move().isUnconditional() ? NULL :
1425  &mn.move().guard().guard()))) {
1426  rfDistanceFromDestination[j] = dstDist + 1;
1427  modified = true;
1428  if (rfDistanceFromSource[j] == 1) {
1429  int dst = dstDist + 2;
1430  if (dst < shortest) {
1431  result.clear();
1432  shortest = dst;
1433  }
1434  if (dst == shortest) {
1435  result.insert(rfSrc);
1436  }
1437  }
1438  }
1439  }
1440  }
1441  }
1442  }
1443  }
1444  return result;
1445  }
1446 }
#define __func__
Definition: Application.hh:67
static bool isConnected(const TTAMachine::Port &sourcePort, const TTAMachine::Port &destinationPort, TTAMachine::Guard *guard=NULL)
InterPassDatum & datum(const std::string &key)
bool isUnconditional() const
Definition: Move.cc:156
static std::set< const TTAMachine::Port * > findReadPorts(TTAMachine::Unit &rf)
static std::set< const TTAMachine::Port * > findWritePorts(TTAMachine::Unit &rf)
static bool canAnyPortWriteToDestination(std::set< const TTAMachine::Port *> &ports, const MoveNode &dest)
static int canSourceWriteToAnyDestinationPort(const MoveNode &src, std::set< const TTAMachine::Port *> &ports)
InterPassData & interPassData()
TTAMachine::Guard & guard() const
Definition: MoveGuard.cc:86
MoveGuard & guard() const
Definition: Move.cc:331
TTAProgram::Move & move()
Here is the call graph for this function:

◆ renameSourceIfNotConnected()

bool BypassingBUBasicBlockScheduler::renameSourceIfNotConnected ( MoveNode moveNode,
int  latestCycle 
)
private

Tries to rename source register of unconnected move to make it connected.

Definition at line 1156 of file BypassingBUBasicBlockScheduler.cc.

References MachineConnectivityCheck::canTransportMove(), BasicBlockScheduler::ddg_, DataDependenceGraph::findLiveRange(), LiveRange::reads, RegisterRenamer::renameLiveRange(), BasicBlockScheduler::renamer_, renameRegisters_, RegisterRenamer::renameSourceRegister(), BasicBlockScheduler::targetMachine_, LiveRange::toString(), MoveNode::toString(), and LiveRange::writes.

Referenced by scheduleMoveBU().

1157  {
1158 
1159  if (!renameRegisters_) {
1160  return false;
1161  }
1162 
1164  moveNode, false, false, false, latestCycle)) {
1165  return false;
1166  }
1167 
1169  moveNode, *targetMachine_)) {
1170  return true;
1171  } else {
1172  return false;
1173  }
1174 
1175 
1176 
1177 #if 0
1178  LiveRange* lr = ddg_->findLiveRange(moveNode, false);
1179  // todo: should rename here
1180  if (lr == NULL) {
1181  std::cerr << "Could not find liverange for:" << moveNode.toString() << std::endl;
1182  return false;
1183  }
1184 
1185  // for now limit to simple cases.
1186  if (!(lr->writes.size() == 1 && lr->reads.size() > 0)) {
1187  std::cerr << "Liverange too complex to rename: " << lr->toString()
1188  <<" for: " << moveNode.toString() << std::endl;
1189  return false;
1190  }
1191 
1192  std::cerr << "(Not really yeat)Trying to rename lr: " << lr->toString() << std::endl;
1193 
1194  // TODO: find the register.
1195 
1196  return renamer_->renameLiveRange(*lr, "", false, false, false);
1197 #endif
1198 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
RegisterRenamer * renamer_
const TTAMachine::Machine * targetMachine_
The target machine we are scheduling the program against.
TCEString toString() const
Definition: LiveRange.cc:53
std::string toString() const
Definition: MoveNode.cc:492
bool renameLiveRange(LiveRange &liveRange, const TCEString &newReg, bool usedBefore, bool usedAfter, bool loopScheduling)
DataDependenceGraph::NodeSet writes
Definition: LiveRange.hh:39
bool renameSourceRegister(MoveNode &node, bool loopScheduling, bool allowSameRf, bool differentRfOnlyDirectlyReachable, int latestCycle=INT_MAX)
LiveRange * findLiveRange(MoveNode &lrNode, bool writingNode=true) const
static bool canTransportMove(MoveNode &moveNode, const TTAMachine::Machine &machine)
DataDependenceGraph::NodeSet reads
Definition: LiveRange.hh:40
Here is the call graph for this function:

◆ scheduleMoveBU()

bool BypassingBUBasicBlockScheduler::scheduleMoveBU ( MoveNode mn,
int  earliestCycle,
int  latestCycle,
TempRegCopyLocation  t 
)
private

Schedule a single move with bottom-up-scheduling.

If the machine does not have sufficient connectivity, tries to rename the source register or add regcopies.

Parameters
mnMoveNode to be scheduled
earliestCycleearliestCycle allowed.
latestCyclelatest allowed cycle. Tries to schedule close to this.
twhether temp register copies are allowed, and whether they are added after or before this move.

Definition at line 615 of file BypassingBUBasicBlockScheduler.cc.

References SimpleResourceManager::assign(), MachineConnectivityCheck::canTransportMove(), TTAMachine::Machine::controlUnit(), createTempRegCopy(), BasicBlockScheduler::ddg_, TTAMachine::ControlUnit::delaySlots(), endCycle_, TTAProgram::Move::isControlFlowMove(), MoveNode::isScheduled(), SimpleResourceManager::latestCycle(), DataDependenceGraph::latestCycle(), MoveNode::move(), pendingBypassSources_, regCopiesAfter_, regCopiesBefore_, renameSourceIfNotConnected(), BasicBlockScheduler::rm_, scheduledMoves_, BasicBlockScheduler::targetMachine_, TempRegAfter, TempRegBefore, TempRegNotAllowed, MoveNode::toString(), and unschedule().

Referenced by handleDDG(), scheduleOperandOrTrigger(), scheduleOperation(), and scheduleResults().

617  {
618  int endCycle = endCycle_;
619 
620  std::cerr << "\t\tSchedulign moveBU: " << mn.toString() <<
621  " Cycle limits: " << earliestCycle << " , " << latestCycle
622  << std::endl;
623 
624  // if control flow move, limit delay slots before end
625  if (mn.move().isControlFlowMove()) {
626  endCycle -= targetMachine_->controlUnit()->delaySlots();
627  }
628 
629  // if regcpy is unscheudled it must be rescheduled
630  if (t == TempRegAfter) {
631  MoveNode* regCopyAfter = regCopiesAfter_[&mn];
632  if (regCopyAfter != NULL &&
633  pendingBypassSources_.find(regCopyAfter) ==
634  pendingBypassSources_.end()) {
635  if (!regCopyAfter->isScheduled()) {
636  std::cerr << "\t\t\tScheduling regcopyafter: " <<
637  regCopyAfter->toString() << std::endl;
638  if (!(scheduleMoveBU(
639  *regCopyAfter, 0, latestCycle, t))) {
640  std::cerr << "\t\t\t\tRegcopyafter scheduling failed" << std::endl;
641  return false;
642  }
643  }
644  }
645  }
646 
648  mn, *targetMachine_)) {
649  std::cerr << "\t\t\tSchedulemoveBU cannot transport move" << std::endl;
650 
651  if (t == TempRegNotAllowed) {
652  return false;
653  }
654 
655  if (!renameSourceIfNotConnected(mn, latestCycle)) {
656 
657  MoveNode* reg2RegCopy =
659  // recursively call this first, then the generated copy.
660 
661  if (reg2RegCopy == NULL) {
662  return false;
663  }
664  std::cerr << "\t\t\tCreated regcopy: " << reg2RegCopy->toString()
665  << std::endl;
666  if (t == TempRegBefore) {
667  MoveNode* oldRC = regCopiesBefore_[&mn];
668  if (oldRC != NULL) {
669  std::cerr << "Existing regcopy before: " << oldRC->toString()
670  << " setting it as regcopy of regcopy"
671  << std::endl;
672  regCopiesBefore_[reg2RegCopy] = oldRC;
673  }
674  regCopiesBefore_[&mn] = reg2RegCopy;
675  std::cerr << "\t\t\t\tRegcopybefore added." << std::endl;
676 
677  return scheduleMoveBU(
678  mn, earliestCycle, latestCycle, TempRegBefore);
679 
680  } else {
681  MoveNode* oldRC = regCopiesAfter_[&mn];
682  if (oldRC != NULL) {
683  std::cerr << "Existing regcopy after: "<<oldRC->toString()
684  << " setting it as regcopy of regcopy"
685  << std::endl;
686  regCopiesAfter_[reg2RegCopy] = oldRC;
687  }
688 
689  regCopiesAfter_[&mn] = reg2RegCopy;
690  if (!scheduleMoveBU(
691  *reg2RegCopy, 0, endCycle_, TempRegAfter)) {
692  return false;
693  }
694 
695  if (!scheduleMoveBU(
696  mn, earliestCycle, latestCycle, TempRegAfter)) {
697  unschedule(*reg2RegCopy);
698  return false;
699  } else {
700  return true;
701  }
702  }
703  } else {
704  std::cerr << "\t\t\tRenamed source to get connectivity: " <<
705  mn.toString() << std::endl;
706  }
707  } else {
708  std::cerr << "\t\t\tCantransportmove ok for: " << mn.toString() << std::endl;
709  }
710 
711  latestCycle = std::min(latestCycle, endCycle);
712  int ddgCycle = ddg_->latestCycle(mn,UINT_MAX,false, false);
713  if (ddgCycle == -1) {
714  std::cerr << "ddg cycle -1, ddg prevents scheduling!" << std::endl;
715  return false;
716  }
717  int maxCycle = std::min(latestCycle, ddgCycle);
718  std::cerr << "\t\t\tmaxCycle after ddg: " << maxCycle << std::endl;
719  int rmCycle = rm_->latestCycle(maxCycle, mn);
720  std::cerr << "\t\t\trmCycle: " << rmCycle << std::endl;
721  if (rmCycle != -1 && rmCycle >= earliestCycle) {
722  rm_->assign(rmCycle, mn);
723  scheduledMoves_.insert(&mn);
724  std::cerr << "\t\tScheduled to cycle: " << rmCycle << std::endl;
725 
726  // if regcpy is unscheudled it must be rescheduled
727  if (t == TempRegBefore) {
728  MoveNode* regCopyBefore = regCopiesBefore_[&mn];
729  if (regCopyBefore != NULL &&
730  pendingBypassSources_.find(regCopyBefore) ==
731  pendingBypassSources_.end()) {
732  if (!regCopyBefore->isScheduled()) {
733  std::cerr << "scheduling regcopybefore: " <<
734  regCopyBefore->toString() << std::endl;
735  if (!(scheduleMoveBU(
736  *regCopyBefore, 0, rmCycle-1, t))) {
737  std::cerr << "regcopybefore scheduling failed" <<
738  std::endl;
739  unschedule(mn);
740  return false;
741  }
742  }
743  }
744  }
745  return true;
746  } else {
747  std::cerr << "\t\t\trmcycle is -1, cannot schedule move" << std::endl;
748  return false;
749  }
750 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
const TTAMachine::Machine * targetMachine_
The target machine we are scheduling the program against.
virtual void assign(int cycle, MoveNode &node)
virtual int latestCycle(MoveNode &node) const
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:331
std::string toString() const
Definition: MoveNode.cc:492
bool isControlFlowMove() const
Definition: Move.cc:219
SimpleResourceManager * rm_
Resource Manager of the currently scheduled BB.
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesAfter_
MoveNode * createTempRegCopy(MoveNode &mn, bool after)
static bool canTransportMove(MoveNode &moveNode, const TTAMachine::Machine &machine)
std::set< MoveNode *, MoveNode::Comparator > scheduledMoves_
bool renameSourceIfNotConnected(MoveNode &moveNode, int latestCycle)
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
int latestCycle(const MoveNode &moveNode, unsigned int ii=UINT_MAX, bool ignoreRegAntideps=false, bool ignoreUnscheduledSuccessors=true) const
TTAProgram::Move & move()
bool scheduleMoveBU(MoveNode &mn, int earlistCycle, int latestCycle, TempRegCopyLocation t)
std::set< MoveNode *, MoveNode::Comparator > pendingBypassSources_
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ scheduleMoveUB()

bool BypassingBUBasicBlockScheduler::scheduleMoveUB ( MoveNode mn,
int  earliestCycle,
int  latestCycle 
)
private

Schedule a single move with up-down scheduling.

Currently used only for results which also have bypassed read of the result, to get this as close to the bypassed one as possible.

Definition at line 545 of file BypassingBUBasicBlockScheduler.cc.

References SimpleResourceManager::assign(), MachineConnectivityCheck::canTransportMove(), BasicBlockScheduler::ddg_, SimpleResourceManager::earliestCycle(), DataDependenceGraph::earliestCycle(), endCycle_, DataDependenceGraph::latestCycle(), BasicBlockScheduler::rm_, scheduledMoves_, BasicBlockScheduler::targetMachine_, and MoveNode::toString().

Referenced by scheduleResults().

546  {
547  std::cerr << "\t\tSchedulign moveUB: " << mn.toString() <<
548  " Cycle limits: " << earliestCycle << " , " << latestCycle
549  << std::endl;
550  // TODO: unscheduld ones
551 
552  // Does not try to rename as this ub is mostly used with non-dre'd result
553  // when bypassing
555  return false;
556  }
557 /*
558  MoveNode* reg2RegCopy = createTempRegCopy(mn, true);
559  // recursively call this first, then the generated copy.
560 
561  if (reg2RegCopy == NULL) {
562  return false;
563  }
564  std::cerr << "Created regcopy: " << reg2RegCopy->toString();
565 
566  if (!scheduleMoveUB(mn, earliestCycle, latestCycle)) {
567  return false;
568  }
569 
570  if (!scheduleMoveUB(*reg2RegCopy, 0, endCycle_)) {
571  unschedule(mn);
572  return false;
573  }
574  }
575 */
576 
577  latestCycle = std::min(latestCycle, (int)endCycle_);
578  std::cerr << "\t\tlc: " << latestCycle << std::endl;
579  int ddgLC = ddg_->latestCycle(mn);
580  latestCycle = std::min(latestCycle, ddgLC);
581  std::cerr << "\t\tddglc: " << latestCycle << std::endl;
582  int ddgEC = ddg_->earliestCycle(mn);
583  std::cerr << "\t\tddgec: " << ddgEC << std::endl;
584  if (ddgEC == -1 || ddgEC == INT_MAX) {
585  return false;
586  }
587  int minCycle = std::max(earliestCycle, ddgEC);
588  std::cerr << "\t\tmincycle: " << minCycle << std::endl;
589  int rmCycle = rm_->earliestCycle(minCycle, mn);
590  std::cerr << "\t\trmcycle: " << rmCycle << std::endl;
591  if (rmCycle != -1 && rmCycle <= latestCycle) {
592  rm_->assign(rmCycle, mn);
593  scheduledMoves_.insert(&mn);
594 
595  std::cerr << "\t\tScheduled to cycle: " << rmCycle << std::endl;
596  return true;
597  } else {
598  return false;
599  }
600 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
const TTAMachine::Machine * targetMachine_
The target machine we are scheduling the program against.
virtual void assign(int cycle, MoveNode &node)
std::string toString() const
Definition: MoveNode.cc:492
SimpleResourceManager * rm_
Resource Manager of the currently scheduled BB.
virtual int earliestCycle(MoveNode &node) const
int earliestCycle(const MoveNode &moveNode, unsigned int ii=UINT_MAX, bool ignoreRegWaRs=false, bool ignoreRegWaWs=false, bool ignoreGuards=false, bool ignoreFUDeps=false, bool ignoreSameOperationEdges=false) const
static bool canTransportMove(MoveNode &moveNode, const TTAMachine::Machine &machine)
std::set< MoveNode *, MoveNode::Comparator > scheduledMoves_
int latestCycle(const MoveNode &moveNode, unsigned int ii=UINT_MAX, bool ignoreRegAntideps=false, bool ignoreUnscheduledSuccessors=true) const
Here is the call graph for this function:

◆ scheduleOperandOrTrigger()

bool BypassingBUBasicBlockScheduler::scheduleOperandOrTrigger ( MoveNode operand,
MoveNode trigger,
int  latestCycle,
bool  allowRegCopies 
)
private

Tries to schedue operand or trigger, but not trying to bypass

Definition at line 939 of file BypassingBUBasicBlockScheduler.cc.

References operandCycleLimits(), scheduleMoveBU(), TempRegBefore, and TempRegNotAllowed.

Referenced by bypassAndScheduleNode().

941  {
942  std::pair<int,int> cycleLimits =
943  operandCycleLimits(operand, trigger);
944 
945  return scheduleMoveBU(operand, cycleLimits.first,
946  std::min(latestCycle,cycleLimits.second),
947  allowRegCopies ?
948  TempRegBefore :
950 }
std::pair< int, int > operandCycleLimits(MoveNode &mn, MoveNode *trigger)
bool scheduleMoveBU(MoveNode &mn, int earlistCycle, int latestCycle, TempRegCopyLocation t)
Here is the call graph for this function:

◆ scheduleOperation() [1/2]

void BypassingBUBasicBlockScheduler::scheduleOperation ( MoveNodeGroup moves,
MoveNodeSelector selector 
)

Schedules moves in a single operation execution.

Assumes the given MoveNodeGroup contains all moves in the operation execution. Also assumes that all outputs of the MoveNodeGroup have been scheduled.

Parameters
movesMoves of the operation execution.

Definition at line 247 of file BypassingBUBasicBlockScheduler.cc.

References __func__, BasicBlockScheduler::ddg_, MoveNode::destinationOperation(), endCycle_, finalizeOperation(), MoveNode::isScheduled(), MoveNode::isSourceOperation(), MoveNodeGroup::node(), MoveNodeGroup::nodeCount(), MoveNode::sourceOperation(), MoveNodeGroup::toString(), GraphBase< GraphNode, GraphEdge >::writeToDotFile(), and DataDependenceGraph::writeToXMLFile().

Referenced by bypassAndScheduleNode(), and handleDDG().

248  {
249 
250  std::cerr << "ScheduleOperation from selector: " << moves.toString()
251  << std::endl;
252 
253  for (int i = 0; i < moves.nodeCount(); i++) {
254  if (moves.node(0).isScheduled()) {
255  ddg_->writeToDotFile("op_already_sched.dot");
256  throw Exception(__FILE__,__LINE__,__func__,
257  "Scheduling failed for opsched, operation: "
258  + moves.toString());
259  }
260  }
261  ProgramOperation& po =
262  (moves.node(0).isSourceOperation())?
263  (moves.node(0).sourceOperation()):
264  (moves.node(0).destinationOperation());
265 
266  for (int lastCycle = endCycle_; lastCycle > 0; lastCycle--) {
267  if (scheduleOperation(po, lastCycle , true)) {
268 // ddg_->writeToDotFile("op_schedok.dot");
269 
270  finalizeOperation(selector);
271  return;
272  }
273  std::cerr << "Trying to schedule op again with smaller cycle"
274  << std::endl;
275  }
276 
277  ddg_->writeToDotFile("fail.dot");
278  ddg_->writeToXMLFile("fail.xml");
279 
280  throw Exception(__FILE__,__LINE__,__func__,
281  "Scheduling failed for unknown reason!, operation: "
282  + po.toString());
283 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
void scheduleOperation(MoveNodeGroup &mng, MoveNodeSelector &selector)
#define __func__
Definition: Application.hh:67
void finalizeOperation(MoveNodeSelector &selector)
bool isSourceOperation() const
Definition: MoveNode.cc:157
int nodeCount() const
void writeToXMLFile(std::string fileName) const
virtual void writeToDotFile(const TCEString &fileName) const
ProgramOperation & destinationOperation(unsigned int index=0) const
std::string toString() const
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:402
MoveNode & node(int index) const
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ scheduleOperation() [2/2]

bool BypassingBUBasicBlockScheduler::scheduleOperation ( ProgramOperation po,
int &  latestCycle,
bool  allowRegCopies 
)
private

Tries to schedule an operation.

This function is called recursively, when bypassing.

Definition at line 364 of file BypassingBUBasicBlockScheduler.cc.

References __func__, assert, bypassAndScheduleNode(), bypassAndScheduleOperands(), MoveNode::cycle(), BasicBlockScheduler::ddg_, endCycle_, BasicBlockScheduler::findTrigger(), ProgramOperation::isAnyNodeAssigned(), MoveNode::isScheduled(), ProgramOperation::outputMove(), ProgramOperation::outputMoveCount(), scheduleMoveBU(), scheduleResults(), TempRegBefore, TempRegNotAllowed, ProgramOperation::toString(), MoveNode::toString(), unscheduleOperands(), unscheduleResults(), and GraphBase< GraphNode, GraphEdge >::writeToDotFile().

365  {
366 
367  int lc = latestCycle;
368  std::cerr << "Scheduling operation: " << po.toString()
369  << " lc: " << latestCycle << std::endl;
370  if (po.isAnyNodeAssigned()) {
371  ddg_->writeToDotFile("po_already_assigned.dot");
372  throw Exception(__FILE__,__LINE__,__func__,
373  "po already scheduled!" +
374  po.toString());
375  }
376  if (!scheduleResults(po, latestCycle, allowRegCopies)) {
377  std::cerr << "results fail for: " << po.toString() << std::endl;
378  return false;
379  }
380 
381  // update latestcycle
382  int lastRes = -1;
383  for (int i = 0; i < po.outputMoveCount(); i++) {
384  MoveNode& mn = po.outputMove(i);
385  if (mn.isScheduled()) {
386  if (mn.cycle() > lastRes) {
387  lastRes = mn.cycle();
388  }
389  lc = endCycle_;
390  // TODO: why does this make the schedule worse?
391 // if (mn.cycle() < lc) {
392 // lc = mn.cycle() -1;
393 // }
394  }
395  }
396  if (lastRes > -1) {
397  std::cerr << "Last result cycle: " << lastRes << std::endl;
398  assert(lastRes <= latestCycle);
399  latestCycle = lastRes;
400 
401  }
402 
403  MoveNode* trigger = findTrigger(po);
404 
405  // this occurs if operation without retvals
406  // has different trigger selections?
407  if (trigger == NULL) {
408  std::cerr << "Trigger was null for: " << po.toString() << std::endl;
409  return false;
410  }
411 
412  if (!bypassAndScheduleNode(*trigger, trigger, lc, allowRegCopies)) {
413  unscheduleResults(po);
414  std::cerr << "trigger bypass or shed fail for: " <<
415  po.toString() << std::endl;
416  return false;
417  }
418 
419  // if trigger bypass jamms fu, this may fail.
420  if (!bypassAndScheduleOperands(po, trigger, lc, allowRegCopies)) {
421  unscheduleOperands(po);
422 
423  // try to remove bypass of trigger and then re-schedule this
424  if (!scheduleMoveBU(*trigger, 0, latestCycle,
425  allowRegCopies ?
426  TempRegBefore :
428  unscheduleResults(po);
429  std::cerr << "Unscheduled trigger fail:" << trigger->toString()
430  << std::endl;
431  return false;
432  }
433 
434  // try now operands, with bypass.
435  if (!bypassAndScheduleOperands(po, trigger, lc, allowRegCopies)) {
436  // advance latest cycle retry counter
437  if (po.outputMoveCount() == 0) {
438  latestCycle = trigger->cycle();
439  }
440  unscheduleOperands(po);
441  unscheduleResults(po);
442 
443  std::cerr << "Operands scheduling fail for: " <<
444  po.toString()<< std::endl;
445  return false;
446  }
447  }
448  std::cerr << "Operation scheduled ok!" << po.toString() << std::endl;
449 // ddg_->writeToDotFile("op_schedok.dot");
450 // if (!po.isScheduled()) {
451 
452  return true;
453 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
bool scheduleResults(ProgramOperation &po, int latestCycle, bool allowTempRegCopies)
#define __func__
Definition: Application.hh:67
int outputMoveCount() const
std::string toString() const
virtual void writeToDotFile(const TCEString &fileName) const
std::string toString() const
Definition: MoveNode.cc:492
MoveNode & outputMove(int index) const
bool bypassAndScheduleNode(MoveNode &node, MoveNode *trigger, int latestCycle, bool allowRegCopies)
bool bypassAndScheduleOperands(ProgramOperation &po, MoveNode *trigger, int latestCycle, bool allowRegCopies)
int cycle() const
Definition: MoveNode.cc:365
MoveNode * findTrigger(ProgramOperation &po)
#define assert(condition)
Definition: Application.hh:80
bool scheduleMoveBU(MoveNode &mn, int earlistCycle, int latestCycle, TempRegCopyLocation t)
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ scheduleResults()

bool BypassingBUBasicBlockScheduler::scheduleResults ( ProgramOperation po,
int  latestCycle,
bool  allowRegCopies 
)
private

Schedules result writes to an operation.

There result writes may be bypasses.

Definition at line 461 of file BypassingBUBasicBlockScheduler.cc.

References assert, MoveNode::cycle(), BasicBlockScheduler::ddg_, MoveNode::isDestinationOperation(), TTAMachine::HWOperation::latency(), MoveNode::move(), Operation::name(), operandCycleLimits(), TTAMachine::FunctionUnit::operation(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), ProgramOperation::outputMove(), ProgramOperation::outputMoveCount(), TTAMachine::Port::parentUnit(), pendingBypassSources_, TTAProgram::Terminal::port(), scheduleMoveBU(), scheduleMoveUB(), TTAProgram::Move::source(), DataDependenceGraph::successorsReady(), TempRegAfter, TempRegNotAllowed, MoveNode::toString(), and unscheduleResults().

Referenced by scheduleOperation().

462  {
463 
464  TTAMachine::HWOperation* hwop = NULL;
465  int ectrig = -1;
466  // TODO: do bypasses first? then put other close to them?
467  for (int i = 0; i < po.outputMoveCount(); i++) {
468  MoveNode& mn = po.outputMove(i);
469  if (mn.isDestinationOperation()) {
470  std::pair<int,int> cycleLimits = operandCycleLimits(mn, NULL);
471  if (!scheduleMoveBU(
472  mn, cycleLimits.first, std::min(
473  cycleLimits.second, latestCycle),
474  allowRegCopies ? TempRegAfter : TempRegNotAllowed)) {
475  unscheduleResults(po);
476  return false;
477  } else {
478  // bypassed move is now scheduled.
479  TTAProgram::Terminal& src = mn.move().source();
481  dynamic_cast<TTAMachine::FunctionUnit*>(
482  src.port().parentUnit());
483  assert(fu != NULL);
484  hwop = fu->operation(po.operation().name());
485  ectrig = mn.cycle() - hwop->latency(src.operationIndex());
486  }
487  }
488  }
489 
490  // then non-bypasseds.
491  for (int i = 0; i < po.outputMoveCount(); i++) {
492  MoveNode& mn = po.outputMove(i);
493  if (!mn.isDestinationOperation()) {
494  // if this is
495  if (pendingBypassSources_.find(&mn) !=
496  pendingBypassSources_.end()) {
497  std::cerr << "This node is to be DRE'd: " << mn.toString()
498  << std::endl;
499  continue;
500  }
501  // is some bypassed move already scheduled?
502  if (hwop != NULL) {
503  TTAProgram::Terminal& src = mn.move().source();
504 
505  // try to put as close to other results as possible.
506  // so use top-down-scheduling here.
507 
508  // todo: make sure successors not scheduled?
509  if (ddg_->successorsReady(mn)) {
510  if (scheduleMoveUB(
511  mn, ectrig + hwop->latency(src.operationIndex()),
512  latestCycle)) {
513  return true;
514  }
515  } else {
516  unscheduleResults(po);
517  return false;
518  }
519  }
520 
521  // old regcopy may mess up scheduling result
522  // TODO: remove those regcopies?
523  if (!scheduleMoveBU(
524  mn, 0, latestCycle,
525  allowRegCopies?
526  TempRegAfter :
527  TempRegNotAllowed)) {
528  unscheduleResults(po);
529  return false;
530  }
531  }
532  }
533 
534 
535  return true;
536 }
bool successorsReady(MoveNode &node) const
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
int outputMoveCount() const
bool scheduleMoveUB(MoveNode &mn, int earlistCycle, int latestCycle)
Terminal & source() const
Definition: Move.cc:288
std::pair< int, int > operandCycleLimits(MoveNode &mn, MoveNode *trigger)
virtual TCEString name() const
Definition: Operation.cc:88
std::string toString() const
Definition: MoveNode.cc:492
virtual int operationIndex() const
Definition: Terminal.cc:352
MoveNode & outputMove(int index) const
const Operation & operation() const
Unit * parentUnit() const
bool isDestinationOperation() const
virtual HWOperation * operation(const std::string &name) const
int cycle() const
Definition: MoveNode.cc:365
virtual const TTAMachine::Port & port() const
Definition: Terminal.cc:366
#define assert(condition)
Definition: Application.hh:80
TTAProgram::Move & move()
bool scheduleMoveBU(MoveNode &mn, int earlistCycle, int latestCycle, TempRegCopyLocation t)
std::set< MoveNode *, MoveNode::Comparator > pendingBypassSources_
Here is the call graph for this function:

◆ shortDescription()

std::string BypassingBUBasicBlockScheduler::shortDescription ( ) const
virtual

A short description of the pass, usually the optimization name, such as "basic block scheduler".

Returns
The description as a string.

Reimplemented from BasicBlockScheduler.

Definition at line 292 of file BypassingBUBasicBlockScheduler.cc.

292  {
293  return "Bypassing recursive Bottom-up list scheduler with a basic block scope.";
294 }

◆ undoBypass()

void BypassingBUBasicBlockScheduler::undoBypass ( MoveNode mn)
private

undoes a bypass.

Definition at line 1015 of file BypassingBUBasicBlockScheduler.cc.

References assert, bypassSources_, BasicBlockScheduler::ddg_, pendingBypassSources_, regCopiesBefore_, MoveNode::toString(), and DataDependenceGraph::unMerge().

Referenced by bypassAndScheduleNode(), and undoBypassAndUnschedule().

1015  {
1016  std::cerr << "\tundoing bypass: " << mn.toString() << std::endl;
1017  MoveNode* source = bypassSources_[&mn];
1018  if (source != NULL) {
1019  if (pendingBypassSources_.erase(source)) {
1020  std::cerr << "undid dre: " << source->toString()
1021  << std::endl;
1022  if (regCopiesBefore_[source] != NULL) {
1023  assert(regCopiesBefore_[source] == regCopiesBefore_[&mn]);
1024  regCopiesBefore_[&mn] = source;
1025  // TODO: what if bypassed over 2 moves?
1026  // ddg does not support it anyway, not yet a problem
1027  }
1028  }
1029  ddg_->unMerge(*source, mn);
1030  bypassSources_[&mn] = NULL;
1031  }
1032  std::cerr << "\tundid bypass: " << mn.toString() << std::endl;
1033 }
DataDependenceGraph * ddg_
DDG of the currently scheduled BB.
std::string toString() const
Definition: MoveNode.cc:492
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > bypassSources_
void unMerge(MoveNode &resultNode, MoveNode &mergedNode)
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
#define assert(condition)
Definition: Application.hh:80
std::set< MoveNode *, MoveNode::Comparator > pendingBypassSources_
Here is the call graph for this function:

◆ undoBypassAndUnschedule()

void BypassingBUBasicBlockScheduler::undoBypassAndUnschedule ( MoveNode mn)
private

Undoes bypass and unschedules a move.

This also recursively unschedules the source operation of the bypass.

Definition at line 1041 of file BypassingBUBasicBlockScheduler.cc.

References MoveNode::isBypass(), MoveNode::sourceOperation(), undoBypass(), unschedule(), and unscheduleOperation().

Referenced by bypassAndScheduleOperands(), and unscheduleOperands().

1041  {
1042  if (mn.isBypass()) {
1044  }
1045  unschedule(mn);
1046  undoBypass(mn);
1047 }
bool isBypass() const
Definition: MoveNode.cc:241
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:402
Here is the call graph for this function:

◆ unschedule()

void BypassingBUBasicBlockScheduler::unschedule ( MoveNode mn)
private

Unschedule a move

Also unschedules the tempregcopies of that move.

Definition at line 1069 of file BypassingBUBasicBlockScheduler.cc.

References MoveNode::isScheduled(), regCopiesAfter_, regCopiesBefore_, BasicBlockScheduler::rm_, scheduledMoves_, MoveNode::toString(), and SimpleResourceManager::unassign().

Referenced by scheduleMoveBU(), undoBypassAndUnschedule(), and unscheduleResults().

1069  {
1070  std::cerr << "UnScheduling: " << mn.toString() << std::endl;
1071  MoveNode* regcopy = regCopiesBefore_[&mn];
1072  if (regcopy != NULL) {
1073  unschedule(*regcopy);
1074  }
1075  if (mn.isScheduled()) {
1076  rm_->unassign(mn);
1077  }
1078 /*
1079  if (regcopy != NULL) {
1080  revertRegCopyBefore(mn);
1081  }
1082 */
1083  scheduledMoves_.erase(&mn);
1084  regcopy = regCopiesAfter_[&mn];
1085  if (regcopy != NULL) {
1086  unschedule(*regcopy);
1087 // revertRegCopyAfter(mn);
1088  }
1089 
1090 
1091 }
std::string toString() const
Definition: MoveNode.cc:492
virtual void unassign(MoveNode &node)
SimpleResourceManager * rm_
Resource Manager of the currently scheduled BB.
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesAfter_
std::set< MoveNode *, MoveNode::Comparator > scheduledMoves_
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > regCopiesBefore_
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

◆ unscheduleOperands()

void BypassingBUBasicBlockScheduler::unscheduleOperands ( ProgramOperation po)
private

Unschedules all operands of an operation. Also reverts bypasses and unschedules the bypass sources.

Definition at line 1112 of file BypassingBUBasicBlockScheduler.cc.

References ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), and undoBypassAndUnschedule().

Referenced by scheduleOperation(), and unscheduleOperation().

1113  {
1114  for (int i = 0; i < po.inputMoveCount(); i++) {
1116  }
1117 }
int inputMoveCount() const
MoveNode & inputMove(int index) const
Here is the call graph for this function:

◆ unscheduleOperation()

void BypassingBUBasicBlockScheduler::unscheduleOperation ( ProgramOperation po)
private

Unschedules an operation (and recursively the bypass sources

Definition at line 1123 of file BypassingBUBasicBlockScheduler.cc.

References unscheduleOperands(), and unscheduleResults().

Referenced by undoBypassAndUnschedule().

1123  {
1124  unscheduleOperands(po);
1125  unscheduleResults(po);
1126 }
Here is the call graph for this function:

◆ unscheduleResults()

void BypassingBUBasicBlockScheduler::unscheduleResults ( ProgramOperation po)
private

Unschedule all result moves of an operation.

Definition at line 1097 of file BypassingBUBasicBlockScheduler.cc.

References MoveNode::isScheduled(), ProgramOperation::outputMove(), ProgramOperation::outputMoveCount(), and unschedule().

Referenced by scheduleOperation(), scheduleResults(), and unscheduleOperation().

1097  {
1098  std::cerr << "\tUnschedulign results" << std::endl;
1099  for (int i = 0; i < po.outputMoveCount(); i++) {
1100  MoveNode& mn = po.outputMove(i);
1101  if (mn.isScheduled()) {
1102  unschedule(mn);
1103  }
1104  }
1105 }
int outputMoveCount() const
MoveNode & outputMove(int index) const
bool isScheduled() const
Definition: MoveNode.cc:353
Here is the call graph for this function:

Member Data Documentation

◆ bypassSources_

std::map<MoveNode*, MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::bypassSources_
private

◆ endCycle_

int BypassingBUBasicBlockScheduler::endCycle_
private

◆ killDeadResults_

bool BypassingBUBasicBlockScheduler::killDeadResults_
private

◆ pendingBypassSources_

std::set<MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::pendingBypassSources_
private

◆ regCopiesAfter_

std::map<MoveNode*, MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::regCopiesAfter_
private

◆ regCopiesBefore_

std::map<MoveNode*, MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::regCopiesBefore_
private

◆ removedBypassSources_

std::map<MoveNode*, MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::removedBypassSources_
private

Definition at line 172 of file BypassingBUBasicBlockScheduler.hh.

◆ removedNodes_

std::set<MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::removedNodes_
private

Definition at line 174 of file BypassingBUBasicBlockScheduler.hh.

Referenced by clearCaches(), and finalizeOperation().

◆ renameRegisters_

bool BypassingBUBasicBlockScheduler::renameRegisters_
private

◆ scheduledMoves_

std::set<MoveNode*, MoveNode::Comparator> BypassingBUBasicBlockScheduler::scheduledMoves_
private

The documentation for this class was generated from the following files: