OpenASIP 2.2
Loading...
Searching...
No Matches
SimpleIfConverter.cc
Go to the documentation of this file.
1/**
2 * @file SimpleIfConverter.cc
3 *
4 * Implementation of if converter optimizer class.
5 *
6 * This does if conversion for simple control structures
7 * where only one predicate is used.
8 *
9 * @author Heikki Kultala 2008 (heikki.kultala@tut.fi)
10 * @note rating: red
11 */
12
13#include <cmath>
14#include <iostream>
15
16#include "SimpleIfConverter.hh"
17
18#include "Move.hh"
19#include "Instruction.hh"
20#include "Terminal.hh"
21#include "TerminalRegister.hh"
22#include "Guard.hh"
23#include "MoveGuard.hh"
24#include "ControlFlowGraph.hh"
25#include "CodeGenerator.hh"
26#include "NullInstruction.hh"
27#include "Procedure.hh"
29#include "UniversalMachine.hh"
31#include "MachineAnalysis.hh"
32#include "ControlUnit.hh"
33#include "TerminalFUPort.hh"
34#include "MoveNode.hh"
36#include "Program.hh"
37#include "BasicBlock.hh"
38
48
50class InterPassData;
51
52/**
53 * Constructor
54 *
55 * @param InterPassData InterPassData. Not used.
56 * @param dsLimit diamond-shape size limit
57 * @param tsLimit1 triangle-shape size limit(convert fall-thru)
58 * @param tsLimit2 triangle-shape size limit(convert jump)
59 */
61 InterPassData& data, const TTAMachine::Machine& targetMachine) :
63 ProgramPass(data), codeGenerator_(NULL), irm_(NULL),
64 diamonds_(0), diamonds2_(0), triangles1_(0), triangles2_(0),
65 grAborts_(0), grDefAborts_(0), grUseAborts_(0),
66 loopAborts_(0), uncondAborts_(0) , sizeAborts_(0), succAborts_(0),
67 diamondSizeLimit_(-1), triangleSizeLimit1_(-1),
68 triangleSizeLimit2_(-1) {
69
70 // allow overriding the thresholds using a scheduler command line switch
73 if (opts != NULL && opts->ifConversionThreshold() > -1) {
77 } else if (diamondSizeLimit_ == -1 ||
78 triangleSizeLimit1_ == -1 ||
79 triangleSizeLimit2_ == -1) {
80
81 // fall back to an heuristics to determine proper limits for
82 // if-conversion according to the available ILP in the target
83 // machine
84
85 MachineAnalysis ma(targetMachine);
86
87 // rf ports can be shared by ops with neg guards, so
88 // rfilp * 2 on this heuristic.
89 float diamondOperations =
90 pow(pow(ma.busILP(), -2) +
91 pow((ma.fuILP()*2), -2) +
92 pow((ma.bypassedRfILP()*2), -2), -0.5)
93 * (1+targetMachine.controlUnit()->delaySlots());
94
95 // on triangle structures there is no moves with opposite guards,
96 // use the default averageilp
97 float triangleOperations = ma.averageILP()
98 * (1+targetMachine.controlUnit()->delaySlots());
99
100 if (diamondSizeLimit_ == -1) {
101 diamondSizeLimit_ = int(diamondOperations*2.25);
102 }
103 if (triangleSizeLimit1_ == -1) {
104 triangleSizeLimit1_ = int(triangleOperations*1.5);
105 }
106 if (triangleSizeLimit2_ == -1) {
107 triangleSizeLimit2_ = int(triangleOperations*1.5);
108 }
109 }
110
111 if (Application::verboseLevel() > 2) {
113 << "if-conversion thresholds:" << std::endl
114 << " diamond: " << diamondSizeLimit_ << std::endl
115 << "triangle1: " << triangleSizeLimit1_ << std::endl
116 << "triangle2: " << triangleSizeLimit2_ << std::endl;
117 }
118
119}
120
121/**
122 * Tells what this scheduler pass does
123 */
124std::string
126 return std::string("Simple if converter");
127}
128
129/**
130 * Handles a cfg. Does if conversion for the cfg.
131 *
132 * @param cfg cfg to be if-converted.
133 */
134void
136 ControlFlowGraph& cfg, const TTAMachine::Machine& targetMachine) {
139 const bool printCFGs = opts != NULL && opts->dumpIfConversionCFGs();
140
141 if (printCFGs)
142 cfg.writeToDotFile(cfg.name() + ".cfg.before_ifc.dot");
143
144 if (codeGenerator_ == NULL) {
146 new CodeGenerator(targetMachine);
147 }
148
150
151 while (true) {
152 // do thru cfg..
153 CandidateBlocks* bblocks = searchCandidate(cfg);
154 if (bblocks == NULL) {
155 break;
156 } else {
157 convert(*bblocks, cfg);
158 delete bblocks;
159 }
160 }
161
162 if (Application::verboseLevel() > 2) {
164 "Converted: " << std::endl <<
165 "\tDiamonds: " << diamonds_ << std::endl <<
166 "\tDiamonds(2): " << diamonds2_ << std::endl <<
167 "\tTriangles(1): " << triangles1_ << std::endl <<
168 "\tTriangles(2): " << triangles2_ << std::endl <<
169
170 "Aborts: " << std::endl <<
171 "\tGrDef: " << grDefAborts_ << std::endl <<
172 "\tAlready guarded: " << grUseAborts_ << std::endl <<
173 "\tLoop Aborts: " << loopAborts_ << std::endl <<
174 "\tUncond jump: " << uncondAborts_ << std::endl <<
175 "\tSize: " << sizeAborts_ << std::endl <<
176 "\tSucc unknown aborts: " << succAborts_ << std::endl;
177 }
178
179 if (printCFGs)
180 cfg.writeToDotFile(cfg.name() + ".cfg.after_ifc.dot");
181}
182
183/**
184 * Handles a procedure. Does if conversion for the procedure.
185 *
186 * @param procedure procedure to be if-converted.
187 * @param targetMachine machine for which to be compiled.
188 */
189void
191 TTAProgram::Procedure& procedure,
192 const TTAMachine::Machine& targetMachine) {
193 irm_ = &procedure.parent().instructionReferenceManager();
194 ControlFlowGraph cfg(procedure);
195
197
198 handleControlFlowGraph(cfg, targetMachine);
199
200 cfg.copyToProcedure(procedure);
201}
202
203/**
204 * Handles a program. Does if conversion for the whole program.
205 *
206 * @param program program to be if-converted.
207 * @param targetMachine machine for which to be compiled.
208 */
209void
211 TTAProgram::Program& program, const TTAMachine::Machine& targetMachine) {
212 if (codeGenerator_ == NULL) {
213 codeGenerator_ = new CodeGenerator(targetMachine);
214 }
215
216 ProgramPass::executeProcedurePass(program, targetMachine, *this);
217
218 delete codeGenerator_; codeGenerator_ = NULL;
219}
220
221/**
222 * Searches a single area of basic blocs to be converted at once.
223 *
224 * Conversion should always be possible for blocks this returns,
225 * All checks are done here.
226 *
227 * This always returnsa the first area of blocks that can be
228 * converted. If actual conversion is not done/cfg is not changed,
229 * returns the same are again and again.
230 *
231 * @param cfg ControlFlowGraph.
232 */
235 for (int i = 0; i < cfg.nodeCount(); i++) {
236
237 BasicBlockNode& bbn = cfg.node(i);
238
239 // entry/exit node or too many successors
240 if (!bbn.isNormalBB() || cfg.outDegree(bbn) != 2) {
241 continue;
242 }
243
244 std::pair<BasicBlockNode*,BasicBlockNode*> nodes =
245 successors(bbn, cfg);
246
247 BasicBlockNode* fallThruNode = nodes.first;
248 BasicBlockNode* jumpDestNode = nodes.second;
249
250 if (fallThruNode == NULL || jumpDestNode == NULL ||
251 !fallThruNode->isNormalBB() || !jumpDestNode->isNormalBB()) {
252 continue;
253 }
254
255 CandidateBlocks* cb =
256 detectDiamond(bbn, *fallThruNode, *jumpDestNode, cfg);
257 if (canConvert(cb, cfg)) {
258 diamonds_++;
259 return cb;
260 }
261 if (cb == NULL) {
262 cb = detectTriangleViaJump(bbn, *fallThruNode, *jumpDestNode, cfg);
263 if (canConvert(cb, cfg)) {
264 triangles2_++;
265 return cb;
266 }
267 }
268 if (cb == NULL) {
269 cb = detectTriangleViaFt(bbn, *fallThruNode, *jumpDestNode, cfg);
270 if (canConvert(cb, cfg)) {
271 triangles1_++;
272 return cb;
273 }
274 }
275 // some canconvert failed.
276 if (cb != NULL) {
277 delete cb;
278 }
279 }
280 return NULL;
281}
282
283/**
284 * Checks whether if conversion is possible for given basic blocks.
285 *
286 * @param candidates Data about area being converted.
287*/
288bool
290 CandidateBlocks* candidates, ControlFlowGraph& cfg) {
291 if (candidates == NULL) {
292 return false;
293 }
294 assert(candidates->firstBB_.instructionCount() > 0);
295 TTAProgram::Instruction* jumpIns =
296 &candidates->firstBB_.lastInstruction();
297 assert(jumpIns->moveCount()==1);
298 TTAProgram::Move* jumpMove = &jumpIns->move(0);
299 assert(jumpMove->source().isInstructionAddress() ||
300 jumpMove->source().isBasicBlockReference());
301 if (jumpMove->isUnconditional()) {
302 jumpIns = &candidates->firstBB_.previousInstruction(*jumpIns);
303 jumpMove = &jumpIns->move(0);
304 assert(jumpMove->source().isInstructionAddress() ||
305 jumpMove->source().isBasicBlockReference());
306 }
307
308 // check that the jump is conditional.
309 // broken cfg may lead it to be unconditional
310 if(jumpMove->isUnconditional()) {
312 return false;
313 }
314
315 // Cannot convert if there are not register guards.
316 if (!jumpMove->guard().guard().parentBus()) {
317 return false;
318 }
319 candidates->guard_ = jumpMove->guard().copy();
320
321 // find the guard reg
322 const Guard &g = candidates->guard_->guard();
323 const RegisterGuard* rg = dynamic_cast<const RegisterGuard*>(&g);
324
325 candidates->invg_ =
327
328 // if something fails on guad generation or extraction
329 // caused for example by port guards or missing inverse guard.
330 if (rg == NULL || candidates->invg_ == NULL) {
331 grAborts_++;
332 return false;
333 }
334 candidates->grIndex_ = rg->registerIndex();
335 candidates->grFile_ = rg->registerFile();
336
337 // if converting fall-thru-node
338 if (candidates->joinNode_ != &candidates->fallThruNode_ &&
339 candidates->succNode1_ != &candidates->fallThruNode_) {
340 bool lastToConvert = &candidates->fallThruBB_ == candidates->joinBB_;
341 if (writesRegister(
342 candidates->fallThruBB_, candidates->grIndex_,
343 *candidates->grFile_, lastToConvert)) {
344 grDefAborts_++;
345#if 0
346 PRINT_VAR(candidates->fallThruNode_.nodeID());
347 PRINT_VAR(candidates->grIndex_);
348 PRINT_VAR(candidates->grFile_);
349
351 << candidates->fallThruBB_.disassembly()
352 << std::endl;
353#endif
354 return false;
355 }
356 // cannot have double guards
357 if (hasConditionals(candidates->fallThruBB_)) {
358 grUseAborts_++;
359 return false;
360 }
361 }
362
363 // if converting jump node
364 if (candidates->joinNode_ != &candidates->jumpDestNode_ &&
365 candidates->succNode1_ != &candidates->jumpDestNode_) {
366
367 bool lastToConvert = &candidates->fallThruBB_ != candidates->joinBB_;
368 if (writesRegister(
369 candidates->jumpDestBB_, candidates->grIndex_,
370 *candidates->grFile_, lastToConvert)) {
371 grDefAborts_++;
372 return false;
373 }
374 // cannot have double guards
375 if (hasConditionals(candidates->jumpDestBB_)) {
376 grUseAborts_++;
377 return false;
378 }
379 }
380
381 // Do not allow backwards fall throughs from the last BB to the first!
382 // TODO: some day convert these to jumps. For now, just give up when
383 // encountering these.
384 ControlFlowGraph::EdgeSet outEdges = cfg.outEdges(candidates->lastNode_);
385 for (auto o: outEdges) {
386 if (!o->isJumpEdge() &&
387 &cfg.headNode(*o) == &candidates->firstNode_) {
388 return false;
389 }
390 }
391
392 // no reason why not
393 return true;
394
395}
396
397/**
398 * Do the if conversion for given area.
399 * All checks are already done, this must not fail.
400 *
401 * @param bblocks The data about blocks being merged
402 * @param cfg ControlFlowGraph.
403 */
404void
406
407 // combines blocks
408 combineBlocks(bblocks);
409
410 // update cfg about the changes
411 updateCfg(bblocks, cfg);
412}
413
414/**
415 * Updates CFG after if conversion
416 *
417 * @param bblocks The data about blocks being merged
418 * @param cfg The cfg to update
419 */
420void
422
423 // these should not be needed but just for sure.
424 cfg.disconnectNodes(bblocks.firstNode_, bblocks.jumpDestNode_);
425 cfg.disconnectNodes(bblocks.firstNode_, bblocks.fallThruNode_);
426
427// assert(cfg.outDegree(bblocks.firstNode_) == 0);
428 if (bblocks.joinNode_ != NULL) {
429 if (bblocks.joinNode_ != &bblocks.jumpDestNode_ && bblocks.removeJd_) {
430 cfg.disconnectNodes(bblocks.jumpDestNode_, *bblocks.joinNode_);
431 }
432 if (bblocks.joinNode_ != &bblocks.fallThruNode_ && bblocks.removeFt_) {
433 cfg.disconnectNodes(bblocks.fallThruNode_, *bblocks.joinNode_);
434 }
435 }
436
437 // copy out edges
438 ControlFlowGraph::EdgeSet outEdges = cfg.outEdges(bblocks.lastNode_);
439 for (ControlFlowGraph::EdgeSet::iterator i = outEdges.begin();
440 i != outEdges.end(); i++) {
441 BasicBlockNode& bbn = cfg.headNode(**i);
442 ControlFlowEdge oldEdge = **i;
443
444 // some fall-thru's may become jumps.
446 ControlFlowEdge::CFLOW_EDGE_JUMP : (*i)->edgeType();
447
449 (*i)->edgePredicate(), eType);
450
451 if (oldEdge.isBackEdge()) {
452 cfe->setBackEdge();
453 }
454
455 cfg.connectNodes(bblocks.firstNode_, bbn, *cfe);
456
457 // if the original join node is being deleted, remove edges
458 if (bblocks.removeJoin_) {
459 cfg.removeEdge(oldEdge);
460 }
461 }
462
463 if (bblocks.joinNode_ != &bblocks.fallThruNode_ &&
464 bblocks.succNode1_ != &bblocks.fallThruNode_ && bblocks.removeFt_) {
465 //assert(cfg.inDegree(bblocks.fallThruNode_) == 0);
466 // remove nodes from CFG.
467 cfg.deleteNodeAndRefs(bblocks.fallThruNode_);
468 }
469
470 if (bblocks.joinNode_ != &bblocks.jumpDestNode_ &&
471 bblocks.succNode1_ != &bblocks.jumpDestNode_ && bblocks.removeJd_) {
472 //assert(cfg.inDegree(bblocks.jumpDestNode_) == 0);
473 cfg.deleteNodeAndRefs(bblocks.jumpDestNode_);
474 }
475
476 if (bblocks.joinNode_ != NULL) {
477 if (bblocks.removeJoin_) {
478 //assert(cfg.inDegree(*bblocks.joinNode_) == 0);
479 cfg.deleteNodeAndRefs(*bblocks.joinNode_);
480 }
481 }
482}
483
484
485/**
486 * Combines many basic blocks into one and sets the guards
487 * accordingly.
488 *
489 * @param bblocks All the data needed for the operation
490 */
491void
493
494 // TODO: should not set guard of jump of lastbb.
495
496 // remove the branch jump.
497 assert(removeJump(bblocks.firstBB_));
498
499 // fall thru node handling.
500 if (&bblocks.fallThruNode_ != bblocks.succNode1_) {
501
502 if (&bblocks.fallThruBB_ != bblocks.joinBB_) {
503 appendBB(
504 bblocks.fallThruBB_, bblocks.firstBB_, bblocks.invg_,
505 &bblocks.fallThruBB_ != &bblocks.lastBB_);
506 }
507 }
508
509 // jump dest node handling
510 if (&bblocks.jumpDestNode_ != bblocks.succNode1_) {
511
512 if (&bblocks.jumpDestBB_ != bblocks.joinBB_) {
513 appendBB(bblocks.jumpDestBB_, bblocks.firstBB_, bblocks.guard_,
514 &bblocks.jumpDestBB_ != &bblocks.lastBB_ ||
515 (bblocks.succNode2_ == NULL &&
516 bblocks.succNode1_->isNormalBB()));
517 }
518 }
519
520 if (bblocks.joinBB_ != NULL) {
521 appendBB(*bblocks.joinBB_, bblocks.firstBB_, NULL, false);
522 }
523
524 bool isLastUncondJump = false;
525 if (bblocks.firstBB_.instructionCount() != 0) {
527 for (int i = 0; i < last.moveCount(); i++) {
528 TTAProgram::Move& move = last.move(i);
529 if (move.isUnconditional() && move.isJump()) {
530 isLastUncondJump = true;
531 }
532 }
533 }
534
535 // handle the last jump which may need to be added.
536 if (bblocks.succNode1_->isNormalBB() &&
537 !isLastUncondJump && !bblocks.removeJoin_) {
538 bblocks.createJump_ = true;
539 addJump(bblocks.firstBB_, *bblocks.succNode1_);
540 }
541}
542
543/**
544 * Checks whether there exists any conditional moves in given BB.
545 *
546 * @param bb BasicBlock where to check for conditional moves.
547 * @return true if some move is conditional
548*/
549bool
551 for (int j = 0; j < bb.instructionCount(); j++) {
552 Instruction& ins = bb.instructionAtIndex(j);
553 for (int i = 0; i < ins.moveCount(); i++) {
554 if (!ins.move(i).isUnconditional()) {
555 return true;
556 }
557 }
558 }
559 return false;
560}
561
564 std::map<ProgramOperationPtr,ProgramOperationPtr>& poMapping) {
565
567 if (po == NULL) {
568 return ProgramOperationPtr();
569 }
570 std::map<ProgramOperationPtr,ProgramOperationPtr>::iterator i =
571 poMapping.find(po);
572
573 if (i == poMapping.end()) {
574 // create new programOperation
576 new ProgramOperation(terminal.hintOperation(), po->machineInstr()));
577 poMapping[po] = newPO;
578 terminal.setProgramOperation(newPO);
579 return newPO;
580 } else {
581 terminal.setProgramOperation(i->second);
582 return i->second;
583 }
584}
585
586
589 MoveGuard* mg, bool removeJumps) {
590
591 std::map<ProgramOperationPtr,ProgramOperationPtr> poMapping;
592
593 for (int j = 0; j < src.instructionCount(); j++) {
594 const Instruction& ins = src.instructionAtIndex(j);
595 Instruction* newIns = new Instruction();
596 dest.add(newIns);
597 for (int i = 0; i < ins.moveCount(); i++) {
598 const TTAProgram::Move& move = ins.move(i);
599 if (!(move.isJump() && removeJumps)) {
600 auto moveCopy = move.copy();
601 if (moveCopy->source().isFUPort()) {
602 ProgramOperationPtr newPO =
604 static_cast<TTAProgram::TerminalFUPort&>(
605 moveCopy->source()),
606 poMapping);
607 if (newPO != NULL) {
608 MoveNode* mn = new MoveNode(moveCopy);
609 newPO->addOutputNode(*mn);
610 mn->setSourceOperationPtr(newPO);
611 }
612 }
613 if (moveCopy->destination().isFUPort()) {
615 static_cast<TTAProgram::TerminalFUPort&>(
616 moveCopy->destination()),
617 poMapping);
618 if (newPO != NULL) {
619 MoveNode* mn = new MoveNode(moveCopy);
620 newPO->addInputNode(*mn);
622 }
623 }
624
625 if (!moveCopy->isReturn() && mg != NULL) {
626 moveCopy->setGuard(mg->copy());
627 }
628 newIns->addMove(moveCopy);
629 }
630 }
631 }
632}
633
634
635/**
636 * Checks whether a given register is written in given BB.
637 *
638 * @param bb BasicBlock where to check for register writes
639 * @param index index of the register in a registerfile
640 * @param rf register file of the register
641 * @return true if there exists a write to given register
642 */
643bool
645 const TTAProgram::BasicBlock& bb, int index, const RegisterFile& rf,
646 bool ignoreLastInstruction) {
647 // check that jump does not mess the guard reg.
648 // TODO: if could do register renaming to counter this?
649 int iCount = ignoreLastInstruction ?
650 bb.instructionCount() -1 :
651 bb.instructionCount();
652 for (int i = 0; i < iCount; i++) {
654 // should be only 1 move / ins. but loop to be sure.
655 for (int j = 0; j < ins.moveCount(); j++) {
656 TTAProgram::Move& move = ins.move(j);
657 Terminal& dest = move.destination();
658 // if writes to the guard reg?
659 if (dest.isGPR()) {
660 TerminalRegister& tr = dynamic_cast<TerminalRegister&>(dest);
661 if (tr.index() == index && &tr.registerFile() == &rf) {
662 // simple solution is to disallow this.
663 // moderate solution is o allow only for last
664 // best solution is to allow this for one that can be last
665 return true;
666 }
667 }
668 }
669 }
670 return false;
671}
672/**
673 * Tries to remove a jump from the end of a basic block.
674 *
675 * @param bb basic block where to remove the jump from
676 * @return true if removed, false if not removed
677 */
678bool
680
681 for (int i = bb.instructionCount() -1 ; i >= 0; i--) {
682 Instruction* jumpIns = &bb.lastInstruction();
683 if (jumpIns->moveCount() != 0) {
684 if (jumpIns->hasJump()) {
685 Move *move = &jumpIns->move(0);
686 jumpIns->removeMove(*move);
687 return true;
688 } else {
689 return false;
690 }
691 }
692 }
693 return false;
694}
695
696/**
697 * Adds a jump at the end of a basic block.
698 *
699 * This may create an dangling instr reference?
700 *
701 * @param bb basicBlock add the jump at end of this basic block.
702 * @param dest destination of the jump.
703 */
715
716/**
717 * Returns 2 successors blocks of given block in specified order.
718 *
719 * First contains the unconditional successor.
720 * Second contains the jumo target of conditional jump if exists, or null.
721 * If cannot analyze, returns both nulls.
722 *
723 * @param node Node whose successors to check
724 * @param cfg cfg where the successors are searched.
725
726 */
727std::pair<BasicBlockNode*,BasicBlockNode*>
729 BasicBlockNode& node, ControlFlowGraph& cfg) {
730 ControlFlowGraph::NodeSet succs = cfg.successors(node);
731 if (succs.size() == 1) {
732 return std::pair<BasicBlockNode*,BasicBlockNode*>(*succs.begin(),NULL);
733 }
734 if (succs.size() != 2) {
736 << "Warning: Successor cound of node: " << node.toString()
737 << " is: " << succs.size() << std::endl;
738 cfg.writeToDotFile("IfConverterInvalidNumberOfSuccessors_cfg.dot");
739 }
740
741 if (node.basicBlock().instructionCount() == 0) {
742 return std::pair<BasicBlockNode*,BasicBlockNode*>(NULL,NULL);
743 }
744
745 assert(succs.size() == 2);
746 ControlFlowEdge& edge = cfg.outEdge(node,0);
747
748 TTAProgram::Instruction* jumpIns =
749 &node.basicBlock().lastInstruction();
750 TTAProgram::Move* jumpMove = &jumpIns->move(0);
751 if (!jumpMove->isJump()) {
752 return std::pair<BasicBlockNode*,BasicBlockNode*>(NULL,NULL);
753 }
754
755 if (jumpMove->isUnconditional()) {
756 jumpIns = &node.basicBlock().previousInstruction(*jumpIns);
757 if (jumpIns == NULL ||
760 return std::pair<BasicBlockNode*,BasicBlockNode*>(NULL,NULL);
761 }
762 jumpMove = &jumpIns->move(0);
763 if (jumpMove->isUnconditional() || !jumpMove->isJump()) {
765 return std::pair<BasicBlockNode*,BasicBlockNode*>(NULL,NULL);
766 }
767 }
768
769 if (edge.isTrueEdge() == jumpMove->guard().guard().isInverted()) {
770 return std::pair<BasicBlockNode*,BasicBlockNode*>(
771 &cfg.headNode(edge),
772 &cfg.headNode(cfg.outEdge(node,1)));
773 } else {
774 return std::pair<BasicBlockNode*,BasicBlockNode*>(
775 &cfg.headNode(cfg.outEdge(node,1)),
776 &cfg.headNode(edge));
777 }
778}
779
782 BasicBlockNode& fallThruNode,
783 BasicBlockNode& jumpDestNode,
784 ControlFlowGraph& cfg) {
785
786 if (cfg.outDegree(fallThruNode) != 1 ||
787 cfg.outDegree(jumpDestNode) != 1) {
788 return NULL;
789 }
790
791 ControlFlowEdge& jdse = cfg.outEdge(jumpDestNode,0);
792 ControlFlowEdge& ftse = cfg.outEdge(fallThruNode,0);
793
794 BasicBlockNode& jdSucc = cfg.headNode(jdse);
795 BasicBlockNode& ftSucc = cfg.headNode(ftse);
796
797 if (jdse.isCallPassEdge() ||
798 ftse.isCallPassEdge() ||
799 &jdSucc != &ftSucc ||
800 jdse.isBackEdge() ||
801 ftse.isBackEdge()) {
802 return NULL;
803 }
804
805 if (&jdSucc == &bbn) {
806 loopAborts_++;
807 return NULL;
808 }
809 //not desirable if nodes are too big.
810 if (fallThruNode.basicBlock().instructionCount() >
812 jumpDestNode.basicBlock().instructionCount() >
814 sizeAborts_++;
815 return NULL;
816 }
817
818 bool keepFt = (cfg.inDegree(fallThruNode) != 1);
819 bool keepJd = (cfg.inDegree(jumpDestNode) != 1);
820
821 // temporary fix as these are hard for cfg updates
822 if (keepFt || keepJd) {
823 return NULL;
824 }
825
826 if (!jdSucc.isNormalBB()) {
827 // last BB of diamond is exit node?
828 return new CandidateBlocks(
829 bbn, fallThruNode, jumpDestNode,
830 jumpDestNode, NULL, &jdSucc, NULL,
831 false, !keepFt, !keepJd);
832 }
833
834 // find successors.
835 std::pair<BasicBlockNode*,BasicBlockNode*> succ =
836 successors(jdSucc, cfg);
837
838 if (succ.first == NULL) {
839 succAborts_++;
840 return NULL;
841 }
842
843 bool keepJoin = (keepJd | keepFt) || cfg.inDegree(jdSucc) > 2 ||
844 !jdSucc.isNormalBB();
845
846 // Cannot if-convert code where possibility of fall-through loop.
847 if (jdSucc.nodeID() < bbn.nodeID()) {
848 keepJoin = true;
849 }
850
851 if (keepJoin) {
852 ControlFlowGraph::EdgeSet joinOutEdges = cfg.outEdges(jdSucc);
853 for (ControlFlowGraph::EdgeSet::iterator i = joinOutEdges.begin();
854 i != joinOutEdges.end(); i++) {
855 ControlFlowEdge& e = **i;
858 // then do not contain last BB in the diamond
859 return new CandidateBlocks(
860 bbn, fallThruNode, jumpDestNode, jumpDestNode,
861 NULL, &jdSucc, NULL, false, !keepFt, !keepJd);
862 }
863 }
864 }
865
866 return new CandidateBlocks(
867 bbn, fallThruNode, jumpDestNode, jdSucc, &jdSucc,
868 succ.first, succ.second, !keepJoin, !keepFt, !keepJd);
869}
870
871
874 BasicBlockNode& bbn,
875 BasicBlockNode& fallThruNode,
876 BasicBlockNode& jumpDestNode,
877 ControlFlowGraph& cfg) {
878
879 if (cfg.outDegree(jumpDestNode) != 1) {
880 return NULL;
881 }
882 ControlFlowEdge& jdse = cfg.outEdge(jumpDestNode,0);
883 BasicBlockNode& jdSucc = cfg.headNode(jdse);
884 if (&jdSucc != &fallThruNode || jdse.isBackEdge()) {
885 return NULL;
886 }
887
888 // find successors.
889 std::pair<BasicBlockNode*,BasicBlockNode*> succ =
890 successors(fallThruNode, cfg);
891
892 bool keepJd = (cfg.inDegree(jumpDestNode) != 1);
893 bool keepFt = keepJd|(cfg.inDegree(fallThruNode) > 2);
894 //assert(cfg.inDegree(fallThruNode) > 1);
895
896 // temporary fix as these are hard for cfg updates
897 if (keepFt || keepJd) {
898 return NULL;
899 }
900
901 // Cannot if-convert code where possibility of fall-through loop.
902 if ((succ.first != NULL && succ.first->nodeID() < bbn.nodeID()) ||
903 (succ.second != NULL && succ.second->nodeID() < bbn.nodeID())) {
904 return NULL;
905 }
906
907 // we have a triangle first->jump->ft(branch)
908
909 //not desirable if jump dest node is big.
910 if (jumpDestNode.basicBlock().instructionCount() >
912 sizeAborts_++;
913 return NULL;
914 }
915
916 if (succ.first == NULL) {
917 return new CandidateBlocks(
918 bbn, fallThruNode, jumpDestNode, fallThruNode,
919 NULL, succ.first, succ.second, !keepFt,
920 !keepFt, !keepJd);
921 } else {
922 return new CandidateBlocks(
923 bbn, fallThruNode, jumpDestNode, fallThruNode,
924 &fallThruNode, succ.first, succ.second, !keepFt,
925 !keepFt, !keepJd);
926 }
927 return NULL;
928}
929
930
933 BasicBlockNode& bbn,
934 BasicBlockNode& fallThruNode,
935 BasicBlockNode& jumpDestNode,
936 ControlFlowGraph& cfg) {
937
938 if (cfg.outDegree(fallThruNode) != 1) {
939 return NULL;
940 }
941 ControlFlowEdge& e = cfg.outEdge(fallThruNode,0);
942 if (e.isCallPassEdge() || e.isBackEdge() ||
943 &cfg.headNode(e) != &jumpDestNode) {
944 return NULL;
945 }
946
947 // find successors.
948 std::pair<BasicBlockNode*,BasicBlockNode*> succ =
949 successors(jumpDestNode, cfg);
950
951 bool keepFt = (cfg.inDegree(fallThruNode) != 1);
952 bool keepJd = keepFt|(cfg.inDegree(jumpDestNode) > 2);
953 //assert(cfg.inDegree(jumpDestNode) > 1);
954
955 // temporary fix as these are hard for cfg updates
956 if (keepFt) {
957 return NULL;
958 }
959
960 //not desirable if fallThruNnode is big.
961 if (fallThruNode.basicBlock().instructionCount() >
963 sizeAborts_++;
964 return NULL;
965 }
966
967 if (keepJd) {
968 if (cfg.jumpSuccessor(fallThruNode) != NULL) {
969 return NULL;
970 }
971 return new CandidateBlocks(
972 bbn, fallThruNode, jumpDestNode, fallThruNode, NULL,
973 &jumpDestNode, NULL, false, true, false);
974 }
975 // Cannot if-convert code where possibility of fall-through loop.
976 if ((succ.first != NULL && succ.first->nodeID() < bbn.nodeID()) ||
977 (succ.second != NULL && succ.second->nodeID() < bbn.nodeID())) {
978 return NULL;
979 }
980
981 if (succ.first == NULL) {
982 // we have a triangle first->jump->ft(branch)
983 return new CandidateBlocks(
984 bbn, fallThruNode, jumpDestNode, jumpDestNode,
985 NULL, succ.first, succ.second, !keepJd,
986 !keepFt, !keepJd);
987 } else {
988 // we have a triangle first->jump->ft(branch)
989 return new CandidateBlocks(
990 bbn, fallThruNode, jumpDestNode, jumpDestNode,
991 &jumpDestNode, succ.first, succ.second, !keepJd,
992 !keepFt, !keepJd);
993 }
994 return NULL;
995}
996
997
998/**
999 * Sub class CandidateBlocks
1000 */
1001
1002/**
1003 * Constructor
1004 *
1005 * @param firstNode node where the branch was
1006 * @param fallThruNode node where fell thru if branch not taken
1007 * @param jumpDestNode node where the jump jumped
1008 * @param lastNode last node in the area being converter.
1009 May be fallThruNode, jumpDestNode or joinNode.
1010 * @param joinNode node where the paths join. Can be jumpNode, fallThruNode,
1011 lastNode or NULL if paths join outside converted area(at succNode1)
1012 * @param succNode1 1st successor node(fall-thru of original lastNode)
1013 * @param succNode2 2nd succossor node(if lastNode has branch, branch target)
1014 */
1016 BasicBlockNode& firstNode, BasicBlockNode& fallThruNode,
1017 BasicBlockNode& jumpDestNode, BasicBlockNode& lastNode,
1018 BasicBlockNode* joinNode, BasicBlockNode* succNode1,
1019 BasicBlockNode* succNode2,
1020 bool removeJoin, bool removeFT, bool removeJd) :
1021 firstNode_(firstNode), fallThruNode_(fallThruNode),
1022 jumpDestNode_(jumpDestNode), lastNode_(lastNode),
1023 joinNode_(joinNode), succNode1_(succNode1),
1024 succNode2_(succNode2),
1025 firstBB_(firstNode.basicBlock()), fallThruBB_(fallThruNode.basicBlock()),
1026 jumpDestBB_(jumpDestNode.basicBlock()),
1027 lastBB_(lastNode.basicBlock()),
1028 joinBB_(joinNode == NULL ? NULL : &joinNode->basicBlock()),
1029 removeJoin_(removeJoin), removeFt_(removeFT), removeJd_(removeJd),
1030 createJump_(false),
1031 guard_(NULL), invg_(NULL), grIndex_(-1), grFile_(NULL) {}
1032
1033
1034/**
1035 * Destructor
1036 */
1038 if (guard_ != NULL) {
1039 delete guard_;
1040 }
1041 if (invg_ != NULL) {
1042 delete invg_;
1043 }
1044}
1045
1046
#define PRINT_VAR(VARIABLE__)
#define assert(condition)
find Finds info of the inner loops in the program
find Finds info of the inner loops in the false
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition MoveNode.hh:53
static CmdLineOptions * cmdLineOptions()
static int verboseLevel()
static std::ostream & logStream()
TTAProgram::BasicBlock & basicBlock()
bool isNormalBB() const
std::string toString() const
virtual void removeEdge(Edge &e)
virtual void disconnectNodes(const Node &nTail, const Node &nHead)
virtual Node & headNode(const Edge &edge) const
int nodeCount() const
virtual Edge & outEdge(const Node &node, const int index) const
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
Node & node(const int index) const
virtual const TCEString & name() const
virtual int inDegree(const Node &node) const
virtual int outDegree(const Node &node) const
virtual EdgeSet outEdges(const Node &node) const
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
bool isBackEdge() const
CFGEdgeType edgeType()
void setBackEdge()
Add property to edge to mark is as back edge - loop edge DO NOT USE unless you know what you are doin...
bool isCallPassEdge() const
bool isTrueEdge() const
CFGEdgePredicate edgePredicate() const
void deleteNodeAndRefs(BasicBlockNode &node)
TTAProgram::InstructionReferenceManager & instructionReferenceManager()
void copyToProcedure(TTAProgram::Procedure &proc, TTAProgram::InstructionReferenceManager *irm=NULL)
BasicBlockNode * jumpSuccessor(BasicBlockNode &bbn)
virtual void writeToDotFile(const TCEString &fileName) const
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53
std::set< GraphEdge *, typename GraphEdge::Comparator > EdgeSet
Definition Graph.hh:54
int nodeID() const
float fuILP() const
float averageILP() const
float busILP() const
float bypassedRfILP() const
void setSourceOperationPtr(ProgramOperationPtr po)
Definition MoveNode.cc:541
void addDestinationOperationPtr(ProgramOperationPtr po)
Definition MoveNode.cc:533
static void executeProcedurePass(TTAProgram::Program &program, const TTAMachine::Machine &targetMachine, ProcedurePass &procedurePass)
virtual bool dumpIfConversionCFGs() const
virtual int ifConversionThreshold() const
static ProgramOperationPtr fixTerminalPO(TTAProgram::TerminalFUPort &terminal, std::map< ProgramOperationPtr, ProgramOperationPtr > &poMapping)
std::pair< BasicBlockNode *, BasicBlockNode * > successors(BasicBlockNode &node, ControlFlowGraph &cfg)
bool writesRegister(const TTAProgram::BasicBlock &bb, int index, const TTAMachine::RegisterFile &rf, bool ignoreLastInstruction)
CandidateBlocks * detectTriangleViaFt(BasicBlockNode &bbn, BasicBlockNode &fallThruNode, BasicBlockNode &jumpDestNode, ControlFlowGraph &cfg)
bool canConvert(CandidateBlocks *candidates, ControlFlowGraph &cfg)
bool hasConditionals(TTAProgram::BasicBlock &bb)
CandidateBlocks * detectDiamond(BasicBlockNode &bbn, BasicBlockNode &fallThruNode, BasicBlockNode &jumpDestNode, ControlFlowGraph &cfg)
SimpleIfConverter(InterPassData &data, const TTAMachine::Machine &targetMachine)
virtual std::string shortDescription() const
CandidateBlocks * detectTriangleViaJump(BasicBlockNode &bbn, BasicBlockNode &fallThruNode, BasicBlockNode &jumpDestNode, ControlFlowGraph &cfg)
void convert(CandidateBlocks &bblocks, ControlFlowGraph &cfg)
virtual void handleProcedure(TTAProgram::Procedure &procedure, const TTAMachine::Machine &targetMachine)
CandidateBlocks * searchCandidate(ControlFlowGraph &cfg)
void appendBB(const TTAProgram::BasicBlock &src, TTAProgram::BasicBlock &dest, TTAProgram::MoveGuard *mg, bool removeJumps)
virtual void handleProgram(TTAProgram::Program &program, const TTAMachine::Machine &targetMachine)
void addJump(TTAProgram::BasicBlock &bb, BasicBlockNode &bbn)
TTAProgram::InstructionReferenceManager * irm_
void updateCfg(CandidateBlocks &bblocks, ControlFlowGraph &cfg)
void combineBlocks(CandidateBlocks &bblocks)
static bool removeJump(TTAProgram::BasicBlock &bb)
TTAProgram::CodeGenerator * codeGenerator_
virtual void handleControlFlowGraph(ControlFlowGraph &cfg, const TTAMachine::Machine &targetMachine)
virtual bool isInverted() const
virtual Bus * parentBus() const
virtual ControlUnit * controlUnit() const
Definition Machine.cc:345
const RegisterFile * registerFile() const
static TTAProgram::MoveGuard * createInverseGuard(const TTAProgram::MoveGuard &mg, const TTAMachine::Bus *bus=NULL)
std::shared_ptr< TTAProgram::Move > createJump(TTAProgram::InstructionReference &dst)
virtual Instruction & previousInstruction(const Instruction &ins) const
virtual Instruction & firstInstruction() const
virtual void add(Instruction *ins)
virtual int instructionCount() const
virtual std::string disassembly() const
virtual Program & parent() const
virtual Instruction & lastInstruction() const
virtual Instruction & instructionAtIndex(int index) const
InstructionReference createReference(Instruction &ins)
Move & move(int i) const
void addMove(std::shared_ptr< Move > move)
void removeMove(Move &move)
MoveGuard * copy() const
Definition MoveGuard.cc:96
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Terminal & source() const
Definition Move.cc:302
std::shared_ptr< Move > copy() const
Definition Move.cc:413
bool isJump() const
Definition Move.cc:164
Terminal & destination() const
Definition Move.cc:323
static NullInstruction & instance()
InstructionReferenceManager & instructionReferenceManager() const
Definition Program.cc:688
virtual Operation & hintOperation() const
void setProgramOperation(ProgramOperationPtr po)
ProgramOperationPtr programOperation() const
virtual int index() const
virtual const TTAMachine::RegisterFile & registerFile() const
virtual bool isBasicBlockReference() const
Definition Terminal.cc:139
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isInstructionAddress() const
Definition Terminal.cc:87
TTAProgram::BasicBlock & fallThruBB_
CandidateBlocks(BasicBlockNode &firstNode, BasicBlockNode &fallThruNode, BasicBlockNode &jumpNode, BasicBlockNode &lastNode, BasicBlockNode *joinNode, BasicBlockNode *succNode1, BasicBlockNode *succNode2, bool removeJoin, bool removeFT, bool removeJd)
const TTAMachine::RegisterFile * grFile_
TTAProgram::BasicBlock & jumpDestBB_