* device/lib/Makefile.in: remove abspath for PORTDIR, introduced in
[fw/sdcc] / src / SDCCptropt.c
index 3660bb7f1631b88a4edf09fa6a3a35ee36f0425f..b3ff931f885b0db7c837f57b8772ddd81d631838 100644 (file)
@@ -218,3 +218,178 @@ int ptrAddition (iCode *sic)
        if (addPattern1(sic)) return 1;
        return 0;
 }
+
+/*--------------------------------------------------------------------*/
+/* ptrBaseRematSym - find the base symbol of a remat. pointer         */
+/*--------------------------------------------------------------------*/
+symbol *
+ptrBaseRematSym (symbol *ptrsym)
+{
+  iCode * ric;
+  
+  if (!ptrsym->remat)
+    return NULL;
+  
+  ric = ptrsym->rematiCode;
+  while (ric)
+    {
+      if (ric->op == '+' || ric->op == '-')
+       ric = OP_SYMBOL (IC_LEFT (ric))->rematiCode;
+      else if (IS_CAST_ICODE (ric))
+        ric = OP_SYMBOL (IC_RIGHT (ric))->rematiCode;
+      else
+        break;
+    }
+  
+  if (ric && IS_SYMOP (IC_LEFT (ric)))
+    return OP_SYMBOL (IC_LEFT (ric));
+  else
+    return NULL;
+}
+
+
+/*--------------------------------------------------------------------*/
+/* ptrPseudoSymSafe - check to see if the conversion of the result of */
+/*   a pointerGet of a rematerializable pointer to a pseudo symbol is */
+/*   safe. Returns true if safe, or false if hazards were detected.   */
+/*--------------------------------------------------------------------*/
+int
+ptrPseudoSymSafe (symbol *sym, iCode *dic)
+{
+  symbol * ptrsym;
+  symbol * basesym;
+  iCode * ric;
+  iCode * ic;
+  int ptrsymDclType;
+  //int isGlobal;
+  
+  assert(POINTER_GET (dic));
+
+  /* Can't if spills to this symbol are prohibited */
+  if (sym->noSpilLoc)
+    return 0;
+  
+  /* Get the pointer */
+  if (!IS_SYMOP (IC_LEFT (dic)))
+    return 0;
+  ptrsym = OP_SYMBOL (IC_LEFT (dic));
+  
+  /* Must be a rematerializable pointer */
+  if (!ptrsym->remat)
+    return 0;
+  
+  /* The pointer type must be uncasted */
+  if (IS_CAST_ICODE (ptrsym->rematiCode))
+    return 0;
+  
+  /* The symbol's live range must not preceed its definition */
+  if (dic->seq > sym->liveFrom)
+    return 0;
+        
+  /* Ok, this is a good candidate for a pseudo symbol.      */
+  /* However, we must check for two hazards:                */
+  /*   1) The symbol's live range must not include a CALL   */
+  /*      or PCALL iCode.                                   */
+  /*   2) The symbol's live range must not include any      */
+  /*      writes to the variable the pointer rematerializes */
+  /*      within (to avoid aliasing problems)               */
+  
+  /* Find the base symbol the rematerialization is based on */
+  ric = ptrsym->rematiCode;
+  while (ric->op == '+' || ric->op == '-')
+    ric = OP_SYMBOL (IC_LEFT (ric))->rematiCode;
+  if (IS_CAST_ICODE(ric))
+    return 0;
+  basesym = OP_SYMBOL (IC_LEFT (ric));
+
+  //isGlobal = !basesym->islocal && !basesym->ismyparm;
+  ptrsymDclType = aggrToPtrDclType (ptrsym->type, FALSE);
+
+  ic = dic->next;
+  while (ic && ic->seq <= sym->liveTo)
+    {
+      if (!(SKIP_IC3 (ic) || ic->op == IFX))
+        {
+         /* Check for hazard #1 */
+         if ((ic->op == CALL || ic->op == PCALL) /* && isGlobal */ )
+           {
+             if (ic->seq <= sym->liveTo)
+               return 0;
+           }
+         /* Check for hazard #2 */
+         else if (POINTER_SET (ic))
+           {
+             symbol * ptrsym2 = OP_SYMBOL (IC_RESULT (ic));
+         
+             if (ptrsym2->remat)
+               {
+                 /* Must not be the same base symbol */
+                 if (basesym == ptrBaseRematSym (ptrsym2))
+                   return 0;
+               }
+             else
+               {
+                 int ptrsym2DclType = aggrToPtrDclType (ptrsym2->type, FALSE);
+
+                 /* Pointer must have no memory space in common */
+                 if (ptrsym2DclType == ptrsymDclType
+                     || ptrsym2DclType == GPOINTER
+                     || ptrsymDclType == GPOINTER)
+                   return 0;
+               }
+           }
+         else if (IC_RESULT (ic))
+           {
+             symbol * rsym = OP_SYMBOL (IC_RESULT (ic));
+         
+             /* Make sure there is no conflict with another pseudo symbol */
+             if (rsym->psbase == basesym)
+               return 0;
+             if (rsym->isspilt && rsym->usl.spillLoc)
+               rsym = rsym->usl.spillLoc;
+             if (rsym->psbase == basesym)
+               return 0;
+           }
+       }
+       
+      if (ic->seq == sym->liveTo)
+        break;
+      ic = ic->next;
+    }
+
+  /* If the live range went past the end of the defining basic */
+  /* block, then a full analysis is too complicated to attempt */
+  /* here. To be safe, we must assume the worst.               */
+  if (!ic)
+    return 0;
+    
+  /* Ok, looks safe */
+  return 1;
+}
+
+/*--------------------------------------------------------------------*/
+/* ptrPseudoSymConvert - convert the result of a pointerGet to a      */
+/*   pseudo symbol. The pointer must be rematerializable.             */
+/*--------------------------------------------------------------------*/
+void
+ptrPseudoSymConvert (symbol *sym, iCode *dic, char *name)
+{
+  symbol *psym = newSymbol (name, 1);
+  psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (dic)));
+  psym->type = sym->type;
+  psym->etype = psym->psbase->etype;
+
+  strcpy (psym->rname, psym->name);
+  sym->isspilt = 1;
+  sym->usl.spillLoc = psym;
+#if 0 // an alternative fix for bug #480076
+  /* now this is a useless assignment to itself */
+  remiCodeFromeBBlock (ebbs, dic);
+#else
+  /* now this really is an assignment to itself, make it so;
+     it will be optimized out later */
+  dic->op='=';
+  ReplaceOpWithCheaperOp(&IC_RIGHT(dic), IC_RESULT(dic));
+  IC_LEFT(dic)=NULL;
+#endif
+}