1 /*-------------------------------------------------------------------------
2 SDCCpeeph.c - The peep hole optimizer: for interpreting the
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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 #define ISCHARDIGIT(c) isdigit((unsigned char)c)
29 #define ISCHARSPACE(c) isspace((unsigned char)c)
30 #define ISCHARALNUM(c) isalnum((unsigned char)c)
32 static peepRule *rootRules = NULL;
33 static peepRule *currRule = NULL;
38 char name[SDCC_NAME_MAX + 1];
43 static hTab *labelHash = NULL;
51 static int hashSymbolName (const char *name);
52 static void buildLabelRefCountHash (lineNode * head);
54 static bool matchLine (char *, char *, hTab **);
55 bool isLabelDefinition (const char *line, const char **start, int *len);
57 #define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *endPl, \
58 lineNode *head, char *cmdLine)
61 void peepRules2pCode(peepRule *);
64 #if !OPT_DISABLE_PIC16
65 void pic16_peepRules2pCode(peepRule *);
68 /*-----------------------------------------------------------------*/
69 /* pcDistance - afinds a label back ward or forward */
70 /*-----------------------------------------------------------------*/
73 pcDistance (lineNode * cpos, char *lbl, bool back)
76 char buff[MAX_PATTERN_LEN];
79 SNPRINTF (buff, sizeof(buff), "%s:", lbl);
85 pl->line[strlen (pl->line) - 1] != ':' &&
87 if (port->peep.getSize) {
88 dist += port->peep.getSize(pl);
94 if (strncmp (pl->line, buff, strlen (buff)) == 0)
106 /*-----------------------------------------------------------------*/
107 /* flat24bitModeAndPortDS390 - */
108 /*-----------------------------------------------------------------*/
109 FBYNAME (flat24bitModeAndPortDS390)
111 return (((strcmp(port->target,"ds390") == 0) ||
112 (strcmp(port->target,"ds400") == 0)) &&
113 (options.model == MODEL_FLAT24));
116 /*-----------------------------------------------------------------*/
117 /* portIsDS390 - return true if port is DS390 */
118 /*-----------------------------------------------------------------*/
119 FBYNAME (portIsDS390)
121 return ((strcmp(port->target,"ds390") == 0) ||
122 (strcmp(port->target,"ds400") == 0));
125 /*-----------------------------------------------------------------*/
126 /* flat24bitMode - will check to see if we are in flat24 mode */
127 /*-----------------------------------------------------------------*/
128 FBYNAME (flat24bitMode)
130 return (options.model == MODEL_FLAT24);
133 /*-----------------------------------------------------------------*/
134 /* xramMovcOption - check if using movc to read xram */
135 /*-----------------------------------------------------------------*/
136 FBYNAME (xramMovcOption)
138 return (options.xram_movc && (strcmp(port->target,"mcs51") == 0));
146 /*-----------------------------------------------------------------*/
147 /* labelInRange - will check to see if label %5 is within range */
148 /*-----------------------------------------------------------------*/
149 FBYNAME (labelInRange)
151 /* assumes that %5 pattern variable has the label name */
152 char *lbl = hTabItemWithKey (vars, 5);
158 /* Don't optimize jumps in a jump table; a more generic test */
159 if (currPl->ic && currPl->ic->op == JUMPTABLE)
162 /* if the previous two instructions are "ljmp"s then don't
163 do it since it can be part of a jump table */
164 if (currPl->prev && currPl->prev->prev &&
165 strstr (currPl->prev->line, "ljmp") &&
166 strstr (currPl->prev->prev->line, "ljmp"))
169 /* calculate the label distance : the jump for reladdr can be
170 +/- 127 bytes, here Iam assuming that an average 8051
171 instruction is 2 bytes long, so if the label is more than
172 63 intructions away, the label is considered out of range
173 for a relative jump. we could get more precise this will
174 suffice for now since it catches > 90% cases */
175 dist = (pcDistance (currPl, lbl, TRUE) +
176 pcDistance (currPl, lbl, FALSE));
178 /* changed to 127, now that pcDistance return actual number of bytes */
179 if (!dist || dist > 127)
186 /*-----------------------------------------------------------------*/
187 /* labelJTInRange - will check to see if label %5 and up are */
189 /* Specifically meant to optimize long (3-byte) jumps to short */
190 /* (2-byte) jumps in jumptables */
191 /*-----------------------------------------------------------------*/
192 FBYNAME (labelJTInRange)
197 if (!getenv("SDCC_SJMP_JUMPTABLE"))
200 /* Only optimize within a jump table */
201 if (currPl->ic && currPl->ic->op != JUMPTABLE)
204 count = elementsInSet( IC_JTLABELS (currPl->ic) );
206 /* check all labels (this is needed if the case statements are unsorted) */
207 for (i=0; i<count; i++)
209 /* assumes that the %5 pattern variable has the first ljmp label */
210 lbl = hTabItemWithKey (vars, 5+i);
214 dist = pcDistance (currPl, lbl, FALSE);
216 /* three terms used to calculate allowable distance */
217 // printf("\nlabel %s %i dist %i cdist 0x%02x 0x%02x\n", lbl, i, dist, dist -(count-i-1)-(7+3*i), 127+(count-i-1)+(7+3*i) - dist);
219 dist > 127+ /* range of sjmp */
220 (7+3*i)+ /* offset between this jump and currPl,
221 should use pcDistance instead? */
222 (count-i-1) /* if peephole applies distance is shortened */
230 /*-----------------------------------------------------------------*/
231 /* labelIsReturnOnly - Check if label %5 is followed by RET */
232 /*-----------------------------------------------------------------*/
233 FBYNAME (labelIsReturnOnly)
235 /* assumes that %5 pattern variable has the label name */
236 const char *label, *p;
241 label = hTabItemWithKey (vars, 5);
242 if (!label) return FALSE;
245 for(pl = currPl; pl; pl = pl->next) {
246 if (pl->line && !pl->isDebug && !pl->isComment &&
247 pl->line[strlen(pl->line)-1] == ':') {
248 if (strncmp(pl->line, label, len) == 0) break; /* Found Label */
249 if (strlen(pl->line) != 7 || !ISCHARDIGIT(*(pl->line)) ||
250 !ISCHARDIGIT(*(pl->line+1)) || !ISCHARDIGIT(*(pl->line+2)) ||
251 !ISCHARDIGIT(*(pl->line+3)) || !ISCHARDIGIT(*(pl->line+4)) ||
252 *(pl->line+5) != '$') {
253 return FALSE; /* non-local label encountered */
257 if (!pl) return FALSE; /* did not find the label */
259 while (pl && (pl->isDebug || pl->isComment))
261 if (!pl || !pl->line || pl->isDebug) return FALSE; /* next line not valid */
263 for (p = pl->line; *p && ISCHARSPACE(*p); p++)
269 if (strcmp(p, retInst) == 0) return TRUE;
274 /*-----------------------------------------------------------------*/
275 /* okToRemoveSLOC - Check if label %1 is a SLOC and not other */
276 /* usage of it in the code depends on a value from this section */
277 /*-----------------------------------------------------------------*/
278 FBYNAME (okToRemoveSLOC)
281 const char *sloc, *p;
282 int dummy1, dummy2, dummy3;
284 /* assumes that %1 as the SLOC name */
285 sloc = hTabItemWithKey (vars, 1);
286 if (sloc == NULL) return FALSE;
287 p = strstr(sloc, "sloc");
288 if (p == NULL) return FALSE;
290 if (sscanf(p, "%d_%d_%d", &dummy1, &dummy2, &dummy3) != 3) return FALSE;
291 /*TODO: ultra-paranoid: get funtion name from "head" and check that */
292 /* the sloc name begins with that. Probably not really necessary */
294 /* Look for any occurance of this SLOC before the peephole match */
295 for (pl = currPl->prev; pl; pl = pl->prev) {
296 if (pl->line && !pl->isDebug && !pl->isComment
297 && *pl->line != ';' && strstr(pl->line, sloc))
300 /* Look for any occurance of this SLOC after the peephole match */
301 for (pl = endPl->next; pl; pl = pl->next) {
302 if (pl->line && !pl->isDebug && !pl->isComment
303 && *pl->line != ';' && strstr(pl->line, sloc))
306 return TRUE; /* safe for a peephole to remove it :) */
310 /*-----------------------------------------------------------------*/
311 /* operandsNotSame - check if %1 & %2 are the same */
312 /*-----------------------------------------------------------------*/
313 FBYNAME (operandsNotSame)
315 char *op1 = hTabItemWithKey (vars, 1);
316 char *op2 = hTabItemWithKey (vars, 2);
318 if (strcmp (op1, op2) == 0)
324 /*-----------------------------------------------------------------*/
325 /* operandsNotSame3- check if any pair of %1,%2,%3 are the same */
326 /*-----------------------------------------------------------------*/
327 FBYNAME (operandsNotSame3)
329 char *op1 = hTabItemWithKey (vars, 1);
330 char *op2 = hTabItemWithKey (vars, 2);
331 char *op3 = hTabItemWithKey (vars, 3);
333 if ( (strcmp (op1, op2) == 0) ||
334 (strcmp (op1, op3) == 0) ||
335 (strcmp (op2, op3) == 0) )
341 /*-----------------------------------------------------------------*/
342 /* operandsNotSame4- check if any pair of %1,%2,%3,.. are the same */
343 /*-----------------------------------------------------------------*/
344 FBYNAME (operandsNotSame4)
346 char *op1 = hTabItemWithKey (vars, 1);
347 char *op2 = hTabItemWithKey (vars, 2);
348 char *op3 = hTabItemWithKey (vars, 3);
349 char *op4 = hTabItemWithKey (vars, 4);
351 if ( (strcmp (op1, op2) == 0) ||
352 (strcmp (op1, op3) == 0) ||
353 (strcmp (op1, op4) == 0) ||
354 (strcmp (op2, op3) == 0) ||
355 (strcmp (op2, op4) == 0) ||
356 (strcmp (op3, op4) == 0) )
362 /*-----------------------------------------------------------------*/
363 /* operandsNotSame5- check if any pair of %1,%2,%3,.. are the same */
364 /*-----------------------------------------------------------------*/
365 FBYNAME (operandsNotSame5)
367 char *op1 = hTabItemWithKey (vars, 1);
368 char *op2 = hTabItemWithKey (vars, 2);
369 char *op3 = hTabItemWithKey (vars, 3);
370 char *op4 = hTabItemWithKey (vars, 4);
371 char *op5 = hTabItemWithKey (vars, 5);
373 if ( (strcmp (op1, op2) == 0) ||
374 (strcmp (op1, op3) == 0) ||
375 (strcmp (op1, op4) == 0) ||
376 (strcmp (op1, op5) == 0) ||
377 (strcmp (op2, op3) == 0) ||
378 (strcmp (op2, op4) == 0) ||
379 (strcmp (op2, op5) == 0) ||
380 (strcmp (op3, op4) == 0) ||
381 (strcmp (op3, op5) == 0) ||
382 (strcmp (op4, op5) == 0) )
388 /*-----------------------------------------------------------------*/
389 /* operandsNotSame6- check if any pair of %1,%2,%3,.. are the same */
390 /*-----------------------------------------------------------------*/
391 FBYNAME (operandsNotSame6)
393 char *op1 = hTabItemWithKey (vars, 1);
394 char *op2 = hTabItemWithKey (vars, 2);
395 char *op3 = hTabItemWithKey (vars, 3);
396 char *op4 = hTabItemWithKey (vars, 4);
397 char *op5 = hTabItemWithKey (vars, 5);
398 char *op6 = hTabItemWithKey (vars, 6);
400 if ( (strcmp (op1, op2) == 0) ||
401 (strcmp (op1, op3) == 0) ||
402 (strcmp (op1, op4) == 0) ||
403 (strcmp (op1, op5) == 0) ||
404 (strcmp (op1, op6) == 0) ||
405 (strcmp (op2, op3) == 0) ||
406 (strcmp (op2, op4) == 0) ||
407 (strcmp (op2, op5) == 0) ||
408 (strcmp (op2, op6) == 0) ||
409 (strcmp (op3, op4) == 0) ||
410 (strcmp (op3, op5) == 0) ||
411 (strcmp (op3, op6) == 0) ||
412 (strcmp (op4, op5) == 0) ||
413 (strcmp (op4, op6) == 0) ||
414 (strcmp (op5, op6) == 0) )
421 /*-----------------------------------------------------------------*/
422 /* operandsNotSame7- check if any pair of %1,%2,%3,.. are the same */
423 /*-----------------------------------------------------------------*/
424 FBYNAME (operandsNotSame7)
426 char *op1 = hTabItemWithKey (vars, 1);
427 char *op2 = hTabItemWithKey (vars, 2);
428 char *op3 = hTabItemWithKey (vars, 3);
429 char *op4 = hTabItemWithKey (vars, 4);
430 char *op5 = hTabItemWithKey (vars, 5);
431 char *op6 = hTabItemWithKey (vars, 6);
432 char *op7 = hTabItemWithKey (vars, 7);
434 if ( (strcmp (op1, op2) == 0) ||
435 (strcmp (op1, op3) == 0) ||
436 (strcmp (op1, op4) == 0) ||
437 (strcmp (op1, op5) == 0) ||
438 (strcmp (op1, op6) == 0) ||
439 (strcmp (op1, op7) == 0) ||
440 (strcmp (op2, op3) == 0) ||
441 (strcmp (op2, op4) == 0) ||
442 (strcmp (op2, op5) == 0) ||
443 (strcmp (op2, op6) == 0) ||
444 (strcmp (op2, op7) == 0) ||
445 (strcmp (op3, op4) == 0) ||
446 (strcmp (op3, op5) == 0) ||
447 (strcmp (op3, op6) == 0) ||
448 (strcmp (op3, op7) == 0) ||
449 (strcmp (op4, op5) == 0) ||
450 (strcmp (op4, op6) == 0) ||
451 (strcmp (op4, op7) == 0) ||
452 (strcmp (op5, op6) == 0) ||
453 (strcmp (op5, op7) == 0) ||
454 (strcmp (op6, op7) == 0) )
460 /*-----------------------------------------------------------------*/
461 /* operandsNotSame8- check if any pair of %1,%2,%3,.. are the same */
462 /*-----------------------------------------------------------------*/
463 FBYNAME (operandsNotSame8)
465 char *op1 = hTabItemWithKey (vars, 1);
466 char *op2 = hTabItemWithKey (vars, 2);
467 char *op3 = hTabItemWithKey (vars, 3);
468 char *op4 = hTabItemWithKey (vars, 4);
469 char *op5 = hTabItemWithKey (vars, 5);
470 char *op6 = hTabItemWithKey (vars, 6);
471 char *op7 = hTabItemWithKey (vars, 7);
472 char *op8 = hTabItemWithKey (vars, 8);
474 if ( (strcmp (op1, op2) == 0) ||
475 (strcmp (op1, op3) == 0) ||
476 (strcmp (op1, op4) == 0) ||
477 (strcmp (op1, op5) == 0) ||
478 (strcmp (op1, op6) == 0) ||
479 (strcmp (op1, op7) == 0) ||
480 (strcmp (op1, op8) == 0) ||
481 (strcmp (op2, op3) == 0) ||
482 (strcmp (op2, op4) == 0) ||
483 (strcmp (op2, op5) == 0) ||
484 (strcmp (op2, op6) == 0) ||
485 (strcmp (op2, op7) == 0) ||
486 (strcmp (op2, op8) == 0) ||
487 (strcmp (op3, op4) == 0) ||
488 (strcmp (op3, op5) == 0) ||
489 (strcmp (op3, op6) == 0) ||
490 (strcmp (op3, op7) == 0) ||
491 (strcmp (op3, op8) == 0) ||
492 (strcmp (op4, op5) == 0) ||
493 (strcmp (op4, op6) == 0) ||
494 (strcmp (op4, op7) == 0) ||
495 (strcmp (op4, op8) == 0) ||
496 (strcmp (op5, op6) == 0) ||
497 (strcmp (op5, op7) == 0) ||
498 (strcmp (op5, op8) == 0) ||
499 (strcmp (op6, op7) == 0) ||
500 (strcmp (op6, op8) == 0) ||
501 (strcmp (op7, op8) == 0) )
510 * takes two parameters: a variable (bound to a label name)
511 * and an expected reference count.
513 * Returns TRUE if that label is defined and referenced exactly
514 * the given number of times.
516 FBYNAME (labelRefCount)
518 int varNumber, expectedRefCount;
521 /* If we don't have the label hash table yet, build it. */
524 buildLabelRefCountHash (head);
527 if (sscanf (cmdLine, "%*[ \t%]%d %d", &varNumber, &expectedRefCount) == 2)
529 char *label = hTabItemWithKey (vars, varNumber);
533 labelHashEntry *entry;
535 entry = hTabFirstItemWK (labelHash, hashSymbolName (label));
539 if (!strcmp (label, entry->name))
543 entry = hTabNextItemWK (labelHash);
549 fprintf (stderr, "labelRefCount: %s has refCount %d, want %d\n",
550 label, entry->refCount, expectedRefCount);
553 rc = (expectedRefCount == entry->refCount);
557 fprintf (stderr, "*** internal error: no label has entry for"
558 " %s in labelRefCount peephole.\n",
564 fprintf (stderr, "*** internal error: var %d not bound"
565 " in peephole labelRefCount rule.\n",
573 "*** internal error: labelRefCount peephole restriction"
574 " malformed: %s\n", cmdLine);
580 /* labelRefCountChange:
581 * takes two parameters: a variable (bound to a label name)
582 * and a signed int for changing the reference count.
584 * Please note, this function is not a conditional. It unconditionally
585 * changes the label. It should be passed as the 'last' function
586 * so it only is applied if all other conditions have been met.
588 * should always return TRUE
590 FBYNAME (labelRefCountChange)
592 int varNumber, RefCountDelta;
595 /* If we don't have the label hash table yet, build it. */
598 buildLabelRefCountHash (head);
601 if (sscanf (cmdLine, "%*[ \t%]%d %i", &varNumber, &RefCountDelta) == 2)
603 char *label = hTabItemWithKey (vars, varNumber);
607 labelHashEntry *entry;
609 entry = hTabFirstItemWK (labelHash, hashSymbolName (label));
613 if (!strcmp (label, entry->name))
617 entry = hTabNextItemWK (labelHash);
621 if (0 <= entry->refCount + RefCountDelta)
623 entry->refCount += RefCountDelta;
628 fprintf (stderr, "*** internal error: label %s may not get"
629 " negative refCount in %s peephole.\n",
630 label, __FUNCTION__);
635 fprintf (stderr, "*** internal error: no label has entry for"
636 " %s in %s peephole.\n",
637 label, __FUNCTION__);
642 fprintf (stderr, "*** internal error: var %d not bound"
643 " in peephole %s rule.\n",
644 varNumber, __FUNCTION__);
650 "*** internal error: labelRefCount peephole restriction"
651 " malformed: %s\n", cmdLine);
657 /* Within the context of the lines currPl through endPl, determine
658 ** if the variable var contains a symbol that is volatile. Returns
659 ** TRUE only if it is certain that this was not volatile (the symbol
660 ** was found and not volatile, or var was a constant or CPU register).
661 ** Returns FALSE if the symbol was found and volatile, the symbol was
662 ** not found, or var was a indirect/pointer addressing mode.
665 notVolatileVariable(char *var, lineNode *currPl, lineNode *endPl)
667 char symname[SDCC_NAME_MAX + 1];
674 /* Can't tell if indirect accesses are volatile or not, so
675 ** assume they are, just to be safe.
677 if (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_DS400)
682 if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
684 if (strstr(var,"(bc)"))
686 if (strstr(var,"(de)"))
688 if (strstr(var,"(hl)"))
690 if (strstr(var,"(ix"))
692 if (strstr(var,"(iy"))
696 /* Extract a symbol name from the variable */
697 while (*vp && (*vp!='_'))
699 while (*vp && (ISCHARALNUM(*vp) || *vp=='_'))
705 /* Nothing resembling a symbol name was found, so it can't
712 for (cl = currPl; cl!=endPl->next; cl = cl->next)
714 if (cl->ic && (cl->ic!=last_ic))
720 op = IC_COND (cl->ic);
721 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
722 return !op->isvolatile;
724 op = IC_JTCOND (cl->ic);
725 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
726 return !op->isvolatile;
728 op = IC_LEFT (cl->ic);
729 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
730 return !op->isvolatile;
731 op = IC_RIGHT (cl->ic);
732 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
733 return !op->isvolatile;
734 op = IC_RESULT (cl->ic);
735 if (IS_SYMOP (op) && !strcmp(OP_SYMBOL (op)->rname,symname) )
736 return !op->isvolatile;
741 /* Couldn't find the symbol for some reason. Assume volatile. */
747 * This rule restriction has two different behaviours depending on
748 * the number of parameters given.
750 * if notVolatile (no parameters given)
751 * The rule is applied only if none of the iCodes originating
752 * the matched pattern reference a volatile operand.
754 * if notVolatile %1 ... (one or more parameters given)
755 * The rule is applied if the parameters are not expressions
756 * containing volatile symbols and are not pointer accesses.
759 FBYNAME (notVolatile)
770 /* If no parameters given, just scan the iCodes for volatile operands */
771 for (cl = currPl; cl!=endPl->next; cl = cl->next)
778 op = IC_COND (cl->ic);
779 if (IS_SYMOP (op) && op->isvolatile)
782 op = IC_JTCOND (cl->ic);
783 if (IS_SYMOP (op) && op->isvolatile)
786 op = IC_LEFT (cl->ic);
787 if (IS_SYMOP (op) && op->isvolatile)
789 op = IC_RIGHT (cl->ic);
790 if (IS_SYMOP (op) && op->isvolatile)
792 op = IC_RESULT (cl->ic);
793 if (IS_SYMOP (op) && op->isvolatile)
801 /* There were parameters; check the volatility of each */
802 while (*cmdLine && ISCHARSPACE(*cmdLine))
809 if (!ISCHARDIGIT(*cmdLine))
811 varNumber = strtol(cmdLine, &digitend, 10);
813 while (*cmdLine && ISCHARSPACE(*cmdLine))
816 var = hTabItemWithKey (vars, varNumber);
820 notvol = notVolatileVariable (var, currPl, endPl);
826 fprintf (stderr, "*** internal error: var %d not bound"
827 " in peephole notVolatile rule.\n",
838 "*** internal error: notVolatile peephole restriction"
839 " malformed: %s\n", cmdLine);
844 /*------------------------------------------------------------------*/
845 /* setFromConditionArgs - parse a peephole condition's arguments */
846 /* to produce a set of strings, one per argument. Variables %x will */
847 /* be replaced with their values. String literals (in single quotes)*/
848 /* are accepted and return in unquoted form. */
849 /*------------------------------------------------------------------*/
851 setFromConditionArgs (char *cmdLine, hTab * vars)
856 set *operands = NULL;
861 while (*cmdLine && ISCHARSPACE(*cmdLine))
869 if (!ISCHARDIGIT(*cmdLine))
871 varNumber = strtol(cmdLine, &digitend, 10);
874 var = hTabItemWithKey (vars, varNumber);
878 addSetHead (&operands, var);
883 else if (*cmdLine == '\'' )
885 char quote = *cmdLine;
888 while (*cmdLine && *cmdLine != quote)
890 if (*cmdLine == quote)
894 addSetHead (&operands, var);
899 while (*cmdLine && ISCHARSPACE(*cmdLine))
906 deleteSet (&operands);
911 operandBaseName (const char *op)
913 if (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_DS400)
915 if (!strcmp (op, "acc") || !strncmp (op, "acc.", 4))
917 if (!strncmp (op, "ar", 2) && ISCHARDIGIT(*(op+2)) && !*(op+3))
925 /*-------------------------------------------------------------------*/
926 /* operandsNotRelated - returns true of the condition's operands are */
927 /* not related (taking into account register name aliases). N-way */
928 /* comparison performed between all operands. */
929 /*-------------------------------------------------------------------*/
930 FBYNAME (operandsNotRelated)
933 const char *op1, *op2;
935 operands = setFromConditionArgs (cmdLine, vars);
940 "*** internal error: operandsNotRelated peephole restriction"
941 " malformed: %s\n", cmdLine);
945 while ((op1 = setFirstItem (operands)))
947 deleteSetItem (&operands, (void*)op1);
948 op1 = operandBaseName (op1);
950 for (op2 = setFirstItem (operands); op2; op2 = setNextItem (operands))
952 op2 = operandBaseName (op2);
953 if (strcmp (op1, op2) == 0)
955 deleteSet (&operands);
961 deleteSet (&operands);
966 /*-------------------------------------------------------------------*/
967 /* operandsLiteral - returns true of the condition's operands are */
969 /*-------------------------------------------------------------------*/
970 FBYNAME (operandsLiteral)
975 operands = setFromConditionArgs (cmdLine, vars);
980 "*** internal error: operandsLiteral peephole restriction"
981 " malformed: %s\n", cmdLine);
985 for (op = setFirstItem (operands); op; op = setNextItem (operands))
989 deleteSet (&operands);
994 deleteSet (&operands);
999 /*-----------------------------------------------------------------*/
1000 /* callFuncByName - calls a function as defined in the table */
1001 /*-----------------------------------------------------------------*/
1003 callFuncByName (char *fname,
1012 int (*func) (hTab *, lineNode *, lineNode *, lineNode *, char *);
1017 "labelInRange", labelInRange
1021 "labelJTInRange", labelJTInRange
1025 "operandsNotSame", operandsNotSame
1029 "operandsNotSame3", operandsNotSame3
1033 "operandsNotSame4", operandsNotSame4
1037 "operandsNotSame5", operandsNotSame5
1041 "operandsNotSame6", operandsNotSame6
1045 "operandsNotSame7", operandsNotSame7
1049 "operandsNotSame8", operandsNotSame8
1053 "24bitMode", flat24bitMode
1057 "xramMovcOption", xramMovcOption
1061 "labelRefCount", labelRefCount
1065 "portIsDS390", portIsDS390
1068 "labelIsReturnOnly", labelIsReturnOnly
1071 "okToRemoveSLOC", okToRemoveSLOC
1074 "24bitModeAndPortDS390", flat24bitModeAndPortDS390
1077 "notVolatile", notVolatile
1080 "operandsNotRelated", operandsNotRelated
1083 "operandsLiteral", operandsLiteral
1086 "labelRefCountChange", labelRefCountChange
1090 char *cmdCopy, *funcName, *funcArgs, *cmdTerm;
1094 /* Isolate the function name part (we are passed the full condition
1095 * string including arguments)
1097 cmdTerm = cmdCopy = Safe_strdup(fname);
1101 funcArgs = funcName = cmdTerm;
1102 while ((c = *funcArgs) && c != ' ' && c != '\t' && c != '(')
1104 *funcArgs = '\0'; /* terminate the function name */
1108 /* Find the start of the arguments */
1109 if (c == ' ' || c == '\t')
1110 while ((c = *funcArgs) && (c == ' ' || c == '\t'))
1113 /* If the arguments started with an opening parenthesis, */
1114 /* use the closing parenthesis for the end of the */
1115 /* arguments and look for the start of another condition */
1116 /* that can optionally follow. If there was no opening */
1117 /* parethesis, then everything that follows are arguments */
1118 /* and there can be no additional conditions. */
1122 while ((c = *cmdTerm) && c != ')')
1124 *cmdTerm = '\0'; /* terminate the arguments */
1128 while ((c = *cmdTerm) && (c == ' ' || c == '\t' || c == ','))
1134 cmdTerm = NULL; /* closing parenthesis missing */
1143 for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++)
1145 if (strcmp (ftab[i].fname, funcName) == 0)
1147 rc = (*ftab[i].func) (vars, currPl, endPl, head,
1156 "could not find named function \"%s\" in "
1157 "peephole function table\n",
1159 // If the function couldn't be found, let's assume it's
1160 // a bad rule and refuse it.
1165 while (rc && cmdTerm);
1172 /*-----------------------------------------------------------------*/
1173 /* printLine - prints a line chain into a given file */
1174 /*-----------------------------------------------------------------*/
1176 printLine (lineNode * head, FILE * of)
1178 iCode *last_ic = NULL;
1179 bool debug_iCode_tracking = (getenv("DEBUG_ICODE_TRACKING")!=NULL);
1186 if (head->ic!=last_ic)
1189 if (debug_iCode_tracking)
1192 fprintf (of, "; block = %d, seq = %d\n",
1193 head->ic->block, head->ic->seq);
1195 fprintf (of, "; iCode lost\n");
1199 /* don't indent comments & labels */
1201 (*head->line == ';' ||
1202 head->line[strlen (head->line) - 1] == ':')) {
1203 fprintf (of, "%s\n", head->line);
1205 if (head->isInline && *head->line=='#') {
1206 // comment out preprocessor directives in inline asm
1209 fprintf (of, "\t%s\n", head->line);
1215 /*-----------------------------------------------------------------*/
1216 /* newPeepRule - creates a new peeprule and attach it to the root */
1217 /*-----------------------------------------------------------------*/
1219 newPeepRule (lineNode * match,
1226 pr = Safe_alloc ( sizeof (peepRule));
1228 pr->replace = replace;
1229 pr->restart = restart;
1233 pr->cond = Safe_strdup (cond);
1238 pr->vars = newHashTable (100);
1240 /* if root is empty */
1242 rootRules = currRule = pr;
1244 currRule = currRule->next = pr;
1249 /*-----------------------------------------------------------------*/
1250 /* newLineNode - creates a new peep line */
1251 /*-----------------------------------------------------------------*/
1253 newLineNode (char *line)
1257 pl = Safe_alloc ( sizeof (lineNode));
1258 pl->line = Safe_strdup (line);
1263 /*-----------------------------------------------------------------*/
1264 /* connectLine - connects two lines */
1265 /*-----------------------------------------------------------------*/
1267 connectLine (lineNode * pl1, lineNode * pl2)
1271 fprintf (stderr, "trying to connect null line\n");
1281 #define SKIP_SPACE(x,y) { while (*x && (ISCHARSPACE(*x) || *x == '\n')) x++; \
1282 if (!*x) { fprintf(stderr,y); return ; } }
1284 #define EXPECT_STR(x,y,z) { while (*x && strncmp(x,y,strlen(y))) x++ ; \
1285 if (!*x) { fprintf(stderr,z); return ; } }
1286 #define EXPECT_CHR(x,y,z) { while (*x && *x != y) x++ ; \
1287 if (!*x) { fprintf(stderr,z); return ; } }
1289 /*-----------------------------------------------------------------*/
1290 /* getPeepLine - parses the peep lines */
1291 /*-----------------------------------------------------------------*/
1293 getPeepLine (lineNode ** head, char **bpp)
1295 char lines[MAX_PATTERN_LEN];
1299 lineNode *currL = NULL;
1306 fprintf (stderr, "unexpected end of match pattern\n");
1313 while (ISCHARSPACE (*bp) ||
1324 /* read till end of line */
1326 while ((*bp != '\n' && *bp != '}') && *bp)
1331 while (*lp && ISCHARSPACE(*lp))
1333 isComment = (*lp == ';');
1335 if (!isComment || (isComment && !options.noPeepComments))
1338 *head = currL = newLineNode (lines);
1340 currL = connectLine (currL, newLineNode (lines));
1341 currL->isComment = isComment;
1349 /*-----------------------------------------------------------------*/
1350 /* readRules - reads the rules from a string buffer */
1351 /*-----------------------------------------------------------------*/
1353 readRules (char *bp)
1356 char lines[MAX_PATTERN_LEN];
1360 lineNode *currL = NULL;
1366 /* look for the token "replace" that is the
1368 while (*bp && strncmp (bp, "replace", 7))
1375 /* then look for either "restart" or '{' */
1376 while (strncmp (bp, "restart", 7) &&
1383 fprintf (stderr, "expected 'restart' or '{'\n");
1391 { /* must be restart */
1393 bp += strlen ("restart");
1395 EXPECT_CHR (bp, '{', "expected '{'\n");
1399 /* skip thru all the blank space */
1400 SKIP_SPACE (bp, "unexpected end of rule\n");
1402 match = replace = currL = NULL;
1403 /* we are the start of a rule */
1404 getPeepLine (&match, &bp);
1406 /* now look for by */
1407 EXPECT_STR (bp, "by", "expected 'by'\n");
1409 /* then look for a '{' */
1410 EXPECT_CHR (bp, '{', "expected '{'\n");
1413 /* save char position (needed for generating error msg) */
1416 SKIP_SPACE (bp, "unexpected end of rule\n");
1417 getPeepLine (&replace, &bp);
1419 /* look for a 'if' */
1420 while ((ISCHARSPACE (*bp) || *bp == '\n') && *bp)
1423 if (strncmp (bp, "if", 2) == 0)
1426 while ((ISCHARSPACE (*bp) || *bp == '\n') && *bp)
1430 fprintf (stderr, "expected condition name\n");
1434 /* look for the condition */
1436 while (*bp && (*bp != '\n'))
1442 newPeepRule (match, replace, lines, restart);
1446 if (*bp && strncmp (bp, "replace", 7))
1448 /* not the start of a new peeprule, so "if" should be here */
1453 /* go to the start of the line following "{" of the "by" token */
1454 while (*rp && (*rp == '\n'))
1457 /* copy text of rule starting with line after "by {" */
1459 while (*rp && (rp < bp) && ((cp - strbuff) < sizeof(strbuff)))
1462 /* and now the rest of the line */
1463 while (*rp && (*rp != '\n') && ((cp - strbuff) < sizeof(strbuff)))
1467 fprintf (stderr, "%s\nexpected '} if ...'\n", strbuff);
1470 newPeepRule (match, replace, NULL, restart);
1476 /*-----------------------------------------------------------------*/
1477 /* keyForVar - returns the numeric key for a var */
1478 /*-----------------------------------------------------------------*/
1484 while (ISCHARDIGIT (*d))
1493 /*-----------------------------------------------------------------*/
1494 /* bindVar - binds a value to a variable in the given hashtable */
1495 /*-----------------------------------------------------------------*/
1497 bindVar (int key, char **s, hTab ** vtab)
1499 char vval[MAX_PATTERN_LEN];
1503 /* first get the value of the variable */
1505 /* the value is ended by a ',' or space or newline or null or ) */
1508 !ISCHARSPACE (*vvx) &&
1514 /* if we find a '(' then we need to balance it */
1526 // include the trailing ')'
1535 vvx = traceAlloc (&_G.values, Safe_strdup(vval));
1537 hTabAddItem (vtab, key, vvx);
1540 /*-----------------------------------------------------------------*/
1541 /* matchLine - matches one line */
1542 /*-----------------------------------------------------------------*/
1544 matchLine (char *s, char *d, hTab ** vars)
1553 /* skip white space in both */
1554 while (ISCHARSPACE (*s))
1556 while (ISCHARSPACE (*d))
1559 /* if the destination is a var */
1560 if (*d == '%' && ISCHARDIGIT (*(d + 1)) && vars)
1562 char *v = hTabItemWithKey (*vars, keyForVar (d + 1));
1563 /* if the variable is already bound
1564 then it MUST match with dest */
1572 /* variable not bound we need to
1574 bindVar (keyForVar (d + 1), &s, vars);
1576 /* in either case go past the variable */
1578 while (ISCHARDIGIT (*d))
1581 while (ISCHARSPACE (*s))
1583 while (ISCHARSPACE (*d))
1587 /* they should be an exact match other wise */
1596 /* get rid of the trailing spaces
1597 in both source & destination */
1599 while (ISCHARSPACE (*s))
1603 while (ISCHARSPACE (*d))
1606 /* after all this if only one of them
1607 has something left over then no match */
1614 /*-----------------------------------------------------------------*/
1615 /* matchRule - matches a all the rule lines */
1616 /*-----------------------------------------------------------------*/
1618 matchRule (lineNode * pl,
1623 lineNode *spl; /* source pl */
1624 lineNode *rpl; /* rule peep line */
1626 /* setToNull((void *) &pr->vars); */
1627 /* pr->vars = newHashTable(100); */
1629 /* for all the lines defined in the rule */
1635 /* if the source line starts with a ';' then
1636 comment line don't process or the source line
1637 contains == . debugger information skip it */
1639 (*spl->line == ';' || spl->isDebug))
1645 if (!matchLine (spl->line, rpl->line, &pr->vars))
1653 /* if rules ended */
1656 /* if this rule has additional conditions */
1659 if (callFuncByName (pr->cond, pr->vars, pl, spl, head))
1678 reassociate_ic_down (lineNode *shead, lineNode *stail,
1679 lineNode *rhead, lineNode *rtail)
1681 lineNode *csl; /* current source line */
1682 lineNode *crl; /* current replacement line */
1688 /* skip over any comments */
1689 while (csl!=stail->next && csl->isComment)
1691 while (crl!=rtail->next && crl->isComment)
1694 /* quit if we reach the end */
1695 if ((csl==stail->next) || (crl==rtail->next) || crl->ic)
1698 if (matchLine(csl->line,crl->line,NULL))
1710 reassociate_ic_up (lineNode *shead, lineNode *stail,
1711 lineNode *rhead, lineNode *rtail)
1713 lineNode *csl; /* current source line */
1714 lineNode *crl; /* current replacement line */
1720 /* skip over any comments */
1721 while (csl!=shead->prev && csl->isComment)
1723 while (crl!=rhead->prev && crl->isComment)
1726 /* quit if we reach the end */
1727 if ((csl==shead->prev) || (crl==rhead->prev) || crl->ic)
1730 if (matchLine(csl->line,crl->line,NULL))
1741 /*------------------------------------------------------------------*/
1742 /* reassociate_ic - reassociate replacement lines with origin iCode */
1743 /*------------------------------------------------------------------*/
1745 reassociate_ic (lineNode *shead, lineNode *stail,
1746 lineNode *rhead, lineNode *rtail)
1748 lineNode *csl; /* current source line */
1749 lineNode *crl; /* current replacement line */
1753 /* Check to see if all the source lines (excluding comments) came
1754 ** for the same iCode
1757 for (csl=shead;csl!=stail->next;csl=csl->next)
1758 if (csl->ic && !csl->isComment)
1763 single_iCode = (ic!=NULL);
1764 for (csl=shead;csl!=stail->next;csl=csl->next)
1765 if ((csl->ic != ic) && !csl->isComment)
1767 /* More than one iCode was found. However, if it's just the
1768 ** last line with the different iCode and it was not changed
1769 ** in the replacement, everything else must be the first iCode.
1771 if ((csl==stail) && matchLine (stail->line, rtail->line, NULL))
1773 rtail->ic = stail->ic;
1774 for (crl=rhead;crl!=rtail;crl=crl->next)
1779 single_iCode = FALSE;
1783 /* If all of the source lines came from the same iCode, then so have
1784 ** all of the replacement lines too.
1788 for (crl=rhead;crl!=rtail->next;crl=crl->next)
1793 /* The source lines span iCodes, so we may end up with replacement
1794 ** lines that we don't know which iCode(s) to associate with. Do the
1795 ** best we can by using the following strategies:
1796 ** 1) Start at the top and scan down. As long as the source line
1797 ** matches the replacement line, they have the same iCode.
1798 ** 2) Start at the bottom and scan up. As long as the source line
1799 ** matches the replacement line, they have the same iCode.
1800 ** 3) For any label in the source, look for a matching label in
1801 ** the replacment. If found, they have the same iCode. From
1802 ** these matching labels, scan down for additional matching
1803 ** lines; if found, they also have the same iCode.
1806 /* Strategy #1: Start at the top and scan down for matches
1808 reassociate_ic_down(shead,stail,rhead,rtail);
1810 /* Strategy #2: Start at the bottom and scan up for matches
1812 reassociate_ic_up(shead,stail,rhead,rtail);
1814 /* Strategy #3: Try to match labels
1819 const char *labelStart;
1822 /* skip over any comments */
1823 while (csl!=stail->next && csl->isComment)
1825 if (csl==stail->next)
1828 if (isLabelDefinition(csl->line, &labelStart, &labelLength))
1830 /* found a source line label; look for it in the replacment lines */
1834 while (crl!=rtail->next && crl->isComment)
1836 if (crl==rtail->next)
1838 if (matchLine(csl->line, crl->line, NULL))
1840 reassociate_ic_down(csl,stail,crl,rtail);
1850 /* Try to assign a meaningful iCode to any comment that is missing
1851 one. Since they are comments, it's ok to make mistakes; we are just
1852 trying to improve continuity to simplify other tests.
1855 for (crl=rtail;crl!=rhead->prev;crl=crl->prev)
1857 if (!crl->ic && ic && crl->isComment)
1864 /*-----------------------------------------------------------------*/
1865 /* replaceRule - does replacement of a matching pattern */
1866 /*-----------------------------------------------------------------*/
1868 replaceRule (lineNode ** shead, lineNode * stail, peepRule * pr)
1870 lineNode *cl = NULL;
1871 lineNode *pl = NULL, *lhead = NULL;
1872 /* a long function name and long variable name can evaluate to
1873 4x max pattern length e.g. "mov dptr,((fie_var>>8)<<8)+fie_var" */
1874 char lb[MAX_PATTERN_LEN*4];
1876 lineNode *comment = NULL;
1878 /* collect all the comment lines in the source */
1879 for (cl = *shead; cl != stail; cl = cl->next)
1881 if (cl->line && (*cl->line == ';' || cl->isDebug))
1883 pl = (pl ? connectLine (pl, newLineNode (cl->line)) :
1884 (comment = newLineNode (cl->line)));
1885 pl->isDebug = cl->isDebug;
1886 pl->isComment = cl->isComment || (*cl->line == ';');
1891 /* for all the lines in the replacement pattern do */
1892 for (pl = pr->replace; pl; pl = pl->next)
1902 /* if the line contains a variable */
1903 if (*l == '%' && ISCHARDIGIT (*(l + 1)))
1905 v = hTabItemWithKey (pr->vars, keyForVar (l + 1));
1908 fprintf (stderr, "used unbound variable in replacement\n");
1916 while (ISCHARDIGIT (*l)) {
1926 cl = connectLine (cl, newLineNode (lb));
1928 lhead = cl = newLineNode (lb);
1929 cl->isComment = pl->isComment;
1932 /* add the comments if any to the head of list */
1935 lineNode *lc = comment;
1946 /* determine which iCodes the replacment lines relate to */
1947 reassociate_ic(*shead,stail,lhead,cl);
1949 /* now we need to connect / replace the original chain */
1950 /* if there is a prev then change it */
1953 (*shead)->prev->next = lhead;
1954 lhead->prev = (*shead)->prev;
1957 /* now for the tail */
1958 if (stail && stail->next)
1960 stail->next->prev = cl;
1962 cl->next = stail->next;
1967 /* the replacement is empty - delete the source lines */
1969 (*shead)->prev->next = stail->next;
1971 stail->next->prev = (*shead)->prev;
1972 *shead = stail->next;
1976 /* Returns TRUE if this line is a label definition.
1978 * If so, start will point to the start of the label name,
1979 * and len will be it's length.
1982 isLabelDefinition (const char *line, const char **start, int *len)
1984 const char *cp = line;
1986 /* This line is a label if if consists of:
1987 * [optional whitespace] followed by identifier chars
1988 * (alnum | $ | _ ) followed by a colon.
1991 while (*cp && ISCHARSPACE (*cp))
2003 while (ISCHARALNUM (*cp) || (*cp == '$') || (*cp == '_'))
2008 if ((cp == *start) || (*cp != ':'))
2013 *len = (cp - (*start));
2017 /* Quick & dirty string hash function. */
2019 hashSymbolName (const char *name)
2025 hash = (hash << 6) ^ *name;
2034 return hash % HTAB_SIZE;
2037 /* Build a hash of all labels in the passed set of lines
2038 * and how many times they are referenced.
2041 buildLabelRefCountHash (lineNode * head)
2048 assert (labelHash == NULL);
2049 labelHash = newHashTable (HTAB_SIZE);
2051 /* First pass: locate all the labels. */
2056 if (isLabelDefinition (line->line, &label, &labelLen)
2057 && labelLen <= SDCC_NAME_MAX)
2059 labelHashEntry *entry;
2061 entry = traceAlloc (&_G.labels, Safe_alloc(sizeof (labelHashEntry)));
2063 memcpy (entry->name, label, labelLen);
2064 entry->name[labelLen] = 0;
2065 entry->refCount = -1;
2067 /* Assume function entry points are referenced somewhere, */
2068 /* even if we can't find a reference (might be from outside */
2070 if (line->ic && (line->ic->op == FUNCTION))
2073 hTabAddItem (&labelHash, hashSymbolName (entry->name), entry);
2079 /* Second pass: for each line, note all the referenced labels. */
2080 /* This is ugly, O(N^2) stuff. Optimizations welcome... */
2084 for (i = 0; i < HTAB_SIZE; i++)
2086 labelHashEntry *thisEntry;
2088 thisEntry = hTabFirstItemWK (labelHash, i);
2092 if (strstr (line->line, thisEntry->name))
2094 thisEntry->refCount++;
2096 thisEntry = hTabNextItemWK (labelHash);
2103 /* Spew the contents of the table. Debugging fun only. */
2104 for (i = 0; i < HTAB_SIZE; i++)
2106 labelHashEntry *thisEntry;
2108 thisEntry = hTabFirstItemWK (labelHash, i);
2112 fprintf (stderr, "label: %s ref %d\n",
2113 thisEntry->name, thisEntry->refCount);
2114 thisEntry = hTabNextItemWK (labelHash);
2120 /* How does this work?
2126 replace and restart.
2131 Where is stuff allocated?
2135 /*-----------------------------------------------------------------*/
2136 /* peepHole - matches & substitutes rules */
2137 /*-----------------------------------------------------------------*/
2139 peepHole (lineNode ** pls)
2143 lineNode *mtail = NULL;
2146 #if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
2147 /* The PIC port uses a different peep hole optimizer based on "pCode" */
2148 if (TARGET_IS_PIC || TARGET_IS_PIC16)
2152 assert(labelHash == NULL);
2159 for (pr = rootRules; pr; pr = pr->next)
2161 for (spl = *pls; spl; spl = spl->next)
2163 /* if inline assembler then no peep hole */
2167 /* don't waste time starting a match on debug symbol
2169 if (spl->isDebug || spl->isComment || *(spl->line)==';')
2174 /* Tidy up any data stored in the hTab */
2177 if (matchRule (spl, &mtail, pr, *pls))
2182 replaceRule (pls, mtail, pr);
2184 replaceRule (&spl, mtail, pr);
2186 /* if restart rule type then
2187 start at the top again */
2196 hTabDeleteAll (pr->vars);
2197 Safe_free (pr->vars);
2201 freeTrace (&_G.values);
2204 } while (restart == TRUE);
2208 hTabDeleteAll (labelHash);
2209 freeTrace (&_G.labels);
2215 /*-----------------------------------------------------------------*/
2216 /* readFileIntoBuffer - reads a file into a string buffer */
2217 /*-----------------------------------------------------------------*/
2219 readFileIntoBuffer (char *fname)
2225 char lb[MAX_PATTERN_LEN];
2227 if (!(f = fopen (fname, "r")))
2229 fprintf (stderr, "cannot open peep rule file\n");
2233 while ((ch = fgetc (f)) != EOF)
2237 /* if we maxed out our local buffer */
2238 if (nch >= (MAX_PATTERN_LEN - 2))
2241 /* copy it into allocated buffer */
2244 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
2245 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
2249 rs = Safe_strdup (lb);
2255 /* if some charaters left over */
2259 /* copy it into allocated buffer */
2262 rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
2263 strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
2267 rs = Safe_strdup (lb);
2273 /*-----------------------------------------------------------------*/
2274 /* initPeepHole - initialises the peep hole optimizer stuff */
2275 /*-----------------------------------------------------------------*/
2281 /* read in the default rules */
2282 if (!options.nopeep)
2284 readRules (port->peep.default_rules);
2287 /* if we have any additional file read it too */
2288 if (options.peep_file)
2290 readRules (s = readFileIntoBuffer (options.peep_file));
2291 setToNull ((void *) &s);
2292 /* override nopeep setting, default rules have not been read */
2297 #if !OPT_DISABLE_PIC
2298 /* Convert the peep rules into pcode.
2299 NOTE: this is only support in the PIC port (at the moment)
2302 peepRules2pCode(rootRules);
2305 #if !OPT_DISABLE_PIC16
2306 /* Convert the peep rules into pcode.
2307 NOTE: this is only support in the PIC port (at the moment)
2308 and the PIC16 port (VR 030601)
2310 if (TARGET_IS_PIC16)
2311 pic16_peepRules2pCode(rootRules);