1 /*-------------------------------------------------------------------------
3 SDCCptropt.c - source file for pointer arithmetic Optimizations
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
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
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.
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.
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 -------------------------------------------------------------------------*/
28 /*-----------------------------------------------------------------------*/
29 /* findPointerGetSet - find the pointer get or set for a operand */
30 /*-----------------------------------------------------------------------*/
32 findPointerGetSet (iCode
* sic
, operand
* op
)
36 for (; ic
; ic
= ic
->next
)
38 if ((POINTER_SET (ic
) && isOperandEqual (op
, IC_RESULT (ic
))) || (POINTER_GET (ic
) && isOperandEqual (op
, IC_LEFT (ic
))))
41 /* if we find any other usage or definition of op null */
42 if (IC_RESULT (ic
) && isOperandEqual (IC_RESULT (ic
), op
))
45 if (IC_RIGHT (ic
) && isOperandEqual (IC_RIGHT (ic
), op
))
48 if (IC_LEFT (ic
) && isOperandEqual (IC_LEFT (ic
), op
))
57 pattern1 (iCode
* sic
, eBBlock
* ebb
)
59 /* this is what we do. look for sequences like
61 iTempX := _SOME_POINTER_;
62 iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next
63 _SOME_POINTER_ := iTempY; sic->next->next
65 iTempZ := @[iTempX]; sic->next->next->next
67 *(iTempX) := ..something.. sic->next->next->next
68 if we find this then transform this to
69 iTempX := _SOME_POINTER_;
73 *(iTempX) := ..something..
74 iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object)
75 _SOME_POINTER_ := iTempY; */
77 /* sounds simple enough so let's start , here I use negative
78 tests all the way to return if any test fails */
81 if (!(sic
->next
&& sic
->next
->next
&& sic
->next
->next
->next
))
83 if (sic
->next
->op
!= '+' && sic
->next
->op
!= '-')
85 if (!(sic
->next
->next
->op
== '=' && !POINTER_SET (sic
->next
->next
)))
87 if (!isOperandEqual (IC_LEFT (sic
->next
), IC_RIGHT (sic
)) || !IS_OP_LITERAL (IC_RIGHT (sic
->next
)))
89 if (operandLitValue (IC_RIGHT (sic
->next
)) != getSize (operandType (IC_RIGHT (sic
))->next
))
91 if (!isOperandEqual (IC_RESULT (sic
->next
->next
), IC_RIGHT (sic
)))
93 if (!isOperandEqual (IC_RESULT (sic
->next
), IC_RIGHT (sic
->next
->next
)))
95 if (!(pgs
= findPointerGetSet (sic
->next
->next
, IC_RESULT (sic
))))
98 /* found the pattern .. now do the transformation */
100 st
= sic
->next
->next
;
102 /* take the two out of the chain */
103 sic
->next
= st
->next
;
104 st
->next
->prev
= sic
;
106 /* and put them after the pointer get/set icode */
107 if ((st
->next
= pgs
->next
))
117 pattern2 (iCode
* sic
, eBBlock
* ebb
)
119 /* this is what we do. look for sequences like
121 iTempX := _SOME_POINTER_;
122 iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next
123 iTempK := iTempY; sic->next->next
124 _SOME_POINTER_ := iTempK; sic->next->next->next
126 iTempZ := @[iTempX]; sic->next->next->next->next
128 *(iTempX) := ..something.. sic->next->next->next->next
129 if we find this then transform this to
130 iTempX := _SOME_POINTER_;
134 *(iTempX) := ..something..
135 iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object)
137 _SOME_POINTER_ := iTempK; */
139 /* sounds simple enough so let's start , here I use negative
140 tests all the way to return if any test fails */
141 iCode
*pgs
, *sh
, *st
;
143 if (!(sic
->next
&& sic
->next
->next
&& sic
->next
->next
->next
&& sic
->next
->next
->next
->next
))
146 /* yes I can OR them together and make one large if... but I have
147 simple mind and like to keep things simple & readable */
148 if (!(sic
->next
->op
== '+' || sic
->next
->op
== '-'))
150 if (!isOperandEqual (IC_RIGHT (sic
), IC_LEFT (sic
->next
)))
152 if (!IS_OP_LITERAL (IC_RIGHT (sic
->next
)))
154 if (operandLitValue (IC_RIGHT (sic
->next
)) != getSize (operandType (IC_RIGHT (sic
))->next
))
156 if (!IS_ASSIGN_ICODE (sic
->next
->next
))
158 if (!isOperandEqual (IC_RIGHT (sic
->next
->next
), IC_RESULT (sic
->next
)))
160 if (!IS_ASSIGN_ICODE (sic
->next
->next
->next
))
162 if (!isOperandEqual (IC_RIGHT (sic
->next
->next
->next
), IC_RESULT (sic
->next
->next
)))
164 if (!isOperandEqual (IC_RESULT (sic
->next
->next
->next
), IC_LEFT (sic
->next
)))
166 if (!(pgs
= findPointerGetSet (sic
->next
->next
->next
, IC_RESULT (sic
))))
169 /* found the pattern .. now do the transformation */
171 st
= sic
->next
->next
->next
;
173 /* take the three out of the chain */
174 sic
->next
= st
->next
;
175 st
->next
->prev
= sic
;
177 /* and put them after the pointer get/set icode */
178 if ((st
->next
= pgs
->next
))
187 /*-----------------------------------------------------------------------*/
188 /* ptrPostIncDecOpts - will do some pointer post increment optimizations */
189 /* this will help register allocation amongst others */
190 /*-----------------------------------------------------------------------*/
192 ptrPostIncDecOpt (iCode
* sic
, eBBlock
* ebb
)
194 if (pattern1 (sic
, ebb
))
199 /*-----------------------------------------------------------------------*/
200 /* addPattern1 - transform addition to pointer of variables */
201 /*-----------------------------------------------------------------------*/
203 addPattern1 (iCode
* ic
)
208 iTempAA = iTempBB + iTempCC
209 iTempDD = iTempAA + CONST
211 iTempAA = iTempBB + CONST
212 iTempDD = iTempAA + iTempCC
214 if (!isOperandLiteral (IC_RIGHT (ic
)))
216 if ((dic
= findBackwardDef (IC_LEFT (ic
), ic
->prev
)) == NULL
)
218 if (bitVectnBitsOn (OP_SYMBOL (IC_RESULT (dic
))->uses
) > 1)
223 IC_RIGHT (ic
) = IC_RIGHT (dic
);
224 IC_RIGHT (dic
) = tmp
;
228 /*-----------------------------------------------------------------------*/
229 /* ptrAddition - optimize pointer additions */
230 /*-----------------------------------------------------------------------*/
232 ptrAddition (iCode
* sic
)
234 if (addPattern1 (sic
))
239 /*--------------------------------------------------------------------*/
240 /* ptrBaseRematSym - find the base symbol of a remat. pointer */
241 /*--------------------------------------------------------------------*/
243 ptrBaseRematSym (symbol
* ptrsym
)
250 ric
= ptrsym
->rematiCode
;
253 if (ric
->op
== '+' || ric
->op
== '-')
254 ric
= OP_SYMBOL (IC_LEFT (ric
))->rematiCode
;
255 else if (IS_CAST_ICODE (ric
))
256 ric
= OP_SYMBOL (IC_RIGHT (ric
))->rematiCode
;
261 if (ric
&& IS_SYMOP (IC_LEFT (ric
)))
262 return OP_SYMBOL (IC_LEFT (ric
));
268 /*--------------------------------------------------------------------*/
269 /* ptrPseudoSymSafe - check to see if the conversion of the result of */
270 /* a pointerGet of a rematerializable pointer to a pseudo symbol is */
271 /* safe. Returns true if safe, or false if hazards were detected. */
272 /*--------------------------------------------------------------------*/
274 ptrPseudoSymSafe (symbol
* sym
, iCode
* dic
)
283 assert (POINTER_GET (dic
));
285 /* Can't if spills to this symbol are prohibited */
289 /* Get the pointer */
290 if (!IS_SYMOP (IC_LEFT (dic
)))
292 ptrsym
= OP_SYMBOL (IC_LEFT (dic
));
294 /* Must be a rematerializable pointer */
298 /* The pointer type must be uncasted */
299 if (IS_CAST_ICODE (ptrsym
->rematiCode
))
302 /* The symbol's live range must not preceed its definition */
303 if (dic
->seq
> sym
->liveFrom
)
306 /* Ok, this is a good candidate for a pseudo symbol. */
307 /* However, we must check for two hazards: */
308 /* 1) The symbol's live range must not include a CALL */
309 /* or PCALL iCode. */
310 /* 2) The symbol's live range must not include any */
311 /* writes to the variable the pointer rematerializes */
312 /* within (to avoid aliasing problems) */
314 /* Find the base symbol the rematerialization is based on */
315 ric
= ptrsym
->rematiCode
;
316 while (ric
->op
== '+' || ric
->op
== '-')
317 ric
= OP_SYMBOL (IC_LEFT (ric
))->rematiCode
;
318 if (IS_CAST_ICODE (ric
))
320 basesym
= OP_SYMBOL (IC_LEFT (ric
));
322 //isGlobal = !basesym->islocal && !basesym->ismyparm;
323 ptrsymDclType
= aggrToPtrDclType (ptrsym
->type
, FALSE
);
326 while (ic
&& ic
->seq
<= sym
->liveTo
)
328 if (!(SKIP_IC3 (ic
) || ic
->op
== IFX
))
330 /* Check for hazard #1 */
331 if ((ic
->op
== CALL
|| ic
->op
== PCALL
) /* && isGlobal */ )
333 if (ic
->seq
<= sym
->liveTo
)
336 /* Check for hazard #2 */
337 else if (POINTER_SET (ic
))
341 if (!IS_SYMOP (IC_RESULT (ic
)))
344 ptrsym2
= OP_SYMBOL (IC_RESULT (ic
));
348 /* Must not be the same base symbol */
349 if (basesym
== ptrBaseRematSym (ptrsym2
))
354 int ptrsym2DclType
= aggrToPtrDclType (ptrsym2
->type
, FALSE
);
356 /* Pointer must have no memory space in common */
357 if (ptrsym2DclType
== ptrsymDclType
|| ptrsym2DclType
== GPOINTER
|| ptrsymDclType
== GPOINTER
)
361 else if (IC_RESULT (ic
))
365 if (!IS_SYMOP (IC_RESULT (ic
)))
368 rsym
= OP_SYMBOL (IC_RESULT (ic
));
370 /* Make sure there is no conflict with another pseudo symbol */
371 if (rsym
->psbase
== basesym
)
373 if (rsym
->isspilt
&& rsym
->usl
.spillLoc
)
374 rsym
= rsym
->usl
.spillLoc
;
375 if (rsym
->psbase
== basesym
)
380 if (ic
->seq
== sym
->liveTo
)
385 /* If the live range went past the end of the defining basic */
386 /* block, then a full analysis is too complicated to attempt */
387 /* here. To be safe, we must assume the worst. */
395 /*--------------------------------------------------------------------*/
396 /* ptrPseudoSymConvert - convert the result of a pointerGet to a */
397 /* pseudo symbol. The pointer must be rematerializable. */
398 /*--------------------------------------------------------------------*/
400 ptrPseudoSymConvert (symbol
* sym
, iCode
* dic
, const char *name
)
402 symbol
*psym
= newSymbol (name
, 1);
403 psym
->psbase
= ptrBaseRematSym (OP_SYMBOL (IC_LEFT (dic
)));
404 psym
->type
= sym
->type
;
405 psym
->etype
= psym
->psbase
->etype
;
407 strcpy (psym
->rname
, psym
->name
);
409 sym
->usl
.spillLoc
= psym
;
410 #if 0 // an alternative fix for bug #480076
411 /* now this is a useless assignment to itself */
412 remiCodeFromeBBlock (ebbs
, dic
);
414 /* now this really is an assignment to itself, make it so;
415 it will be optimized out later */
417 ReplaceOpWithCheaperOp (&IC_RIGHT (dic
), IC_RESULT (dic
));
418 IC_LEFT (dic
) = NULL
;