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