static void
parse_ssa_operands (gimple stmt)
{
  enum gimple_code code = gimple_code (stmt);

  if (code == GIMPLE_ASM)
    get_asm_expr_operands (stmt);
  else if (is_gimple_debug (stmt))
    {
      if (gimple_debug_bind_p (stmt)
	  && gimple_debug_bind_has_value_p (stmt))
	get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt),
			   opf_use | opf_no_vops);
    }
  else
    {
      size_t i, start = 0;

      if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
	{
	  get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def);
	  start = 1;
	}

      for (i = start; i < gimple_num_ops (stmt); i++)
	get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use);

      /* Add call-clobbered operands, if needed.  */
      if (code == GIMPLE_CALL)
	maybe_add_call_vops (stmt);

      if (code == GIMPLE_RETURN)
	append_vuse (gimple_vop (cfun));
    }
}
Пример #2
0
void
insert_debug_temp_for_var_def (gimple stmt)
{
  gimple def_stmt = ((void *) 0);
  int usecount = 0;
  tree value = ((void *) 0);
  for (; arf ();)
    {
      if (!gimple_debug_bind_p (stmt))
        continue;
      if (usecount++)
        break;
      unsigned char no_value = 0;
      if (!gimple_bb (def_stmt))
        no_value = 1;
      if (!no_value)
        value = gimple_assign_rhs_to_tree ();
    }
  if (value)
    {
      if ((tree_code_type[(int) (((value)->code))] == 42)
          || (usecount == 1 && (is_gimple_min_invariant (value))))
        value = unshare_expr (value);
    }
}
Пример #3
0
void
insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
{
  imm_use_iterator imm_iter;
  use_operand_p use_p;
  gimple *stmt;
  gimple *def_stmt = NULL;
  int usecount = 0;
  tree value = NULL;

  if (!MAY_HAVE_DEBUG_STMTS)
    return;

  /* If this name has already been registered for replacement, do nothing
     as anything that uses this name isn't in SSA form.  */
  if (name_registered_for_update_p (var))
    return;

  /* Check whether there are debug stmts that reference this variable and,
     if there are, decide whether we should use a debug temp.  */
  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
    {
      stmt = USE_STMT (use_p);

      if (!gimple_debug_bind_p (stmt))
	continue;

      if (usecount++)
	break;

      if (gimple_debug_bind_get_value (stmt) != var)
	{
	  /* Count this as an additional use, so as to make sure we
	     use a temp unless VAR's definition has a SINGLE_RHS that
	     can be shared.  */
	  usecount++;
	  break;
	}
    }
static void
get_expr_operands (gimple stmt, tree *expr_p, int flags)
{
  enum tree_code code;
  enum tree_code_class codeclass;
  tree expr = *expr_p;
  int uflags = opf_use;

  if (expr == NULL)
    return;

  if (is_gimple_debug (stmt))
    uflags |= (flags & opf_no_vops);

  code = TREE_CODE (expr);
  codeclass = TREE_CODE_CLASS (code);

  switch (code)
    {
    case ADDR_EXPR:
      /* Taking the address of a variable does not represent a
	 reference to it, but the fact that the statement takes its
	 address will be of interest to some passes (e.g. alias
	 resolution).  */
      if ((!(flags & opf_non_addressable)
	   || (flags & opf_not_non_addressable))
	  && !is_gimple_debug (stmt))
	mark_address_taken (TREE_OPERAND (expr, 0));

      /* If the address is invariant, there may be no interesting
	 variable references inside.  */
      if (is_gimple_min_invariant (expr))
	return;

      /* Otherwise, there may be variables referenced inside but there
	 should be no VUSEs created, since the referenced objects are
	 not really accessed.  The only operands that we should find
	 here are ARRAY_REF indices which will always be real operands
	 (GIMPLE does not allow non-registers as array indices).  */
      flags |= opf_no_vops;
      get_expr_operands (stmt, &TREE_OPERAND (expr, 0),
			 flags | opf_not_non_addressable);
      return;

    case SSA_NAME:
     add_stmt_operand (expr_p, stmt, flags);
     return;

    case VAR_DECL:
    case PARM_DECL:
    case RESULT_DECL:
      add_stmt_operand (expr_p, stmt, flags);
      return;

    case DEBUG_EXPR_DECL:
      gcc_assert (gimple_debug_bind_p (stmt));
      return;

    case MEM_REF:
      get_indirect_ref_operands (stmt, expr, flags, true);
      return;

    case TARGET_MEM_REF:
      get_tmr_operands (stmt, expr, flags);
      return;

    case ARRAY_REF:
    case ARRAY_RANGE_REF:
    case COMPONENT_REF:
    case REALPART_EXPR:
    case IMAGPART_EXPR:
      {
	if (TREE_THIS_VOLATILE (expr))
	  gimple_set_has_volatile_ops (stmt, true);

	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);

	if (code == COMPONENT_REF)
	  {
	    if (TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1)))
	      gimple_set_has_volatile_ops (stmt, true);
	    get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
	  }
	else if (code == ARRAY_REF || code == ARRAY_RANGE_REF)
	  {
            get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
            get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
            get_expr_operands (stmt, &TREE_OPERAND (expr, 3), uflags);
	  }

	return;
      }

    case WITH_SIZE_EXPR:
      /* WITH_SIZE_EXPR is a pass-through reference to its first argument,
	 and an rvalue reference to its second argument.  */
      get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
      get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
      return;

    case COND_EXPR:
    case VEC_COND_EXPR:
      get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags);
      get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
      get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
      return;

    case CONSTRUCTOR:
      {
	/* General aggregate CONSTRUCTORs have been decomposed, but they
	   are still in use as the COMPLEX_EXPR equivalent for vectors.  */
	constructor_elt *ce;
	unsigned HOST_WIDE_INT idx;

	for (idx = 0;
	     VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce);
	     idx++)
	  get_expr_operands (stmt, &ce->value, uflags);

	return;
      }

    case BIT_FIELD_REF:
      if (TREE_THIS_VOLATILE (expr))
	gimple_set_has_volatile_ops (stmt, true);
      /* FALLTHRU */

    case VIEW_CONVERT_EXPR:
    do_unary:
      get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
      return;

    case COMPOUND_EXPR:
    case OBJ_TYPE_REF:
    case ASSERT_EXPR:
    do_binary:
      {
	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
	return;
      }

    case DOT_PROD_EXPR:
    case REALIGN_LOAD_EXPR:
    case WIDEN_MULT_PLUS_EXPR:
    case WIDEN_MULT_MINUS_EXPR:
    case FMA_EXPR:
      {
	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
	get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags);
	return;
      }

    case FUNCTION_DECL:
    case LABEL_DECL:
    case CONST_DECL:
    case CASE_LABEL_EXPR:
      /* Expressions that make no memory references.  */
      return;

    default:
      if (codeclass == tcc_unary)
	goto do_unary;
      if (codeclass == tcc_binary || codeclass == tcc_comparison)
	goto do_binary;
      if (codeclass == tcc_constant || codeclass == tcc_type)
	return;
    }

  /* If we get here, something has gone wrong.  */
#ifdef ENABLE_CHECKING
  fprintf (stderr, "unhandled expression in get_expr_operands():\n");
  debug_tree (expr);
  fputs ("\n", stderr);
#endif
  gcc_unreachable ();
}