Initial revision
[fw/sdcc] / src / SDCCptropt.c
1 /*-------------------------------------------------------------------------
2
3   SDCCptropt.c - source file for pointer arithmetic Optimizations
4
5              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
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    In other words, you are welcome to use, share and improve this program.
22    You are forbidden to forbid anyone else to use, share and improve
23    what you give them.   Help stamp out software-hoarding!  
24 -------------------------------------------------------------------------*/
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "SDCCglobl.h"
29 #include "SDCCast.h"
30 #include "SDCCmem.h"
31 #include "SDCCy.h"
32 #include "SDCChasht.h"
33 #include "SDCCbitv.h"
34 #include "SDCCset.h"
35 #include "SDCCicode.h"
36 #include "SDCClabel.h"
37 #include "SDCCBBlock.h"
38 #include "SDCCcflow.h"
39 #include "SDCCloop.h"
40 #include "SDCCcse.h"
41
42
43 /*-----------------------------------------------------------------*/
44 /* pointerArithOpts - does some pointer arithmetic operations      */
45 /*-----------------------------------------------------------------*/
46  int pointerArithOpts (iCode *ic,  hTab *ptrs)
47 {
48     operand *asym ;
49     long  cval;
50     hashtItem *htip;
51     induction *ip ;
52     int lr = 0 ;
53
54     /* the aim here is to reduce the arithmetics performed */
55     /* during repeated pointer access . for eg. there are  */
56     /* lot of places the code generated looks like this    */
57     /*  iTempNN = &[somevar]                               */
58     /*  iTempNX = iTempNN + constant-1                     */
59     /*  *(iTempNX) := somevalue                            */
60     /*  iTempNY = iTempNN + constant-2                     */
61     /*  *(iTempNY) := somevalue                            */
62     /*          we want to change this sequence to         */
63     /*  iTempNN = &[somevar]                               */
64     /*  iTempNN = iTempNN + constant-1                     */
65     /*  (*iTempNN) := someValue                            */
66     /* WHY ? this will reduce the number of definitions    */
67     /* as well as help us in register allocation           */
68     
69     /* first check if +/- */
70     if (ic->op != '+' && ic->op != '-' )
71         return 0;
72
73     /* if the result is not an iTemp */
74     if (!IS_ITEMP(IC_RESULT(ic)))
75         return 0;
76
77     /* if +/- then check if one of them is literal */
78     if (! IS_OP_LITERAL(IC_LEFT(ic)) &&
79         ! IS_OP_LITERAL(IC_RIGHT(ic)) )
80         return 0;
81
82     /* get the operand & literal value */
83     if  (IS_OP_LITERAL(IC_LEFT(ic))) {
84             cval = operandLitValue(IC_LEFT(ic));
85             asym = IC_RIGHT(ic) ;
86     } else {
87         cval = operandLitValue(IC_RIGHT(ic)) ;
88         lr++ ;
89         asym = IC_LEFT(ic);
90     }
91
92     /* if this symbol does not exist the address of */
93     /* or if the symbol is the same as the result   */
94     if (asym->key == IC_RESULT(ic)->key ||
95         (htip = hTabSearch(ptrs,asym->key)) == NULL )
96         return 0;
97     
98     ip = htip->item;
99
100     
101     /* if the constant value in induction is zero */
102     /* then we just change the operand            */
103     if (ip->cval == 0) {        
104         ip->asym = IC_RESULT(ic) ;
105         ip->cval = cval ; /* update the offset info */
106         return 0;
107     }
108     /* we can do the substitution */
109     replaceAllSymBySym (ic->next, IC_RESULT(ic),ip->asym);
110     IC_RESULT(ic) = operandFromOperand(ip->asym);
111     
112     /* now we know that the constant value is greater than zero */
113     /* we have to do some arithmetic here : if the offset is greater */
114     /* than what we want then rechange it to subtraction        */
115     if ( ip->cval > cval) {
116         ic->op = '-' ;
117         if (lr) {
118             IC_LEFT(ic) = operandFromOperand(ip->asym);
119             IC_RIGHT(ic) = operandFromLit(ip->cval - cval);
120         }
121         else {
122             IC_RIGHT(ic) = operandFromOperand(ip->asym);
123             IC_LEFT(ic) = operandFromLit(ip->cval - cval);
124         }
125     } else {
126         if (lr) {
127             IC_LEFT(ic) = operandFromOperand(ip->asym);
128             IC_RIGHT(ic) = operandFromLit(cval - ip->cval);
129         }
130         else {
131             IC_RIGHT(ic) = operandFromOperand (ip->asym);
132             IC_LEFT(ic) = operandFromLit(cval - ip->cval);
133         }
134     }
135     
136     ip->cval = cval ;
137     return 1;
138 }
139
140 /*-----------------------------------------------------------------*/
141 /* ptrAopts - pointer arithmetic optimizations for a basic block   */
142 /*-----------------------------------------------------------------*/
143 void ptrAopts (eBBlock **ebbs, int count)
144 {
145     int i;
146
147     hTab *pointers ; 
148
149     /* for each basic block do */
150     for (i = 0 ; i < count ; i++ ) {
151         iCode *ic;
152
153         setToNull((void **) &pointers);
154         /* iterate thru intructions in the basic block */
155         for (ic = ebbs[i]->sch ; ic ; ic = ic->next ) {
156
157             if (SKIP_IC(ic) ||ic->op == IFX)
158                 continue ;
159             
160             if (pointers)
161                 pointerArithOpts(ic,pointers);
162
163             if (!POINTER_SET(ic) && IC_RESULT(ic))
164                 /* delete from pointer access */
165                 hTabDeleteItem (&pointers, IC_RESULT(ic)->key,NULL,DELETE_CHAIN,NULL);
166
167                 /* set up for pointers */
168             if ((ic->op == ADDRESS_OF  || ADD_SUBTRACT_ITEMP(ic)) &&
169                 IS_ITEMP(IC_RESULT(ic)) ) {
170                 operand *sym ;
171                 operand *asym ;
172                 long cval    ;
173                 
174                 if ( ic->op == ADDRESS_OF){           
175                     sym = IC_RESULT(ic);
176                     asym = NULL ;
177                     cval = 0;
178                 } else {
179                     sym = IC_LEFT(ic);
180                     asym = IC_RESULT(ic);
181                     cval = operandLitValue(IC_RIGHT(ic));
182                 }
183                 
184                 /* put it in the pointer set */                 
185             }   
186         }
187
188     }
189 }