示例#1
0
static struct mem_ref_group *
gather_memory_references (struct loop *loop, bool *no_other_refs)
{
  basic_block *body = get_loop_body_in_dom_order (loop);
  basic_block bb;
  unsigned i;
  gimple_stmt_iterator bsi;
  gimple stmt;
  tree lhs, rhs;
  struct mem_ref_group *refs = NULL;

  *no_other_refs = true;

  /* Scan the loop body in order, so that the former references precede the
     later ones.  */
  for (i = 0; i < loop->num_nodes; i++)
    {
      bb = body[i];
      if (bb->loop_father != loop)
	continue;

      for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
	{
	  stmt = gsi_stmt (bsi);

	  if (gimple_code (stmt) != GIMPLE_ASSIGN)
	    {
	      if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)
		  || (is_gimple_call (stmt)
		      && !(gimple_call_flags (stmt) & ECF_CONST)))
		*no_other_refs = false;
	      continue;
	    }

	  lhs = gimple_assign_lhs (stmt);
	  rhs = gimple_assign_rhs1 (stmt);

	  if (REFERENCE_CLASS_P (rhs))
	    *no_other_refs &= gather_memory_references_ref (loop, &refs,
							    rhs, false, stmt);
	  if (REFERENCE_CLASS_P (lhs))
	    *no_other_refs &= gather_memory_references_ref (loop, &refs,
							    lhs, true, stmt);
	}
    }
  free (body);

  return refs;
}
static struct mem_ref_group *
gather_memory_references (struct loop *loop, bool *no_other_refs)
{
  basic_block *body = get_loop_body_in_dom_order (loop);
  basic_block bb;
  unsigned i;
  block_stmt_iterator bsi;
  tree stmt, lhs, rhs, call;
  struct mem_ref_group *refs = NULL;

  *no_other_refs = true;

  /* Scan the loop body in order, so that the former references precede the
     later ones.  */
  for (i = 0; i < loop->num_nodes; i++)
    {
      bb = body[i];
      if (bb->loop_father != loop)
	continue;

      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
	{
	  stmt = bsi_stmt (bsi);
	  call = get_call_expr_in (stmt);
	  if (call && !(call_expr_flags (call) & ECF_CONST))
	    *no_other_refs = false;

	  if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
	    {
	      if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
		*no_other_refs = false;
	      continue;
	    }

	  lhs = GIMPLE_STMT_OPERAND (stmt, 0);
	  rhs = GIMPLE_STMT_OPERAND (stmt, 1);

	  if (REFERENCE_CLASS_P (rhs))
	    *no_other_refs &= gather_memory_references_ref (loop, &refs,
							    rhs, false, stmt);
	  if (REFERENCE_CLASS_P (lhs))
	    *no_other_refs &= gather_memory_references_ref (loop, &refs,
							    lhs, true, stmt);
	}
    }
  free (body);

  return refs;
}
static bool
bb_no_side_effects_p (basic_block bb)
{
  gimple_stmt_iterator gsi;

  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    {
      gimple stmt = gsi_stmt (gsi);

      if (gimple_has_volatile_ops (stmt)
	  || !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
	return false;
    }

  return true;
}
static bool
stmt_may_generate_copy (gimple stmt)
{
    if (gimple_code (stmt) == GIMPLE_PHI)
        return !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (stmt));

    if (gimple_code (stmt) != GIMPLE_ASSIGN)
        return false;

    /* If the statement has volatile operands, it won't generate a
       useful copy.  */
    if (gimple_has_volatile_ops (stmt))
        return false;

    /* Statements with loads and/or stores will never generate a useful copy.  */
    if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
        return false;

    /* Otherwise, the only statements that generate useful copies are
       assignments whose RHS is just an SSA name that doesn't flow
       through abnormal edges.  */
    return (gimple_assign_rhs_code (stmt) == SSA_NAME
            && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)));
}
示例#5
0
static inline bool
is_replaceable_p (gimple stmt)
{
  use_operand_p use_p;
  tree def;
  gimple use_stmt;
  location_t locus1, locus2;
  tree block1, block2;

  /* Only consider modify stmts.  */
  if (!is_gimple_assign (stmt))
    return false;

  /* If the statement may throw an exception, it cannot be replaced.  */
  if (stmt_could_throw_p (stmt))
    return false;

  /* Punt if there is more than 1 def.  */
  def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
  if (!def)
    return false;

  /* Only consider definitions which have a single use.  */
  if (!single_imm_use (def, &use_p, &use_stmt))
    return false;

  /* If the use isn't in this block, it wont be replaced either.  */
  if (gimple_bb (use_stmt) != gimple_bb (stmt))
    return false;

  locus1 = gimple_location (stmt);
  block1 = gimple_block (stmt);

  if (gimple_code (use_stmt) == GIMPLE_PHI)
    {
      locus2 = 0;
      block2 = NULL_TREE;
    }
  else
    {
      locus2 = gimple_location (use_stmt);
      block2 = gimple_block (use_stmt);
    }

  if (!optimize
      && ((locus1 && locus1 != locus2) || (block1 && block1 != block2)))
    return false;

  /* Used in this block, but at the TOP of the block, not the end.  */
  if (gimple_code (use_stmt) == GIMPLE_PHI)
    return false;

  /* There must be no VDEFs.  */
  if (!(ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF)))
    return false;

  /* Without alias info we can't move around loads.  */
  if (gimple_references_memory_p (stmt) && !optimize)
    return false;

  /* Float expressions must go through memory if float-store is on.  */
  if (flag_float_store 
      && FLOAT_TYPE_P (gimple_expr_type (stmt)))
    return false;

  /* An assignment with a register variable on the RHS is not
     replaceable.  */
  if (gimple_assign_rhs_code (stmt) == VAR_DECL
      && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
    return false;

  /* No function calls can be replaced.  */
  if (is_gimple_call (stmt))
    return false;

  /* Leave any stmt with volatile operands alone as well.  */
  if (gimple_has_volatile_ops (stmt))
    return false;

  return true;
}
示例#6
0
static unsigned int
get_rank (tree e)
{
  operand_entry_t vr;

  /* Constants have rank 0.  */
  if (is_gimple_min_invariant (e))
    return 0;

  /* SSA_NAME's have the rank of the expression they are the result
     of.
     For globals and uninitialized values, the rank is 0.
     For function arguments, use the pre-setup rank.
     For PHI nodes, stores, asm statements, etc, we use the rank of
     the BB.
     For simple operations, the rank is the maximum rank of any of
     its operands, or the bb_rank, whichever is less.
     I make no claims that this is optimal, however, it gives good
     results.  */

  if (TREE_CODE (e) == SSA_NAME)
    {
      tree stmt;
      tree rhs;
      unsigned int rank, maxrank;
      int i;

      if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
	  && e == default_def (SSA_NAME_VAR (e)))
	return find_operand_rank (e)->rank;

      stmt = SSA_NAME_DEF_STMT (e);
      if (bb_for_stmt (stmt) == NULL)
	return 0;

      if (TREE_CODE (stmt) != MODIFY_EXPR
	  || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
	return bb_rank[bb_for_stmt (stmt)->index];

      /* If we already have a rank for this expression, use that.  */
      vr = find_operand_rank (e);
      if (vr)
	return vr->rank;

      /* Otherwise, find the maximum rank for the operands, or the bb
	 rank, whichever is less.   */
      rank = 0;
      maxrank = bb_rank[bb_for_stmt(stmt)->index];
      rhs = TREE_OPERAND (stmt, 1);
      if (TREE_CODE_LENGTH (TREE_CODE (rhs)) == 0)
	rank = MAX (rank, get_rank (rhs));
      else
	{
	  for (i = 0;
	       i < TREE_CODE_LENGTH (TREE_CODE (rhs))
		 && TREE_OPERAND (rhs, i)
		 && rank != maxrank;
	       i++)
	    rank = MAX(rank, get_rank (TREE_OPERAND (rhs, i)));
	}

      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "Rank for ");
	  print_generic_expr (dump_file, e, 0);
	  fprintf (dump_file, " is %d\n", (rank + 1));
	}

      /* Note the rank in the hashtable so we don't recompute it.  */
      insert_operand_rank (e, (rank + 1));
      return (rank + 1);
    }

  /* Globals, etc,  are rank 0 */
  return 0;
}