Update svn merge history.
[sdcc.git] / sdcc / src / pic14 / pcoderegs.c
blob84d9335c5c6318fae60334adc3f53163773a086d
1 /*-------------------------------------------------------------------------
3 pcoderegs.c - post code generation register optimizations
5 Written By - Scott Dattalo scott@dattalo.com
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
24 pcoderegs.c
26 The purpose of the code in this file is to optimize the register usage.
30 #include "main.h"
31 #include "pcoderegs.h"
32 #include "pcodeflow.h"
33 #include "ralloc.h"
36 static int total_registers_saved=0;
37 static int register_optimization=1;
39 /*-----------------------------------------------------------------*
40 * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
41 *-----------------------------------------------------------------*/
42 static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
45 pCode *pc=NULL;
47 reg_info *reg;
49 if(!pcfl)
50 return;
53 pc = findNextInstruction(pcfl->pc.next);
55 while(pc && !isPCFL(pc)) {
56 while (pc && !isPCI(pc) && !isPCFL(pc))
58 pc = pc->next;
59 } // while
60 if (!pc || isPCFL(pc)) continue;
61 assert( isPCI(pc) );
63 reg = getRegFromInstruction(pc);
64 #if 0
65 pc->print(stderr, pc);
66 fprintf( stderr, "--> reg %p (%s,%u), inCond/outCond: %x/%x\n",
67 reg, reg ? reg->name : "(null)", reg ? reg->rIdx : -1,
68 PCI(pc)->inCond, PCI(pc)->outCond );
69 #endif
70 if(reg) {
72 fprintf(stderr, "flow seq %d, inst seq %d %s ",PCODE(pcfl)->seq,pc->seq,reg->name);
73 fprintf(stderr, "addr = 0x%03x, type = %d rIdx=0x%03x\n",
74 reg->address,reg->type,reg->rIdx);
77 addSetIfnotP(& (PCFL(pcfl)->registers), reg);
79 if(PCC_REGISTER & PCI(pc)->inCond)
80 addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
82 if(PCC_REGISTER & PCI(pc)->outCond)
83 addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl);
85 addSetIfnotP(& (reg->reglives.usedpCodes), pc);
86 reg->wasUsed = TRUE;
90 //pc = findNextInstruction(pc->next);
91 pc = pc->next;
97 /*-----------------------------------------------------------------*
98 * void pCodeRegMapLiveRanges(pBlock *pb)
99 *-----------------------------------------------------------------*/
100 void pCodeRegMapLiveRanges(pBlock *pb)
102 pCode *pcflow;
104 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
105 pcflow != NULL;
106 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
108 if(!isPCFL(pcflow)) {
109 fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
110 continue;
112 pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
115 #if 0
116 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
117 pcflow != NULL;
118 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
120 regs *r = setFirstItem(PCFL(pcflow)->registers);
121 fprintf(stderr,"flow seq %d\n", pcflow->seq);
123 while (r) {
124 fprintf(stderr, " %s\n",r->name);
125 r = setNextItem(PCFL(pcflow)->registers);
130 #endif
135 /*-----------------------------------------------------------------*
137 *-----------------------------------------------------------------*/
138 static void Remove1pcode(pCode *pc, reg_info *reg, int debug_code)
141 pCode *pcn=NULL;
143 if(!reg || !pc)
144 return;
146 deleteSetItem (&(reg->reglives.usedpCodes),pc);
148 if(PCI(pc)->label) {
149 pcn = findNextInstruction(pc->next);
151 if(pcn)
152 PCI(pcn)->label = pBranchAppend(PCI(pcn)->label,PCI(pc)->label);
155 if(PCI(pc)->cline) {
156 if(!pcn)
157 pcn = findNextInstruction(pc->next);
159 if(pcn) {
160 if(PCI(pcn)->cline) {
161 //fprintf(stderr, "source line has been optimized completely out\n");
162 //pc->print(stderr,pc);
163 } else {
164 PCI(pcn)->cline = PCI(pc)->cline;
170 if(1) {
172 * Debug stuff. Comment out the instruction we're about to delete.
175 char buff1[256];
176 size_t size = 256;
178 char *pbuff;
179 pbuff = &buff1[0];
181 SNPRINTF(pbuff, size, ";%d", debug_code);
182 size -= strlen(pbuff);
183 pbuff += strlen(pbuff);
184 pCode2str(pbuff, size, pc);
185 pCodeInsertBefore(pc, newpCodeCharP(buff1));
186 //fprintf(stderr,"removing instruction:\n%s\n",buff1);
189 pc->destruct(pc);
193 /*-----------------------------------------------------------------*
194 * void RemoveRegsFromSet(set *regset)
196 *-----------------------------------------------------------------*/
197 static void RemoveRegsFromSet(set *regset)
199 reg_info *reg;
200 int used;
202 while(regset) {
203 reg = regset->item;
204 regset = regset->next;
206 used = elementsInSet(reg->reglives.usedpCodes);
208 if(used <= 1) {
210 //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);
211 if(used == 0) {
212 //fprintf(stderr," getting rid of reg %s\n",reg->name);
213 reg->isFree = TRUE;
214 reg->wasUsed = FALSE;
215 } else {
216 pCode *pc;
219 pc = setFirstItem(reg->reglives.usedpCodes);
221 if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern) {
222 //fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name);
223 continue;
227 if(isPCI(pc)) {
228 if(PCI(pc)->label) {
229 pCode *pcn = findNextInstruction(pc->next);
231 if(pcn && PCI(pcn)->label) {
232 //fprintf(stderr,"can't delete instruction with label...\n");
233 //pc->print(stderr,pc);
234 continue;
236 /* Move the label to the next instruction */
238 PCI(pcn)->label = PCI(pc)->label;
242 if(isPCI_SKIP(pc)) {
243 reg_info *r = getRegFromInstruction(pc);
244 fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
245 pc->print(stderr,pc);
246 fprintf(stderr,"reg %s, type =%d\n",r->name, r->type);
248 //fprintf(stderr," removing reg %s because it is used only once\n",reg->name);
249 Remove1pcode(pc, reg, 1);
251 unlinkpCode(pc);
252 deleteSetItem (&(reg->reglives.usedpCodes),pc);
254 reg->isFree = TRUE;
255 reg->wasUsed = FALSE;
256 total_registers_saved++; // debugging stats.
264 static void pic14_ReMapLiveRanges(void)
266 pBlock *pb;
267 if (!the_pFile) return;
268 RegsUnMapLiveRanges();
269 for (pb = the_pFile->pbHead; pb; pb = pb->next)
271 #if 0
272 pCode *pc = findNextpCode(pb->pcHead, PC_FLOW);
273 if (pc) {
274 pc->print( stderr, pc );
275 } else {
276 fprintf( stderr, "unnamed pBlock\n");
278 pc = findNextInstruction(pb->pcHead);
279 while (pc) {
280 pc->print( stderr, pc );
281 pc = findNextInstruction(pc->next);;
283 #endif
284 pCodeRegMapLiveRanges(pb);
285 } // for
288 /*-----------------------------------------------------------------*
289 * void RemoveUnusedRegisters(void)
291 *-----------------------------------------------------------------*/
292 void RemoveUnusedRegisters(void)
294 /* First, get rid of registers that are used only one time */
295 pic14_ReMapLiveRanges();
297 //RemoveRegsFromSet(dynInternalRegs);
298 RemoveRegsFromSet(dynAllocRegs);
299 RemoveRegsFromSet(dynStackRegs);
301 don't do DirectRegs yet - there's a problem with arrays
302 RemoveRegsFromSet(dynDirectRegs);
304 RemoveRegsFromSet(dynDirectBitRegs);
306 if(total_registers_saved) DFPRINTF((stderr, " *** Saved %d registers ***\n", total_registers_saved));
310 /*-----------------------------------------------------------------*
312 *-----------------------------------------------------------------*/
313 static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, reg_info *reg, int can_free)
315 static int debug_code=99;
316 if(!reg)
317 return;
318 #if 0
319 fprintf (stderr, "%s:%d(%s): %d (reg:%s)\n", __FILE__, __LINE__, __FUNCTION__, debug_code, reg ? reg->name : "???");
320 printpCode (stderr, pc1);
321 printpCode (stderr, pc2);
322 #endif
324 //fprintf(stderr,"%s\n",__FUNCTION__);
325 if(pc1)
326 Remove1pcode(pc1, reg, debug_code++);
328 if(pc2) {
329 Remove1pcode(pc2, reg, debug_code++);
330 deleteSetItem (&(PCFL(pcflow)->registers), reg);
332 if(can_free) {
333 reg->isFree = TRUE;
334 reg->wasUsed = FALSE;
339 pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
342 /*-----------------------------------------------------------------*
344 *-----------------------------------------------------------------*/
345 static int regUsedinRange(pCode *pc1, pCode *pc2, reg_info *reg)
347 int i=0;
348 reg_info *testreg;
350 do {
351 testreg = getRegFromInstruction(pc1);
352 if(testreg && (testreg->rIdx == reg->rIdx)) {
353 return 1;
355 if (i++ > 1000) {
356 fprintf(stderr, "warning, regUsedinRange searched through too many pcodes\n");
357 return 0;
360 pc1 = findNextInstruction(pc1->next);
362 } while (pc1 && (pc1 != pc2)) ;
364 return 0;
367 static int regIsSpecial (reg_info *reg, int mayBeGlobal)
369 if (!reg) return 0;
371 if (reg->type == REG_SFR || reg->type == REG_STK || (!mayBeGlobal && (reg->isPublic || reg->isExtern))) return 1;
373 return 0;
376 /*-----------------------------------------------------------------*
377 * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2)
379 * ADHOC pattern checking
380 * Now look for specific sequences that are easy to optimize.
381 * Many of these sequences are characteristic of the compiler
382 * (i.e. it'd probably be a waste of time to apply these adhoc
383 * checks to hand written assembly.)
386 *-----------------------------------------------------------------*/
387 static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, reg_info *reg, int can_free, int optimize_level)
389 pCode *pct1, *pct2;
390 reg_info *reg1, *reg2;
392 int t = total_registers_saved;
394 if (!isPCI(pc1) || !isPCI(pc2)) return 0;
395 if (PCI(pc1)->pcflow != PCI(pc2)->pcflow) return 0;
397 if (pc2->seq < pc1->seq) {
398 pct1 = pc2;
399 pc2 = pc1;
400 pc1 = pct1;
403 /* disable this optimization for now -- it's buggy */
404 if (pic14_options.disable_df) return 0;
406 //fprintf(stderr,"pCodeOptime2pCodes\n");
407 //pc1->print(stderr,pc1);
408 //pc2->print(stderr,pc2);
410 if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
412 * CLRF sets Z
413 * MOVFW affects Z
414 * MOVWF does not touch Z
415 * MOVLW does not touch Z
417 pCode *newpc;
419 clrf reg ; pc1
420 stuff...
421 movf reg,w ; pc2
423 can be replaced with (only if following instructions are not going to use W and reg is not used again later)
425 stuff...
426 movlw 0 or clrf reg
428 DFPRINTF((stderr, " optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n"));
429 pct2 = findNextInstruction(pc2->next);
430 if (pCodeSearchCondition(pct2, PCC_Z, 0) == -1) {
431 /* Z is definitely overwritten before use */
432 newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
434 pCodeInsertAfter(pc2, newpc);
435 PCI(newpc)->pcflow = PCFL(pcfl_used);
436 newpc->seq = pc2->seq;
438 //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF reg, ..., MOVF reg,W)\n", __FILE__, __LINE__, __FUNCTION__);
439 //Remove2pcodes(pcfl_used, pc2, NULL, reg, 0);
440 pc2->destruct(pc2);
441 //total_registers_saved++; // debugging stats.
443 } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
444 DFPRINTF((stderr, " optimising CLRF/IORFW\n"));
446 pct2 = findNextInstruction(pc2->next);
448 /* We must ensure that Z is destroyed before being read---IORLW must be performed unless this is proven. */
449 if (pCodeSearchCondition(pct2, PCC_Z, 0) != -1) {
450 pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
451 pct2->seq = pc2->seq;
452 PCI(pct2)->pcflow = PCFL(pcfl_used);
453 pCodeInsertAfter(pc1,pct2);
455 //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF/IORFW)\n", __FILE__, __LINE__, __FUNCTION__);
456 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
457 total_registers_saved++; // debugging stats.
459 } else if(PCI(pc1)->op == POC_MOVWF) {
460 // Optimising MOVWF reg ...
462 pct2 = findNextInstruction(pc2->next);
464 if(PCI(pc2)->op == POC_MOVFW) {
465 // Optimising MOVWF reg ... MOVF reg,W
467 if(PCI(pct2)->op == POC_MOVWF) {
469 Change:
471 movwf reg ; pc1
472 stuff...
473 movf reg,w ; pc2
474 movwf reg2 ; pct2
476 To: ( as long as 'stuff' does not use reg2 or if following instructions do not use W or reg is not used later)
478 movwf reg2
479 stuff...
482 reg2 = getRegFromInstruction(pct2);
483 /* Check reg2 is not used for something else before it is loaded with reg */
484 if (reg2 && !regIsSpecial (reg2, 1) && !regUsedinRange(pc1,pc2,reg2)) {
485 pCode *pct3 = findNextInstruction(pct2->next);
486 /* Check following instructions are not relying on the use of W or the Z flag condiction */
487 /* XXX: We must ensure that this value is destroyed before use---otherwise it might be used in
488 * subsequent flows (checking for < 1 is insufficient). */
489 if ((pCodeSearchCondition(pct3,PCC_Z,0) == -1) && (pCodeSearchCondition(pct3,PCC_W,0) == -1)) {
490 DFPRINTF((stderr, " optimising MOVF reg ... MOVF reg,W MOVWF reg2 to MOVWF reg2 ...\n"));
491 pct2->seq = pc1->seq;
492 unlinkpCode(pct2);
493 pCodeInsertBefore(pc1,pct2);
494 if(regUsedinRange(pct2,0,reg))
496 //fprintf (stderr, "%s:%d(%s): Remove2pcodes IF (MOVWF reg, ..., MOVW reg,W MOVWF reg2)\n", __FILE__, __LINE__, __FUNCTION__);
497 Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
498 } else {
499 //fprintf (stderr, "%s:%d(%s): Remove2pcodes ELSE (MOVWF reg, ..., MOVW reg,W MOVWF reg2)\n", __FILE__, __LINE__, __FUNCTION__);
500 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
502 total_registers_saved++; // debugging stats.
503 return 1;
509 pct1 = findPrevInstruction(pc1->prev);
510 if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
512 if ( (PCI(pct1)->op == POC_MOVFW) &&
513 (PCI(pc2)->op == POC_MOVFW)) {
515 reg1 = getRegFromInstruction(pct1);
516 if(reg1 && !regIsSpecial (reg1, 0) && !regUsedinRange(pc1,pc2,reg1)) {
517 DFPRINTF((stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
519 Change:
521 movf reg1,w
522 movwf reg
524 stuff...
525 movf reg,w
529 stuff...
531 movf reg1,w
533 Or, if we're not deleting the register then the "To" is:
535 stuff...
537 movf reg1,w
538 movwf reg
540 pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
541 pCodeInsertAfter(pc2, pct2);
542 PCI(pct2)->pcflow = PCFL(pcfl_used);
543 pct2->seq = pc2->seq;
545 if(can_free) {
546 //fprintf (stderr, "%s:%d(%s): Remove2pcodes CANFREE (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
547 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
548 } else {
549 /* If we're not freeing the register then that means (probably)
550 * the register is needed somewhere else.*/
551 unlinkpCode(pc1);
552 pCodeInsertAfter(pct2, pc1);
554 //fprintf (stderr, "%s:%d(%s): Remove2pcodes ELSE (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
555 Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
558 //fprintf (stderr, "%s:%d(%s): Remove2pcodes ALWAYS (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
559 Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
560 total_registers_saved++; // debugging stats.
567 return (total_registers_saved != t);
570 /*-----------------------------------------------------------------*
571 * void pCodeRegOptimeRegUsage(pBlock *pb)
572 *-----------------------------------------------------------------*/
573 static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
575 reg_info *reg;
576 int used;
577 pCode *pc1=NULL, *pc2=NULL;
580 while(fregs) {
581 pCode *pcfl_used, *pcfl_assigned;
583 /* Step through the set by directly accessing the 'next' pointer.
584 * We could also step through by using the set API, but the
585 * the (debug) calls to print instructions affect the state
586 * of the set pointers */
588 reg = fregs->item;
589 fregs = fregs->next;
591 if (strcmp(reg->name,"_SubState")==0)
592 fprintf(stderr,"Reg: %s\n",reg->name);
595 /* Catch inconsistently set-up live ranges
596 * (see tracker items #1469504 + #1474602)
597 * FIXME: Actually we should rather fix the
598 * computation of the liveranges instead...
600 if (!reg || !reg->reglives.usedpFlows
601 || !reg->reglives.assignedpFlows)
603 //fprintf( stderr, "skipping reg w/o liveranges: %s\n", reg ? reg->name : "(unknown)");
604 continue;
607 if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern|| reg->isFixed) {
608 //fprintf(stderr,"skipping SFR: %s\n",reg->name);
609 continue;
612 pcfl_used = setFirstItem(reg->reglives.usedpFlows);
613 pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
615 used = elementsInSet(reg->reglives.usedpCodes);
616 if(used == 2) {
618 In this section, all registers that are used in only in two
619 instructions are examined. If possible, they're optimized out.
623 fprintf (stderr, "OptimizeRegUsage: %s addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
624 reg->name,
625 reg->address,
626 reg->rIdx, reg->type, used);
628 pc1 = setFirstItem(reg->reglives.usedpCodes);
629 pc2 = setNextItem(reg->reglives.usedpCodes);
631 if(pcfl_used && pcfl_assigned) {
633 expected case - the register has been assigned a value and is
634 subsequently used
637 //fprintf(stderr," used only twice\n");
638 if(pcfl_used->seq == pcfl_assigned->seq) {
640 //fprintf(stderr, " and used in same flow\n");
642 pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
644 } else {
645 // fprintf(stderr, " and used in different flows\n");
649 } else if(pcfl_used) {
651 /* register has been used twice without ever being assigned */
652 fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
654 } else {
655 //fprintf(stderr,"WARNING %s.1: reg %s assigned without being used\n",__FUNCTION__,reg->name);
656 Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
657 total_registers_saved++; // debugging stats.
659 } else {
661 /* register has been used either once, or more than twice */
663 if(used && !pcfl_used && pcfl_assigned) {
664 pCode *pc;
666 //fprintf(stderr,"WARNING %s.2: reg %s assigned without being used\n",__FUNCTION__,reg->name);
668 pc = setFirstItem(reg->reglives.usedpCodes);
669 while(pc) {
671 pcfl_assigned = PCODE(PCI(pc)->pcflow);
672 Remove1pcode(pc, reg,2);
674 deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
676 deleteSetItem (&(reg->reglives.usedpCodes),pc);
677 pc->destruct(pc);
679 pc = setNextItem(reg->reglives.usedpCodes);
683 reg->isFree = TRUE;
684 reg->wasUsed = FALSE;
686 total_registers_saved++; // debugging stats.
687 } else if( (used > 2) && optimize_multi_uses) {
689 set *rset1=NULL;
690 set *rset2=NULL;
691 int searching=1;
693 pCodeFlow *pcfl1=NULL, *pcfl2=NULL;
695 /* examine the number of times this register is used */
698 rset1 = reg->reglives.usedpCodes;
699 while(rset1 && searching) {
701 pc1 = rset1->item;
702 rset2 = rset1->next;
704 if(pc1 && isPCI(pc1) && ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
706 if(rset2) {
708 pc2 = rset2->item;
709 if(pc2 && isPCI(pc2) && ( (pcfl2 = PCI(pc2)->pcflow) != NULL) ) {
710 if(pcfl2 == pcfl1) {
712 if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
713 searching = 0;
717 //rset2 = rset2->next;
721 rset1 = rset2;
728 /*-----------------------------------------------------------------*
729 * void pCodeRegOptimeRegUsage(pBlock *pb)
730 *-----------------------------------------------------------------*/
731 void pCodeRegOptimizeRegUsage(int level)
734 int passes;
735 int saved = 0;
736 int t = total_registers_saved;
738 #if 0
739 /* This is currently broken (need rewrite to correctly
740 * handle arbitrary pCodeOps instead of registers only). */
741 if (!pic14_options.disable_df)
742 optimizeDataflow ();
743 #endif
745 if(!register_optimization)
746 return;
747 #define OPT_PASSES 4
748 passes = OPT_PASSES;
750 do {
751 saved = total_registers_saved;
753 /* Identify registers used in one flow sequence */
754 OptimizeRegUsage(dynAllocRegs,level, (OPT_PASSES-passes));
755 OptimizeRegUsage(dynStackRegs,level, (OPT_PASSES-passes));
756 OptimizeRegUsage(dynDirectRegs,0, (OPT_PASSES-passes));
758 if(total_registers_saved != saved)
759 DFPRINTF((stderr, " *** pass %d, Saved %d registers, total saved %d ***\n",
760 (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved));
762 passes--;
764 } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
766 if(total_registers_saved == t)
767 DFPRINTF((stderr, "No registers saved on this pass\n"));
771 /*-----------------------------------------------------------------*
772 * void RegsUnMapLiveRanges(set *regset)
774 *-----------------------------------------------------------------*/
775 static void RegsSetUnMapLiveRanges(set *regset)
777 reg_info *reg;
779 while(regset) {
780 reg = regset->item;
781 regset = regset->next;
784 deleteSet(&reg->reglives.usedpCodes);
785 deleteSet(&reg->reglives.usedpFlows);
786 deleteSet(&reg->reglives.assignedpFlows);
792 void RegsUnMapLiveRanges(void)
795 RegsSetUnMapLiveRanges(dynAllocRegs);
796 RegsSetUnMapLiveRanges(dynStackRegs);
797 RegsSetUnMapLiveRanges(dynDirectRegs);
798 RegsSetUnMapLiveRanges(dynProcessorRegs);
799 RegsSetUnMapLiveRanges(dynDirectBitRegs);
800 RegsSetUnMapLiveRanges(dynInternalRegs);