pCode live-range analysis algorithms have been added.
[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 void unlinkpCode(pCode *pc);
41
42 /*-----------------------------------------------------------------*
43  * void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
44  *-----------------------------------------------------------------*/
45 /*
46 void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
47 {
48
49   if(!reg || ! pcfl || !isPCFL(pcflow))
50     return;
51
52   if(!pcfl->registers) 
53     pcfl->registers =  newSet();
54
55 }
56 */
57
58
59 /*-----------------------------------------------------------------*
60  * 
61  *-----------------------------------------------------------------*/
62 void dbg_regusage(set *fregs)
63 {
64   regs *reg;
65   pCode *pcfl;
66   pCode *pc;
67
68
69   for (reg = setFirstItem(fregs) ; reg ;
70        reg = setNextItem(fregs)) {
71     
72     fprintf (stderr, "%s  addr=0x%03x rIdx=0x%03x",
73              reg->name,
74              reg->address,
75              reg->rIdx);
76
77     pcfl = setFirstItem(reg->reglives.usedpFlows);
78     if(pcfl)
79       fprintf(stderr, "\n   used in seq");
80
81     while(pcfl) {
82       fprintf(stderr," 0x%03x",pcfl->seq);
83       pcfl = setNextItem(reg->reglives.usedpFlows);
84     }
85
86     pcfl = setFirstItem(reg->reglives.assignedpFlows);
87     if(pcfl)
88       fprintf(stderr, "\n   assigned in seq");
89
90     while(pcfl) {
91       fprintf(stderr," 0x%03x",pcfl->seq);
92       pcfl = setNextItem(reg->reglives.assignedpFlows);
93     }
94
95     pc = setFirstItem(reg->reglives.usedpCodes);
96     if(pc)
97       fprintf(stderr, "\n   used in instructions ");
98
99     while(pc) {
100       pcfl = PCODE(PCI(pc)->pcflow);
101       if(pcfl)
102         fprintf(stderr," 0x%03x:",pcfl->seq);
103       fprintf(stderr,"0x%03x",pc->seq);
104
105       pc = setNextItem(reg->reglives.usedpCodes);
106     }
107
108     fprintf(stderr, "\n");
109
110   }
111 }
112
113 /*-----------------------------------------------------------------*
114  * 
115  *-----------------------------------------------------------------*/
116 void dbg_dumpregusage(void)
117 {
118
119   fprintf(stderr,"***  Register Usage  ***\n");
120   fprintf(stderr,"InternalRegs:\n");
121   dbg_regusage(dynInternalRegs);
122   fprintf(stderr,"AllocRegs:\n");
123   dbg_regusage(dynAllocRegs);
124   fprintf(stderr,"StackRegs:\n");
125   dbg_regusage(dynStackRegs);
126   fprintf(stderr,"DirectRegs:\n");
127   dbg_regusage(dynDirectRegs);
128   fprintf(stderr,"DirectBitRegs:\n");
129   dbg_regusage(dynDirectBitRegs);
130   fprintf(stderr,"ProcessorRegs:\n");
131   dbg_regusage(dynProcessorRegs);
132
133 }
134
135
136 /*-----------------------------------------------------------------*
137  * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
138  *-----------------------------------------------------------------*/
139 void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
140 {
141
142   pCode *pc=NULL;
143   pCode *pcprev=NULL;
144
145   regs *reg;
146
147   if(!pcfl)
148     return;
149
150
151   pc = findNextInstruction(pcfl->pc.next);
152
153   while(isPCinFlow(pc,PCODE(pcfl))) {
154
155
156     reg = getRegFromInstruction(pc);
157
158     if(reg) {
159 /*
160       fprintf(stderr, "flow seq %d, inst seq %d  %s  ",PCODE(pcfl)->seq,pc->seq,reg->name);
161       fprintf(stderr, "addr = 0x%03x, type = %d  rIdx=0x%03x\n",
162               reg->address,reg->type,reg->rIdx);
163 */
164
165       addSetIfnotP(& (PCFL(pcfl)->registers), reg);
166
167       if(PCC_REGISTER & PCI(pc)->inCond)
168         addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
169
170       if(PCC_REGISTER & PCI(pc)->outCond)
171         addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl);
172
173       addSetIfnotP(& (reg->reglives.usedpCodes), pc);
174     }
175
176
177     pcprev = pc;
178     pc = findNextInstruction(pc->next);
179
180   }
181
182 }
183 /*-----------------------------------------------------------------*
184  * void pCodeRegMapLiveRanges(pBlock *pb) 
185  *-----------------------------------------------------------------*/
186 void pCodeRegMapLiveRanges(pBlock *pb)
187 {
188   pCode *pcflow;
189
190   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
191        pcflow != NULL;
192        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
193
194     if(!isPCFL(pcflow)) {
195       fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
196       continue;
197     }
198     pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
199   }
200
201
202   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
203        pcflow != NULL;
204        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
205
206     regs *r = setFirstItem(PCFL(pcflow)->registers);
207     //fprintf(stderr,"flow seq %d\n", pcflow->seq);
208     while (r) {
209       //fprintf(stderr, "  %s\n",r->name);
210       r = setNextItem(PCFL(pcflow)->registers);
211
212     }
213
214   }
215
216   //  dbg_dumpregusage();
217
218 }
219
220
221 /*-----------------------------------------------------------------*
222  * void RemoveRegsFromSet(set *regset)
223  *
224  *-----------------------------------------------------------------*/
225 void  RemoveRegsFromSet(set *regset)
226 {
227   regs *reg;
228   int used;
229   for (reg = setFirstItem(regset) ; reg ;
230        reg = setNextItem(regset)) {
231
232
233     used = elementsInSet(reg->reglives.usedpCodes);
234
235     if(used <= 1) {
236
237       //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);
238
239       if(used == 0) {
240         //fprintf(stderr," getting rid of reg %s\n",reg->name);
241         reg->isFree = 1;
242         reg->wasUsed = 0;
243       } else {
244         pCode *pc;
245
246         //fprintf(stderr," reg %s used only once\n",reg->name);
247
248         pc = setFirstItem(reg->reglives.usedpCodes);
249         if(isPCI(pc)) {
250           if(PCI(pc)->label) {
251             pCode *pcn = findNextInstruction(pc->next);
252
253             if(pcn && PCI(pcn)->label) {
254               fprintf(stderr,"can't delete instruction with label...\n");
255               pc->print(stderr,pc);
256               continue;
257             } 
258             /* Move the label to the next instruction */
259
260             PCI(pcn)->label = PCI(pc)->label;
261
262           }
263
264           if(isPCI_SKIP(pc))
265             fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
266
267           unlinkpCode(pc);
268           deleteSetItem (&(reg->reglives.usedpCodes),pc);
269           reg->isFree = 1;
270           reg->wasUsed = 0;
271         }
272       }
273     }
274
275   }
276 }
277 /*-----------------------------------------------------------------*
278  * void RemoveUnusedRegisters(void)
279  *
280  *-----------------------------------------------------------------*/
281 void RemoveUnusedRegisters(void)
282 {
283
284
285   //fprintf(stderr,"InternalRegs:\n");
286   RemoveRegsFromSet(dynInternalRegs);
287   //fprintf(stderr,"AllocRegs:\n");
288   RemoveRegsFromSet(dynAllocRegs);
289   //fprintf(stderr,"StackRegs:\n");
290   RemoveRegsFromSet(dynStackRegs);
291
292   /*
293     don't do DirectRegs yet - there's a problem with arrays
294   //fprintf(stderr,"DirectRegs:\n");
295   RemoveRegsFromSet(dynDirectRegs);
296   */
297   //fprintf(stderr,"DirectBitRegs:\n");
298   RemoveRegsFromSet(dynDirectBitRegs);
299
300
301
302 }