OpenASIP 2.2
Loading...
Searching...
No Matches
RegisterRenamer.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file RegisterRenamer.cc
26 *
27 * Definition of RegisterRenamer class.
28 *
29 * @todo rename the file to match the class name
30 *
31 * @author Heikki Kultala 2009-2011 (hkultala-no.spam-cs.tut.fi)
32 * @note rating: red
33 */
34
35#include "MapTools.hh"
36
37#include "RegisterRenamer.hh"
38
39#include "RegisterFile.hh"
40#include "Guard.hh"
41#include "Machine.hh"
43#include "BasicBlock.hh"
45#include "MoveNode.hh"
46#include "Terminal.hh"
48#include "LiveRangeData.hh"
49#include "TerminalRegister.hh"
50#include "MoveNodeSelector.hh"
51#include "Move.hh"
52#include "MoveGuard.hh"
53#include "LiveRange.hh"
54
55// #define DEBUG_REG_RENAMER
56#include "tce_config.h"
57
58/**
59 * Constructor.
60 *
61 * @param machine machine for which we are scheudling
62
63RegisterRenamer::RegisterRenamer(const TTAMachine::Machine& machine) :
64 machine_(machine) {
65 initialize();
66}
67*/
68
69/**
70 * Constructor.
71*
72 * @param machine machine for which we are scheudling
73 */
76 machine_(machine), bb_(bb), ddg_(NULL){
77 initialize();
78}
79
80void
85
86void
88 auto regNav = machine_.registerFileNavigator();
89
90 auto trCacheIter = tempRegFileCache_.find(&machine_);
91
92 if (trCacheIter == tempRegFileCache_.end()) {
96 } else {
97 tempRegFiles_ = trCacheIter->second;
98 }
99
100 for (int i = 0; i < regNav.count(); i++) {
101 bool isTempRf = false;
102 TTAMachine::RegisterFile* rf = regNav.item(i);
104 isTempRf = true;
105 }
106 unsigned int regCount = isTempRf ? rf->size()-1 : rf->size();
107 for (unsigned int j = 0; j < regCount; j++ ) {
109 }
110 }
111}
112
113void
115
116 assert(ddg_ != NULL);
121
122 std::map<TCEString,int> lastUses;
123
124 // find regs inside this BB.
125 for (int i = 0; i < ddg_->nodeCount(); i++) {
126 MoveNode& node = ddg_->node(i);
127
128 // any write to a reg means it's not alive.
129 TTAProgram::Terminal& dest = node.move().destination();
130 if (dest.isGPR()) {
132 dest.registerFile(), dest.index());
133 onlyMidPartiallyUsedRegs_.insert(regName);
134 }
135 TTAProgram::Terminal& src = node.move().source();
136 if (src.isGPR()) {
138 src.registerFile(), src.index());
139 onlyMidPartiallyUsedRegs_.insert(regName);
140 }
141 }
142
143 // then loop for deps outside or inside this bb.
144 for (std::set<TCEString>::iterator allIter = freeGPRs_.begin();
145 allIter != freeGPRs_.end();) {
146 bool aliveOver = false;
147 bool aliveAtBeginning = false;
148 bool aliveAtEnd = false;
149 bool aliveAtMid = false;
150 // defined before and used here or after?
151 if (bb_.liveRangeData_->regDefReaches_.find(*allIter) !=
153 if (bb_.liveRangeData_->registersUsedAfter_.find(*allIter)
155 aliveOver = true;
156 }
157 if (bb_.liveRangeData_->regFirstUses_.find(*allIter) !=
159 aliveAtBeginning = true;
160 LiveRangeData::MoveNodeUseMapSet::iterator i =
161 bb_.liveRangeData_->regLastUses_.find(*allIter);
162 if (i != bb_.liveRangeData_->regLastUses_.end()) {
163 LiveRangeData::MoveNodeUseSet& lastUses = i->second;
164 for (LiveRangeData::MoveNodeUseSet::iterator j =
165 lastUses.begin(); j != lastUses.end(); j++) {
166 if (j->pseudo()) {
167 aliveOver = true;
168 }
169 }
170 }
171 }
172 aliveAtBeginning = true;
173 }
174 // used after this?
175 if (bb_.liveRangeData_->registersUsedAfter_.find(*allIter) !=
177 // defined here?
178 if (bb_.liveRangeData_->regDefines_.find(*allIter) !=
180 aliveAtEnd = true;
181 }
182 }
183
184 if (aliveAtEnd && aliveAtBeginning) {
185 aliveOver = true;
186 }
187
188 // TODO: why was this here?
189 if (onlyMidPartiallyUsedRegs_.find(*allIter) !=
191 aliveAtMid = true;
192 }
193
194 if (aliveOver) {
195 // can not be used for renaming.
196 onlyMidPartiallyUsedRegs_.erase(*allIter);
197 freeGPRs_.erase(allIter++);
198 } else {
199 if (aliveAtBeginning) {
200 onlyBeginPartiallyUsedRegs_.insert(*allIter);
201
202 onlyMidPartiallyUsedRegs_.erase(*allIter);
203 freeGPRs_.erase(allIter++);
204 } else {
205 if (aliveAtEnd) {
206 onlyEndPartiallyUsedRegs_.insert(*allIter);
207
208 onlyMidPartiallyUsedRegs_.erase(*allIter);
209 freeGPRs_.erase(allIter++);
210 } else { // only mid if has reads of writes?
211 if (aliveAtMid) {
212 freeGPRs_.erase(allIter++);
213 } else {
214 allIter++;
215 }
216 }
217 }
218 }
219 }
220}
221
222std::set<TCEString>
224 const RegisterRenamer::RegisterFileSet& rfs) const {
225
226 std::set<TCEString> allowedGprs = registersOfRFs(rfs);
227 std::set<TCEString> regs;
228 SetTools::intersection(allowedGprs, freeGPRs_, regs);
229 return regs;
230}
231
232std::set<TCEString>
234 const RegisterFileSet& rfs) const {
235
236 std::set<TCEString> gprs;
237 for (std::set<const TTAMachine::RegisterFile*,
238 TTAMachine::MachinePart::Comparator>::iterator i = rfs.begin();
239 i != rfs.end(); i++) {
240 bool isTempRF = false;
241 const TTAMachine::RegisterFile* rf = *i;
243 isTempRF = true;
244 }
245 int lowestFreeIndex = 0;
246 if (rf->zeroRegister()) {
247 lowestFreeIndex = 1;
248 }
249 for (int j = lowestFreeIndex;
250 j < (isTempRF ? rf->size() - 1 : rf->size()); j++) {
251 gprs.insert(DisassemblyRegister::registerName(*rf, j));
252 }
253 }
254 return gprs;
255}
256/**
257 * Finds registers which are used but only before given earliestCycle.
258 */
259std::set<TCEString>
261 const RegisterFileSet& rfs, int earliestCycle,
262 const DataDependenceGraph::NodeSet& guardMoves) const {
263
264 std::set<TCEString> availableRegs;
265 // nothing can be scheduled earlier than cycle 0.
266 // in that case we have empty set, no need to check.
267 if (earliestCycle < 1) {
268 return availableRegs;
269 }
270
271 std::set<TCEString> allowedGprs = registersOfRFs(rfs);
272 std::set<TCEString> regs = usedGPRs_;
275 std::set<TCEString> regs2;
276 SetTools::intersection(allowedGprs, regs, regs2);
277
278
279 // find from used gprs.
280 // todo: this is too conservative? leaves one cycle netween war?
281 for (std::set<TCEString>::iterator i = regs2.begin();
282 i != regs2.end(); i++) {
283 TCEString rfName = i->substr(0, i->find('.'));
286
287 unsigned int regIndex = atoi(i->substr(i->find('.')+1).c_str());
288 if (ddg_->lastRegisterCycle(*rf, regIndex) < earliestCycle) {
289 availableRegs.insert(*i);
290 }
291 }
292
293 // if need to have guards?
294 if (guardMoves.empty()) {
295 return availableRegs;
296 } else {
297 std::set<TCEString> guardedRegs =
298 findGuardRegisters(guardMoves, rfs);
299 std::set<TCEString> guardedAvailableRegs;
301 availableRegs, guardedRegs, guardedAvailableRegs);
302 return guardedAvailableRegs;
303 }
304}
305
306/**
307 * Finds registers which are used but only after given earliestCycle.
308 */
309std::set<TCEString>
311 const RegisterRenamer::RegisterFileSet& rfs, int latestCycle) const {
312
313 std::set<TCEString> availableRegs;
314 // nothing can be scheduled earlier than cycle 0.
315 // in that case we have empty set, no need to check.
316
317 std::set<TCEString> allowedGprs = registersOfRFs(rfs);
318 std::set<TCEString> regs = usedGPRs_;
321 std::set<TCEString> regs2;
322 SetTools::intersection(allowedGprs, regs, regs2);
323
324 // find from used gprs.
325 // todo: this is too conservative? leaves one cycle netween war?
326 for (std::set<TCEString>::iterator i = regs2.begin();
327 i != regs2.end(); i++) {
328 TCEString rfName = i->substr(0, i->find('.'));
331
332 unsigned int regIndex = atoi(i->substr(i->find('.')+1).c_str());
333 if (ddg_->firstRegisterCycle(*rf, regIndex) > latestCycle) {
334 availableRegs.insert(*i);
335 }
336 }
337 return availableRegs;
338}
339
340std::set<TCEString>
342 int bitWidth, int earliestCycle,
343 const DataDependenceGraph::NodeSet& guardMoves) const {
344 std::set<TCEString> availableRegs;
345 // nothing can be scheduled earlier than cycle 0.
346 // in that case we have empty set, no need to check.
347 if (earliestCycle < 1) {
348 return availableRegs;
349 }
350
351 std::set<TCEString> regs = onlyMidPartiallyUsedRegs_;
354
355 for (std::set<TCEString>::iterator i = regs.begin();
356 i != regs.end(); i++) {
357
358 TCEString rfName = i->substr(0, i->find('.'));
361 unsigned int regIndex = atoi(i->substr(i->find('.')+1).c_str());
362 if (ddg_->lastRegisterCycle(*rf, regIndex) < earliestCycle &&
363 rf->width() == bitWidth) {
364 availableRegs.insert(*i);
365 }
366 }
367 // if need to have guards?
368 if (guardMoves.empty()) {
369 return availableRegs;
370 } else {
371#ifdef DEBUG_REGISTER_RENAMER
372 if (!liveRange->guards.empty()) {
373 std::cerr << "\t\t\t\tpartiallyusedregs: ";
374 for (std::set<TCEString>::iterator i =
375 regs.begin();
376 i != regs.end(); i++) {
377 std::cerr << *i << " ";
378 }
379 std::cerr << std::endl;
380 }
381#endif
382
383 RegisterFileSet rfs; // empty, all rf's
384 std::set<TCEString> guardedRegs =
385 findGuardRegisters(guardMoves, rfs);
386 std::set<TCEString> guardedAvailableRegs;
388 availableRegs, guardedRegs, guardedAvailableRegs);
389 return guardedAvailableRegs;
390 }
391}
392
393std::set<TCEString>
395 int bitWidth, int latestCycle) const {
396 std::set<TCEString> availableRegs;
397
398 std::set<TCEString> regs = onlyMidPartiallyUsedRegs_;
401
402 for (std::set<TCEString>::iterator i = regs.begin();
403 i != regs.end(); i++) {
404
405 TCEString rfName = i->substr(0, i->find('.'));
408 unsigned int regIndex = atoi(i->substr(i->find('.')+1).c_str());
409 if (ddg_->firstRegisterCycle(*rf, regIndex) > latestCycle &&
410 rf->width() == bitWidth) {
411 availableRegs.insert(*i);
412 }
413 }
414 return availableRegs;
415}
416
417std::set<TCEString>
419 int bitWidth) const {
420
421 std::set<TCEString> availableRegs;
422
423 for (std::set<TCEString>::iterator i = freeGPRs_.begin();
424 i != freeGPRs_.end(); i++) {
425
426 TCEString rfName = i->substr(0, i->find('.'));
429 if (rf->width() == bitWidth) {
430 availableRegs.insert(*i);
431 }
432 }
433 return availableRegs;
434}
435
436std::set<TCEString>
438 const DataDependenceGraph::NodeSet& guardUseNodes,
439 int bitWidth, const RegisterFileSet& rfs) const {
440 std::set<TCEString> availableRegs;
441
443 (rfs.empty() ?
444 findFreeRegisters(bitWidth) :
446 findGuardRegisters(guardUseNodes, rfs),
447 availableRegs);
448
449 return availableRegs;
450}
451
452
453/**
454 * Renames destination register of a move (from the move itself and
455 * from all other moves in same liverange)
456 */
457bool
459 MoveNode& node, bool loopScheduling,
460 bool allowSameRf, bool differentRfOnlyDirectlyReachable,
461 int earliestCycle) {
462
463 if (!node.isMove() || !node.move().destination().isGPR()) {
464 return false;
465 }
466 const TTAMachine::RegisterFile& rf =
467 node.move().destination().registerFile();
468
469 // don't allow using same reg multiple times if loop scheduling.
470 // unscheudling would cause problems, missing war edges.
471 if (loopScheduling) {
472 earliestCycle = -1;
473 }
474 // first find used fully scheduled ones!
475 bool reused = true;
476
477 std::unique_ptr<LiveRange> liveRange(
478 ddg_->findLiveRange(node, true, false));
479
480 if (liveRange->writes.empty()) {
481 return false;
482 }
483 std::set<TCEString> availableRegisters;
484
485 if (!liveRange->noneScheduled()) {
486 // not yet allow guards rename when some movenodes of lr
487 // already sched
488 if (!allowSameRf) {
489 return false;
490 }
491 RegisterFileSet rfs;
492 rfs.insert(&rf);
493 earliestCycle = std::min(earliestCycle, liveRange->firstCycle());
494 availableRegisters =
496 liveRange->guards);
497 } else { // none scheduled.
498 if (tempRegFiles_.empty()) {
499
500#ifdef DEBUG_REG_RENAMER
501 if (!liveRange->guards.empty()) {
502 std::cerr<<"\t\tSearching for avail guard regs before cycle:"
503 << earliestCycle << std::endl;
504 }
505#endif
506
507 availableRegisters =
509 rf.width(), earliestCycle, liveRange->guards);
510
511#ifdef DEBUG_REG_RENAMER
512 if (!liveRange->guards.empty()) {
513 std::cerr << "\t\t\tfound free gaurd regs: ";
514 for (std::set<TCEString>::iterator i =
515 availableRegisters.begin();
516 i != availableRegisters.end(); i++) {
517 std::cerr << *i << " ";
518 }
519 std::cerr << std::endl;
520 }
521#endif
522
523 } else {
524 if (!differentRfOnlyDirectlyReachable) {
525 // only connected RFs
526 RegisterFileSet rfs = findConnectedRFs(*liveRange, false);
527 availableRegisters =
529 rfs, earliestCycle, liveRange->guards);
530 if (availableRegisters.empty()) {
531 // allow usasge of limm.
532 rfs = findConnectedRFs(*liveRange, true);
533 availableRegisters =
535 rfs, earliestCycle, liveRange->guards);
536 }
537 }
538 }
539 } // if not guards - after this can be guards
540 if (availableRegisters.empty()) {
541 reused = false;
542
543 if (!liveRange->noneScheduled()) {
544 if (liveRange->guards.empty()) {
545 RegisterFileSet rfs;
546 rfs.insert(&rf);
547 availableRegisters =
549 }
550 } else {
551 if (tempRegFiles_.empty()) {
552 if (liveRange->guards.empty()) {
553 availableRegisters =
555 } else { // guards use..
556#ifdef DEBUG_REG_RENAMER
557 std::cerr << "\t\tSearching for avail guard regs" << std::endl;
558#endif
559 RegisterFileSet rfs; // empty, use all RF's
560 availableRegisters =
562 liveRange->guards, rf.width(), rfs);
563#ifdef DEBUG_REG_RENAMER
564 std::cerr << "\t\t\tfound free gaurd regs: ";
565 for (std::set<TCEString>::iterator i =
566 availableRegisters.begin();
567 i != availableRegisters.end(); i++) {
568 std::cerr << *i << " ";
569 }
570 std::cerr << std::endl;
571#endif
572 }
573
574 } else {
575 // TODO: this disables guard renaming with regcopyadder
576 if (liveRange->guards.empty()) {
577 if (!differentRfOnlyDirectlyReachable) {
578 // only connected RFs
579 RegisterFileSet rfs =
580 findConnectedRFs(*liveRange, false);
581 availableRegisters =
583 if (availableRegisters.empty()) {
584 // allow usage of LIMM
585 rfs = findConnectedRFs(*liveRange, true);
586 availableRegisters =
588 }
589 }
590 } else {
591 // guards. use only same rf for now.
592 // TODO: update findconnectedRF's to work with guards
593 RegisterFileSet rfs;
594 rfs.insert(&rf);
595 availableRegisters =
597 liveRange->guards, rf.width(), rfs);
598 }
599 }
600 }
601 if (availableRegisters.empty()) {
602 return false;
603 }
604 }
605
606 // then actually do it.
607 return renameLiveRange(
608 *liveRange, *availableRegisters.begin(),
609 reused, false, loopScheduling);
610}
611
612/**
613 * Renames source register of a move (from the move itself and
614 * from all other moves in same liverange)
615 */
616bool
618 MoveNode& node, bool loopScheduling,
619 bool allowSameRf, bool differentRfOnlyDirectlyReachable, int latestCycle) {
620
621 if (!node.isMove() || !node.move().source().isGPR()) {
622 return false;
623 }
624 const TTAMachine::RegisterFile& rf =
625 node.move().source().registerFile();
626
627 if (loopScheduling) {
628 latestCycle = -1;
629 }
630
631 // first find used fully scheduled ones!
632 bool reused = true;
633
634 std::unique_ptr<LiveRange> liveRange(
635 ddg_->findLiveRange(node, false, false));
636
637 if (liveRange->writes.empty()) {
638 return false;
639 }
640 std::set<TCEString> availableRegisters;
641
642 if (!liveRange->noneScheduled()) {
643 if (!allowSameRf) {
644 return false;
645 }
646 std::set<const TTAMachine::RegisterFile*,
648 rfs.insert(&rf);
649 latestCycle = std::max(latestCycle, liveRange->lastCycle());
650
651 availableRegisters =
653 } else {
654 if (tempRegFiles_.empty()) {
655 availableRegisters =
657 } else {
658 if (!differentRfOnlyDirectlyReachable) {
659 // only connected RFs
660 std::set<const TTAMachine::RegisterFile*,
662 rfs = findConnectedRFs(*liveRange, false);
663 availableRegisters =
665 if (availableRegisters.empty()) {
666 rfs = findConnectedRFs(*liveRange, true);
667 availableRegisters =
669 rfs, latestCycle);
670 }
671 }
672 }
673 }
674
675 if (availableRegisters.empty()) {
676 reused = false;
677
678 if (!liveRange->noneScheduled()) {
679 std::set<const TTAMachine::RegisterFile*,
681 rfs.insert(&rf);
682 availableRegisters =
684 } else {
685 if (tempRegFiles_.empty()) {
686 availableRegisters =
688 } else {
689 if (!differentRfOnlyDirectlyReachable) {
690 // only connected RFs
691 std::set<const TTAMachine::RegisterFile*,
693 rfs = findConnectedRFs(*liveRange, false);
694 availableRegisters = findFreeRegistersInRF(rfs);
695 if (availableRegisters.empty()) {
696 rfs = findConnectedRFs(*liveRange, true);
697 availableRegisters = findFreeRegistersInRF(rfs);
698 }
699 }
700 }
701 }
702 if (availableRegisters.empty()) {
703 return false;
704 }
705 }
706
707 return
709 *liveRange, *availableRegisters.begin(), false, reused,
710 loopScheduling);
711}
712
713bool
715 LiveRange& liveRange, const TCEString& newReg, bool usedBefore,
716 bool usedAfter, bool loopScheduling) {
717
718 if (liveRange.writes.size() <1) {
719 return false;
720 }
721
722 if (liveRange.reads.size() == 0 && liveRange.guards.size() == 0) {
723 return false;
724 }
725
726 assert(newReg.length() > 2);
727 TCEString rfName = newReg.substr(0, newReg.find('.'));
730
731 int newRegIndex =
732 atoi(newReg.substr(newReg.find('.')+1).c_str());
733
734 if (usedBefore) {
735 // create antidependencies from the previous use of this temp reg.
736
737 //todo: if in a loop, create antidependencies to first ones in the BB.
740 *rf, newRegIndex);
741
742 DataDependenceGraph::NodeSet lastWrites =
744 *rf, newRegIndex);
745
746 DataDependenceGraph::NodeSet lastGuards =
748 *rf, newRegIndex);
749
750 // create the deps.
751 for (DataDependenceGraph::NodeSet::iterator i =
752 liveRange.writes.begin(); i != liveRange.writes.end(); i++) {
753
754 // create WAR's from previous reads
755 for (DataDependenceGraph::NodeSet::iterator
756 j = lastReads.begin(); j != lastReads.end(); j++) {
757
761
762 ddg_->connectNodes(**j, **i, *edge);
763 }
764
765 // create WAR's from previous guard uses
766 for (DataDependenceGraph::NodeSet::iterator
767 j = lastGuards.begin(); j != lastGuards.end(); j++) {
768
771 DataDependenceEdge::DEP_WAR, newReg, true);
772
773 ddg_->connectNodes(**j, **i, *edge);
774 }
775
776 // create WAW's from previous writes.
777 for (DataDependenceGraph::NodeSet::iterator
778 j = lastWrites.begin(); j != lastWrites.end(); j++) {
779
783
784 ddg_->connectNodes(**j, **i, *edge);
785 }
786 }
787 } else {
788 // this is not used before.
789
790 // update bookkeeping about first use of this reg
791 if (!usedAfter)
792 assert(bb_.liveRangeData_->regFirstUses_[newReg].empty());
793
794 // killing write.
795 if (liveRange.writes.size() == 1 &&
796 (*liveRange.writes.begin())->move().isUnconditional()) {
797 bb_.liveRangeData_->regKills_[newReg].first =
798 MoveNodeUse(**liveRange.writes.begin());
799 bb_.liveRangeData_->regFirstDefines_[newReg].clear();
800 bb_.liveRangeData_->regFirstUses_[newReg].clear();
801 }
802
803 // for writing.
804 for (DataDependenceGraph::NodeSet::iterator i =
805 liveRange.writes.begin(); i != liveRange.writes.end(); i++) {
806
807 MoveNodeUse mnd(**i);
808 bb_.liveRangeData_->regFirstDefines_[newReg].insert(mnd);
809 // TODO: only if intra-bb-antideps enabled?
810 static_cast<DataDependenceGraph*>(ddg_->rootGraph())->
811 updateRegWrite(mnd, newReg, bb_);
812 }
813
814 // for reading.
815 for (DataDependenceGraph::NodeSet::iterator i =
816 liveRange.reads.begin(); i != liveRange.reads.end(); i++) {
817
818 MoveNodeUse mnd(**i);
819 bb_.liveRangeData_->regFirstUses_[newReg].insert(mnd);
820 // no need to create raw deps here
821 }
822
823 // for guards.
824 for (DataDependenceGraph::NodeSet::iterator i =
825 liveRange.guards.begin(); i != liveRange.guards.end(); i++) {
826
827 MoveNodeUse mnd(**i);
828 bb_.liveRangeData_->regFirstUses_[newReg].insert(mnd);
829 // no need to create raw deps here
830 }
831
832 }
833
834 if (usedAfter) {
835
836 DataDependenceGraph::NodeSet firstWrites =
838 *rf, newRegIndex);
839
840 // make sure no circular antidep path
841 for (DataDependenceGraph::NodeSet::iterator
842 j = firstWrites.begin(); j != firstWrites.end(); j++) {
843
844 for (DataDependenceGraph::NodeSet::iterator i =
845 liveRange.reads.begin(); i != liveRange.reads.end();
846 i++) {
847 if (ddg_->hasPath(**j, **i)) {
848 return false;
849 }
850 }
851
852 for (DataDependenceGraph::NodeSet::iterator i =
853 liveRange.writes.begin(); i != liveRange.writes.end();
854 i++) {
855 if (ddg_->hasPath(**j, **i)) {
856 return false;
857 }
858 }
859 }
860
861
862 // create the antidep deps.
863
864 for (DataDependenceGraph::NodeSet::iterator
865 j = firstWrites.begin(); j != firstWrites.end(); j++) {
866
867 // WaW's
868 for (DataDependenceGraph::NodeSet::iterator i =
869 liveRange.writes.begin(); i != liveRange.writes.end();
870 i++) {
871
875
876 ddg_->connectNodes(**i,**j, *edge);
877 }
878
879 // WaR's
880 for (DataDependenceGraph::NodeSet::iterator i =
881 liveRange.reads.begin(); i != liveRange.reads.end();
882 i++) {
886
887 ddg_->connectNodes(**i,**j, *edge);
888 }
889 }
890
891 } else {
892
893 // killing write.
894 if (liveRange.writes.size() == 1 &&
895 (*liveRange.writes.begin())->move().isUnconditional()) {
896 bb_.liveRangeData_->regLastKills_[newReg].first =
897 MoveNodeUse(**liveRange.writes.begin());
898 bb_.liveRangeData_->regDefines_[newReg].clear();
899 }
900
901 // for writing.
902 for (DataDependenceGraph::NodeSet::iterator i =
903 liveRange.writes.begin(); i != liveRange.writes.end(); i++) {
904
905 MoveNodeUse mnd(**i);
906 bb_.liveRangeData_->regDefines_[newReg].insert(mnd);
907 }
908
909 // for reading.
910 for (DataDependenceGraph::NodeSet::iterator i =
911 liveRange.reads.begin(); i != liveRange.reads.end(); i++) {
912
913 MoveNodeUse mnd(**i);
914 bb_.liveRangeData_->regLastUses_[newReg].insert(mnd);
915 }
916
917 // need to create backedges to first if we are loop scheduling.
918 if (loopScheduling) {
919 updateAntiEdgesFromLRTo(liveRange, newReg, bb_, 1);
920 }
921 }
922
923 // first update the movenodes.
924
925 // for writes.
926 for (DataDependenceGraph::NodeSet::iterator i = liveRange.writes.begin();
927 i != liveRange.writes.end(); i++) {
928 TTAProgram::Move& move = (**i).move();
929 const TTAMachine::Port& oldPort = move.destination().port();
930 if (oldPort.parentUnit() == rf) {
932 oldPort, newRegIndex));
933 } else {
935 *rf->firstWritePort(), newRegIndex));
936 }
937
938 }
939
940 // for reads.
941 for (DataDependenceGraph::NodeSet::iterator i = liveRange.reads.begin();
942 i != liveRange.reads.end(); i++) {
943 TTAProgram::Move& move = (**i).move();
944 const TTAMachine::Port& oldPort = move.source().port();
945 if (oldPort.parentUnit() == rf) {
947 oldPort, newRegIndex));
948 } else {
950 *rf->firstReadPort(), newRegIndex));
951 }
952 }
953
954
955 // for reads.
956 for (DataDependenceGraph::NodeSet::iterator i = liveRange.guards.begin();
957 i != liveRange.guards.end(); i++) {
958 MoveNode& mn = **i;
959 TTAProgram::Move& move = mn.move();
960 const TTAMachine::Guard& guard = move.guard().guard();
961 // TODO: update the guard here
962
963#ifdef DEBUG_REG_RENAMER
964
965 TTAMachine::Bus& bus = move.bus();
966
967 std::cerr << "We should be updating guard here for: "
968 << mn.toString()
969 << std::endl;
970 std::cerr << "\tnew guard reg: " << rf->name() << "." << newRegIndex
971 << std::endl;
972
973 std::cerr << "\tBus: " << bus.name() << std::endl;
974
975#endif
976 TTAMachine::Bus* guardBus = guard.parentBus();
977#ifdef DEBUG_REG_RENAMER
978 std::cerr << "\tGuard bus: " << guardBus->name() << std::endl;
979#endif
980 for (int j = 0 ; j < guardBus->guardCount(); j++) {
981 TTAMachine::Guard *g = guardBus->guard(j);
983 dynamic_cast<TTAMachine::RegisterGuard*>(g);
984 if (rg) {
985 if (rg->registerFile() == rf &&
986 rg->registerIndex() == newRegIndex &&
987 rg->isInverted() == guard.isInverted()) {
988 move.setGuard(new TTAProgram::MoveGuard(*g));
989#ifdef DEBUG_REG_RENAMER
990 std::cerr << "\tset new guard: " << mn.toString()
991 << std::endl;
992#endif
993 }
994 }
995 }
996
997 }
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008 // then update ddg and notify selector.
1009
1010 // for writes.
1011 for (DataDependenceGraph::NodeSet::iterator i = liveRange.writes.begin();
1012 i != liveRange.writes.end(); i++) {
1013
1014 DataDependenceGraph::NodeSet writeSuccessors =
1015 ddg_->successors(**i);
1016
1017 DataDependenceGraph::NodeSet writePredecessors =
1018 ddg_->predecessors(**i);
1019
1020 ddg_->destRenamed(**i);
1021
1022 // notify successors of write to prevent orphan nodes.
1023 for (DataDependenceGraph::NodeSet::iterator iter =
1024 writeSuccessors.begin();
1025 iter != writeSuccessors.end(); iter++) {
1026 selector_->mightBeReady(**iter);
1027 }
1028
1029 // notify successors of write to prevent orphan nodes.
1030 for (DataDependenceGraph::NodeSet::iterator iter =
1031 writePredecessors.begin();
1032 iter != writePredecessors.end(); iter++) {
1033 selector_->mightBeReady(**iter);
1034 }
1035
1036 }
1037
1038 // for reads
1039 for (DataDependenceGraph::NodeSet::iterator i = liveRange.reads.begin();
1040 i != liveRange.reads.end(); i++) {
1041 DataDependenceGraph::NodeSet successors =
1042 ddg_->successors(**i);
1043
1044 ddg_->sourceRenamed(**i);
1045
1046 DataDependenceGraph::NodeSet predecessors =
1047 ddg_->predecessors(**i);
1048
1049 // notify successors to prevent orphan nodes.
1050 for (DataDependenceGraph::NodeSet::iterator iter =
1051 successors.begin();
1052 iter != successors.end(); iter++) {
1053 selector_->mightBeReady(**iter);
1054 }
1055
1056 // notify successors to prevent orphan nodes.
1057 for (DataDependenceGraph::NodeSet::iterator iter =
1058 predecessors.begin();
1059 iter != predecessors.end(); iter++) {
1060 selector_->mightBeReady(**iter);
1061 }
1062 }
1063
1064 // for guards
1065 for (DataDependenceGraph::NodeSet::iterator i = liveRange.guards.begin();
1066 i != liveRange.guards.end(); i++) {
1067 DataDependenceGraph::NodeSet successors =
1068 ddg_->successors(**i);
1069
1070 ddg_->guardRenamed(**i);
1071
1072 DataDependenceGraph::NodeSet predecessors =
1073 ddg_->predecessors(**i);
1074
1075 // notify successors to prevent orphan nodes.
1076 for (DataDependenceGraph::NodeSet::iterator iter =
1077 successors.begin();
1078 iter != successors.end(); iter++) {
1079 selector_->mightBeReady(**iter);
1080 }
1081
1082 // notify successors to prevent orphan nodes.
1083 for (DataDependenceGraph::NodeSet::iterator iter =
1084 predecessors.begin();
1085 iter != predecessors.end(); iter++) {
1086 selector_->mightBeReady(**iter);
1087 }
1088 }
1089
1090 renamedToRegister(newReg);
1091 return true;
1092}
1093
1095
1096 freeGPRs_.erase(newReg);
1097
1098 onlyBeginPartiallyUsedRegs_.erase(newReg);
1099 onlyEndPartiallyUsedRegs_.erase(newReg);
1100 onlyMidPartiallyUsedRegs_.erase(newReg);
1101
1102 usedGPRs_.insert(newReg);
1103
1104}
1105
1107 if (bb_.liveRangeData_->regFirstUses_[reg].empty() &&
1108 bb_.liveRangeData_->regLastUses_[reg].empty() &&
1109 bb_.liveRangeData_->regDefines_[reg].empty() &&
1110 bb_.liveRangeData_->regFirstDefines_[reg].empty()) {
1111 freeGPRs_.insert(reg);
1112 }
1113}
1114
1115/**
1116 * Registers the selector being used to the bypasser.
1117 *
1118 * If the bypasser has been registered to the selector,
1119 * bypasses can notify the selector about dependence changes.
1120 * Currently it notifies the successors of a node being removed due
1121 * dead result elimination.
1122 *
1123 * @param selector selector which bypasser notifies on some dependence changes.
1124 */
1125void
1127 selector_ = selector;
1128}
1129
1130/**
1131 * Updates antidep edges from this liverange to first def of some other bb.
1132 *
1133 * @param liveRange liverange which is the origin of the deps
1134 * @param newReg name of the new register
1135 * @param bb destination BB where to draw the edges to
1136 * @loopDepth loop depth of added edges.
1137 */
1138void
1140 LiveRange& liveRange, const TCEString& newReg, TTAProgram::BasicBlock& bb,
1141 int loopDepth) const {
1142 std::set<MoveNodeUse>& firstDefs =
1144
1145 for (std::set<MoveNodeUse>::iterator i = firstDefs.begin();
1146 i != firstDefs.end(); i++) {
1147
1148 const MoveNodeUse& destination = *i;
1149 if (ddg_->hasNode(*destination.mn())) {
1150
1151 //WaW's of writes.
1152 for (DataDependenceGraph::NodeSet::iterator j =
1153 liveRange.writes.begin();
1154 j != liveRange.writes.end(); j++) {
1155
1156 // create dependency edge
1157 DataDependenceEdge* dde =
1161 false, false, false, destination.pseudo(), loopDepth);
1162
1163 // and connect.
1165 **j, *destination.mn(), dde);
1166 }
1167
1168 //War's of reads.
1169 for (DataDependenceGraph::NodeSet::iterator j =
1170 liveRange.reads.begin();
1171 j != liveRange.reads.end(); j++) {
1172
1173 // create dependency edge
1174 DataDependenceEdge* dde =
1178 false, false, false, destination.pseudo(), 1);
1179
1180 // and connect.
1182 **j, *destination.mn(), dde);
1183 }
1184
1185 //War's of guards.
1186 for (DataDependenceGraph::NodeSet::iterator j =
1187 liveRange.guards.begin();
1188 j != liveRange.guards.end(); j++) {
1189
1190 // create dependency edge
1191 DataDependenceEdge* dde =
1195 true, false, false, destination.pseudo(), 1);
1196
1197 // and connect.
1199 **j, *destination.mn(), dde);
1200 }
1201 }
1202 }
1203}
1204
1207
1208 assert(!lr.writes.empty());
1209 TTAMachine::RegisterFile* originalRF =
1210 dynamic_cast<TTAMachine::RegisterFile*>(
1211 (*lr.writes.begin())->move().destination().port().parentUnit());
1212 assert(originalRF != 0);
1213 int bitwidth = originalRF->width();
1214 std::set<const TTAMachine::RegisterFile*,
1216
1217 // TODO: loop over movenoeds or RF's? this routine could be made faster.
1220 for (int i = 0; i < rfNav.count(); i++) {
1221 TTAMachine::RegisterFile* rf = rfNav.item(i);
1222 if (rf->width() != bitwidth) {
1223 continue;
1224 }
1227 bool connected = true;
1228
1229 for (DataDependenceGraph::NodeSet::iterator j = lr.writes.begin();
1230 j != lr.writes.end() && connected; j++) {
1231 const MoveNode& write = **j;
1233 write, writePorts)) {
1234 case -1:
1235 connected = allowLimm;
1236 break;
1237 case 0:
1238 connected = false;
1239 default:
1240 break;
1241 }
1242 }
1243 if (!connected) {
1244 continue;
1245 }
1246
1249
1250 for (DataDependenceGraph::NodeSet::iterator j = lr.reads.begin();
1251 j != lr.reads.end() && connected; j++) {
1252 const MoveNode& read = **j;
1254 readPorts, read)) {
1255 connected = false;
1256 }
1257 }
1258 if (connected) {
1259 rv.insert(rf);
1260 }
1261 }
1262 return rv;
1263}
1264
1265
1266
1267
1268
1269std::set<TCEString>
1271 const DataDependenceGraph::NodeSet& guardMoves,
1272 const RegisterFileSet& rfs) const {
1273
1274
1275 TTAMachine::Bus* bus = NULL;
1276 for (DataDependenceGraph::NodeSet::iterator i = guardMoves.begin();
1277 i != guardMoves.end(); i++) {
1278 const MoveNode& mn = **i;
1279 const TTAProgram::Move& move = mn.move();
1280 assert(!move.isUnconditional());
1281 if (bus == NULL) {
1282 bus = move.guard().guard().parentBus();
1283 } else {
1284 TTAMachine::Bus* bus2 = move.guard().guard().parentBus();
1285 if (bus != bus2) {
1286 return std::set<TCEString>();
1287 }
1288 }
1289 }
1290
1291 if (bus != NULL) {
1292 return findGuardRegisters(*bus, rfs);
1293 } else {
1294 return std::set<TCEString>();
1295 }
1296}
1297
1298/**
1299 * Finds registers which can guard moves from the given bus.
1300 */
1301std::set<TCEString>
1303 const TTAMachine::Bus& bus, const RegisterFileSet& rfs) const {
1304
1305 std::set<TCEString> trueGuards;
1306 std::set<TCEString> falseGuards;
1307
1308 // find guard
1309 for (int i = 0 ; i < bus.guardCount(); i++) {
1310 TTAMachine::Guard *g = bus.guard(i);
1312 dynamic_cast<TTAMachine::RegisterGuard*>(g);
1313 if (rg) {
1314 bool rfOk = true;
1315 if (!rfs.empty()) {
1316 if (rfs.find(rg->registerFile()) == rfs.end()) {
1317 rfOk = false;
1318 continue;
1319 }
1320 }
1321
1322 if (rfOk) {
1323 if (rg->isInverted()) {
1324 falseGuards.insert(
1326 *rg->registerFile(), rg->registerIndex()));
1327 } else {
1328 trueGuards.insert(
1330 *rg->registerFile(), rg->registerIndex()));
1331 }
1332 }
1333 }
1334 }
1335
1336 for (std::set<TCEString>::iterator i = trueGuards.begin();
1337 i != trueGuards.end(); i++) {
1338 if (falseGuards.find(*i) == falseGuards.end()) {
1339 trueGuards.erase(i);
1340 i = trueGuards.begin();
1341 }
1342 }
1343 return trueGuards;
1344}
1345
1346
1347
1348/// To avoid reanalysing machine every time hen new rr created.
1349std::map<const TTAMachine::Machine*,
1350 std::set <const TTAMachine::RegisterFile*,
#define assert(condition)
TTAMachine::Machine * machine
the architecture definition of the estimated processor
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
static void append(const ContainerType &src, ContainerType &dest)
BoostGraph * rootGraph()
int nodeCount() const
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
Node & node(const int index) const
bool hasNode(const Node &) const
bool hasPath(GraphNode &src, const GraphNode &dest) const
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
LiveRange * findLiveRange(MoveNode &lrNode, bool writingNode, bool guardUseNode) const
NodeSet lastScheduledRegisterWrites(const TTAMachine::BaseRegisterFile &rf, int registerIndex) const
int firstRegisterCycle(const TTAMachine::BaseRegisterFile &rf, int registerIndex) const
DataDependenceGraph::UndoData sourceRenamed(MoveNode &mn)
NodeSet lastScheduledRegisterGuardReads(const TTAMachine::BaseRegisterFile &rf, int registerIndex) const
NodeSet firstScheduledRegisterWrites(const TTAMachine::BaseRegisterFile &rf, int registerIndex) const
NodeSet lastScheduledRegisterReads(const TTAMachine::BaseRegisterFile &rf, int registerIndex) const
int lastRegisterCycle(const TTAMachine::BaseRegisterFile &rf, int registerIndex) const
DataDependenceGraph::UndoData guardRenamed(MoveNode &mn)
DataDependenceGraph::UndoData destRenamed(MoveNode &mn)
bool connectOrDeleteEdge(const MoveNode &tailNode, const MoveNode &headNode, DataDependenceEdge *edge)
static TCEString registerName(const TTAMachine::RegisterFile &rf, int index, char delim='.')
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53
static std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > tempRegisterFiles(const TTAMachine::Machine &machine)
static PortSet findWritePorts(const TTAMachine::Unit &rf)
static int canSourceWriteToAnyDestinationPort(const MoveNode &src, PortSet &ports, bool ignoreGuard=false)
static PortSet findReadPorts(const TTAMachine::Unit &rf)
static bool canAnyPortWriteToDestination(PortSet &ports, const MoveNode &dest)
std::set< const TTAMachine::Port *, const TTAMachine::MachinePart::Comparator > PortSet
virtual void mightBeReady(MoveNode &node)=0
const MoveNode * mn() const
bool pseudo() const
bool isMove() const
std::string toString() const
Definition MoveNode.cc:576
TTAProgram::Move & move()
std::set< TCEString > findPartiallyUsedRegistersInRFBeforeCycle(const RegisterFileSet &rfs, int earliestCycle, const DataDependenceGraph::NodeSet &guardMoves) const
void revertedRenameToRegister(const TCEString &reg)
MoveNodeSelector * selector_
std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > tempRegFiles_
std::set< TCEString > findPartiallyUsedRegistersBeforeCycle(int bitWidth, int earliestCycle, const DataDependenceGraph::NodeSet &guardMoves) const
DataDependenceGraph * ddg_
std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > RegisterFileSet
TTAProgram::BasicBlock & bb()
std::set< TCEString > allNormalGPRs_
static std::map< const TTAMachine::Machine *, std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > > tempRegFileCache_
To avoid reanalysing machine every time hen new rr created.
std::set< TCEString > freeGPRs_
bool renameLiveRange(LiveRange &liveRange, const TCEString &newReg, bool usedBefore, bool usedAfter, bool loopScheduling)
bool renameDestinationRegister(MoveNode &node, bool loopScheduling, bool allowSameRf, bool differentRfOnlyDirectlyReachable, int earliestCycle=-1)
std::set< TCEString > findFreeGuardRegisters(const DataDependenceGraph::NodeSet &guardUseNodes, int bitWidth, const RegisterFileSet &rfs) const
void setSelector(MoveNodeSelector *selector)
RegisterRenamer(const TTAMachine::Machine &machine, TTAProgram::BasicBlock &bb)
std::set< TCEString > onlyEndPartiallyUsedRegs_
bool renameSourceRegister(MoveNode &node, bool loopScheduling, bool allowSameRf, bool differentRfOnlyDirectlyReachable, int latestCycle=INT_MAX)
std::set< TCEString > registersOfRFs(const RegisterFileSet &rfs) const
std::set< TCEString > findFreeRegistersInRF(const RegisterFileSet &rfs) const
std::set< TCEString > onlyBeginPartiallyUsedRegs_
std::set< TCEString > findGuardRegisters(const DataDependenceGraph::NodeSet &guardMoves, const RegisterFileSet &rfs) const
std::set< TCEString > findPartiallyUsedRegistersAfterCycle(int bitWidth, int latestCycle) const
std::set< TCEString > findFreeRegisters(int bitWidth) const
const TTAMachine::Machine & machine_
std::set< TCEString > findPartiallyUsedRegistersInRFAfterCycle(const RegisterFileSet &rfs, int latestCycle) const
TTAProgram::BasicBlock & bb_
void renamedToRegister(const TCEString &newReg)
std::set< TCEString > onlyMidPartiallyUsedRegs_
RegisterFileSet findConnectedRFs(LiveRange &lr, bool allowLimm)
std::set< TCEString > usedGPRs_
void updateAntiEdgesFromLRTo(LiveRange &liveRange, const TCEString &newReg, TTAProgram::BasicBlock &bb, int loopDepth) const
static void intersection(const std::set< ValueType > &firstContainer, const std::set< ValueType > &secondContainer, std::set< ValueType > &intersection)
virtual int size() const
virtual int width() const
Guard * guard(int index) const
Definition Bus.cc:456
int guardCount() const
Definition Bus.cc:441
virtual TCEString name() const
virtual bool isInverted() const
virtual Bus * parentBus() const
ComponentType * item(int index) const
virtual RegisterFileNavigator registerFileNavigator() const
Definition Machine.cc:450
Unit * parentUnit() const
Port * firstReadPort() const
virtual bool zeroRegister() const
Port * firstWritePort() const
const RegisterFile * registerFile() const
LiveRangeData * liveRangeData_
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
void setSource(Terminal *src)
Definition Move.cc:312
MoveGuard & guard() const
Definition Move.cc:345
bool isUnconditional() const
Definition Move.cc:154
Terminal & source() const
Definition Move.cc:302
void setGuard(MoveGuard *guard)
Definition Move.cc:360
Terminal & destination() const
Definition Move.cc:323
void setDestination(Terminal *dst)
Definition Move.cc:333
const TTAMachine::Bus & bus() const
Definition Move.cc:373
virtual int index() const
Definition Terminal.cc:274
virtual bool isGPR() const
Definition Terminal.cc:107
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
MoveNodeUseMapSet regFirstUses_
MoveNodeUseMapSet regLastUses_
std::set< MoveNodeUse > MoveNodeUseSet
std::set< TCEString > registersUsedAfter_
MoveNodeUseMapSet regFirstDefines_
MoveNodeUseMapPair regKills_
MoveNodeUseMapPair regLastKills_
MoveNodeUseMapSet regDefines_
MoveNodeUseMapSet regDefReaches_
DataDependenceGraph::NodeSet reads
Definition LiveRange.hh:40
DataDependenceGraph::NodeSet guards
Definition LiveRange.hh:41
DataDependenceGraph::NodeSet writes
Definition LiveRange.hh:39