コード例 #1
0
ファイル: SDCCptropt.c プロジェクト: chamalo90/PIC_DHCP_Relay
/*-----------------------------------------------------------------------*/
static iCode *
findPointerGetSet (iCode * sic, operand * op)
{
  iCode *ic = sic;

  for (; ic; ic = ic->next)
    {
      if ((POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic))) ||
          (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic))))
        return ic;

      /* if we find any other usage or definition of op null */
      if (IC_RESULT (ic) && isOperandEqual (IC_RESULT (ic), op))
        return NULL;

      if (IC_RIGHT (ic) && isOperandEqual (IC_RIGHT (ic), op))
        return NULL;

      if (IC_LEFT (ic) && isOperandEqual (IC_LEFT (ic), op))
        return NULL;

    }

  return NULL;
}
コード例 #2
0
ファイル: SDCClrange.c プロジェクト: Derpybunneh/cpctelera
static void visit (set **visited, iCode *ic, const int key)
{
  symbol *lbl;

  while (ic && !isinSet (*visited, ic) && bitVectBitValue (ic->rlive, key))
    {
      addSet (visited, ic);

      switch (ic->op)
        {
        case GOTO:
          ic = hTabItemWithKey (labelDef, (IC_LABEL (ic))->key);
          break;
        case RETURN:
          ic = hTabItemWithKey (labelDef, returnLabel->key);
          break;
        case JUMPTABLE:
          for (lbl = setFirstItem (IC_JTLABELS (ic)); lbl; lbl = setNextItem (IC_JTLABELS (ic)))
            visit (visited, hTabItemWithKey (labelDef, lbl->key), key);
          break;
        case IFX:
          visit (visited, hTabItemWithKey (labelDef, (IC_TRUE(ic) ? IC_TRUE (ic) : IC_FALSE (ic))->key), key);
          ic = ic->next;
          break;
        default:
          ic = ic->next;
          if (!POINTER_SET (ic) && IC_RESULT (ic) && IS_SYMOP (IC_RESULT (ic)) && OP_SYMBOL_CONST (IC_RESULT (ic))->key == key)
            {
              addSet (visited, ic);
              return;
            }
        }
    }
}
コード例 #3
0
ファイル: ralloc.c プロジェクト: Trewdbal/cpctelera
/** Does some transformations to reduce register pressure.
 */
static void
packRegisters (eBBlock * ebp)
{
  iCode *ic;
  int change = 0;

  D (D_ALLOC, ("packRegisters: entered.\n"));

  for(;;)
    {
      change = 0;
      /* look for assignments of the form */
      /* iTempNN = TRueSym (someoperation) SomeOperand */
      /*       ....                       */
      /* TrueSym := iTempNN:1             */
      for (ic = ebp->sch; ic; ic = ic->next)
        {
          /* find assignment of the form TrueSym := iTempNN:1 */
          if (ic->op == '=' && !POINTER_SET (ic))
            change += packRegsForAssign (ic, ebp);
        }
      if (!change)
        break;
    }
}
コード例 #4
0
ファイル: SDCCBBlock.c プロジェクト: Trewdbal/cpctelera
/*-----------------------------------------------------------------*/
void
replaceSymBySym (set * sset, operand * src, operand * dest)
{
  set *loop;
  eBBlock *rBlock;

  /* for all blocks in the set do */
  for (loop = sset; loop; loop = loop->next)
    {
      iCode *ic;

      rBlock = loop->item;
      /* for all instructions in this block do */
      for (ic = rBlock->sch; ic; ic = ic->next)
        {

          /* if we find usage */
          if (ic->op == IFX && isOperandEqual (src, IC_COND (ic)))
            {
              bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
              IC_COND (ic) = operandFromOperand (dest);
              OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
              continue;
            }

          if (isOperandEqual (IC_RIGHT (ic), src))
            {
              bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
              IC_RIGHT (ic) = operandFromOperand (dest);
              IC_RIGHT (ic)->isaddr = 0;
              OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
            }

          if (isOperandEqual (IC_LEFT (ic), src))
            {
              bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
              if (POINTER_GET (ic) && IS_ITEMP (dest))
                {
                  IC_LEFT (ic) = operandFromOperand (dest);
                  IC_LEFT (ic)->isaddr = 1;
                }
              else
                {
                  IC_LEFT (ic) = operandFromOperand (dest);
                  IC_LEFT (ic)->isaddr = 0;
                }
              OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
            }

          /* special case for pointer sets */
          if (POINTER_SET (ic) && isOperandEqual (IC_RESULT (ic), src))
            {
              bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
              IC_RESULT (ic) = operandFromOperand (dest);
              IC_RESULT (ic)->isaddr = 1;
              OP_USES (dest) = bitVectSetBit (OP_USES (dest), ic->key);
            }
        }
    }
}
コード例 #5
0
ファイル: SDCCptropt.c プロジェクト: chamalo90/PIC_DHCP_Relay
static int pattern1 (iCode *sic)
{
        /* this is what we do. look for sequences like

        iTempX := _SOME_POINTER_;
        iTempY := _SOME_POINTER_ + nn ;   nn  = sizeof (pointed to object)      sic->next
        _SOME_POINTER_ := iTempY;                                               sic->next->next
        either       
        iTempZ := @[iTempX];                                                    sic->next->next->next
        or
        *(iTempX) := ..something..                                              sic->next->next->next
        if we find this then transform this to
        iTempX := _SOME_POINTER_;
        either       
        iTempZ := @[iTempX];
        or 
        *(iTempX) := ..something..
        iTempY := _SOME_POINTER_ + nn ;   nn  = sizeof (pointed to object)
        _SOME_POINTER_ := iTempY; */
        
        /* sounds simple enough so let's start , here I use negative
           tests all the way to return if any test fails */
        iCode *pgs, *sh, *st;

        if (!(sic->next && sic->next->next && sic->next->next->next))
                return 0;
        if (sic->next->op != '+' && sic->next->op != '-')
                return 0;
        if (!(sic->next->next->op == '=' &&
              !POINTER_SET (sic->next->next)))
                return 0;
        if (!isOperandEqual (IC_LEFT (sic->next), IC_RIGHT (sic)) ||
            !IS_OP_LITERAL (IC_RIGHT (sic->next)))
                return 0;
        if (operandLitValue (IC_RIGHT (sic->next)) !=
            getSize (operandType (IC_RIGHT (sic))->next))
                return 0;
        if (!isOperandEqual (IC_RESULT (sic->next->next),
                             IC_RIGHT (sic)))
                return 0;
        if (!isOperandEqual (IC_RESULT (sic->next), IC_RIGHT (sic->next->next)))
                return 0;
        if (!(pgs = findPointerGetSet (sic->next->next, IC_RESULT (sic))))
                return 0;

        /* found the pattern .. now do the transformation */
        sh = sic->next;
        st = sic->next->next;

        /* take the two out of the chain */
        sic->next = st->next;
        st->next->prev = sic;

        /* and put them after the pointer get/set icode */
        if ((st->next = pgs->next))
                st->next->prev = st;
        pgs->next = sh;
        sh->prev = pgs;
        return 1;
}
コード例 #6
0
ファイル: SDCCdflow.c プロジェクト: FurCode/gbdk-darwin
/*-----------------------------------------------------------------*/
iCode *
usedInRemaining (operand * op, iCode * ic)
{
  iCode *lic = ic;

  if (!IS_SYMOP (op))
    return 0;

  for (; lic; lic = lic->next)
    {

      /* if the operand is a parameter */
      /* then check for calls and return */
      /* true if there is a call       */
      /* if this is a global variable then 
         return true */
      if (lic->op == CALL || lic->op == PCALL)
	{

	  if ((IS_PARM (op) &&
	       isParameterToCall (IC_ARGS (lic), op)) ||
	      isOperandGlobal (op))
	    return lic;
	}

      if (ic->op == SEND &&
	  isOperandEqual (IC_LEFT (lic), op))
	return lic;

      if (SKIP_IC1 (lic))
	continue;

      /* if ifx then check the condition */
      if (lic->op == IFX &&
	  isOperandEqual (IC_COND (lic), op))
	return lic;

      if (lic->op == JUMPTABLE &&
	  isOperandEqual (IC_JTCOND (lic), op))
	return lic;

      if (IC_RIGHT (lic) &&
	  isOperandEqual (IC_RIGHT (lic), op))
	return lic;

      if (IC_LEFT (lic) &&
	  isOperandEqual (IC_LEFT (lic), op))
	return lic;

      /* for a pointer assignment usage */
      if (POINTER_SET (lic) &&
	  isOperandEqual (op, IC_RESULT (lic)))
	return lic;
      else if (IC_RESULT (lic) && isOperandEqual (IC_RESULT (lic), op))
	return NULL;
    }

  return NULL;
}
コード例 #7
0
ファイル: SDCClrange.c プロジェクト: Derpybunneh/cpctelera
/*------------------------------------------------------------------*/
static bool
findPrevUseSym  (eBBlock *ebp, iCode *ic, symbol * sym)
{
  eBBlock * pred;
  iCode * uic;

  if (ebp->visited)
    {
     /* already visited: this branch must have been succesfull, */
     /* because otherwise the search would have been aborted. */
      return TRUE;
    }
  ebp->visited = 1;

  /* search backward in the current block */
  for (uic = ic; uic; uic = uic->prev)
    {
      if (!POINTER_SET (uic) && IS_AUTOSYM (IC_RESULT (uic)))
        {
          if (IC_RESULT (uic)->key == sym->key)
            {
              /* Ok, found a definition */
              return TRUE;
            }
        }
      /* address taken from symbol? */
      if (uic->op == ADDRESS_OF && IS_AUTOSYM (IC_LEFT (uic)))
        {
          if (IC_LEFT (uic)->key == sym->key)
            {
              /* Ok, found a definition */
              return TRUE;
            }
        }
    }

  /* There's no definition in this bblock, */
  /* let's have a look at all predecessors. */
  pred = setFirstItem (ebp->predList);
  if (!pred)
    {
      /* no more predecessors and nothing found yet :-( */
      return FALSE;
    }
  for (; pred; pred = setNextItem (ebp->predList))
    {
      /* recurse into all predecessors */
      if (!findPrevUseSym (pred, pred->ech, sym))
        {
          /* found nothing: abort */
          return FALSE;
        }
    }

  /* Success! Went through all branches with no abort: */
  /* all branches end with a definition */
  return TRUE;
}
コード例 #8
0
ファイル: SDCCdflow.c プロジェクト: FurCode/gbdk-darwin
/*-----------------------------------------------------------------*/
int 
usedBetweenPoints (operand * op, iCode * start, iCode * end)
{
  iCode *lic = start;

  for (; lic != end; lic = lic->next)
    {

      /* if the operand is a parameter */
      /* then check for calls and return */
      /* true if there is a call       */
      if (IS_PARM (op) &&
	  (lic->op == CALL ||
	   lic->op == PCALL))
	if (isParameterToCall (IC_ARGS (lic), op))
	  return 1;

      if (SKIP_IC2 (lic))
	continue;

      /* if ifx then check the condition */
      if (lic->op == IFX &&
	  IC_COND (lic)->key == op->key)
	return 1;

      if (lic->op == JUMPTABLE &&
	  IC_JTCOND (lic)->key == op->key)
	return 1;

      if (IC_RIGHT (lic) &&
	  IC_RIGHT (lic)->key == op->key)
	return 1;

      if (IC_LEFT (lic) &&
	  IC_LEFT (lic)->key == op->key)
	return 1;

      /* for a pointer assignment usage */
      if (POINTER_SET (lic) &&
	  op->key == IC_RESULT (lic)->key)
	return 1;
      else if (IC_RESULT (lic) && op->key == IC_RESULT (lic)->key)
	return 0;
    }

  return 0;

}
コード例 #9
0
ファイル: SDCClospre.hpp プロジェクト: JackieXie168/sdcc
static int implement_lospre_assignment(const assignment_lospre a, T_t &T, G_t &G, const iCode *ic) // Assignment has to be passed as a copy (not reference), since the transformations on the tree-decomposition will invalidate it otherwise.
{
  operand *tmpop;
  unsigned substituted = 0, split = 0;

  typedef typename boost::graph_traits<G_t>::edge_iterator edge_iter_t;
  typedef typename boost::graph_traits<G_t>::edge_descriptor edge_desc_t;
  std::set<edge_desc_t> calculation_edges; // Use descriptor, not iterator due to possible invalidation of iterators when inserting vertices or edges.
  edge_iter_t e, e_end;
  for(boost::tie(e, e_end) = boost::edges(G); e != e_end; ++e)
    if(!((a.global[boost::source(*e, G)] & true) && !G[boost::source(*e, G)].invalidates) && (a.global[boost::target(*e, G)] & true))
      calculation_edges.insert(*e);

  if(!calculation_edges.size())
    return(0);

#ifdef DEBUG_LOSPRE
  std::cout << "Optimizing at " << ic->key << "\n"; std::cout.flush();
#endif

  tmpop = newiTempOperand (operandType (IC_RESULT (ic)), TRUE);
  tmpop->isvolatile = false;
#ifdef DEBUG_LOSPRE
  std::cout << "New tmpop: " << OP_SYMBOL_CONST(tmpop)->name << " "; printTypeChain(operandType (IC_RESULT(ic)), stdout); std::cout << "\n";
#endif

  for(typename std::set<edge_desc_t>::iterator i = calculation_edges.begin(); i != calculation_edges.end(); ++i)
  {
    split_edge(T, G, *i, ic, tmpop);
    split++;
  }

  typedef typename boost::graph_traits<G_t>::vertex_iterator vertex_iter_t;
  vertex_iter_t v, v_end;

  for(boost::tie(v, v_end) = boost::vertices(G); v != v_end; ++v)
    {
      if(!G[*v].uses)
        continue;
      typename boost::graph_traits<G_t>::in_edge_iterator e = in_edges(*v, G).first;
      if (a.global.size() <= *v)
        continue;
      if(!((a.global[*v] & true) && !G[*v].invalidates || boost::source(*e, G) < a.global.size() && (a.global[boost::source(*e, G)] & true)))
        continue;
#ifdef DEBUG_LOSPRE
      std::cout << "Substituting ic " << G[*v].ic->key << "\n";
#endif
      substituted++;

      iCode *ic = G[*v].ic;
      //if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
      //  bitVectUnSetBit (OP_SYMBOL (IC_LEFT (ic))->uses, ic->key);
      //if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
       // bitVectUnSetBit (OP_SYMBOL (IC_RIGHT (ic))->uses, ic->key);
      IC_RIGHT(ic) = tmpop;
      //bitVectSetBit (OP_SYMBOL (IC_RIGHT(ic))->uses, ic->key);
      if (!POINTER_SET (ic))
        {
          IC_LEFT(ic) = 0;
          ic->op = '=';
          IC_RESULT(ic) = operandFromOperand (IC_RESULT (ic));
          IC_RESULT(ic)->isaddr = 0;
        }
      if(IS_OP_VOLATILE(IC_RESULT (ic)))
        continue;

      {
        typedef typename boost::graph_traits<G_t>::adjacency_iterator adjacency_iter_t;
        adjacency_iter_t c, c_end;
        boost::tie(c, c_end) = adjacent_vertices(*v, G);
        if (c != c_end)
          forward_lospre_assignment(G, *c, ic, a);
      }
    }

  if(substituted <= 0)
    {
      std::cerr << "Introduced " << OP_SYMBOL_CONST(tmpop)->name << ", but did not substitute any calculations.\n";
      return (-1);
    }

  if(substituted < split) // Todo: Remove this warning when optimization for speed instead of code size is implemented!
    std::cout << "Introduced " << OP_SYMBOL_CONST(tmpop)->name << ", but did substitute only " << substituted << " calculations, while introducing "<< split << ".\n"; std::cout.flush();

  return(1);
}
コード例 #10
0
ファイル: SDCClospre.hpp プロジェクト: JackieXie168/sdcc
static void forward_lospre_assignment(G_t &G, typename boost::graph_traits<G_t>::vertex_descriptor i, const iCode *ic, const assignment_lospre& a)
{
  typedef typename boost::graph_traits<G_t>::adjacency_iterator adjacency_iter_t;

  adjacency_iter_t c, c_end;

  operand *tmpop = IC_RIGHT(ic);
  const std::pair<int, int> forward(IC_RESULT(ic)->key, IC_RIGHT(ic)->key);

  for(;;)
    {
      if (G[i].forward == forward)
        break; // Was here before.

      iCode *nic = G[i].ic;

      if (isOperandEqual(IC_RESULT(ic), IC_LEFT(nic)) && nic->op != ADDRESS_OF && (!POINTER_GET(nic) || !IS_PTR(operandType(IC_RESULT(nic))) || !IS_BITFIELD(operandType(IC_LEFT(nic))->next) || compareType(operandType(IC_LEFT(nic)), operandType(tmpop)) == 1))
        {
          bool isaddr = IC_LEFT (nic)->isaddr;
#ifdef DEBUG_LOSPRE
          std::cout << "Forward substituted left operand " << OP_SYMBOL_CONST(IC_LEFT(nic))->name << " at " << nic->key << "\n";
#endif
          //bitVectUnSetBit (OP_SYMBOL (IC_LEFT (nic))->uses, nic->key);
          IC_LEFT(nic) = operandFromOperand (tmpop);
          //bitVectSetBit (OP_SYMBOL (IC_LEFT (nic))->uses, nic->key);
          IC_LEFT (nic)->isaddr = isaddr;
        }
      if (isOperandEqual(IC_RESULT(ic), IC_RIGHT(nic)))
        {
#ifdef DEBUG_LOSPRE
          std::cout << "Forward substituted right operand " << OP_SYMBOL_CONST(IC_RIGHT(nic))->name << " at " << nic->key << "\n";
#endif
          //bitVectUnSetBit (OP_SYMBOL (IC_RIGHT (nic))->uses, nic->key);
          IC_RIGHT(nic) = operandFromOperand (tmpop);
          //bitVectSetBit (OP_SYMBOL (IC_RIGHT (nic))->uses, nic->key);
        }
      if (POINTER_SET(nic) && isOperandEqual(IC_RESULT(ic), IC_RESULT(nic)) && (!IS_PTR(operandType(IC_RESULT(nic))) || !IS_BITFIELD(operandType(IC_RESULT(nic))->next) || compareType(operandType(IC_RESULT(nic)), operandType(tmpop)) == 1))
        {
#ifdef DEBUG_LOSPRE
          std::cout << "Forward substituted result operand " << OP_SYMBOL_CONST(IC_RESULT(nic))->name << " at " << nic->key << "\n";
#endif
          //bitVectUnSetBit (OP_SYMBOL (IC_RESULT (nic))->uses, nic->key);
          IC_RESULT(nic) = operandFromOperand (tmpop);
          IC_RESULT(nic)->isaddr = true;
          //bitVectSetBit (OP_SYMBOL (IC_RESULT (nic))->uses, nic->key);
        }

      if (nic->op == LABEL) // Reached label. Continue only if all edges goining here are safe.
        {
          typedef typename boost::graph_traits<G_t>::in_edge_iterator in_edge_iter_t;
          in_edge_iter_t e, e_end;
          for (boost::tie(e, e_end) = boost::in_edges(i, G); e != e_end; ++e)
            if (G[boost::source(*e, G)].forward != forward)
              break;
          if(e != e_end)
            break;
        }
      if (isOperandEqual(IC_RESULT (ic), IC_RESULT(nic)) && !POINTER_SET(nic) /*|| G[i].uses*/)
        break;
      if ((nic->op == CALL || nic->op == PCALL || POINTER_SET(nic)) && IS_TRUE_SYMOP(IC_RESULT(ic)))
        break;

      G[i].forward = forward;

      if (nic->op == GOTO || nic->op == IFX || nic->op == JUMPTABLE)
        {
          adjacency_iter_t c, c_end;
          for(boost::tie(c, c_end) = boost::adjacent_vertices(i, G); c != c_end; ++c)
            {
              if(!((a.global[i] & true) && !G[i].invalidates) && (a.global[*c] & true)) // Calculation edge
                continue;
              forward_lospre_assignment(G, *c, ic, a);
            }
          break;
        }

      boost::tie(c, c_end) = adjacent_vertices(i, G);
      if(c == c_end)
        break;
      if(!((a.global[i] & true) && !G[i].invalidates) && (a.global[*c] & true)) // Calculation edge
        break;
      i = *c;
    }
}
コード例 #11
0
ファイル: SDCCopt.c プロジェクト: FurCode/gbdk-darwin
/*-----------------------------------------------------------------*/
int 
killDeadCode (eBBlock ** ebbs, int count)
{
  int change = 1;
  int gchange = 0;
  int i = 0;


  /* basic algorithm :-                                          */
  /* first the exclusion rules :-                                */
  /*  1. if result is a global or volatile then skip             */
  /*  2. if assignment and result is a temp & isaddr  then skip  */
  /*     since this means array & pointer access, will be taken  */
  /*     care of by alias analysis.                              */
  /*  3. if the result is used in the remainder of the block skip */
  /*  4. if this definition does not reach the end of the block  */
  /*     i.e. the result is not present in the outExprs then KILL */
  /*  5. if it reaches the end of block & is used by some success */
  /*     or then skip                                            */
  /*     else            KILL                                    */
  /* this whole process is carried on iteratively till no change */
  while (1)
    {

      change = 0;
      /* for all blocks do */
      for (i = 0; i < count; i++)
	{
	  iCode *ic;

	  /* for all instructions in the block do */
	  for (ic = ebbs[i]->sch; ic; ic = ic->next)
	    {
	      int kill, j;
	      kill = 0;

	      if (SKIP_IC (ic) ||
		  ic->op == IFX ||
		  ic->op == RETURN)
		continue;

	      /* if the result is volatile then continue */
	      if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
		continue;

	      /* if the result is a temp & isaddr then skip */
	      if (IC_RESULT (ic) && POINTER_SET (ic))
		continue;

	      /* if the result is used in the remainder of the */
	      /* block then skip */
	      if (usedInRemaining (IC_RESULT (ic), ic->next))
		continue;

	      /* does this definition reach the end of the block 
	         or the usage is zero then we can kill */
	      if (!bitVectBitValue (ebbs[i]->outDefs, ic->key))
		kill = 1;	/* if not we can kill it */
	      else
		{
		  /* if this is a global variable or function parameter */
		  /* we cannot kill anyway             */
		  if (isOperandGlobal (IC_RESULT (ic)) ||
		      (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
		       !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
		    continue;

		  /* if we are sure there are no usages */
		  if (bitVectIsZero (OP_USES (IC_RESULT (ic))))
		    {
		      kill = 1;
		      goto kill;
		    }

		  /* reset visited flag */
		  for (j = 0; j < count; ebbs[j++]->visited = 0);

		  /* find out if this definition is alive */
		  if (applyToSet (ebbs[i]->succList,
				  isDefAlive,
				  ic))
		    continue;

		  kill = 1;
		}

	    kill:
	      /* kill this one if required */
	      if (kill)
		{
		  change = 1;
		  gchange++;
		  /* eliminate this */
		  remiCodeFromeBBlock (ebbs[i], ic);

		  /* now delete from defUseSet */
		  deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic);
		  bitVectUnSetBit (ebbs[i]->outDefs, ic->key);

		  /* and defset of the block */
		  bitVectUnSetBit (ebbs[i]->defSet, ic->key);

		  /* for the left & right remove the usage */
		  if (IS_SYMOP (IC_LEFT (ic)))
		    bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);

		  if (IS_SYMOP (IC_RIGHT (ic)))
		    bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
		}

	    }			/* end of all instructions */

	  if (!ebbs[i]->sch && !ebbs[i]->noPath)
	    disconBBlock (ebbs[i], ebbs, count);

	}			/* end of for all blocks */

      if (!change)
	break;
    }				/* end of while(1) */

  return gchange;
}
コード例 #12
0
ファイル: SDCCopt.c プロジェクト: FurCode/gbdk-darwin
/*-----------------------------------------------------------------*/
static void 
replaceRegEqv (eBBlock ** ebbs, int count)
{
  int i;

  for (i = 0; i < count; i++)
    {

      iCode *ic;

      for (ic = ebbs[i]->sch; ic; ic = ic->next)
	{

	  if (SKIP_IC2 (ic))
	    continue;

	  if (ic->op == IFX)
	    {

	      if (IS_TRUE_SYMOP (IC_COND (ic)) &&
		  OP_REQV (IC_COND (ic)))
		IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)),
					     OP_SYMBOL (IC_COND (ic))->defs,
					    OP_SYMBOL (IC_COND (ic))->uses);

	      continue;
	    }

	  if (ic->op == JUMPTABLE)
	    {
	      if (IS_TRUE_SYMOP (IC_JTCOND (ic)) &&
		  OP_REQV (IC_JTCOND (ic)))
		IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)),
					   OP_SYMBOL (IC_JTCOND (ic))->defs,
					  OP_SYMBOL (IC_JTCOND (ic))->uses);
	      continue;
	    }

	  if (ic->op == RECEIVE)
	    {
	      if (OP_SYMBOL (IC_RESULT (ic))->addrtaken)
		OP_SYMBOL (IC_RESULT (ic))->isspilt = 1;
	    }

	  /* general case */
	  if (IC_RESULT (ic) &&
	      IS_TRUE_SYMOP (IC_RESULT (ic)) &&
	      OP_REQV (IC_RESULT (ic)))
	    {
	      if (POINTER_SET (ic))
		{
		  IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
					   OP_SYMBOL (IC_RESULT (ic))->defs,
					  OP_SYMBOL (IC_RESULT (ic))->uses);
		  IC_RESULT (ic)->isaddr = 1;
		}
	      else
		IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)),
					   OP_SYMBOL (IC_RESULT (ic))->defs,
					  OP_SYMBOL (IC_RESULT (ic))->uses);
	    }

	  if (IC_RIGHT (ic) &&
	      IS_TRUE_SYMOP (IC_RIGHT (ic)) &&
	      OP_REQV (IC_RIGHT (ic)))
	    {
	      IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)),
					    OP_SYMBOL (IC_RIGHT (ic))->defs,
					   OP_SYMBOL (IC_RIGHT (ic))->uses);
	      IC_RIGHT (ic)->isaddr = 0;
	    }

	  if (IC_LEFT (ic) &&
	      IS_TRUE_SYMOP (IC_LEFT (ic)) &&
	      OP_REQV (IC_LEFT (ic)))
	    {
	      IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)),
					     OP_SYMBOL (IC_LEFT (ic))->defs,
					     OP_SYMBOL (IC_LEFT (ic))->uses);
	      IC_LEFT (ic)->isaddr = 0;
	    }
	}
    }
}
コード例 #13
0
ファイル: SDCClrange.c プロジェクト: Derpybunneh/cpctelera
/*-----------------------------------------------------------------*/
void
separateLiveRanges (iCode *sic, ebbIndex *ebbi)
{
  iCode *ic;
  set *candidates = 0;
  symbol *sym;

  // printf("separateLiveRanges()\n");

  for (ic = sic; ic; ic = ic->next)
    {
      if (ic->op == IFX || ic->op == GOTO || ic->op == JUMPTABLE || !IC_RESULT (ic) || !IS_ITEMP (IC_RESULT (ic)) || bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) <= 1 || isinSet (candidates, OP_SYMBOL (IC_RESULT (ic))))
        continue;

      addSet (&candidates, OP_SYMBOL (IC_RESULT (ic)));
    }

  if (!candidates)
    return;

  for(sym = setFirstItem (candidates); sym; sym = setNextItem (candidates))
    {
      // printf("Looking at %s, %d definitions\n", sym->name, bitVectnBitsOn (sym->defs));

      int i;
      set *defs = 0;

      for (i = 0; i < sym->defs->size; i++)
        if (bitVectBitValue (sym->defs, i))
          {
            iCode *dic;
            if(dic = hTabItemWithKey (iCodehTab, i))
              addSet (&defs, hTabItemWithKey (iCodehTab, i));
            else
              {
                werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Definition not found");
                return;
              }
          }

      do
        {
          set *visited = 0;
          set *newdefs = 0;
          int oldsize;

          wassert (defs);
          wassert (setFirstItem (defs));

          // printf("Looking at def at %d now\n", ((iCode *)(setFirstItem (defs)))->key);

          if (!bitVectBitValue (((iCode *)(setFirstItem (defs)))->rlive, sym->key))
            {
              werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Variable is not alive at one of its definitions");
              break;
            }
 
          visit (&visited, setFirstItem (defs), sym->key);
          addSet (&newdefs, setFirstItem (defs));

          do
            {
              oldsize = elementsInSet(visited);
              ic = setFirstItem (defs);
              for(ic = setNextItem (defs); ic; ic = setNextItem (defs))
                {
                  // printf("Looking at other def at %d now\n", ic->key);
                  set *visited2 = 0;
                  set *intersection = 0;
                  visit (&visited2, ic, sym->key);
                  intersection = intersectSets (visited, visited2, THROW_NONE);
                  intersection = subtractFromSet (intersection, defs, THROW_DEST);
                  if (intersection)
                    {
                      visited = unionSets (visited, visited2, THROW_DEST);
                      addSet (&newdefs, ic);
                    }
                  deleteSet (&intersection);
                  deleteSet (&visited2);
                }
             }
          while (oldsize < elementsInSet(visited));

          defs = subtractFromSet (defs, newdefs, THROW_DEST);

          if (newdefs && defs)
            {
              operand *tmpop = newiTempOperand (operandType (IC_RESULT ((iCode *)(setFirstItem (newdefs)))), TRUE);

              // printf("Splitting %s from %s, using def at %d, op %d\n", OP_SYMBOL_CONST(tmpop)->name, sym->name, ((iCode *)(setFirstItem (newdefs)))->key, ((iCode *)(setFirstItem (newdefs)))->op);

              for (ic = setFirstItem (visited); ic; ic = setNextItem (visited))
                {
                  if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic)) == sym)
                    IC_LEFT (ic) = operandFromOperand (tmpop);
                  if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic)) == sym)
                      IC_RIGHT (ic) = operandFromOperand (tmpop);
                  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym && !POINTER_SET(ic) && ic->next && !isinSet (visited, ic->next))
                    continue;
                  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym)
                    {
                      bool pset = POINTER_SET(ic);
                      IC_RESULT (ic) = operandFromOperand (tmpop);
                      if (pset)
                        IC_RESULT(ic)->isaddr = TRUE;
                    }
                  bitVectUnSetBit (sym->uses, ic->key);
                }
            }
          deleteSet (&newdefs);
          deleteSet (&visited);
        }
      while (elementsInSet(defs) > 1);

      deleteSet (&defs);
    }

  deleteSet (&candidates);
}
コード例 #14
0
ファイル: SDCClrange.c プロジェクト: Derpybunneh/cpctelera
/*-----------------------------------------------------------------*/
static int
findNextUseSym (eBBlock *ebp, iCode *ic, symbol * sym)
{
  int retval = 0;
  iCode *uic;
  eBBlock *succ;

  hTabAddItemIfNotP (&liveRanges, sym->key, sym);

  if (!ic)
    goto check_successors;

  /* if we check a complete block and the symbol */
  /* is alive at the beginning of the block */
  /* and not defined in the first instructions */
  /* then a next use exists (return 1) */
  if ((ic == ebp->sch) && bitVectBitValue(ic->rlive, sym->key))
    {
      /* check if the first instruction is a def of this op */
      if (ic->op == JUMPTABLE || ic->op == IFX || SKIP_IC2(ic))
        return 1;

      if (IS_ITEMP(IC_RESULT(ic)))
        if (IC_RESULT(ic)->key == sym->key)
          return 0;

      return 1;
    }

  if (ebp->visited)
    return 0;

  if (ic == ebp->sch)
    ebp->visited = 1;

  /* for all remaining instructions in current block */
  for (uic = ic; uic; uic = uic->next)
    {

      if (SKIP_IC2(uic))
        continue;

      if (uic->op == JUMPTABLE)
        {
          if (IS_ITEMP(IC_JTCOND(uic)) && IC_JTCOND(uic)->key == sym->key)
            {
	      markAlive(ic, uic, sym->key);
	      return 1;
	    }
	   continue;
	}

      if (uic->op == IFX)
        {
          if (IS_ITEMP(IC_COND(uic)) && IC_COND(uic)->key == sym->key)
            {
	      markAlive(ic, uic, sym->key);
	      return 1;
	    }
	   continue;
	}

      if (IS_ITEMP (IC_LEFT (uic)))
        if (IC_LEFT (uic)->key == sym->key)
          {
	    markAlive(ic, uic, sym->key);
	    return 1;
	  }

      if (IS_ITEMP (IC_RIGHT (uic)))
        if (IC_RIGHT (uic)->key == sym->key)
	  {
	    markAlive (ic, uic, sym->key);
	    return 1;
	  }

      if (IS_ITEMP (IC_RESULT (uic)))
        if (IC_RESULT (uic)->key == sym->key)
	  {
	    if (POINTER_SET (uic))
	      {
	        markAlive (ic, uic, sym->key);
                return 1;
	      }
	    else
	      return 0;
	  }

    }

  /* check all successors */
check_successors:

  succ = setFirstItem (ebp->succList);
  for (; succ; succ = setNextItem (ebp->succList))
    {
      retval += findNextUseSym (succ, succ->sch, sym);
    }

  if (retval)
    {
      if (ic) markAlive (ic, ebp->ech, sym->key);
      return 1;
    }

  return 0;
}
コード例 #15
0
ファイル: ralloc.c プロジェクト: Trewdbal/cpctelera
/**
  Mark variables for assignment by the register allocator.
 */
static void
serialRegMark (eBBlock ** ebbs, int count)
{
  int i;
  short int max_alloc_bytes = SHRT_MAX; // Byte limit. Set this to a low value to pass only few variables to the register allocator. This can be useful for debugging.

  stm8_call_stack_size = 2; // Saving of register to stack temporarily.

  /* for all blocks */
  for (i = 0; i < count; i++)
    {
      iCode *ic;

      if (ebbs[i]->noPath && (ebbs[i]->entryLabel != entryLabel && ebbs[i]->entryLabel != returnLabel))
        continue;

      /* for all instructions do */
      for (ic = ebbs[i]->sch; ic; ic = ic->next)
        {
          if ((ic->op == CALL || ic->op == PCALL) && ic->parmBytes + 5 > stm8_call_stack_size)
            {
              sym_link *dtype = operandType (IC_LEFT (ic));
              sym_link *ftype = IS_FUNCPTR (dtype) ? dtype->next : dtype;

              /* 5 for saving all registers at call site + 2 for big return value */
              stm8_call_stack_size = ic->parmBytes + 5 + 2 * (getSize (ftype->next) > 4);
            }

          if (ic->op == IPOP)
            wassert (0);

          /* if result is present && is a true symbol */
          if (IC_RESULT (ic) && ic->op != IFX && IS_TRUE_SYMOP (IC_RESULT (ic)))
            OP_SYMBOL (IC_RESULT (ic))->allocreq++;

          /* some don't need registers, since there is no result. */
          if (SKIP_IC2 (ic) ||
              ic->op == JUMPTABLE || ic->op == IFX || ic->op == IPUSH || ic->op == IPOP || (IC_RESULT (ic) && POINTER_SET (ic)))
            continue;

          /* now we need to allocate registers only for the result */
          if (IC_RESULT (ic))
            {
              symbol *sym = OP_SYMBOL (IC_RESULT (ic));

              D (D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym));

              if (sym->isspilt && sym->usl.spillLoc) // todo: Remove once remat is supported!
                {
                  sym->usl.spillLoc->allocreq--;
                  sym->isspilt = FALSE;
                }

              /* Make sure any spill location is definately allocated */
              if (sym->isspilt && !sym->remat && sym->usl.spillLoc && !sym->usl.spillLoc->allocreq)
                sym->usl.spillLoc->allocreq++;

              /* if it does not need or is spilt
                 or is already marked for the new allocator
                 or will not live beyond this instructions */
              if (!sym->nRegs ||
                  sym->isspilt || sym->for_newralloc || sym->liveTo <= ic->seq)
                {
                  D (D_ALLOC, ("serialRegAssign: won't live long enough.\n"));
                  continue;
                }

              if (sym->nRegs > 4 && ic->op == CALL)
                {
                  spillThis (sym, TRUE);
                }
              else if (max_alloc_bytes >= sym->nRegs)
                {
                  sym->for_newralloc = 1;
                  max_alloc_bytes -= sym->nRegs;
                }
              else if (!sym->for_newralloc)
                {
                  spillThis (sym, TRUE);
                  printf ("Spilt %s due to byte limit.\n", sym->name);
                }
            }
        }
    }
}
コード例 #16
0
ファイル: ralloc.c プロジェクト: Trewdbal/cpctelera
/** Register reduction for assignment.
 */
static int
packRegsForAssign (iCode *ic, eBBlock *ebp)
{
  iCode *dic, *sic;

  if (!IS_ITEMP (IC_RIGHT (ic)) || OP_SYMBOL (IC_RIGHT (ic))->isind || OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
    return 0;
  
  /* Avoid having multiple named address spaces in one iCode. */
  if (IS_SYMOP (IC_RESULT (ic)) && SPEC_ADDRSPACE (OP_SYMBOL (IC_RESULT (ic))->etype))
    return 0;

  /* find the definition of iTempNN scanning backwards if we find a
     a use of the true symbol in before we find the definition then
     we cannot */
  for (dic = ic->prev; dic; dic = dic->prev)
    {
      /* PENDING: Don't pack across function calls. */
      if (dic->op == CALL || dic->op == PCALL)
        {
          dic = NULL;
          break;
        }

      if (SKIP_IC2 (dic))
        continue;

      if (dic->op == IFX)
        {
          if (IS_SYMOP (IC_COND (dic)) &&
              (IC_COND (dic)->key == IC_RESULT (ic)->key || IC_COND (dic)->key == IC_RIGHT (ic)->key))
            {
              dic = NULL;
              break;
            }
        }
      else
        {
          if (IS_TRUE_SYMOP (IC_RESULT (dic)) && IS_OP_VOLATILE (IC_RESULT (dic)))
            {
              dic = NULL;
              break;
            }

          if (IS_SYMOP (IC_RESULT (dic)) && IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
            {
              if (POINTER_SET (dic))
                dic = NULL;

              break;
            }

          if (IS_SYMOP (IC_RIGHT (dic)) &&
              (IC_RIGHT (dic)->key == IC_RESULT (ic)->key || IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
            {
              dic = NULL;
              break;
            }

          if (IS_SYMOP (IC_LEFT (dic)) &&
              (IC_LEFT (dic)->key == IC_RESULT (ic)->key || IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
            {
              dic = NULL;
              break;
            }

          if (IS_SYMOP (IC_RESULT (dic)) && IC_RESULT (dic)->key == IC_RESULT (ic)->key)
            {
              dic = NULL;
              break;
            }
        }
    }

  if (!dic)
    return 0;                   /* did not find */

  /* if assignment then check that right is not a bit */
  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
    {
      sym_link *etype = operandType (IC_RESULT (dic));
      if (IS_BITFIELD (etype))
        {
          /* if result is a bit too then it's ok */
          etype = operandType (IC_RESULT (ic));
          if (!IS_BITFIELD (etype))
            {
              return 0;
            }
        }
    }

  /* if the result is on stack or iaccess then it must be
     the same atleast one of the operands */
  if (OP_SYMBOL (IC_RESULT (ic))->onStack || OP_SYMBOL (IC_RESULT (ic))->iaccess)
    {
      /* the operation has only one symbol
         operator then we can pack */
      if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) || (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
        goto pack;

      if (!((IC_LEFT (dic) &&
             IC_RESULT (ic)->key == IC_LEFT (dic)->key) || (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
        return 0;
    }
pack:
  /* found the definition */
  /* replace the result with the result of */
  /* this assignment and remove this assignment */
  bitVectUnSetBit (OP_SYMBOL (IC_RESULT (dic))->defs, dic->key);
  IC_RESULT (dic) = IC_RESULT (ic);

  if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
    {
      OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
    }
  /* delete from liverange table also
     delete from all the points inbetween and the new
     one */
  for (sic = dic; sic != ic; sic = sic->next)
    {
      bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
      if (IS_ITEMP (IC_RESULT (dic)))
        bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
    }

  remiCodeFromeBBlock (ebp, ic);
  // PENDING: Check vs mcs51
  bitVectUnSetBit (OP_SYMBOL (IC_RESULT (ic))->defs, ic->key);
  hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
  OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
  return 1;
}
コード例 #17
0
ファイル: SDCClrange.c プロジェクト: Derpybunneh/cpctelera
/*-----------------------------------------------------------------*/
static void
rlivePoint (eBBlock ** ebbs, int count, bool emitWarnings)
{
  int i, key;
  eBBlock *succ;
  bitVect *alive;

  /* for all blocks do */
  for (i = 0; i < count; i++)
    {
      iCode *ic;

      /* for all instructions in this block do */
      for (ic = ebbs[i]->sch; ic; ic = ic->next)
        {

	  if (!ic->rlive)
	    ic->rlive = newBitVect (operandKey);

	  if (SKIP_IC2(ic))
	    continue;

	  if (ic->op == JUMPTABLE && IS_SYMOP(IC_JTCOND(ic)))
	    {
	      incUsed (ic, IC_JTCOND(ic));

	      if (!IS_AUTOSYM(IC_JTCOND(ic)))
	        continue;

	      findPrevUse (ebbs[i], ic, IC_JTCOND(ic), ebbs, count, emitWarnings);
              if (IS_ITEMP(IC_JTCOND(ic)))
                {
                  unvisitBlocks(ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_JTCOND(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_JTCOND(ic));
                }

	      continue;
	    }

	  if (ic->op == IFX && IS_SYMOP(IC_COND(ic)))
	    {
	      incUsed (ic, IC_COND(ic));

	      if (!IS_AUTOSYM(IC_COND(ic)))
	        continue;

	      findPrevUse (ebbs[i], ic, IC_COND(ic), ebbs, count, emitWarnings);
              if (IS_ITEMP(IC_COND(ic)))
                {
                  unvisitBlocks (ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_COND(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_COND(ic));
                }

	      continue;
	    }

	  if (IS_SYMOP(IC_LEFT(ic)))
	    {
	      incUsed (ic, IC_LEFT(ic));
	      if (IS_AUTOSYM(IC_LEFT(ic)) &&
	          ic->op != ADDRESS_OF)
	        {
	          findPrevUse (ebbs[i], ic, IC_LEFT(ic), ebbs, count, emitWarnings);
                  if (IS_ITEMP(IC_LEFT(ic)))
                    {
                      unvisitBlocks(ebbs, count);
                      ic->rlive = bitVectSetBit (ic->rlive, IC_LEFT(ic)->key);
                      findNextUse (ebbs[i], ic->next, IC_LEFT(ic));

                      /* if this is a send extend the LR to the call */
                      if (ic->op == SEND)
                        {
                          iCode *lic;
                          for (lic = ic; lic; lic = lic->next)
                            {
                              if (lic->op == CALL || lic->op == PCALL)
                                {
                                  markAlive (ic, lic->prev, IC_LEFT (ic)->key);
                                  break;
                                }
                            }
                        }
                    }
		}
	    }

	  if (IS_SYMOP(IC_RIGHT(ic)))
	    {
	      incUsed (ic, IC_RIGHT(ic));
              if (IS_AUTOSYM(IC_RIGHT(ic)))
	        {
	          findPrevUse (ebbs[i], ic, IC_RIGHT(ic), ebbs, count, emitWarnings);
                  if (IS_ITEMP(IC_RIGHT(ic)))
                    {
                      unvisitBlocks(ebbs, count);
                      ic->rlive = bitVectSetBit (ic->rlive, IC_RIGHT(ic)->key);
                      findNextUse (ebbs[i], ic->next, IC_RIGHT(ic));
                    }
		}
	    }

	  if (POINTER_SET(ic) && IS_SYMOP(IC_RESULT(ic)))
	    incUsed (ic, IC_RESULT(ic));

          if (IS_AUTOSYM(IC_RESULT(ic)))
	    {
	      if (POINTER_SET(ic))
	        {
	          findPrevUse (ebbs[i], ic, IC_RESULT(ic), ebbs, count, emitWarnings);
		}
              if (IS_ITEMP(IC_RESULT(ic)))
                {
                  unvisitBlocks(ebbs, count);
                  ic->rlive = bitVectSetBit (ic->rlive, IC_RESULT(ic)->key);
                  findNextUse (ebbs[i], ic->next, IC_RESULT(ic));
                  /* findNextUse sometimes returns 0 here, which means that ic is
                     dead code. Something should be done about this dead code since
                     e.g. register allocation suffers. */
                }
	    }

	  if (!POINTER_SET(ic) && IC_RESULT(ic))
	    ic->defKey = IC_RESULT(ic)->key;

	}

      /* check all symbols that are alive in the last instruction */
      /* but are not alive in all successors */

      succ = setFirstItem (ebbs[i]->succList);
      if (!succ)
        continue;

      alive = succ->sch->rlive;
      while ((succ = setNextItem (ebbs[i]->succList)))
        {
	  if (succ->sch)
            alive = bitVectIntersect (alive, succ->sch->rlive);
	}

      if (ebbs[i]->ech)
        alive = bitVectCplAnd ( bitVectCopy (ebbs[i]->ech->rlive), alive);

      if(!alive)
        continue;
      for (key = 1; key < alive->size; key++)
        {
	  if (!bitVectBitValue (alive, key))
	    continue;

	  unvisitBlocks(ebbs, count);
	  findNextUseSym (ebbs[i], NULL, hTabItemWithKey (liveRanges, key));
	}

    }
}
コード例 #18
0
ファイル: SDCCptropt.c プロジェクト: chamalo90/PIC_DHCP_Relay
/*--------------------------------------------------------------------*/
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;
}