OpenASIP 2.2
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
CycleLookBackSoftwareBypasser Class Reference

#include <CycleLookBackSoftwareBypasser.hh>

Inheritance diagram for CycleLookBackSoftwareBypasser:
Inheritance graph
Collaboration diagram for CycleLookBackSoftwareBypasser:
Collaboration graph

Public Member Functions

 CycleLookBackSoftwareBypasser ()
 
virtual ~CycleLookBackSoftwareBypasser ()
 
virtual int bypass (MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm, bool bypassTrigger)
 
virtual void removeBypass (MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm)
 
virtual void removeBypass (MoveNode &moveNode, DataDependenceGraph &ddg, ResourceManager &rm, bool restoreSource=true)
 
virtual int removeDeadResults (MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm, std::set< std::pair< TTAProgram::Move *, int > > &removedMoves)
 
void setSelector (MoveNodeSelector *selector)
 
virtual void clearCaches (DataDependenceGraph &ddg, bool removeDeadResults)
 
- Public Member Functions inherited from SoftwareBypasser
 SoftwareBypasser ()
 
virtual ~SoftwareBypasser ()
 
int bypassCount ()
 
int deadResultCount ()
 

Static Public Member Functions

static void printStats ()
 

Private Member Functions

int bypassNode (MoveNode &nodeToBypass, int &lastOperandCycle, DataDependenceGraph &ddg, ResourceManager &rm)
 

Private Attributes

int cyclesToLookBack_
 count of cycles before the operand write to look for the producer of the read value
 
int cyclesToLookBackNoDRE_
 count of cycles before the operand write to look for the producer of the read value when cannot kill result
 
bool killDeadResults_
 
bool bypassFromRegs_
 
bool bypassToRegs_
 
std::map< MoveNode *, MoveNode *, MoveNode::ComparatorstoredSources_
 Stores sources and bypassed moves in case they have to be unassigned (case when operands are scheduled and bypassed but result can not be scheduled with such operands.
 
std::map< MoveNode *, int > sourceCycles_
 
std::map< MoveNode *, const TTAMachine::Bus * > sourceBuses_
 
std::map< MoveNode *, MoveNode *, MoveNode::ComparatorremovedStoredSources_
 
DataDependenceGraph::NodeSet removedNodes_
 
MoveNodeSelectorselector_
 

Static Private Attributes

static int bypassCount_ = 0
 
static int deadResultCount_ = 0
 
static int triggerAbortCount_ = 0
 

Additional Inherited Members

- Protected Attributes inherited from SoftwareBypasser
int bypassCount_
 
int deadResultCount_
 

Detailed Description

A simple implementation of software bypassing that reschedules operand writes as bypassed moves in case the result has been produced in n previous cycles.

Definition at line 52 of file CycleLookBackSoftwareBypasser.hh.

Constructor & Destructor Documentation

◆ CycleLookBackSoftwareBypasser()

CycleLookBackSoftwareBypasser::CycleLookBackSoftwareBypasser ( )

Constructor.

Definition at line 62 of file CycleLookBackSoftwareBypasser.cc.

62 :
65 selector_(NULL) {
66
69 if (opts != NULL) {
70 if (opts->bypassDistance() > -1) {
72 }
73 if (opts->noDreBypassDistance() > -1) {
75 }
77 }
78}
static CmdLineOptions * cmdLineOptions()
int cyclesToLookBack_
count of cycles before the operand write to look for the producer of the read value
int cyclesToLookBackNoDRE_
count of cycles before the operand write to look for the producer of the read value when cannot kill ...
virtual bool killDeadResults() const
virtual int noDreBypassDistance() const

References SchedulerCmdLineOptions::bypassDistance(), Application::cmdLineOptions(), cyclesToLookBack_, cyclesToLookBackNoDRE_, SchedulerCmdLineOptions::killDeadResults(), killDeadResults_, and SchedulerCmdLineOptions::noDreBypassDistance().

Here is the call graph for this function:

◆ ~CycleLookBackSoftwareBypasser()

CycleLookBackSoftwareBypasser::~CycleLookBackSoftwareBypasser ( )
virtual

Empty destructor.

Definition at line 83 of file CycleLookBackSoftwareBypasser.cc.

83 {
84}

Member Function Documentation

◆ bypass()

int CycleLookBackSoftwareBypasser::bypass ( MoveNodeGroup candidates,
DataDependenceGraph ddg,
ResourceManager rm,
bool  bypassTrigger 
)
virtual

Apply software bypassing to as many moves in the given MoveNodeGroup as possible.

This implementation works only if all operand writes have been scheduled. It tries to bypass all the operand write moves.

Parameters
candidatesThe moves to which apply software bypassing, if possible.
ddgThe data dependence graph in which the movenodes belong to.
rmThe resource manager which is used to check for resource availability.
Returns
The count of bypassed moves.

Implements SoftwareBypasser.

Definition at line 353 of file CycleLookBackSoftwareBypasser.cc.

357 {
358
359 // bypassing disabled with 0
360 if (cyclesToLookBack_ <= 0) {
361 return 0;
362 }
363#ifdef MOVE_BYPASSER
365#endif
366 int bypassCounter = 0;
367
368 MoveNode* trigger = NULL;
369 int lastOperandCycle = 0;
370
371 for (int i = 0; i < candidates.nodeCount(); i++) {
372 MoveNode& moveNode = candidates.node(i);
373
374 // result value or already bypassed - don't bypass this
375 if (moveNode.isSourceOperation()) {
376 continue;
377 }
378
379 // find the trigger, will try to bypass it as the last one
380 if (moveNode.move().isTriggering()) {
381 trigger = &moveNode;
382 continue;
383 }
384
385 // bypass this node.
386 int rv = bypassNode(moveNode, lastOperandCycle, ddg, rm);
387 if (rv == -1) {
388 return -1; // failed, need cleanup
389 } else {
390 bypassCounter += rv;
391 }
392 }
393 // Try to bypass triggering move, if possible ok, if not
394 // it will be rescheduled at the end after all not bypassed
395 // moves are tried to be rescheduled
396 bool triggerWasBypassed = false;
397 if (trigger != NULL && !trigger->move().isControlFlowMove() &&
398 !trigger->isSourceOperation() && bypassTrigger) {
399 int rv = bypassNode(*trigger, lastOperandCycle, ddg, rm);
400 if (rv == -1) {
401 return -1; // failed, need cleanup
402 } else {
403 bypassCounter += rv;
404 if (rv == 1) {
405 triggerWasBypassed = true;
406 }
407 }
408 }
409 // at this point the schedule might be broken in case we
410 // managed to bypass the trigger and it got pushed above
411 // an operand move
412
413 // try to reschedule the moves that were not bypassed because
414 // earlier operand moves might allow scheduling also the trigger
415 // earlier thus shorten the schedule
416
417 // this might fix the schedule in case the previous loop
418 // managed to push trigger above an operand move
419 // if not, the last loop fixes the situation
420
421 for (int i = 0; i < candidates.nodeCount(); i++) {
422 MoveNode& moveNode = candidates.node(i);
423 if (!moveNode.isDestinationOperation() ||
424 moveNode.move().isControlFlowMove()) {
425 continue;
426 }
427 // Bypassed moves and bypassed trigger are not rescheduled here
428 if (moveNode.isBypass() ||
429 (trigger == &moveNode && triggerWasBypassed)) {
430 lastOperandCycle =
431 std::max(lastOperandCycle, moveNode.cycle());
432 continue;
433 }
434 int oldCycle = moveNode.cycle();
435 int earliestCycleDDG = ddg.earliestCycle(moveNode);
436
437 if (earliestCycleDDG >= oldCycle) {
438 continue;
439 }
440 rm.unassign(moveNode);
441 int earliestCycle = earliestCycleDDG;
442
443 if (!moveNode.move().isUnconditional()) {
444 earliestCycle =
445 std::max(earliestCycleDDG, moveNode.guardLatency() - 1);
446 }
447 earliestCycle = rm.earliestCycle(earliestCycle, moveNode);
448 if ((oldCycle > earliestCycle && earliestCycle != -1) ||
449 (trigger == &moveNode && earliestCycle != -1)){
450 try {
451 rm.assign(earliestCycle, moveNode);
452 } catch (const Exception& e) {
453 throw ModuleRunTimeError(__FILE__, __LINE__, __func__,
455 }
456 } else {
457 try {
458 if (!rm.canAssign(oldCycle, moveNode)) {
459 return -1;
460 }
461 rm.assign(oldCycle, moveNode);
462 } catch (const Exception& e) {
463 throw ModuleRunTimeError(__FILE__, __LINE__, __func__,
465 }
466 }
467 lastOperandCycle =
468 std::max(lastOperandCycle, moveNode.cycle());
469 if (!moveNode.isScheduled()){
470 throw InvalidData(
471 __FILE__, __LINE__, __func__, "Move assignment failed");
472 }
473
474 }
475 // Traditional test if trigger is not earlier then some operand,
476 // could happen due to bypass of trigger
477 // todo: this could be optimized by trying to uxchange cycles of
478 // trigger and operand in this case.
479 if (trigger != NULL) {
480 try{
481 if (trigger->cycle() < lastOperandCycle) {
482 rm.unassign(*trigger);
483 int newCycle = rm.earliestCycle(lastOperandCycle, *trigger);
484 int latestDDG = ddg.latestCycle(*trigger);
485 if (newCycle == -1 || newCycle > latestDDG) {
487 // BBScheduler will call removeBypass
488 return -1;
489 }
490 rm.assign(newCycle, *trigger);
491 if (!trigger->isScheduled()){
492 throw InvalidData(
493 __FILE__, __LINE__, __func__,"Trigger assignment failed");
494 }
495 }
496 } catch (const Exception& e) {
497 throw ModuleRunTimeError(
498 __FILE__, __LINE__, __func__,e.errorMessageStack());
499 }
500 }
501 return bypassCounter;
502}
#define __func__
int bypassNode(MoveNode &nodeToBypass, int &lastOperandCycle, DataDependenceGraph &ddg, ResourceManager &rm)
int latestCycle(const MoveNode &moveNode, unsigned int ii=UINT_MAX, bool ignoreRegAntideps=false, bool ignoreUnscheduledSuccessors=true, bool ignoreGuards=false, bool ignoreFUDeps=false, bool ignoreSameOperationEdges=false) 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, bool assumeBypassing=false) const
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
int nodeCount() const
MoveNode & node(int index) const
int cycle() const
Definition MoveNode.cc:421
int guardLatency() const
Definition MoveNode.cc:779
bool isBypass() const
Definition MoveNode.cc:280
bool isDestinationOperation() const
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
bool isScheduled() const
Definition MoveNode.cc:409
virtual int earliestCycle(MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const =0
virtual bool canAssign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1) const =0
virtual void unassign(MoveNode &node)=0
virtual void assign(int cycle, MoveNode &node, const TTAMachine::Bus *bus=nullptr, const TTAMachine::FunctionUnit *srcFU=nullptr, const TTAMachine::FunctionUnit *dstFU=nullptr, int immWriteCycle=-1, const TTAMachine::ImmediateUnit *immu=nullptr, int immRegIndex=-1)=0
bool isControlFlowMove() const
Definition Move.cc:233
bool isUnconditional() const
Definition Move.cc:154
bool isTriggering() const
Definition Move.cc:284

References __func__, ResourceManager::assign(), bypassNode(), ResourceManager::canAssign(), MoveNode::cycle(), cyclesToLookBack_, DataDependenceGraph::earliestCycle(), ResourceManager::earliestCycle(), Exception::errorMessageStack(), MoveNode::guardLatency(), MoveNode::isBypass(), TTAProgram::Move::isControlFlowMove(), MoveNode::isDestinationOperation(), MoveNode::isScheduled(), MoveNode::isSourceOperation(), TTAProgram::Move::isTriggering(), TTAProgram::Move::isUnconditional(), DataDependenceGraph::latestCycle(), MoveNode::move(), MoveNodeGroup::node(), MoveNodeGroup::nodeCount(), triggerAbortCount_, and ResourceManager::unassign().

Here is the call graph for this function:

◆ bypassNode()

int CycleLookBackSoftwareBypasser::bypassNode ( MoveNode moveNode,
int &  lastOperandCycle,
DataDependenceGraph ddg,
ResourceManager rm 
)
privatevirtual

Tries to bypass a MoveNode.

Parameters
moveNodeMoveNode to bypass.
lastOperandCyclein which contains last cycle of operands of the operation
ddgThe data dependence graph in which the movenodes belong to.
rmThe resource manager which is used to check for resource availability.
Returns
-1 if failed and need fixup, 1 is succeeded, 0 if did not bypass.

Implements SoftwareBypasser.

Definition at line 98 of file CycleLookBackSoftwareBypasser.cc.

102 {
103
104 int cyclesToLookBack = cyclesToLookBack_;
105 if (moveNode.isDestinationVariable() && !bypassToRegs_) {
106 return 0;
107 }
108
109 int originalCycle = moveNode.cycle();
110 int latestCycle = originalCycle;
111
112 DataDependenceGraph::EdgeSet edges = ddg.inEdges(moveNode);
113 DataDependenceGraph::EdgeSet::iterator edgeIter = edges.begin();
114 DataDependenceEdge* bypassEdge = NULL;
115
116 // find one incoming raw edge. if multiple, cannot bypass.
117 while (edgeIter != edges.end()) {
118
119 DataDependenceEdge& edge = *(*edgeIter);
120 // if the edge is not a real reg/ra raw edge, skip to next edge
123 edge.guardUse() || edge.headPseudo()) {
124 edgeIter++;
125 continue;
126 }
127
128 if (bypassEdge == NULL) {
129 bypassEdge = &edge;
130 } else {
131 // cannot bypass if multiple inputs
132 return 0;
133 }
134 edgeIter++;
135 }
136
137 // if no bypassable edge found, cannot bypass
138 if (bypassEdge == NULL || bypassEdge->isBackEdge()) {
139 return 0;
140 }
141
142 MoveNode& source = ddg.tailNode(*bypassEdge);
143
144 if (!source.isScheduled()) {
145 return 0;
146 }
147
148 // don't bypass from incoming tempregcopies of immediates
149 if (source.isSourceConstant() &&
150 source.move().hasAnnotations(
152 return 0;
153 }
154
155 // if cannot kill dead result, divide bypass dist by 2
156 if (source.isSourceOperation() &&
157 moveNode.isDestinationOperation() &&
158 cyclesToLookBack != INT_MAX &&
159 cyclesToLookBack > cyclesToLookBackNoDRE_ &&
160 (ddg.regRawSuccessorCount(source, true) > 1 ||
161 ddg.regRawSuccessorCount(source, false) <
162 static_cast<DataDependenceGraph*>(ddg.rootGraph())->
163 regRawSuccessorCount(source, false))) {
164 cyclesToLookBack = cyclesToLookBackNoDRE_;
165 }
166
167 // source node is too far for our purposes
168 // do not bypass this operand
169 if (cyclesToLookBack != INT_MAX &&
170 source.cycle() + cyclesToLookBack < moveNode.cycle()) {
171 return 0;
172 }
173
174 if (!ddg.guardsAllowBypass(source, moveNode)) {
175 return 0;
176 }
177
178 // if dest register, only allow input from reg or imm.
179 // and limit the read to same as original read
180 // in order to not make live ranges longer, limiting schdule
181 if (!moveNode.isDestinationOperation()) {
182 latestCycle = source.cycle();
183 }
184 if (!(source.isSourceOperation() || source.isSourceConstant())) {
185 if (!bypassFromRegs_) {
186 return 0;
187 }
188 // handle antidependencies from reg-reg moves.
190 ddg.regWarSuccessors(source);
191 for (DataDependenceGraph::NodeSet::iterator i = warSuccs.begin();
192 i != warSuccs.end();i++) {
193 MoveNode& mn = **i;
194 if (mn.isScheduled()) {
195 if (mn.cycle() < latestCycle) {
196 latestCycle = std::min(latestCycle, mn.cycle());
197 }
198 }
199 }
200
201 // redundant latest check to prevent loops in ddg.
202 for (edgeIter = edges.begin(); edgeIter != edges.end(); edgeIter++) {
203 DataDependenceEdge& edge = **edgeIter;
204 if (&edge != bypassEdge) {
205 MoveNode& tail = ddg.tailNode(edge);
206 if (!tail.isScheduled()) {
207 return 0;
208 }
210 if (tail.cycle() > latestCycle) {
211 return 0;
212 }
213 } else {
214 if (tail.cycle() > latestCycle-1) {
215 return 0;
216 }
217 }
218 }
219 }
220 }
221 rm.unassign(moveNode);
222 storedSources_.insert(
223 std::pair<MoveNode*, MoveNode*>(&moveNode, &source));
224
225 // if mergeandkeep fails, undo bypass and return 0
226 if (!ddg.mergeAndKeepUser(source, moveNode)) {
227 rm.assign(originalCycle, moveNode);
228 assert(moveNode.isScheduled());
229 storedSources_.erase(&moveNode);
230 return 0;
231 }
232
233 if (moveNode.move().source().isImmediateRegister()) {
234 moveNode.move().setSource(
235 static_cast<SimpleResourceManager&>(rm).immediateValue(source)->copy());
236 }
237
238 // then try to assign the bypassed node..
239 int ddgCycle = ddg.earliestCycle(moveNode);
240 if (!moveNode.move().isUnconditional()) {
241 ddgCycle = std::max(ddgCycle, moveNode.guardLatency() - 1);
242 }
243 if (ddgCycle != INT_MAX) {
244#ifdef MOVE_BYPASSER
245 ddgCycle = originalCycle;
246#endif
247 // remove dead results now?
248 int sourceCycle = source.cycle();
249 bool sourceRemoved = false;
250 // Check if machine is forcing disabling DRE,
251 // if so disable when first move is bypassed.
252 if (killDeadResults_ &&
253 source.move().bus().machine()->alwaysWriteResults()) {
254 killDeadResults_ = false;
255 }
256 // disable DRE if ii != 0
257 // only kill if dest is op
258
259 // >8058 fails
260 // >8059 works
261 if (killDeadResults_ && !ddg.resultUsed(source)) { // && source.nodeID() > 8058) {
262 // if restoring lated
263 sourceCycles_[&source] = sourceCycle;
264 sourceRemoved = true;
265 // results that has no "use" later and are overwritten are
266 // dead if there are some other edges we don't do anything
267 // Resuls is positively death
268 // we need to properly get rid of it
269 sourceBuses_[&source] = &source.move().bus();
270 rm.unassign(source);
271 }
272
273 int cycle = rm.earliestCycle(ddgCycle, moveNode);
274 if (cycle != -1 && cycle <= latestCycle) {
275 rm.assign(cycle, moveNode);
276 if (!moveNode.isScheduled()){
277 throw InvalidData(
278 __FILE__, __LINE__, __func__,
279 "Move assignment failed");
280 }
281 lastOperandCycle = std::max(lastOperandCycle, cycle);
282 // only one bypass per operand is possible, no point to
283 // test other edges of same moveNode
284 if (sourceRemoved) {
285 ddg.copyDepsOver(source, true, false);
286 }
287 bypassCount_++;
288 return 1;
289 } else {
290 // undo only this bypass.
291 // allow other moves of same po to be bypassed.
292 ddg.unMergeUser(source, moveNode);
293 if (!rm.canAssign(originalCycle, moveNode)) {
294 // Cannot return to original position. getting problematic.
295 // return source to it's position
296 if (sourceRemoved) {
297 assert(sourceBuses_[&source] != NULL);
298 source.move().setBus(*sourceBuses_[&source]);
299 assert(rm.canAssign(sourceCycle, source));
300 rm.assign(sourceCycle, source);
301 sourceCycles_.erase(&source);
302 sourceBuses_.erase(&source);
303 }
304 // Try if we can assign it to some earlier place.
305 ddgCycle = ddg.earliestCycle(moveNode);
306 if (!moveNode.move().isUnconditional()) {
307 ddgCycle = std::max(ddgCycle, moveNode.guardLatency()-1);
308 }
309 int ec = rm.earliestCycle(ddgCycle, moveNode);
310 if (ec != -1 && ec < originalCycle) {
311 rm.assign(ec, moveNode);
312 return 0;
313 } else {
314 // Need to abort bypassing.
315 return -1;
316 }
317 }
318 rm.assign(originalCycle, moveNode);
319 assert(moveNode.isScheduled());
320 storedSources_.erase(&moveNode);
321
322 // return source to it's position
323 if (sourceRemoved) {
324 assert(sourceBuses_[&source] != NULL);
325 source.move().setBus(*sourceBuses_[&source]);
326 assert(rm.canAssign(sourceCycle, source));
327 rm.assign(sourceCycle, source);
328 sourceCycles_.erase(&source);
329 sourceBuses_.erase(&source);
330 }
331 return 0;
332 }
333 }
334 // if node could not be bypassed, we return -1 and let
335 // BBScheduler call removeBypass
336 return -1;
337}
#define assert(condition)
BoostGraph * rootGraph()
virtual Node & tailNode(const Edge &edge) const
virtual EdgeSet inEdges(const Node &node) const
std::map< MoveNode *, const TTAMachine::Bus * > sourceBuses_
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > storedSources_
Stores sources and bypassed moves in case they have to be unassigned (case when operands are schedule...
DependenceType dependenceType() const
EdgeReason edgeReason() const
void unMergeUser(MoveNode &resultNode, MoveNode &mergedNode, bool loopBypass=false)
bool mergeAndKeepUser(MoveNode &resultNode, MoveNode &userNode, bool force=false)
int regRawSuccessorCount(const MoveNode &mn, bool onlyScheduled)
bool resultUsed(MoveNode &resultNode)
EdgeSet copyDepsOver(MoveNode &node, bool anti, bool raw)
NodeSet regWarSuccessors(const MoveNode &node) const
bool guardsAllowBypass(const MoveNode &defNode, const MoveNode &useNode, bool loopBypass=false)
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53
std::set< GraphEdge *, typename GraphEdge::Comparator > EdgeSet
Definition Graph.hh:54
bool isSourceConstant() const
Definition MoveNode.cc:238
bool isDestinationVariable() const
Definition MoveNode.cc:264
virtual Machine * machine() const
bool alwaysWriteResults() const
Definition Machine.cc:948
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
void setSource(Terminal *src)
Definition Move.cc:312
Terminal & source() const
Definition Move.cc:302
void setBus(const TTAMachine::Bus &bus)
Definition Move.cc:383
const TTAMachine::Bus & bus() const
Definition Move.cc:373
@ ANN_CONNECTIVITY_MOVE
A reg to reg move that was added because of missing connectivity between the original target and dest...
virtual bool isImmediateRegister() const
Definition Terminal.cc:97

References __func__, TTAMachine::Machine::alwaysWriteResults(), TTAProgram::ProgramAnnotation::ANN_CONNECTIVITY_MOVE, assert, ResourceManager::assign(), TTAProgram::Move::bus(), bypassCount_, bypassFromRegs_, bypassToRegs_, ResourceManager::canAssign(), DataDependenceGraph::copyDepsOver(), MoveNode::cycle(), cyclesToLookBack_, cyclesToLookBackNoDRE_, DataDependenceEdge::DEP_RAW, DataDependenceEdge::DEP_WAR, DataDependenceEdge::dependenceType(), DataDependenceGraph::earliestCycle(), ResourceManager::earliestCycle(), DataDependenceEdge::EDGE_REGISTER, DataDependenceEdge::edgeReason(), MoveNode::guardLatency(), DataDependenceGraph::guardsAllowBypass(), DataDependenceEdge::guardUse(), TTAProgram::AnnotatedInstructionElement::hasAnnotations(), DataDependenceEdge::headPseudo(), BoostGraph< GraphNode, GraphEdge >::inEdges(), DataDependenceEdge::isBackEdge(), MoveNode::isDestinationOperation(), MoveNode::isDestinationVariable(), TTAProgram::Terminal::isImmediateRegister(), MoveNode::isScheduled(), MoveNode::isSourceConstant(), MoveNode::isSourceOperation(), TTAProgram::Move::isUnconditional(), killDeadResults_, TTAMachine::Component::machine(), DataDependenceGraph::mergeAndKeepUser(), MoveNode::move(), DataDependenceGraph::regRawSuccessorCount(), DataDependenceGraph::regWarSuccessors(), DataDependenceGraph::resultUsed(), BoostGraph< GraphNode, GraphEdge >::rootGraph(), TTAProgram::Move::setBus(), TTAProgram::Move::setSource(), TTAProgram::Move::source(), sourceBuses_, sourceCycles_, storedSources_, BoostGraph< GraphNode, GraphEdge >::tailNode(), ResourceManager::unassign(), and DataDependenceGraph::unMergeUser().

Referenced by bypass().

Here is the call graph for this function:

◆ clearCaches()

void CycleLookBackSoftwareBypasser::clearCaches ( DataDependenceGraph ddg,
bool  removeDeletedResults 
)
virtual

Clears the storedSources data structure, when the old values in it are not needed anymore, allowing them to be deleted by the objects who own them.

Delete node from sourceCycles structure, as thesse are not deleted elsewhere.

Implements SoftwareBypasser.

Definition at line 769 of file CycleLookBackSoftwareBypasser.cc.

770 {
771 storedSources_.clear();
772 sourceBuses_.clear();
773 if (removeDeletedResults) {
774 // TODO: somebody should also delete these
775 for (DataDependenceGraph::NodeSet::iterator i = removedNodes_.begin();
776 i != removedNodes_.end(); i++) {
777 if (ddg.rootGraph() != &ddg) {
778 ddg.rootGraph()->removeNode(**i);
779 }
780 delete *i;
781 }
782 }
783 removedNodes_.clear();
784 removedStoredSources_.clear();
785}
virtual void removeNode(Node &node)
std::map< MoveNode *, MoveNode *, MoveNode::Comparator > removedStoredSources_

References removedNodes_, removedStoredSources_, BoostGraph< GraphNode, GraphEdge >::removeNode(), BoostGraph< GraphNode, GraphEdge >::rootGraph(), sourceBuses_, and storedSources_.

Here is the call graph for this function:

◆ printStats()

void CycleLookBackSoftwareBypasser::printStats ( )
static

Definition at line 788 of file CycleLookBackSoftwareBypasser.cc.

788 {
789 std::cerr << "Bypasser statistics: " << std::endl
790 << "\tBypasses: " << bypassCount_ << std::endl
791 << "\tKilled results: " << deadResultCount_ << std::endl
792 << "\tTrigger too early aborts: " << triggerAbortCount_ << std::endl;
793}

References bypassCount_, deadResultCount_, and triggerAbortCount_.

◆ removeBypass() [1/2]

void CycleLookBackSoftwareBypasser::removeBypass ( MoveNode moveNode,
DataDependenceGraph ddg,
ResourceManager rm,
bool  restoreSource = true 
)
virtual

Implements SoftwareBypasser.

Definition at line 543 of file CycleLookBackSoftwareBypasser.cc.

546 {
547
548 // bypassing disabled
549 if (cyclesToLookBack_ <= 0) {
550 return;
551 }
552
553 if (MapTools::containsKey(storedSources_, &moveNode)) {
554 // if node was bypassed, find a original source
555 // and restore it, also unassign if bypass was
556 // assigned
557 MoveNode* tempSource =
559 assert(tempSource != NULL);
560 storedSources_.erase(&moveNode);
561 // if it was bypass and was scheduled we
562 // need to unassign and restore, should allways be a case
563 if (moveNode.isScheduled()) {
564 rm.unassign(moveNode);
565 }
566
567 // if we unassigned the source of the bypass, restore it.
568 if (!tempSource->isScheduled()) {
569 std::map<MoveNode*, int>::iterator cycleIter =
570 sourceCycles_.find(tempSource);
571 if (cycleIter != sourceCycles_.end()) {
572 if (restoreSource) {
573 assert(sourceBuses_[tempSource] != NULL);
574 tempSource->move().setBus(*sourceBuses_[tempSource]);
575 assert(rm.canAssign(cycleIter->second, *tempSource));
576 rm.assign(cycleIter->second, *tempSource); // fails here. somebody else uses the bus?
577 }
578 sourceCycles_.erase(cycleIter);
579 sourceBuses_.erase(tempSource);
580 }
581 }
582 ddg.unMergeUser(*tempSource, moveNode);
583 bypassCount_--;
584 }
585 // this is only for afterwards cleanup.
587 MoveNode* tempSource =
589 assert(tempSource != NULL);
590 removedStoredSources_.erase(&moveNode);
591
592 if (moveNode.isScheduled()) {
593 rm.unassign(moveNode);
594 }
595 ddg.unMergeUser(*tempSource, moveNode);
596 }
597}
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)

References assert, ResourceManager::assign(), bypassCount_, ResourceManager::canAssign(), MapTools::containsKey(), cyclesToLookBack_, MoveNode::isScheduled(), MapTools::keyForValue(), MoveNode::move(), removedStoredSources_, TTAProgram::Move::setBus(), sourceBuses_, sourceCycles_, storedSources_, ResourceManager::unassign(), and DataDependenceGraph::unMergeUser().

Here is the call graph for this function:

◆ removeBypass() [2/2]

void CycleLookBackSoftwareBypasser::removeBypass ( MoveNodeGroup candidates,
DataDependenceGraph ddg,
ResourceManager rm 
)
virtual

Remove software bypassing from all moves in the given MoveNodeGroup if possible.

Parameters
candidatesThe moves from which to remove software bypassing, if possible.
ddgThe data dependence grap in which the movenodes belong to.
rmThe resource manager which is used to check for resource availability.

Implements SoftwareBypasser.

Definition at line 515 of file CycleLookBackSoftwareBypasser.cc.

518 {
519
520 // bypassing disabled
521 if (cyclesToLookBack_ <= 0) {
522 return;
523 }
524
525 // Some of operand bypassing attempts failed
526 // Unschedule all operands, unassign them also since in BBSched
527 // this is followed by another attempt to schedule operands
528
529 for (int i = 0; i < candidates.nodeCount(); i++) {
530 MoveNode& moveNode = candidates.node(i);
531 if (moveNode.isScheduled()) {
532 rm.unassign(moveNode);
533 }
534 }
535
536 for (int k = 0; k < candidates.nodeCount(); k++) {
537 MoveNode& moveNode = candidates.node(k);
538 removeBypass(moveNode, ddg, rm);
539 }
540}
virtual void removeBypass(MoveNodeGroup &candidates, DataDependenceGraph &ddg, ResourceManager &rm)

References cyclesToLookBack_, MoveNode::isScheduled(), MoveNodeGroup::node(), MoveNodeGroup::nodeCount(), removeBypass(), and ResourceManager::unassign().

Referenced by removeBypass().

Here is the call graph for this function:

◆ removeDeadResults()

int CycleLookBackSoftwareBypasser::removeDeadResults ( MoveNodeGroup candidates,
DataDependenceGraph ddg,
ResourceManager rm,
std::set< std::pair< TTAProgram::Move *, int > > &  removedMoves 
)
virtual

Remove dead result moves for each bypassed move of given MoveNodeGroup if possible. That is, no other result reads of result exists. This assumes that result moves in MoveNodeGroup are also scheduled.

Parameters
candidatesThe moves for which remove dead result writes
ddgThe data dependence grap in which the movenodes belong to.
rmThe resource manager which is used to check for resource availability.
removedMovesThe dead result eliminated moves and their original cycles, to allow rescheduling of moves that were previously resource (RF write port usually) constrained by the removed moves.
Returns
number of dead results killed

Implements SoftwareBypasser.

Definition at line 600 of file CycleLookBackSoftwareBypasser.cc.

604 {
605
606 for (int i = 0; i < candidates.nodeCount(); i++) {
607 // For now, this version is called after operands AND results
608 // were scheduled
609 if (!candidates.node(i).isScheduled()) {
610 return 0;
611 }
612 }
613
614 // For each of bypassed moves, look for its original source and
615 // if that one has no more outgoing RAW edges and will be
616 // overwritten in same basic block (WAW edge) remove it
617
618 int resultsRemoved = 0;
619 for (int i = 0; i < candidates.nodeCount(); i++) {
620 MoveNode& moveNode = candidates.node(i);
621 // Results in candidates are freshly scheduled so they have no
622 // bypasses so far
623 if (!MapTools::containsKey(storedSources_, &moveNode)) {
624 // In case the result was already removed by other move from same
625 // candidates set (both operands were bypassed from same result
626 // move) we continue
627 continue;
628 }
629
630 // the original result move for the bypassed move
631 MoveNode& resultMove =
633
634 // if killed this one, finish the kill
635
636 // try to get the original cycle of the result move
637 std::map<MoveNode*, int>::iterator srcIter =
638 sourceCycles_.find(&resultMove);
639 if (srcIter != sourceCycles_.end()) {
640
641 // we lose edges so our notifyScheduled does not notify
642 // some antidependencies, store them for notification.
644 ddg.successors(resultMove);
645
646 successors.erase(&resultMove); // if WaW to itself, remove it.
647
648 ddg.dropNode(resultMove);
649 removedNodes_.insert(&resultMove);
650
651 // remove dead result also from map of sources and bypassed
652 // moves, it should not by tried to get removed second time
653 // by some other bypassed move from same candidate set
654 for (std::map<MoveNode*, MoveNode*, MoveNode::Comparator>::
655 iterator j = storedSources_.begin();
656 j != storedSources_.end();) {
657 if (j->second == &resultMove) {
658 removedStoredSources_[j->first] = &resultMove;
659 storedSources_.erase(j++);
660 } else {
661 j++;
662 }
663 }
664
665 removedMoves.insert(
666 std::make_pair(&resultMove.move(), (*srcIter).second));
667
668 sourceCycles_.erase(srcIter);
669 resultsRemoved++;
671
672 // we lost edges so our notifyScheduled does not notify
673 // some antidependencies. notify them.
674 if (selector_ != NULL) {
675 for (DataDependenceGraph::NodeSet::iterator iter =
676 successors.begin();
677 iter != successors.end(); iter++) {
678 // don't notify other dead results
679 if (sourceCycles_.find(*iter) == sourceCycles_.end()) {
680 selector_->mightBeReady(**iter);
681 }
682 }
683 }
684 } else {
685 // we might have some orhpan nodes because some antideps have moved
686 // from user node to source node,
687 // so make sure notify the scheduler about them.
688 if (ddg.hasNode(resultMove)) {
690 ddg.regWawSuccessors(resultMove);
691 if (selector_ != NULL) {
692 for (DataDependenceGraph::NodeSet::iterator iter =
693 successors.begin();
694 iter != successors.end(); iter++) {
695 // don't notify other dead results
696 if (sourceCycles_.find(*iter) == sourceCycles_.end()) {
697 selector_->mightBeReady(**iter);
698 }
699 }
700 }
701 }
702 }
703
704 // also remove dummy move to itself moves, as the bypassed move.
705 if (moveNode.move().source().equals(
706 moveNode.move().destination())) {
707
708 // we lost edges so our notifyScheduled does not notify
709 // some antidependencies. store them for notification.
711 ddg.successors(moveNode);
712
713 successors.erase(&moveNode); // if WaW to itself, rremove it.
714
715 rm.unassign(moveNode);
716
717 // this may lead to extra raw edges.
718 static_cast<DataDependenceGraph*>(ddg.rootGraph())->
719 copyDepsOver(moveNode, true, true);
720
721 ddg.dropNode(moveNode);
722 removedNodes_.insert(&moveNode);
723
724 // we lost edges so our notifyScheduled does not notify
725 // some antidependencies. notify them.
726 if (selector_ != NULL) {
727 for (DataDependenceGraph::NodeSet::iterator iter =
728 successors.begin();
729 iter != successors.end(); iter++) {
730 // don't notify other dead results
731 if (sourceCycles_.find(*iter) == sourceCycles_.end()) {
732 selector_->mightBeReady(**iter);
733 }
734 }
735 }
736 }
737 }
738
739
740 assert(sourceCycles_.empty());
741
742 return resultsRemoved;
743}
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
bool hasNode(const Node &) const
virtual void dropNode(Node &node)
NodeSet regWawSuccessors(const MoveNode &node) const
virtual void mightBeReady(MoveNode &node)=0
Terminal & destination() const
Definition Move.cc:323
virtual bool equals(const Terminal &other) const =0

References assert, MapTools::containsKey(), deadResultCount_, TTAProgram::Move::destination(), BoostGraph< GraphNode, GraphEdge >::dropNode(), TTAProgram::Terminal::equals(), BoostGraph< GraphNode, GraphEdge >::hasNode(), MoveNode::isScheduled(), MapTools::keyForValue(), MoveNodeSelector::mightBeReady(), MoveNode::move(), MoveNodeGroup::node(), MoveNodeGroup::nodeCount(), DataDependenceGraph::regWawSuccessors(), removedNodes_, removedStoredSources_, BoostGraph< GraphNode, GraphEdge >::rootGraph(), selector_, TTAProgram::Move::source(), sourceCycles_, storedSources_, BoostGraph< GraphNode, GraphEdge >::successors(), and ResourceManager::unassign().

Here is the call graph for this function:

◆ setSelector()

void CycleLookBackSoftwareBypasser::setSelector ( MoveNodeSelector selector)
virtual

Reimplemented from SoftwareBypasser.

Definition at line 756 of file CycleLookBackSoftwareBypasser.cc.

756 {
757 selector_ = selector;
758}

References selector_.

Member Data Documentation

◆ bypassCount_

int CycleLookBackSoftwareBypasser::bypassCount_ = 0
staticprivate

Definition at line 125 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode(), printStats(), and removeBypass().

◆ bypassFromRegs_

bool CycleLookBackSoftwareBypasser::bypassFromRegs_
private

Definition at line 96 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode().

◆ bypassToRegs_

bool CycleLookBackSoftwareBypasser::bypassToRegs_
private

Definition at line 99 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode().

◆ cyclesToLookBack_

int CycleLookBackSoftwareBypasser::cyclesToLookBack_
private

count of cycles before the operand write to look for the producer of the read value

Definition at line 86 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypass(), bypassNode(), CycleLookBackSoftwareBypasser(), removeBypass(), and removeBypass().

◆ cyclesToLookBackNoDRE_

int CycleLookBackSoftwareBypasser::cyclesToLookBackNoDRE_
private

count of cycles before the operand write to look for the producer of the read value when cannot kill result

Definition at line 90 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode(), and CycleLookBackSoftwareBypasser().

◆ deadResultCount_

int CycleLookBackSoftwareBypasser::deadResultCount_ = 0
staticprivate

Definition at line 126 of file CycleLookBackSoftwareBypasser.hh.

Referenced by printStats(), and removeDeadResults().

◆ killDeadResults_

bool CycleLookBackSoftwareBypasser::killDeadResults_
private

Definition at line 93 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode(), and CycleLookBackSoftwareBypasser().

◆ removedNodes_

DataDependenceGraph::NodeSet CycleLookBackSoftwareBypasser::removedNodes_
private

Definition at line 121 of file CycleLookBackSoftwareBypasser.hh.

Referenced by clearCaches(), and removeDeadResults().

◆ removedStoredSources_

std::map<MoveNode*, MoveNode*, MoveNode::Comparator> CycleLookBackSoftwareBypasser::removedStoredSources_
private

Definition at line 117 of file CycleLookBackSoftwareBypasser.hh.

Referenced by clearCaches(), removeBypass(), and removeDeadResults().

◆ selector_

MoveNodeSelector* CycleLookBackSoftwareBypasser::selector_
private

Definition at line 123 of file CycleLookBackSoftwareBypasser.hh.

Referenced by removeDeadResults(), and setSelector().

◆ sourceBuses_

std::map<MoveNode*, const TTAMachine::Bus*> CycleLookBackSoftwareBypasser::sourceBuses_
private

Definition at line 115 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode(), clearCaches(), and removeBypass().

◆ sourceCycles_

std::map<MoveNode*, int> CycleLookBackSoftwareBypasser::sourceCycles_
private

Definition at line 114 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode(), removeBypass(), and removeDeadResults().

◆ storedSources_

std::map<MoveNode*, MoveNode*, MoveNode::Comparator> CycleLookBackSoftwareBypasser::storedSources_
private

Stores sources and bypassed moves in case they have to be unassigned (case when operands are scheduled and bypassed but result can not be scheduled with such operands.

Definition at line 111 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypassNode(), clearCaches(), removeBypass(), and removeDeadResults().

◆ triggerAbortCount_

int CycleLookBackSoftwareBypasser::triggerAbortCount_ = 0
staticprivate

Definition at line 127 of file CycleLookBackSoftwareBypasser.hh.

Referenced by bypass(), and printStats().


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