* src/pic/device.c,
[fw/sdcc] / src / pic / pcoderegs.c
1 /*-------------------------------------------------------------------------
2
3    pcoderegs.c - post code generation register optimizations
4
5    Written By -  Scott Dattalo scott@dattalo.com
6
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.
11    
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.
16    
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.
20    
21 -------------------------------------------------------------------------*/
22
23 /*
24   pcoderegs.c
25
26   The purpose of the code in this file is to optimize the register usage.
27
28 */
29 #include <stdio.h>
30
31 #include "common.h"   // Include everything in the SDCC src directory
32 #include "newalloc.h"
33 #include "ralloc.h"
34 #include "device.h"
35 #include "pcode.h"
36 #include "pcoderegs.h"
37 #include "pcodeflow.h"
38
39 extern void dbg_dumpregusage(void);
40 extern pCode * findPrevInstruction(pCode *pci);
41 extern pBranch * pBranchAppend(pBranch *h, pBranch *n);
42 void unlinkpCode(pCode *pc);
43 extern int pCodeSearchCondition(pCode *pc, unsigned int cond);
44 char *pCode2str(char *str, int size, pCode *pc);
45 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...);
46 int total_registers_saved=0;
47 int register_optimization=1;
48
49 /*-----------------------------------------------------------------*
50  * void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
51  *-----------------------------------------------------------------*/
52 /*
53 void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
54 {
55
56   if(!reg || ! pcfl || !isPCFL(pcflow))
57     return;
58
59   if(!pcfl->registers) 
60     pcfl->registers =  newSet();
61
62 }
63 */
64
65
66 /*-----------------------------------------------------------------*
67  * 
68  *-----------------------------------------------------------------*/
69 void dbg_regusage(set *fregs)
70 {
71   regs *reg;
72   pCode *pcfl;
73   pCode *pc;
74
75
76   for (reg = setFirstItem(fregs) ; reg ;
77        reg = setNextItem(fregs)) {
78
79     if(elementsInSet(reg->reglives.usedpCodes)) {
80     
81       fprintf (stderr, "%s  addr=0x%03x rIdx=0x%03x",
82                reg->name,
83                reg->address,
84                reg->rIdx);
85
86       pcfl = setFirstItem(reg->reglives.usedpFlows);
87       if(pcfl)
88         fprintf(stderr, "\n   used in seq");
89
90       while(pcfl) {
91         fprintf(stderr," 0x%03x",pcfl->seq);
92         pcfl = setNextItem(reg->reglives.usedpFlows);
93       }
94
95       pcfl = setFirstItem(reg->reglives.assignedpFlows);
96       if(pcfl)
97         fprintf(stderr, "\n   assigned in seq");
98
99       while(pcfl) {
100         fprintf(stderr," 0x%03x",pcfl->seq);
101         pcfl = setNextItem(reg->reglives.assignedpFlows);
102       }
103
104       pc = setFirstItem(reg->reglives.usedpCodes);
105       if(pc)
106         fprintf(stderr, "\n   used in instructions ");
107
108       while(pc) {
109         pcfl = PCODE(PCI(pc)->pcflow);
110         if(pcfl)
111           fprintf(stderr," 0x%03x:",pcfl->seq);
112         fprintf(stderr,"0x%03x",pc->seq);
113
114         pc = setNextItem(reg->reglives.usedpCodes);
115       }
116
117       fprintf(stderr, "\n");
118     }
119   }
120 }
121
122 /*-----------------------------------------------------------------*
123  * 
124  *-----------------------------------------------------------------*/
125 void dbg_dumpregusage(void)
126 {
127
128   fprintf(stderr,"***  Register Usage  ***\n");
129   fprintf(stderr,"InternalRegs:\n");
130   dbg_regusage(dynInternalRegs);
131   fprintf(stderr,"AllocRegs:\n");
132   dbg_regusage(dynAllocRegs);
133   fprintf(stderr,"StackRegs:\n");
134   dbg_regusage(dynStackRegs);
135   fprintf(stderr,"DirectRegs:\n");
136   dbg_regusage(dynDirectRegs);
137   fprintf(stderr,"DirectBitRegs:\n");
138   dbg_regusage(dynDirectBitRegs);
139   fprintf(stderr,"ProcessorRegs:\n");
140   dbg_regusage(dynProcessorRegs);
141
142 }
143
144
145 /*-----------------------------------------------------------------*
146  * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
147  *-----------------------------------------------------------------*/
148 void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
149 {
150
151   pCode *pc=NULL;
152   pCode *pcprev=NULL;
153
154   regs *reg;
155
156   if(!pcfl)
157     return;
158
159
160   pc = findNextInstruction(pcfl->pc.next);
161
162   while(isPCinFlow(pc,PCODE(pcfl))) {
163
164
165     reg = getRegFromInstruction(pc);
166
167     if(reg) {
168 /*
169       fprintf(stderr, "flow seq %d, inst seq %d  %s  ",PCODE(pcfl)->seq,pc->seq,reg->name);
170       fprintf(stderr, "addr = 0x%03x, type = %d  rIdx=0x%03x\n",
171               reg->address,reg->type,reg->rIdx);
172 */
173
174       addSetIfnotP(& (PCFL(pcfl)->registers), reg);
175
176       if((PCC_REGISTER | PCC_LITERAL) & PCI(pc)->inCond)
177         addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
178
179       if(PCC_REGISTER & PCI(pc)->outCond)
180         addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl);
181
182       addSetIfnotP(& (reg->reglives.usedpCodes), pc);
183     }
184
185
186     pcprev = pc;
187     pc = findNextInstruction(pc->next);
188
189   }
190
191 }
192
193 /*-----------------------------------------------------------------*
194  * void pCodeRegMapLiveRanges(pBlock *pb) 
195  *-----------------------------------------------------------------*/
196 void pCodeRegMapLiveRanges(pBlock *pb)
197 {
198   pCode *pcflow;
199
200   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
201        pcflow != NULL;
202        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
203
204     if(!isPCFL(pcflow)) {
205       fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
206       continue;
207     }
208     pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
209   }
210
211 #if 0
212   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
213        pcflow != NULL;
214        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
215
216     regs *r = setFirstItem(PCFL(pcflow)->registers);
217     fprintf(stderr,"flow seq %d\n", pcflow->seq);
218
219     while (r) {
220       fprintf(stderr, "  %s\n",r->name);
221       r = setNextItem(PCFL(pcflow)->registers);
222
223     }
224
225   }
226 #endif
227
228 //  dbg_dumpregusage();
229
230 }
231
232
233 /*-----------------------------------------------------------------*
234  *
235  *-----------------------------------------------------------------*/
236 static void Remove1pcode(pCode *pc, regs *reg, int debug_code)
237 {
238
239   pCode *pcn=NULL;
240
241   if(!reg || !pc)
242     return;
243
244   deleteSetItem (&(reg->reglives.usedpCodes),pc);
245
246   if(PCI(pc)->label) {
247     pcn = findNextInstruction(pc->next);
248
249     if(pcn)
250       PCI(pcn)->label = pBranchAppend(PCI(pcn)->label,PCI(pc)->label);
251   }
252
253   if(PCI(pc)->cline) {
254     if(!pcn)
255       pcn = findNextInstruction(pc->next);
256
257     if(pcn) {
258       if(PCI(pcn)->cline) {
259         //fprintf(stderr, "source line has been optimized completely out\n");
260         //pc->print(stderr,pc);
261       } else {
262         PCI(pcn)->cline = PCI(pc)->cline;
263       }
264     }
265   }
266
267
268   if(1){
269     /*
270       Debug stuff. Comment out the instruction we're about to delete.
271     */
272
273     char buff1[256];
274     size_t size = 256;
275
276     char *pbuff,**ppbuff;
277     pbuff = buff1;
278     ppbuff = &pbuff;
279
280     SAFE_snprintf(ppbuff,&size, ";%d", debug_code);
281     pCode2str(*ppbuff, size, pc);
282     pCodeInsertBefore(pc, newpCodeCharP(buff1));
283     //fprintf(stderr,"removing instruction:\n%s\n",buff1);
284   }
285
286   pc->destruct(pc);
287
288 }
289
290 /*-----------------------------------------------------------------*
291  * void RemoveRegsFromSet(set *regset)
292  *
293  *-----------------------------------------------------------------*/
294 void  RemoveRegsFromSet(set *regset)
295 {
296   regs *reg;
297   int used;
298
299   while(regset) {
300     reg = regset->item;
301     regset = regset->next;
302
303     used = elementsInSet(reg->reglives.usedpCodes);
304
305     if(used <= 1) {
306
307       //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);
308       if(used == 0) {
309         //fprintf(stderr," getting rid of reg %s\n",reg->name);
310         reg->isFree = 1;
311         reg->wasUsed = 0;
312       } else {
313         pCode *pc;
314
315
316         pc = setFirstItem(reg->reglives.usedpCodes);
317
318     if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern) {
319           //fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name);
320           continue;
321         }
322
323
324         if(isPCI(pc)) {
325           if(PCI(pc)->label) {
326             pCode *pcn = findNextInstruction(pc->next);
327
328             if(pcn && PCI(pcn)->label) {
329               //fprintf(stderr,"can't delete instruction with label...\n");
330               //pc->print(stderr,pc);
331               continue;
332             } 
333             /* Move the label to the next instruction */
334
335             PCI(pcn)->label = PCI(pc)->label;
336
337           }
338
339           if(isPCI_SKIP(pc)) {
340             regs *r = getRegFromInstruction(pc);
341             fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
342             pc->print(stderr,pc);
343             fprintf(stderr,"reg %s, type =%d\n",r->name, r->type);
344           }
345           //fprintf(stderr," removing reg %s because it is used only once\n",reg->name);
346           Remove1pcode(pc, reg, 1);
347           /*
348             unlinkpCode(pc);
349             deleteSetItem (&(reg->reglives.usedpCodes),pc);
350           */
351           reg->isFree = 1;
352           reg->wasUsed = 0;
353           total_registers_saved++;  // debugging stats.
354         }
355       }
356     }
357
358   }
359 }
360 /*-----------------------------------------------------------------*
361  * void RemoveUnusedRegisters(void)
362  *
363  *-----------------------------------------------------------------*/
364 void RemoveUnusedRegisters(void)
365 {
366   /* First, get rid of registers that are used only one time */
367
368   //RemoveRegsFromSet(dynInternalRegs);
369   RemoveRegsFromSet(dynAllocRegs);
370   RemoveRegsFromSet(dynStackRegs);
371   /*
372     don't do DirectRegs yet - there's a problem with arrays
373   RemoveRegsFromSet(dynDirectRegs);
374   */
375   RemoveRegsFromSet(dynDirectBitRegs);
376
377   if(total_registers_saved) DFPRINTF((stderr, " *** Saved %d registers ***\n", total_registers_saved));
378 }
379
380
381 /*-----------------------------------------------------------------*
382  *
383  *-----------------------------------------------------------------*/
384 static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, regs *reg, int can_free)
385 {
386   static int debug_code=99;
387   if(!reg)
388     return;
389
390   //fprintf(stderr,"%s\n",__FUNCTION__);
391   if(pc1)
392     Remove1pcode(pc1, reg, debug_code++);
393
394   if(pc2) {
395     Remove1pcode(pc2, reg, debug_code++);
396     deleteSetItem (&(PCFL(pcflow)->registers), reg);
397
398     if(can_free) {
399       reg->isFree = 1;
400       reg->wasUsed = 0;
401     }
402
403   }
404
405   pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
406 }
407
408 /*-----------------------------------------------------------------*
409  *
410  *-----------------------------------------------------------------*/
411 int regUsedinRange(pCode *pc1, pCode *pc2, regs *reg)
412 {
413   int i=0;
414   regs *testreg;
415
416   do {
417     testreg = getRegFromInstruction(pc1);
418     if(testreg && (testreg->rIdx == reg->rIdx)) {
419       return 1;
420     }
421
422     pc1 = findNextInstruction(pc1->next);
423
424   } while (pc1 && (pc1 != pc2) && (i++ < 100)) ;
425
426   if(i >= 100)
427     fprintf(stderr, "warning, regUsedinRange searched through too many pcodes\n");
428
429   return 0;
430 }
431
432 /*-----------------------------------------------------------------*
433  * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2) 
434  *
435  * ADHOC pattern checking 
436  * Now look for specific sequences that are easy to optimize.
437  * Many of these sequences are characteristic of the compiler
438  * (i.e. it'd probably be a waste of time to apply these adhoc
439  * checks to hand written assembly.)
440  * 
441  *
442  *-----------------------------------------------------------------*/
443 int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level)
444 {
445   pCode *pct1, *pct2;
446   regs  *reg1, *reg2;
447
448   int t = total_registers_saved;
449
450   if(pc2->seq < pc1->seq) {
451     pct1 = pc2;
452     pc2 = pc1;
453     pc1 = pct1;
454   }
455
456   //fprintf(stderr,"pCodeOptime2pCodes\n");
457   //pc1->print(stderr,pc1);
458   //pc2->print(stderr,pc2);
459
460   if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
461     pCode *pc;
462     int regUsed = 0;
463     int wUsed   = 0;
464     int wSaved  = 0;
465     int wChgd   = 0;
466
467     /*
468       clrf  reg
469       stuff...
470       movf  reg,w
471
472       can be replaced with (only if next instructions are not going to use W and reg is not used again later)
473
474       stuff...
475       movlw 0 or clrf  reg
476     */
477
478     pCode *newpc;
479     DFPRINTF((stderr, "   optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n"));
480     pct1 = pc = findNextInstruction(pc2->next);
481
482     if(PCI(pct1)->op == POC_MOVWF) {
483       wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */
484       pc = findNextInstruction(pc->next);
485     }
486     for (; pc; pc = findNextInstruction(pc->next)) {
487       if (isPCI(pc)) {
488         regs *r;
489         if (!wChgd) {
490           if (PCI(pc)->inCond & PCC_W)
491             wUsed = 1;
492           if (PCI(pc)->outCond & PCC_W) {
493             pCode *pcp = findPrevInstruction(pc);
494             if (pcp && !isPCI_SKIP(pcp)) {
495               wChgd = 1; /* W has changed so we no longer care if it is used, however if there is a preceding skip instruction then maybe current W is still going to be used */
496             if (regUsed)
497               break;
498             }
499           }
500         }
501         r = getRegFromInstruction(pc); /* Check if reg is used later. */
502         if (r && (r->rIdx==reg->rIdx)) {
503           if (!(PCI(pc)->outCond & PCC_REGISTER))
504             regUsed = 1;
505           if (wChgd)
506             break;
507         }
508       }
509     }
510     if(regUsed&&wUsed) {
511       /* Do not optimise as exisiting code is required. */
512     } else {
513       /* Can optimise. */
514       if(regUsed) {
515         newpc = newpCode(POC_CLRF, PCI(pc1)->pcop);
516       } else if(wSaved && !wUsed) {
517         newpc = newpCode(POC_CLRF, PCI(pct1)->pcop);
518         pct1->destruct(pct1);
519       } else {
520         newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
521       }
522
523       pCodeInsertAfter(pc2, newpc);
524       PCI(newpc)->pcflow = PCFL(pcfl_used);
525       newpc->seq = pc2->seq;
526
527       Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
528       total_registers_saved++;  // debugging stats.
529     }
530   } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
531     DFPRINTF((stderr, "   optimising CLRF/IORFW\n"));
532
533     pct2 = findNextInstruction(pc2->next);
534
535     if(pCodeSearchCondition(pct2, PCC_Z) > 0) {
536       pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
537       pct2->seq = pc2->seq;
538       PCI(pct2)->pcflow = PCFL(pcfl_used);
539       pCodeInsertAfter(pc1,pct2);
540     }
541     Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
542     total_registers_saved++;  // debugging stats.
543
544   }  else if(PCI(pc1)->op == POC_MOVWF) {
545     // Optimising MOVWF reg ...
546
547     pct2 = findNextInstruction(pc2->next);
548
549     if(PCI(pc2)->op == POC_MOVFW) {
550       // Optimising MOVWF reg ... MOVF reg,W
551
552       if(PCI(pct2)->op == POC_MOVWF) {
553         /*
554         Change:
555
556         movwf   reg
557
558         stuff...
559
560         movf    reg,w
561         movwf   reg2
562
563         To:
564
565
566         */
567         reg2 = getRegFromInstruction(pct2);
568         if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
569
570           if(pCodeSearchCondition(pct2, PCC_Z) < 1) {
571             pCode *pct3 = findNextInstruction(pct2->next);
572             DFPRINTF((stderr, "   optimising MOVF reg ... MOVF reg,W MOVWF reg2\n"));
573             pct2->seq = pc1->seq;
574             unlinkpCode(pct2);
575             pCodeInsertAfter(findPrevInstruction(pc1->prev),pct2);
576
577 #define usesW(x)       ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0))
578
579             if(usesW(pct3))
580               ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free);
581             else
582               Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
583
584             total_registers_saved++;  // debugging stats.
585             return 1;
586             } else {
587               //fprintf(stderr,"didn't optimize because Z bit is used\n");
588             }
589         }
590 /*
591         fprintf(stderr, " couldn't optimize\n");
592         if(reg2)
593           fprintf(stderr, " %s is used in range\n",reg2->name);
594         else
595           fprintf(stderr, " reg2 is NULL\n");
596 */
597       }
598     }
599
600     pct1 = findPrevInstruction(pc1->prev);
601     if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
602
603       if ( (PCI(pct1)->op == POC_MOVFW) &&
604            (PCI(pc2)->op == POC_MOVFW)) {
605
606         reg1 = getRegFromInstruction(pct1);
607         if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
608           DFPRINTF((stderr, "   optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
609           /*
610             Change:
611
612             movf   reg1,w
613             movwf  reg
614
615             stuff...
616             movf   reg,w
617
618             To:
619
620             stuff...
621
622             movf   reg1,w
623
624             Or, if we're not deleting the register then the "To" is:
625
626             stuff...
627
628             movf   reg1,w
629             movwf  reg
630           */
631           pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
632           pCodeInsertAfter(pc2, pct2);
633           PCI(pct2)->pcflow = PCFL(pcfl_used);
634           pct2->seq = pc2->seq;
635
636           if(can_free) {
637             Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
638           } else {
639             /* If we're not freeing the register then that means (probably)
640              * the register is needed somewhere else.*/
641             unlinkpCode(pc1);
642             pCodeInsertAfter(pct2, pc1);
643
644             Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
645           }
646
647           Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
648           total_registers_saved++;  // debugging stats.
649
650         }
651 /* Note this else if is same conditional as the if - DELETE ME 
652       } else if ( (PCI(pct1)->op == POC_MOVWF) &&
653            (PCI(pc2)->op == POC_MOVFW)) {
654         DFPRINTF(stderr, "   optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n");
655         if(optimize_level > 1 && can_free) {
656           pct2 = newpCode(POC_MOVFW, PCI(pc1)->pcop);
657           pCodeInsertAfter(pc2, pct2);
658           Remove2pcodes(pcfl_used, pc1, pc2, reg, 1);
659           total_registers_saved++;  // debugging stats.
660         }
661 */
662       }
663     }
664   }
665
666   return (total_registers_saved != t);
667 }
668
669 /*-----------------------------------------------------------------*
670  * void pCodeRegOptimeRegUsage(pBlock *pb) 
671  *-----------------------------------------------------------------*/
672 void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
673 {
674   regs *reg;
675   int used;
676   pCode *pc1=NULL, *pc2=NULL;
677
678
679   while(fregs) {
680     pCode *pcfl_used, *pcfl_assigned;
681
682     /* Step through the set by directly accessing the 'next' pointer.
683      * We could also step through by using the set API, but the 
684      * the (debug) calls to print instructions affect the state
685      * of the set pointers */
686
687     reg = fregs->item;
688     fregs = fregs->next;
689 /*
690 if (strcmp(reg->name,"_SubState")==0)
691      fprintf(stderr,"Reg: %s\n",reg->name);
692 */
693
694     if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern|| reg->isFixed) {
695       //fprintf(stderr,"skipping SFR: %s\n",reg->name);
696       continue;
697     }
698
699     pcfl_used = setFirstItem(reg->reglives.usedpFlows);
700     pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
701
702     used = elementsInSet(reg->reglives.usedpCodes);
703     if(used == 2) { 
704
705       /*
706        * In this section, all registers that are used in only in two 
707        * instructions are examined. If possible, they're optimized out.
708        */
709
710 /*
711       fprintf (stderr, "OptimizeRegUsage: %s  addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
712                reg->name,
713                reg->address,
714                reg->rIdx, reg->type, used);
715 */
716       pc1 = setFirstItem(reg->reglives.usedpCodes);
717       pc2 = setNextItem(reg->reglives.usedpCodes);
718
719       if(pcfl_used && pcfl_assigned) {
720
721         /* 
722            expected case - the register has been assigned a value and is
723            subsequently used 
724         */
725
726         //fprintf(stderr," used only twice\n");
727         if(pcfl_used->seq == pcfl_assigned->seq) {
728
729           //fprintf(stderr, "  and used in same flow\n");
730
731           pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
732
733         } else {
734           // fprintf(stderr, "  and used in different flows\n");
735
736         }
737
738       } else if(pcfl_used) {
739
740         /*
741           register has been used twice without ever being assigned */
742         fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
743
744       } else {
745         fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
746         Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
747         total_registers_saved++;  // debugging stats.
748       }
749     } else {
750
751       /* register has been used either once, or more than twice */
752
753       if(used && !pcfl_used && pcfl_assigned) {
754         pCode *pc;
755
756         fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
757
758         pc = setFirstItem(reg->reglives.usedpCodes);
759         while(pc) {
760
761           pcfl_assigned = PCODE(PCI(pc)->pcflow);
762           Remove1pcode(pc, reg,2);
763
764           deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
765           /*
766           deleteSetItem (&(reg->reglives.usedpCodes),pc);
767           pc->destruct(pc);
768           */
769           pc = setNextItem(reg->reglives.usedpCodes);
770         }
771
772
773         reg->isFree = 1;
774         reg->wasUsed = 0;
775
776         total_registers_saved++;  // debugging stats.
777       } else if( (used > 2) && optimize_multi_uses) {
778
779         set *rset1=NULL;
780         set *rset2=NULL;
781         int searching=1;
782
783         pCodeFlow *pcfl1=NULL, *pcfl2=NULL;
784
785         /* examine the number of times this register is used */
786
787
788         rset1 = reg->reglives.usedpCodes;
789         while(rset1 && searching) {
790
791           pc1 = rset1->item;
792           rset2 = rset1->next;
793
794           if(pc1 && isPCI(pc1) &&  ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
795
796             //while(rset2 && searching) {
797             if(rset2) {
798
799               pc2 = rset2->item;
800               if(pc2 && isPCI(pc2)  &&  ( (pcfl2 = PCI(pc2)->pcflow) != NULL) )  {
801                 if(pcfl2 == pcfl1) {
802
803                   if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
804                     searching = 0;
805                 }
806               }
807
808               //rset2 = rset2->next;
809               
810             }
811           }
812           rset1 = rset1->next;
813         }
814       }
815     }
816
817   }
818
819 }
820 /*-----------------------------------------------------------------*
821  * void pCodeRegOptimeRegUsage(pBlock *pb) 
822  *-----------------------------------------------------------------*/
823 void pCodeRegOptimizeRegUsage(int level)
824 {
825
826   int passes;
827   int saved = 0;
828   int t = total_registers_saved;
829
830   if(!register_optimization)
831     return;
832 #define OPT_PASSES 4
833   passes = OPT_PASSES;
834
835   do {
836     saved = total_registers_saved;
837
838     /* Identify registers used in one flow sequence */
839     OptimizeRegUsage(dynAllocRegs,level, (OPT_PASSES-passes));
840     OptimizeRegUsage(dynStackRegs,level, (OPT_PASSES-passes));
841     OptimizeRegUsage(dynDirectRegs,0, (OPT_PASSES-passes));
842
843     if(total_registers_saved != saved)
844       DFPRINTF((stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", 
845               (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved));
846       
847     passes--;
848
849   } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
850
851   if(total_registers_saved == t) 
852     DFPRINTF((stderr, "No registers saved on this pass\n"));
853
854
855 /*
856   fprintf(stderr,"dynamically allocated regs:\n");
857   dbg_regusage(dynAllocRegs);
858   fprintf(stderr,"stack regs:\n");
859   dbg_regusage(dynStackRegs);
860   fprintf(stderr,"direct regs:\n");
861   dbg_regusage(dynDirectRegs);
862 */
863 }
864
865
866 /*-----------------------------------------------------------------*
867  * void RegsUnMapLiveRanges(set *regset)
868  *
869  *-----------------------------------------------------------------*/
870 void  RegsSetUnMapLiveRanges(set *regset)
871 {
872   regs *reg;
873
874   while(regset) {
875     reg = regset->item;
876     regset = regset->next;
877
878     
879     deleteSet(&reg->reglives.usedpCodes);
880     deleteSet(&reg->reglives.usedpFlows);
881     deleteSet(&reg->reglives.assignedpFlows);
882
883   }
884
885 }
886
887 void  RegsUnMapLiveRanges(void)
888 {
889
890   RegsSetUnMapLiveRanges(dynAllocRegs);
891   RegsSetUnMapLiveRanges(dynStackRegs);
892   RegsSetUnMapLiveRanges(dynDirectRegs);
893   RegsSetUnMapLiveRanges(dynProcessorRegs);
894   RegsSetUnMapLiveRanges(dynDirectBitRegs);
895   RegsSetUnMapLiveRanges(dynInternalRegs);
896
897 }