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
30 #include "main.h"
31 #include "pcoderegs.h"
32 #include "pcodeflow.h"
33 #include "ralloc.h"
34
35
36 static int total_registers_saved=0;
37 static int register_optimization=1;
38
39 /*-----------------------------------------------------------------*
40 * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
41 *-----------------------------------------------------------------*/
pCodeRegMapLiveRangesInFlow(pCodeFlow * pcfl)42 static void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
43 {
44
45 pCode *pc=NULL;
46
47 reg_info *reg;
48
49 if(!pcfl)
50 return;
51
52
53 pc = findNextInstruction(pcfl->pc.next);
54
55 while(pc && !isPCFL(pc)) {
56 while (pc && !isPCI(pc) && !isPCFL(pc))
57 {
58 pc = pc->next;
59 } // while
60 if (!pc || isPCFL(pc)) continue;
61 assert( isPCI(pc) );
62
63 reg = getRegFromInstruction(pc);
64 #if 0
65 pc->print(stderr, pc);
66 fprintf( stderr, "--> reg %p (%s,%u), inCond/outCond: %x/%x\n",
67 reg, reg ? reg->name : "(null)", reg ? reg->rIdx : -1,
68 PCI(pc)->inCond, PCI(pc)->outCond );
69 #endif
70 if(reg) {
71 /*
72 fprintf(stderr, "flow seq %d, inst seq %d %s ",PCODE(pcfl)->seq,pc->seq,reg->name);
73 fprintf(stderr, "addr = 0x%03x, type = %d rIdx=0x%03x\n",
74 reg->address,reg->type,reg->rIdx);
75 */
76
77 addSetIfnotP(& (PCFL(pcfl)->registers), reg);
78
79 if(PCC_REGISTER & PCI(pc)->inCond)
80 addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
81
82 if(PCC_REGISTER & PCI(pc)->outCond)
83 addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl);
84
85 addSetIfnotP(& (reg->reglives.usedpCodes), pc);
86 reg->wasUsed = TRUE;
87 }
88
89
90 //pc = findNextInstruction(pc->next);
91 pc = pc->next;
92
93 }
94
95 }
96
97 /*-----------------------------------------------------------------*
98 * void pCodeRegMapLiveRanges(pBlock *pb)
99 *-----------------------------------------------------------------*/
pCodeRegMapLiveRanges(pBlock * pb)100 void pCodeRegMapLiveRanges(pBlock *pb)
101 {
102 pCode *pcflow;
103
104 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
105 pcflow != NULL;
106 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
107
108 if(!isPCFL(pcflow)) {
109 fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
110 continue;
111 }
112 pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
113 }
114
115 #if 0
116 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
117 pcflow != NULL;
118 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
119
120 regs *r = setFirstItem(PCFL(pcflow)->registers);
121 fprintf(stderr,"flow seq %d\n", pcflow->seq);
122
123 while (r) {
124 fprintf(stderr, " %s\n",r->name);
125 r = setNextItem(PCFL(pcflow)->registers);
126
127 }
128
129 }
130 #endif
131
132 }
133
134
135 /*-----------------------------------------------------------------*
136 *
137 *-----------------------------------------------------------------*/
Remove1pcode(pCode * pc,reg_info * reg,int debug_code)138 static void Remove1pcode(pCode *pc, reg_info *reg, int debug_code)
139 {
140
141 pCode *pcn=NULL;
142
143 if(!reg || !pc)
144 return;
145
146 deleteSetItem (&(reg->reglives.usedpCodes),pc);
147
148 if(PCI(pc)->label) {
149 pcn = findNextInstruction(pc->next);
150
151 if(pcn)
152 PCI(pcn)->label = pBranchAppend(PCI(pcn)->label,PCI(pc)->label);
153 }
154
155 if(PCI(pc)->cline) {
156 if(!pcn)
157 pcn = findNextInstruction(pc->next);
158
159 if(pcn) {
160 if(PCI(pcn)->cline) {
161 //fprintf(stderr, "source line has been optimized completely out\n");
162 //pc->print(stderr,pc);
163 } else {
164 PCI(pcn)->cline = PCI(pc)->cline;
165 }
166 }
167 }
168
169
170 if(1) {
171 /*
172 * Debug stuff. Comment out the instruction we're about to delete.
173 */
174
175 char buff1[256];
176 size_t size = 256;
177
178 char *pbuff;
179 pbuff = &buff1[0];
180
181 SNPRINTF(pbuff, size, ";%d", debug_code);
182 size -= strlen(pbuff);
183 pbuff += strlen(pbuff);
184 pCode2str(pbuff, size, pc);
185 pCodeInsertBefore(pc, newpCodeCharP(buff1));
186 //fprintf(stderr,"removing instruction:\n%s\n",buff1);
187 }
188
189 pc->destruct(pc);
190
191 }
192
193 /*-----------------------------------------------------------------*
194 * void RemoveRegsFromSet(set *regset)
195 *
196 *-----------------------------------------------------------------*/
RemoveRegsFromSet(set * regset)197 static void RemoveRegsFromSet(set *regset)
198 {
199 reg_info *reg;
200 int used;
201
202 while(regset) {
203 reg = regset->item;
204 regset = regset->next;
205
206 used = elementsInSet(reg->reglives.usedpCodes);
207
208 if(used <= 1) {
209
210 //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);
211 if(used == 0) {
212 //fprintf(stderr," getting rid of reg %s\n",reg->name);
213 reg->isFree = TRUE;
214 reg->wasUsed = FALSE;
215 } else {
216 pCode *pc;
217
218
219 pc = setFirstItem(reg->reglives.usedpCodes);
220
221 if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern) {
222 //fprintf(stderr, "not removing SFR reg %s even though used only once\n",reg->name);
223 continue;
224 }
225
226
227 if(isPCI(pc)) {
228 if(PCI(pc)->label) {
229 pCode *pcn = findNextInstruction(pc->next);
230
231 if(pcn && PCI(pcn)->label) {
232 //fprintf(stderr,"can't delete instruction with label...\n");
233 //pc->print(stderr,pc);
234 continue;
235 }
236 /* Move the label to the next instruction */
237
238 PCI(pcn)->label = PCI(pc)->label;
239
240 }
241
242 if(isPCI_SKIP(pc)) {
243 reg_info *r = getRegFromInstruction(pc);
244 fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
245 pc->print(stderr,pc);
246 fprintf(stderr,"reg %s, type =%d\n",r->name, r->type);
247 }
248 //fprintf(stderr," removing reg %s because it is used only once\n",reg->name);
249 Remove1pcode(pc, reg, 1);
250 /*
251 unlinkpCode(pc);
252 deleteSetItem (&(reg->reglives.usedpCodes),pc);
253 */
254 reg->isFree = TRUE;
255 reg->wasUsed = FALSE;
256 total_registers_saved++; // debugging stats.
257 }
258 }
259 }
260
261 }
262 }
263
pic14_ReMapLiveRanges(void)264 static void pic14_ReMapLiveRanges(void)
265 {
266 pBlock *pb;
267 if (!the_pFile) return;
268 RegsUnMapLiveRanges();
269 for (pb = the_pFile->pbHead; pb; pb = pb->next)
270 {
271 #if 0
272 pCode *pc = findNextpCode(pb->pcHead, PC_FLOW);
273 if (pc) {
274 pc->print( stderr, pc );
275 } else {
276 fprintf( stderr, "unnamed pBlock\n");
277 }
278 pc = findNextInstruction(pb->pcHead);
279 while (pc) {
280 pc->print( stderr, pc );
281 pc = findNextInstruction(pc->next);;
282 }
283 #endif
284 pCodeRegMapLiveRanges(pb);
285 } // for
286 }
287
288 /*-----------------------------------------------------------------*
289 * void RemoveUnusedRegisters(void)
290 *
291 *-----------------------------------------------------------------*/
RemoveUnusedRegisters(void)292 void RemoveUnusedRegisters(void)
293 {
294 /* First, get rid of registers that are used only one time */
295 pic14_ReMapLiveRanges();
296
297 //RemoveRegsFromSet(dynInternalRegs);
298 RemoveRegsFromSet(dynAllocRegs);
299 RemoveRegsFromSet(dynStackRegs);
300 /*
301 don't do DirectRegs yet - there's a problem with arrays
302 RemoveRegsFromSet(dynDirectRegs);
303 */
304 RemoveRegsFromSet(dynDirectBitRegs);
305
306 if(total_registers_saved) DFPRINTF((stderr, " *** Saved %d registers ***\n", total_registers_saved));
307 }
308
309
310 /*-----------------------------------------------------------------*
311 *
312 *-----------------------------------------------------------------*/
Remove2pcodes(pCode * pcflow,pCode * pc1,pCode * pc2,reg_info * reg,int can_free)313 static void Remove2pcodes(pCode *pcflow, pCode *pc1, pCode *pc2, reg_info *reg, int can_free)
314 {
315 static int debug_code=99;
316 if(!reg)
317 return;
318 #if 0
319 fprintf (stderr, "%s:%d(%s): %d (reg:%s)\n", __FILE__, __LINE__, __FUNCTION__, debug_code, reg ? reg->name : "???");
320 printpCode (stderr, pc1);
321 printpCode (stderr, pc2);
322 #endif
323
324 //fprintf(stderr,"%s\n",__FUNCTION__);
325 if(pc1)
326 Remove1pcode(pc1, reg, debug_code++);
327
328 if(pc2) {
329 Remove1pcode(pc2, reg, debug_code++);
330 deleteSetItem (&(PCFL(pcflow)->registers), reg);
331
332 if(can_free) {
333 reg->isFree = TRUE;
334 reg->wasUsed = FALSE;
335 }
336
337 }
338
339 pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
340 }
341
342 /*-----------------------------------------------------------------*
343 *
344 *-----------------------------------------------------------------*/
regUsedinRange(pCode * pc1,pCode * pc2,reg_info * reg)345 static int regUsedinRange(pCode *pc1, pCode *pc2, reg_info *reg)
346 {
347 int i=0;
348 reg_info *testreg;
349
350 do {
351 testreg = getRegFromInstruction(pc1);
352 if(testreg && (testreg->rIdx == reg->rIdx)) {
353 return 1;
354 }
355 if (i++ > 1000) {
356 fprintf(stderr, "warning, regUsedinRange searched through too many pcodes\n");
357 return 0;
358 }
359
360 pc1 = findNextInstruction(pc1->next);
361
362 } while (pc1 && (pc1 != pc2)) ;
363
364 return 0;
365 }
366
regIsSpecial(reg_info * reg,int mayBeGlobal)367 static int regIsSpecial (reg_info *reg, int mayBeGlobal)
368 {
369 if (!reg) return 0;
370
371 if (reg->type == REG_SFR || reg->type == REG_STK || (!mayBeGlobal && (reg->isPublic || reg->isExtern))) return 1;
372
373 return 0;
374 }
375
376 /*-----------------------------------------------------------------*
377 * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2)
378 *
379 * ADHOC pattern checking
380 * Now look for specific sequences that are easy to optimize.
381 * Many of these sequences are characteristic of the compiler
382 * (i.e. it'd probably be a waste of time to apply these adhoc
383 * checks to hand written assembly.)
384 *
385 *
386 *-----------------------------------------------------------------*/
pCodeOptime2pCodes(pCode * pc1,pCode * pc2,pCode * pcfl_used,reg_info * reg,int can_free,int optimize_level)387 static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, reg_info *reg, int can_free, int optimize_level)
388 {
389 pCode *pct1, *pct2;
390 reg_info *reg1, *reg2;
391
392 int t = total_registers_saved;
393
394 if (!isPCI(pc1) || !isPCI(pc2)) return 0;
395 if (PCI(pc1)->pcflow != PCI(pc2)->pcflow) return 0;
396
397 if (pc2->seq < pc1->seq) {
398 pct1 = pc2;
399 pc2 = pc1;
400 pc1 = pct1;
401 }
402
403 /* disable this optimization for now -- it's buggy */
404 if (pic14_options.disable_df) return 0;
405
406 //fprintf(stderr,"pCodeOptime2pCodes\n");
407 //pc1->print(stderr,pc1);
408 //pc2->print(stderr,pc2);
409
410 if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
411 /*
412 * CLRF sets Z
413 * MOVFW affects Z
414 * MOVWF does not touch Z
415 * MOVLW does not touch Z
416 */
417 pCode *newpc;
418 /*
419 clrf reg ; pc1
420 stuff...
421 movf reg,w ; pc2
422
423 can be replaced with (only if following instructions are not going to use W and reg is not used again later)
424
425 stuff...
426 movlw 0 or clrf reg
427 */
428 DFPRINTF((stderr, " optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n"));
429 pct2 = findNextInstruction(pc2->next);
430 if (pCodeSearchCondition(pct2, PCC_Z, 0) == -1) {
431 /* Z is definitely overwritten before use */
432 newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
433
434 pCodeInsertAfter(pc2, newpc);
435 PCI(newpc)->pcflow = PCFL(pcfl_used);
436 newpc->seq = pc2->seq;
437
438 //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF reg, ..., MOVF reg,W)\n", __FILE__, __LINE__, __FUNCTION__);
439 //Remove2pcodes(pcfl_used, pc2, NULL, reg, 0);
440 pc2->destruct(pc2);
441 //total_registers_saved++; // debugging stats.
442 }
443 } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
444 DFPRINTF((stderr, " optimising CLRF/IORFW\n"));
445
446 pct2 = findNextInstruction(pc2->next);
447
448 /* We must ensure that Z is destroyed before being read---IORLW must be performed unless this is proven. */
449 if (pCodeSearchCondition(pct2, PCC_Z, 0) != -1) {
450 pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
451 pct2->seq = pc2->seq;
452 PCI(pct2)->pcflow = PCFL(pcfl_used);
453 pCodeInsertAfter(pc1,pct2);
454 }
455 //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF/IORFW)\n", __FILE__, __LINE__, __FUNCTION__);
456 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
457 total_registers_saved++; // debugging stats.
458
459 } else if(PCI(pc1)->op == POC_MOVWF) {
460 // Optimising MOVWF reg ...
461
462 pct2 = findNextInstruction(pc2->next);
463
464 if(PCI(pc2)->op == POC_MOVFW) {
465 // Optimising MOVWF reg ... MOVF reg,W
466
467 if(PCI(pct2)->op == POC_MOVWF) {
468 /*
469 Change:
470
471 movwf reg ; pc1
472 stuff...
473 movf reg,w ; pc2
474 movwf reg2 ; pct2
475
476 To: ( as long as 'stuff' does not use reg2 or if following instructions do not use W or reg is not used later)
477
478 movwf reg2
479 stuff...
480
481 */
482 reg2 = getRegFromInstruction(pct2);
483 /* Check reg2 is not used for something else before it is loaded with reg */
484 if (reg2 && !regIsSpecial (reg2, 1) && !regUsedinRange(pc1,pc2,reg2)) {
485 pCode *pct3 = findNextInstruction(pct2->next);
486 /* Check following instructions are not relying on the use of W or the Z flag condiction */
487 /* XXX: We must ensure that this value is destroyed before use---otherwise it might be used in
488 * subsequent flows (checking for < 1 is insufficient). */
489 if ((pCodeSearchCondition(pct3,PCC_Z,0) == -1) && (pCodeSearchCondition(pct3,PCC_W,0) == -1)) {
490 DFPRINTF((stderr, " optimising MOVF reg ... MOVF reg,W MOVWF reg2 to MOVWF reg2 ...\n"));
491 pct2->seq = pc1->seq;
492 unlinkpCode(pct2);
493 pCodeInsertBefore(pc1,pct2);
494 if(regUsedinRange(pct2,0,reg))
495 {
496 //fprintf (stderr, "%s:%d(%s): Remove2pcodes IF (MOVWF reg, ..., MOVW reg,W MOVWF reg2)\n", __FILE__, __LINE__, __FUNCTION__);
497 Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
498 } else {
499 //fprintf (stderr, "%s:%d(%s): Remove2pcodes ELSE (MOVWF reg, ..., MOVW reg,W MOVWF reg2)\n", __FILE__, __LINE__, __FUNCTION__);
500 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
501 }
502 total_registers_saved++; // debugging stats.
503 return 1;
504 }
505 }
506 }
507 }
508
509 pct1 = findPrevInstruction(pc1->prev);
510 if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
511
512 if ( (PCI(pct1)->op == POC_MOVFW) &&
513 (PCI(pc2)->op == POC_MOVFW)) {
514
515 reg1 = getRegFromInstruction(pct1);
516 if(reg1 && !regIsSpecial (reg1, 0) && !regUsedinRange(pc1,pc2,reg1)) {
517 DFPRINTF((stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
518 /*
519 Change:
520
521 movf reg1,w
522 movwf reg
523
524 stuff...
525 movf reg,w
526
527 To:
528
529 stuff...
530
531 movf reg1,w
532
533 Or, if we're not deleting the register then the "To" is:
534
535 stuff...
536
537 movf reg1,w
538 movwf reg
539 */
540 pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
541 pCodeInsertAfter(pc2, pct2);
542 PCI(pct2)->pcflow = PCFL(pcfl_used);
543 pct2->seq = pc2->seq;
544
545 if(can_free) {
546 //fprintf (stderr, "%s:%d(%s): Remove2pcodes CANFREE (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
547 Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
548 } else {
549 /* If we're not freeing the register then that means (probably)
550 * the register is needed somewhere else.*/
551 unlinkpCode(pc1);
552 pCodeInsertAfter(pct2, pc1);
553
554 //fprintf (stderr, "%s:%d(%s): Remove2pcodes ELSE (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
555 Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
556 }
557
558 //fprintf (stderr, "%s:%d(%s): Remove2pcodes ALWAYS (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
559 Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
560 total_registers_saved++; // debugging stats.
561
562 }
563 }
564 }
565 }
566
567 return (total_registers_saved != t);
568 }
569
570 /*-----------------------------------------------------------------*
571 * void pCodeRegOptimeRegUsage(pBlock *pb)
572 *-----------------------------------------------------------------*/
OptimizeRegUsage(set * fregs,int optimize_multi_uses,int optimize_level)573 static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level)
574 {
575 reg_info *reg;
576 int used;
577 pCode *pc1=NULL, *pc2=NULL;
578
579
580 while(fregs) {
581 pCode *pcfl_used, *pcfl_assigned;
582
583 /* Step through the set by directly accessing the 'next' pointer.
584 * We could also step through by using the set API, but the
585 * the (debug) calls to print instructions affect the state
586 * of the set pointers */
587
588 reg = fregs->item;
589 fregs = fregs->next;
590 /*
591 if (strcmp(reg->name,"_SubState")==0)
592 fprintf(stderr,"Reg: %s\n",reg->name);
593 */
594
595 /* Catch inconsistently set-up live ranges
596 * (see tracker items #1469504 + #1474602)
597 * FIXME: Actually we should rather fix the
598 * computation of the liveranges instead...
599 */
600 if (!reg || !reg->reglives.usedpFlows
601 || !reg->reglives.assignedpFlows)
602 {
603 //fprintf( stderr, "skipping reg w/o liveranges: %s\n", reg ? reg->name : "(unknown)");
604 continue;
605 }
606
607 if(reg->type == REG_SFR || reg->type == REG_STK || reg->isPublic || reg->isExtern|| reg->isFixed) {
608 //fprintf(stderr,"skipping SFR: %s\n",reg->name);
609 continue;
610 }
611
612 pcfl_used = setFirstItem(reg->reglives.usedpFlows);
613 pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows);
614
615 used = elementsInSet(reg->reglives.usedpCodes);
616 if(used == 2) {
617 /*
618 In this section, all registers that are used in only in two
619 instructions are examined. If possible, they're optimized out.
620 */
621
622 /*
623 fprintf (stderr, "OptimizeRegUsage: %s addr=0x%03x rIdx=0x%03x type=%d used=%d\n",
624 reg->name,
625 reg->address,
626 reg->rIdx, reg->type, used);
627 */
628 pc1 = setFirstItem(reg->reglives.usedpCodes);
629 pc2 = setNextItem(reg->reglives.usedpCodes);
630
631 if(pcfl_used && pcfl_assigned) {
632 /*
633 expected case - the register has been assigned a value and is
634 subsequently used
635 */
636
637 //fprintf(stderr," used only twice\n");
638 if(pcfl_used->seq == pcfl_assigned->seq) {
639
640 //fprintf(stderr, " and used in same flow\n");
641
642 pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level);
643
644 } else {
645 // fprintf(stderr, " and used in different flows\n");
646
647 }
648
649 } else if(pcfl_used) {
650
651 /* register has been used twice without ever being assigned */
652 fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
653
654 } else {
655 //fprintf(stderr,"WARNING %s.1: reg %s assigned without being used\n",__FUNCTION__,reg->name);
656 Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
657 total_registers_saved++; // debugging stats.
658 }
659 } else {
660
661 /* register has been used either once, or more than twice */
662
663 if(used && !pcfl_used && pcfl_assigned) {
664 pCode *pc;
665
666 //fprintf(stderr,"WARNING %s.2: reg %s assigned without being used\n",__FUNCTION__,reg->name);
667
668 pc = setFirstItem(reg->reglives.usedpCodes);
669 while(pc) {
670
671 pcfl_assigned = PCODE(PCI(pc)->pcflow);
672 Remove1pcode(pc, reg,2);
673
674 deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg);
675 /*
676 deleteSetItem (&(reg->reglives.usedpCodes),pc);
677 pc->destruct(pc);
678 */
679 pc = setNextItem(reg->reglives.usedpCodes);
680 }
681
682
683 reg->isFree = TRUE;
684 reg->wasUsed = FALSE;
685
686 total_registers_saved++; // debugging stats.
687 } else if( (used > 2) && optimize_multi_uses) {
688
689 set *rset1=NULL;
690 set *rset2=NULL;
691 int searching=1;
692
693 pCodeFlow *pcfl1=NULL, *pcfl2=NULL;
694
695 /* examine the number of times this register is used */
696
697
698 rset1 = reg->reglives.usedpCodes;
699 while(rset1 && searching) {
700
701 pc1 = rset1->item;
702 rset2 = rset1->next;
703
704 if(pc1 && isPCI(pc1) && ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) {
705
706 if(rset2) {
707
708 pc2 = rset2->item;
709 if(pc2 && isPCI(pc2) && ( (pcfl2 = PCI(pc2)->pcflow) != NULL) ) {
710 if(pcfl2 == pcfl1) {
711
712 if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level))
713 searching = 0;
714 }
715 }
716
717 //rset2 = rset2->next;
718
719 }
720 }
721 rset1 = rset2;
722 }
723 }
724 }
725 }
726 }
727
728 /*-----------------------------------------------------------------*
729 * void pCodeRegOptimeRegUsage(pBlock *pb)
730 *-----------------------------------------------------------------*/
pCodeRegOptimizeRegUsage(int level)731 void pCodeRegOptimizeRegUsage(int level)
732 {
733
734 int passes;
735 int saved = 0;
736 int t = total_registers_saved;
737
738 #if 0
739 /* This is currently broken (need rewrite to correctly
740 * handle arbitrary pCodeOps instead of registers only). */
741 if (!pic14_options.disable_df)
742 optimizeDataflow ();
743 #endif
744
745 if(!register_optimization)
746 return;
747 #define OPT_PASSES 4
748 passes = OPT_PASSES;
749
750 do {
751 saved = total_registers_saved;
752
753 /* Identify registers used in one flow sequence */
754 OptimizeRegUsage(dynAllocRegs,level, (OPT_PASSES-passes));
755 OptimizeRegUsage(dynStackRegs,level, (OPT_PASSES-passes));
756 OptimizeRegUsage(dynDirectRegs,0, (OPT_PASSES-passes));
757
758 if(total_registers_saved != saved)
759 DFPRINTF((stderr, " *** pass %d, Saved %d registers, total saved %d ***\n",
760 (1+OPT_PASSES-passes),total_registers_saved-saved,total_registers_saved));
761
762 passes--;
763
764 } while( passes && ((total_registers_saved != saved) || (passes==OPT_PASSES-1)) );
765
766 if(total_registers_saved == t)
767 DFPRINTF((stderr, "No registers saved on this pass\n"));
768 }
769
770
771 /*-----------------------------------------------------------------*
772 * void RegsUnMapLiveRanges(set *regset)
773 *
774 *-----------------------------------------------------------------*/
RegsSetUnMapLiveRanges(set * regset)775 static void RegsSetUnMapLiveRanges(set *regset)
776 {
777 reg_info *reg;
778
779 while(regset) {
780 reg = regset->item;
781 regset = regset->next;
782
783
784 deleteSet(®->reglives.usedpCodes);
785 deleteSet(®->reglives.usedpFlows);
786 deleteSet(®->reglives.assignedpFlows);
787
788 }
789
790 }
791
RegsUnMapLiveRanges(void)792 void RegsUnMapLiveRanges(void)
793 {
794
795 RegsSetUnMapLiveRanges(dynAllocRegs);
796 RegsSetUnMapLiveRanges(dynStackRegs);
797 RegsSetUnMapLiveRanges(dynDirectRegs);
798 RegsSetUnMapLiveRanges(dynProcessorRegs);
799 RegsSetUnMapLiveRanges(dynDirectBitRegs);
800 RegsSetUnMapLiveRanges(dynInternalRegs);
801
802 }
803