added some pointer arithmetic optimizations but not stable yet so not
[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 /* findPointerGetSet - find the pointer get or set for a operand         */
30 /*-----------------------------------------------------------------------*/
31 static iCode *
32 findPointerGetSet (iCode * sic, operand * op)
33 {
34   iCode *ic = sic;
35
36   for (; ic; ic = ic->next)
37     {
38       if ((POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic))) ||
39           (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic))))
40         return ic;
41
42       /* if we find any other usage or definition of op null */
43       if (IC_RESULT (ic) && isOperandEqual (IC_RESULT (ic), op))
44         return NULL;
45
46       if (IC_RIGHT (ic) && isOperandEqual (IC_RIGHT (ic), op))
47         return NULL;
48
49       if (IC_LEFT (ic) && isOperandEqual (IC_LEFT (ic), op))
50         return NULL;
51
52     }
53
54   return NULL;
55 }
56
57 static int pattern1 (iCode *sic)
58 {
59         /* this is what we do. look for sequences like
60
61         iTempX := _SOME_POINTER_;
62         iTempY := _SOME_POINTER_ + nn ;   nn  = sizeof (pointed to object)      sic->next
63         _SOME_POINTER_ := iTempY;                                               sic->next->next
64         either       
65         iTempZ := @[iTempX];                                                    sic->next->next->next
66         or
67         *(iTempX) := ..something..                                              sic->next->next->next
68         if we find this then transform this to
69         iTempX := _SOME_POINTER_;
70         either       
71         iTempZ := @[iTempX];
72         or 
73         *(iTempX) := ..something..
74         iTempY := _SOME_POINTER_ + nn ;   nn  = sizeof (pointed to object)
75         _SOME_POINTER_ := iTempY; */
76         
77         /* sounds simple enough so lets start , here I use -ve
78            tests all the way to return if any test fails */
79         iCode *pgs, *sh, *st;
80
81         if (!(sic->next && sic->next->next && sic->next->next->next))
82                 return 0;
83         if (sic->next->op != '+' && sic->next->op != '-')
84                 return 0;
85         if (!(sic->next->next->op == '=' &&
86               !POINTER_SET (sic->next->next)))
87                 return 0;
88         if (!isOperandEqual (IC_LEFT (sic->next), IC_RIGHT (sic)) ||
89             !IS_OP_LITERAL (IC_RIGHT (sic->next)))
90                 return 0;
91         if (operandLitValue (IC_RIGHT (sic->next)) !=
92             getSize (operandType (IC_RIGHT (sic))->next))
93                 return 0;
94         if (!isOperandEqual (IC_RESULT (sic->next->next),
95                              IC_RIGHT (sic)))
96                 return 0;
97         if (!isOperandEqual (IC_RESULT (sic->next), IC_RIGHT (sic->next->next)))
98                 return 0;
99         if (!(pgs = findPointerGetSet (sic->next->next, IC_RESULT (sic))))
100                 return 0;
101
102         /* found the patter .. now do the transformation */
103         sh = sic->next;
104         st = sic->next->next;
105
106         /* take the two out of the chain */
107         sic->next = st->next;
108         st->next->prev = sic;
109
110         /* and put them after the pointer get/set icode */
111         if ((st->next = pgs->next))
112                 st->next->prev = st;
113         pgs->next = sh;
114         sh->prev = pgs;
115         return 1;
116 }
117
118 static int pattern2 (iCode *sic)
119 {
120         /* this is what we do. look for sequences like
121
122         iTempX := _SOME_POINTER_;
123         iTempY := _SOME_POINTER_ + nn ;   nn  = sizeof (pointed to object)      sic->next
124         iTempK := iTempY;                                                       sic->next->next
125         _SOME_POINTER_ := iTempK;                                               sic->next->next->next
126         either       
127         iTempZ := @[iTempX];                                                    sic->next->next->next->next
128         or
129         *(iTempX) := ..something..                                              sic->next->next->next->next
130         if we find this then transform this to
131         iTempX := _SOME_POINTER_;
132         either       
133         iTempZ := @[iTempX];
134         or 
135         *(iTempX) := ..something..
136         iTempY := _SOME_POINTER_ + nn ;   nn  = sizeof (pointed to object)
137         iTempK := iTempY;       
138         _SOME_POINTER_ := iTempK; */
139         
140         /* sounds simple enough so lets start , here I use -ve
141            tests all the way to return if any test fails */
142         iCode *pgs, *sh, *st;
143
144         if (!(sic->next && sic->next->next && sic->next->next->next && 
145               sic->next->next->next->next))
146                 return 0;
147
148         /* yes I can OR them together and make one large if... but I have
149            simple mind and like to keep things simple & readable */
150         if (!(sic->next->op == '+' || sic->next->op == '-')) return 0;
151         if (!isOperandEqual(IC_RIGHT(sic),IC_LEFT(sic->next))) return 0;
152         if (!IS_OP_LITERAL (IC_RIGHT (sic->next))) return 0;
153         if (operandLitValue (IC_RIGHT (sic->next)) !=
154             getSize (operandType (IC_RIGHT (sic))->next)) return 0;
155         if (!IS_ASSIGN_ICODE(sic->next->next)) return 0;
156         if (!isOperandEqual(IC_RIGHT(sic->next->next),IC_RESULT(sic->next))) return 0;
157         if (!IS_ASSIGN_ICODE(sic->next->next->next)) return 0;
158         if (!isOperandEqual(IC_RIGHT(sic->next->next->next),IC_RESULT(sic->next->next))) return 0;
159         if (!isOperandEqual(IC_RESULT(sic->next->next->next),IC_LEFT(sic->next))) return 0;
160         if (!(pgs = findPointerGetSet (sic->next->next->next, IC_RESULT (sic)))) return 0;
161         
162         /* found the patter .. now do the transformation */
163         sh = sic->next;
164         st = sic->next->next->next;
165
166         /* take the three out of the chain */
167         sic->next = st->next;
168         st->next->prev = sic;
169
170         /* and put them after the pointer get/set icode */
171         if ((st->next = pgs->next))
172                 st->next->prev = st;
173         pgs->next = sh;
174         sh->prev = pgs;
175         return 1;
176 }
177
178 /*-----------------------------------------------------------------------*/
179 /* ptrPostIncDecOpts - will do some pointer post increment optimizations */
180 /*                     this will help register allocation amongst others */
181 /*-----------------------------------------------------------------------*/
182 void 
183 ptrPostIncDecOpt (iCode * sic)
184 {
185         if (pattern1(sic)) return ;
186         pattern2(sic);
187 }
188
189 /*-----------------------------------------------------------------------*/
190 /* addPattern1 - transform addition to pointer of variables              */
191 /*-----------------------------------------------------------------------*/
192 static int addPattern1(iCode *ic)
193 {
194         iCode *dic;
195         operand *tmp;
196         /* transform :
197            iTempAA = iTempBB + iTempCC
198            iTempDD = iTempAA + CONST
199            to
200            iTempAA = iTempBB + CONST
201            iTempDD = iTempAA + iTempCC
202         */
203         if (!isOperandLiteral(IC_RIGHT(ic))) return 0;
204         if ((dic=findBackwardDef(IC_LEFT(ic),ic->prev)) == NULL) return 0;
205         if (bitVectnBitsOn(OP_SYMBOL(IC_RESULT(dic))->uses) > 1) return 0;
206         if (dic->op != '+') return 0;
207         tmp = IC_RIGHT(ic);
208         IC_RIGHT(ic) = IC_RIGHT(dic);
209         IC_RIGHT(dic) = tmp;
210         return 1;
211 }
212
213 /*-----------------------------------------------------------------------*/
214 /* ptrAddition - optimize pointer additions                              */
215 /*-----------------------------------------------------------------------*/
216 int ptrAddition (iCode *sic)
217 {
218         if (addPattern1(sic)) return 1;
219         return 0;
220 }