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