Пример #1
0
static tree
make_phi_node (tree var, int len)
{
  tree phi;
  int capacity, i;

  capacity = ideal_phi_node_len (len);

  phi = allocate_phi_node (capacity);

  /* We need to clear the entire PHI node, including the argument
     portion, because we represent a "missing PHI argument" by placing
     NULL_TREE in PHI_ARG_DEF.  */
  memset (phi, 0, (sizeof (struct tree_phi_node) - sizeof (struct phi_arg_d)
		   + sizeof (struct phi_arg_d) * len));
  TREE_SET_CODE (phi, PHI_NODE);
  PHI_NUM_ARGS (phi) = len;
  PHI_ARG_CAPACITY (phi) = capacity;
  TREE_TYPE (phi) = TREE_TYPE (var);
  if (TREE_CODE (var) == SSA_NAME)
    SET_PHI_RESULT (phi, var);
  else
    SET_PHI_RESULT (phi, make_ssa_name (var, phi));

  for (i = 0; i < capacity; i++)
    {
      use_operand_p  imm;
      imm = &(PHI_ARG_IMM_USE_NODE (phi, i));
      imm->use = &(PHI_ARG_DEF_TREE (phi, i));
      imm->prev = NULL;
      imm->next = NULL;
      imm->stmt = phi;
    }
  return phi;
}
Пример #2
0
static void
resize_phi_node (tree *phi, int len)
{
  int old_size, i;
  tree new_phi;

  gcc_assert (len > PHI_ARG_CAPACITY (*phi));

  /* The garbage collector will not look at the PHI node beyond the
     first PHI_NUM_ARGS elements.  Therefore, all we have to copy is a
     portion of the PHI node currently in use.  */
  old_size = (sizeof (struct tree_phi_node)
	     + (PHI_NUM_ARGS (*phi) - 1) * sizeof (struct phi_arg_d));

  new_phi = allocate_phi_node (len);

  memcpy (new_phi, *phi, old_size);

  for (i = 0; i < PHI_NUM_ARGS (new_phi); i++)
    {
      use_operand_p imm, old_imm;
      imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
      old_imm = &(PHI_ARG_IMM_USE_NODE (*phi, i));
      imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
      relink_imm_use_stmt (imm, old_imm, new_phi);
    }

  PHI_ARG_CAPACITY (new_phi) = len;

  for (i = PHI_NUM_ARGS (new_phi); i < len; i++)
    {
      use_operand_p imm;
      imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
      imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
      imm->prev = NULL;
      imm->next = NULL;
      imm->stmt = new_phi;
    }


  *phi = new_phi;
}
Пример #3
0
static unsigned int
tree_ssa_phiopt (void)
{
  basic_block bb;
  basic_block *bb_order;
  unsigned n, i;
  bool cfgchanged = false;

  /* Search every basic block for COND_EXPR we may be able to optimize.

     We walk the blocks in order that guarantees that a block with
     a single predecessor is processed before the predecessor.
     This ensures that we collapse inner ifs before visiting the
     outer ones, and also that we do not try to visit a removed
     block.  */
  bb_order = blocks_in_phiopt_order ();
  n = n_basic_blocks - NUM_FIXED_BLOCKS;

  for (i = 0; i < n; i++) 
    {
      tree cond_expr;
      tree phi;
      basic_block bb1, bb2;
      edge e1, e2;
      tree arg0, arg1;

      bb = bb_order[i];

      cond_expr = last_stmt (bb);
      /* Check to see if the last statement is a COND_EXPR.  */
      if (!cond_expr
          || TREE_CODE (cond_expr) != COND_EXPR)
        continue;

      e1 = EDGE_SUCC (bb, 0);
      bb1 = e1->dest;
      e2 = EDGE_SUCC (bb, 1);
      bb2 = e2->dest;

      /* We cannot do the optimization on abnormal edges.  */
      if ((e1->flags & EDGE_ABNORMAL) != 0
          || (e2->flags & EDGE_ABNORMAL) != 0)
       continue;

      /* If either bb1's succ or bb2 or bb2's succ is non NULL.  */
      if (EDGE_COUNT (bb1->succs) == 0
          || bb2 == NULL
          || EDGE_COUNT (bb2->succs) == 0)
        continue;

      /* Find the bb which is the fall through to the other.  */
      if (EDGE_SUCC (bb1, 0)->dest == bb2)
        ;
      else if (EDGE_SUCC (bb2, 0)->dest == bb1)
        {
          basic_block bb_tmp = bb1;
          edge e_tmp = e1;
          bb1 = bb2;
          bb2 = bb_tmp;
          e1 = e2;
          e2 = e_tmp;
        }
      else
        continue;

      e1 = EDGE_SUCC (bb1, 0);

      /* Make sure that bb1 is just a fall through.  */
      if (!single_succ_p (bb1)
          || (e1->flags & EDGE_FALLTHRU) == 0)
        continue;

      /* Also make sure that bb1 only have one predecessor and that it
         is bb.  */
      if (!single_pred_p (bb1)
          || single_pred (bb1) != bb)
        continue;

      phi = phi_nodes (bb2);

      /* Check to make sure that there is only one PHI node.
         TODO: we could do it with more than one iff the other PHI nodes
         have the same elements for these two edges.  */
      if (!phi || PHI_CHAIN (phi) != NULL)
        continue;

      arg0 = PHI_ARG_DEF_TREE (phi, e1->dest_idx);
      arg1 = PHI_ARG_DEF_TREE (phi, e2->dest_idx);

      /* Something is wrong if we cannot find the arguments in the PHI
         node.  */
      gcc_assert (arg0 != NULL && arg1 != NULL);

      /* Do the replacement of conditional if it can be done.  */
      if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
        cfgchanged = true;
      else if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
        cfgchanged = true;
      else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
        cfgchanged = true;
      else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
        cfgchanged = true;
    }

  free (bb_order);
  
  /* If the CFG has changed, we should cleanup the CFG. */
  return cfgchanged ? TODO_cleanup_cfg : 0;
}