Tidied up tabs.
[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, int contIfSkip);
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 *newpc;
462                 int regUsed = 0;
463                 int wUsed   = 0;
464                 int wSaved  = 0;
465                 /*
466                 clrf  reg    ; pc1
467                 stuff...
468                 movf  reg,w  ; pc2
469                 
470                   can be replaced with (only if following instructions are not going to use W and reg is not used again later)
471                   
472                         stuff...
473                         movlw 0 or clrf  reg
474                 */
475                 DFPRINTF((stderr, "   optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n"));
476                 pct2 = findNextInstruction(pc2->next);
477                 
478                 if(pct2 && PCI(pct2)->op == POC_MOVWF) {
479                         wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */
480                 } else {
481                         wUsed = pCodeSearchCondition(pct2,PCC_W,1) > 0;
482                 }
483                 regUsed = regUsedinRange(pct2,0,reg);
484                 if ((regUsed&&wUsed) || (pCodeSearchCondition(pct2,PCC_Z,0) > 1)) {
485                         /* Do not optimise as exisiting code is required. */
486                 } else {
487                         /* Can optimise. */
488                         if(regUsed) {
489                                 newpc = newpCode(POC_CLRF, PCI(pc1)->pcop);
490                         } else if(wSaved && !wUsed) {
491                                 newpc = newpCode(POC_CLRF, PCI(pct2)->pcop);
492                                 pct2->destruct(pct2);
493                         } else {
494                                 newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
495                         }
496                         
497                         pCodeInsertAfter(pc2, newpc);
498                         PCI(newpc)->pcflow = PCFL(pcfl_used);
499                         newpc->seq = pc2->seq;
500                         
501                         Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
502                         total_registers_saved++;  // debugging stats.
503                 }
504         } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
505                 DFPRINTF((stderr, "   optimising CLRF/IORFW\n"));
506                 
507                 pct2 = findNextInstruction(pc2->next);
508                 
509                 if(pCodeSearchCondition(pct2, PCC_Z,0) > 0) {
510                         pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
511                         pct2->seq = pc2->seq;
512                         PCI(pct2)->pcflow = PCFL(pcfl_used);
513                         pCodeInsertAfter(pc1,pct2);
514                 }
515                 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
516                 total_registers_saved++;  // debugging stats.
517                 
518         }  else if(PCI(pc1)->op == POC_MOVWF) {
519                 // Optimising MOVWF reg ...
520                 
521                 pct2 = findNextInstruction(pc2->next);
522                 
523                 if(PCI(pc2)->op == POC_MOVFW) {
524                         // Optimising MOVWF reg ... MOVF reg,W
525                         
526                         if(PCI(pct2)->op == POC_MOVWF) {
527                         /*
528                         Change:
529                         
530                           movwf   reg    ; pc1
531                           stuff...
532                           movf    reg,w  ; pc2
533                           movwf   reg2   ; pct2
534                           
535                                 To: ( as long as 'stuff' does not use reg2 or if following instructions do not use W or reg is not used later)
536                                 
537                                   movwf   reg2
538                                   stuff...
539                                   
540                                 */
541                                 reg2 = getRegFromInstruction(pct2);
542                                 /* Check reg2 is not used for something else before it is loaded with reg */
543                                 if (reg2 && !regUsedinRange(pc1,pc2,reg2)) {
544                                         pCode *pct3 = findNextInstruction(pct2->next);
545                                         /* Check following instructions are not relying on the use of W or the Z flag condiction */
546                                         if ((pCodeSearchCondition(pct3,PCC_Z,0) < 1) || (pCodeSearchCondition(pct3,PCC_W,0) < 1)) {
547                                                 DFPRINTF((stderr, "   optimising MOVF reg ... MOVF reg,W MOVWF reg2 to MOVWF reg2 ...\n"));
548                                                 pct2->seq = pc1->seq;
549                                                 unlinkpCode(pct2);
550                                                 pCodeInsertBefore(pc1,pct2);
551                                                 if(regUsedinRange(pct2,0,reg))
552                                                         Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
553                                                 else
554                                                         Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
555                                                 
556                                                 total_registers_saved++;  // debugging stats.
557                                                 return 1;
558                                         }
559                                 }
560                         }
561                 }
562                 
563                 pct1 = findPrevInstruction(pc1->prev);
564                 if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
565                         
566                         if ( (PCI(pct1)->op == POC_MOVFW) &&
567                                 (PCI(pc2)->op == POC_MOVFW)) {
568                                 
569                                 reg1 = getRegFromInstruction(pct1);
570                                 if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
571                                         DFPRINTF((stderr, "   optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
572                                         /*
573                                         Change:
574                                         
575                                                 movf   reg1,w
576                                                 movwf  reg
577
578                                                 stuff...
579                                                 movf   reg,w
580                                                 
581                                         To:
582
583                                                 stuff...
584
585                                                 movf   reg1,w
586
587                                         Or, if we're not deleting the register then the "To" is:
588
589                                                 stuff...
590
591                                                 movf   reg1,w
592                                                 movwf  reg
593                                         */
594                                         pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
595                                         pCodeInsertAfter(pc2, pct2);
596                                         PCI(pct2)->pcflow = PCFL(pcfl_used);
597                                         pct2->seq = pc2->seq;
598                                         
599                                         if(can_free) {
600                                                 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
601                                         } else {
602                                         /* If we're not freeing the register then that means (probably)
603                                                 * the register is needed somewhere else.*/
604                                                 unlinkpCode(pc1);
605                                                 pCodeInsertAfter(pct2, pc1);
606                                                 
607                                                 Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
608                                         }
609                                         
610                                         Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
611                                         total_registers_saved++;  // debugging stats.
612                                         
613                                 }
614                                 /* Note this else if is same conditional as the if - DELETE ME 
615                                 } else if ( (PCI(pct1)->op == POC_MOVWF) &&
616                                         (PCI(pc2)->op == POC_MOVFW)) {
617                                         DFPRINTF(stderr, "   optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n");
618                                         if(optimize_level > 1 && can_free) {
619                                                 pct2 = newpCode(POC_MOVFW, PCI(pc1)->pcop);
620                                                 pCodeInsertAfter(pc2, pct2);
621                                                 Remove2pcodes(pcfl_used, pc1, pc2, reg, 1);
622                                         total_registers_saved++;  // debugging stats.
623                                 }
624                                 */
625                         }
626                 }
627   }
628
629   return (total_registers_saved != t);
630 }
631
632 /*-----------------------------------------------------------------*
633 * void pCodeRegOptimeRegUsage(pBlock *pb) 
634 *-----------------------------------------------------------------*/
635 void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
636 {
637         regs *reg;
638         int used;
639         pCode *pc1=NULL, *pc2=NULL;
640         
641         
642         while(fregs) {
643                 pCode *pcfl_used, *pcfl_assigned;
644                 
645                 /* Step through the set by directly accessing the 'next' pointer.
646                 * We could also step through by using the set API, but the 
647                 * the (debug) calls to print instructions affect the state
648                 * of the set pointers */
649                 
650                 reg = fregs->item;
651                 fregs = fregs->next;
652                 /*
653                 if (strcmp(reg->name,"_SubState")==0)
654                 fprintf(stderr,"Reg: %s\n",reg->name);
655                 */
656                 
657                 if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern|| reg->isFixed) {
658                         //fprintf(stderr,"skipping SFR: %s\n",reg->name);
659                         continue;
660                 }
661                 
662                 pcfl_used = setFirstItem(reg->reglives.usedpFlows);
663                 pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
664                 
665                 used = elementsInSet(reg->reglives.usedpCodes);
666                 if(used == 2) { 
667                         /*
668                         In this section, all registers that are used in only in two 
669                         instructions are examined. If possible, they're optimized out.
670                         */
671                         
672                         /*
673                         fprintf (stderr, "OptimizeRegUsage: %s  addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
674                         reg->name,
675                         reg->address,
676                         reg->rIdx, reg->type, used);
677                         */
678                         pc1 = setFirstItem(reg->reglives.usedpCodes);
679                         pc2 = setNextItem(reg->reglives.usedpCodes);
680                         
681                         if(pcfl_used && pcfl_assigned) {
682                                 /* 
683                                 expected case - the register has been assigned a value and is
684                                 subsequently used 
685                                 */
686                                 
687                                 //fprintf(stderr," used only twice\n");
688                                 if(pcfl_used->seq == pcfl_assigned->seq) {
689                                         
690                                         //fprintf(stderr, "  and used in same flow\n");
691                                         
692                                         pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
693                                         
694                                 } else {
695                                         // fprintf(stderr, "  and used in different flows\n");
696                                         
697                                 }
698                                 
699                         } else if(pcfl_used) {
700                                 
701                                 /* register has been used twice without ever being assigned */
702                                 fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
703                                 
704                         } else {
705                                 fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
706                                 Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
707                                 total_registers_saved++;  // debugging stats.
708                         }
709                 } else {
710                         
711                         /* register has been used either once, or more than twice */
712                         
713                         if(used && !pcfl_used && pcfl_assigned) {
714                                 pCode *pc;
715                                 
716                                 fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
717                                 
718                                 pc = setFirstItem(reg->reglives.usedpCodes);
719                                 while(pc) {
720                                         
721                                         pcfl_assigned = PCODE(PCI(pc)->pcflow);
722                                         Remove1pcode(pc, reg,2);
723                                         
724                                         deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
725                                         /*
726                                         deleteSetItem (&(reg->reglives.usedpCodes),pc);
727                                         pc->destruct(pc);
728                                         */
729                                         pc = setNextItem(reg->reglives.usedpCodes);
730                                 }
731                                 
732                                 
733                                 reg->isFree = 1;
734                                 reg->wasUsed = 0;
735                                 
736                                 total_registers_saved++;  // debugging stats.
737                         } else if( (used > 2) && optimize_multi_uses) {
738                                 
739                                 set *rset1=NULL;
740                                 set *rset2=NULL;
741                                 int searching=1;
742                                 
743                                 pCodeFlow *pcfl1=NULL, *pcfl2=NULL;
744                                 
745                                 /* examine the number of times this register is used */
746                                 
747                                 
748                                 rset1 = reg->reglives.usedpCodes;
749                                 while(rset1 && searching) {
750                                         
751                                         pc1 = rset1->item;
752                                         rset2 = rset1->next;
753                                         
754                                         if(pc1 && isPCI(pc1) &&  ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
755                                                 
756                                                 //while(rset2 && searching) {
757                                                 if(rset2) {
758                                                         
759                                                         pc2 = rset2->item;
760                                                         if(pc2 && isPCI(pc2)  &&  ( (pcfl2 = PCI(pc2)->pcflow) != NULL) )  {
761                                                                 if(pcfl2 == pcfl1) {
762                                                                         
763                                                                         if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
764                                                                                 searching = 0;
765                                                                 }
766                                                         }
767                                                         
768                                                         //rset2 = rset2->next;
769                                                         
770                                                 }
771                                         }
772                                         rset1 = rset1->next;
773                                 }
774                         }
775                 }
776         }
777 }
778
779 /*-----------------------------------------------------------------*
780 * void pCodeRegOptimeRegUsage(pBlock *pb) 
781 *-----------------------------------------------------------------*/
782 void pCodeRegOptimizeRegUsage(int level)
783 {
784         
785         int passes;
786         int saved = 0;
787         int t = total_registers_saved;
788         
789         if(!register_optimization)
790                 return;
791 #define OPT_PASSES 4
792         passes = OPT_PASSES;
793         
794         do {
795                 saved = total_registers_saved;
796                 
797                 /* Identify registers used in one flow sequence */
798                 OptimizeRegUsage(dynAllocRegs,level, (OPT_PASSES-passes));
799                 OptimizeRegUsage(dynStackRegs,level, (OPT_PASSES-passes));
800                 OptimizeRegUsage(dynDirectRegs,0, (OPT_PASSES-passes));
801                 
802                 if(total_registers_saved != saved)
803                         DFPRINTF((stderr, " *** pass %d, Saved %d registers, total saved %d ***\n", 
804                         (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved));
805                 
806                 passes--;
807                 
808         } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
809         
810         if(total_registers_saved == t) 
811                 DFPRINTF((stderr, "No registers saved on this pass\n"));
812
813
814         /*
815                 fprintf(stderr,"dynamically allocated regs:\n");
816                 dbg_regusage(dynAllocRegs);
817                 fprintf(stderr,"stack regs:\n");
818                 dbg_regusage(dynStackRegs);
819                 fprintf(stderr,"direct regs:\n");
820                 dbg_regusage(dynDirectRegs);
821         */
822 }
823
824
825 /*-----------------------------------------------------------------*
826 * void RegsUnMapLiveRanges(set *regset)
827 *
828 *-----------------------------------------------------------------*/
829 void  RegsSetUnMapLiveRanges(set *regset)
830 {
831         regs *reg;
832         
833         while(regset) {
834                 reg = regset->item;
835                 regset = regset->next;
836                 
837                 
838                 deleteSet(&reg->reglives.usedpCodes);
839                 deleteSet(&reg->reglives.usedpFlows);
840                 deleteSet(&reg->reglives.assignedpFlows);
841                 
842         }
843         
844 }
845
846 void  RegsUnMapLiveRanges(void)
847 {
848         
849         RegsSetUnMapLiveRanges(dynAllocRegs);
850         RegsSetUnMapLiveRanges(dynStackRegs);
851         RegsSetUnMapLiveRanges(dynDirectRegs);
852         RegsSetUnMapLiveRanges(dynProcessorRegs);
853         RegsSetUnMapLiveRanges(dynDirectBitRegs);
854         RegsSetUnMapLiveRanges(dynInternalRegs);
855         
856 }