Beispiel #1
0
static bool
gate_all_early_optimizations (void)
{
  return (optimize >= 1
	  /* Don't bother doing anything if the program has errors.  */
	  && !seen_error ());
}
Beispiel #2
0
bool
gate_lto_out (void)
{
  return ((flag_generate_lto || flag_generate_offload || in_lto_p)
	  /* Don't bother doing anything if the program has errors.  */
	  && !seen_error ());
}
Beispiel #3
0
/* Optimization of function bodies might've rendered some variables as
   unnecessary so we want to avoid these from being compiled.

   This is done by pruning the queue and keeping only the variables that
   really appear needed (ie they are either externally visible or referenced
   by compiled function). Re-doing the reachability analysis on variables
   brings back the remaining variables referenced by these.  */
void
varpool_remove_unreferenced_decls (void)
{
  struct varpool_node *next, *node = varpool_nodes_queue;

  varpool_reset_queue ();

  if (seen_error ())
    return;

  while (node)
    {
      next = node->next_needed;
      node->needed = 0;

      if (node->analyzed
	  && (!varpool_can_remove_if_no_refs (node)
	      /* We just expanded all function bodies.  See if any of
		 them needed the variable.  */
	      || DECL_RTL_SET_P (node->decl)))
	varpool_mark_needed_node (node);

      node = next;
    }
  /* Make sure we mark alias targets as used targets.  */
  finish_aliases_1 ();
  varpool_analyze_pending_decls ();
}
Beispiel #4
0
/* Output all variables enqueued to be assembled.  */
bool
varpool_assemble_pending_decls (void)
{
  bool changed = false;

  if (seen_error ())
    return false;

  timevar_push (TV_VAROUT);
  /* EH might mark decls as needed during expansion.  This should be safe since
     we don't create references to new function, but it should not be used
     elsewhere.  */
  varpool_analyze_pending_decls ();

  while (varpool_nodes_queue)
    {
      struct varpool_node *node = varpool_nodes_queue;

      varpool_nodes_queue = varpool_nodes_queue->next_needed;
      if (varpool_assemble_decl (node))
	changed = true;
      else
	{
	  node->prev_needed = NULL;
          node->next_needed = NULL;
	}
    }
  /* varpool_nodes_queue is now empty, clear the pointer to the last element
     in the queue.  */
  varpool_last_needed_node = NULL;
  timevar_pop (TV_VAROUT);
  return changed;
}
Beispiel #5
0
static bool
gate_all_optimizations (void)
{
  return (optimize >= 1
	  /* Don't bother doing anything if the program has errors.
	     We have to pass down the queue if we already went into SSA */
	  && (!seen_error () || gimple_in_ssa_p (cfun)));
}
Beispiel #6
0
static void
expand_BUILTIN_EXPECT (gimple stmt)
{
  /* When guessing was done, the hints should be already stripped away.  */
  gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());

  rtx target;
  tree lhs = gimple_call_lhs (stmt);
  if (lhs)
    target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
  else
    target = const0_rtx;
  rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
  if (lhs && val != target)
    emit_move_insn (target, val);
}
Beispiel #7
0
DEBUG_FUNCTION void
verify_symtab_node (symtab_node node)
{
  if (seen_error ())
    return;

  timevar_push (TV_CGRAPH_VERIFY);
  if (symtab_function_p (node))
    verify_cgraph_node (cgraph (node));
  else
    if (verify_symtab_base (node))
      {
        dump_symtab_node (stderr, node);
        internal_error ("verify_symtab_node failed");
      }
  timevar_pop (TV_CGRAPH_VERIFY);
}
Beispiel #8
0
DEBUG_FUNCTION void
symtab_node::verify (void)
{
  if (seen_error ())
    return;

  timevar_push (TV_CGRAPH_VERIFY);
  if (cgraph_node *node = dyn_cast <cgraph_node *> (this))
    node->verify_node ();
  else
    if (verify_base ())
      {
	debug ();
	internal_error ("symtab_node::verify failed");
      }
  timevar_pop (TV_CGRAPH_VERIFY);
}
Beispiel #9
0
/* Output all variables enqueued to be assembled.  */
bool
varpool_output_variables (void)
{
  bool changed = false;
  varpool_node *node;

  if (seen_error ())
    return false;

  varpool_remove_unreferenced_decls ();

  timevar_push (TV_VAROUT);

  FOR_EACH_DEFINED_VARIABLE (node)
    varpool_finalize_named_section_flags (node);

  FOR_EACH_DEFINED_VARIABLE (node)
    if (varpool_assemble_decl (node))
      changed = true;
  timevar_pop (TV_VAROUT);
  return changed;
}
Beispiel #10
0
static void
varpool_remove_unreferenced_decls (void)
{
  varpool_node *next, *node;
  varpool_node *first = (varpool_node *)(void *)1;
  int i;
  struct ipa_ref *ref;
  struct pointer_set_t *referenced = pointer_set_create ();

  if (seen_error ())
    return;

  if (cgraph_dump_file)
    fprintf (cgraph_dump_file, "Trivially needed variables:");
  FOR_EACH_DEFINED_VARIABLE (node)
    {
      if (node->analyzed
	  && (!varpool_can_remove_if_no_refs (node)
	      /* We just expanded all function bodies.  See if any of
		 them needed the variable.  */
	      || DECL_RTL_SET_P (node->decl)))
	{
	  enqueue_node (node, &first);
          if (cgraph_dump_file)
	    fprintf (cgraph_dump_file, " %s", node->asm_name ());
	}
    }
  while (first != (varpool_node *)(void *)1)
    {
      node = first;
      first = (varpool_node *)first->aux;

      if (node->same_comdat_group)
	{
	  symtab_node *next;
	  for (next = node->same_comdat_group;
	       next != node;
	       next = next->same_comdat_group)
	    {
	      varpool_node *vnext = dyn_cast <varpool_node *> (next);
	      if (vnext && vnext->analyzed && !symtab_comdat_local_p (next))
		enqueue_node (vnext, &first);
	    }
	}
      for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
	{
	  varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred);
	  if (vnode
	      && !vnode->in_other_partition
	      && (!DECL_EXTERNAL (ref->referred->decl)
		  || vnode->alias)
	      && vnode->analyzed)
	    enqueue_node (vnode, &first);
	  else
	    pointer_set_insert (referenced, node);
	}
    }
  if (cgraph_dump_file)
    fprintf (cgraph_dump_file, "\nRemoving variables:");
  for (node = varpool_first_defined_variable (); node; node = next)
    {
      next = varpool_next_defined_variable (node);
      if (!node->aux)
	{
          if (cgraph_dump_file)
	    fprintf (cgraph_dump_file, " %s", node->asm_name ());
	  if (pointer_set_contains (referenced, node))
	    varpool_remove_initializer (node);
	  else
	    varpool_remove_node (node);
	}
    }
  pointer_set_destroy (referenced);
  if (cgraph_dump_file)
    fprintf (cgraph_dump_file, "\n");
}
Beispiel #11
0
static bool
gate_all_early_local_passes (void)
{
	  /* Don't bother doing anything if the program has errors.  */
  return (!seen_error () && !in_lto_p);
}
Beispiel #12
0
static void
varpool_remove_unreferenced_decls (void)
{
  struct varpool_node *next, *node;
  struct varpool_node *first = (struct varpool_node *)(void *)1;
  int i;
  struct ipa_ref *ref;

  if (seen_error ())
    return;

  if (cgraph_dump_file)
    fprintf (cgraph_dump_file, "Trivially needed variables:");
  FOR_EACH_DEFINED_VARIABLE (node)
    {
      if (node->analyzed
	  && (!varpool_can_remove_if_no_refs (node)
	      /* We just expanded all function bodies.  See if any of
		 them needed the variable.  */
	      || (!DECL_EXTERNAL (node->symbol.decl)
		  && DECL_RTL_SET_P (node->symbol.decl))))
	{
	  enqueue_node (node, &first);
          if (cgraph_dump_file)
	    fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node));
	}
    }
  while (first != (struct varpool_node *)(void *)1)
    {
      node = first;
      first = (struct varpool_node *)first->symbol.aux;

      if (node->symbol.same_comdat_group)
	{
	  symtab_node next;
	  for (next = node->symbol.same_comdat_group;
	       next != (symtab_node)node;
	       next = next->symbol.same_comdat_group)
	    {
	      varpool_node *vnext = dyn_cast <varpool_node> (next);
	      if (vnext && vnext->analyzed)
		enqueue_node (vnext, &first);
	    }
	}
      for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
	{
	  varpool_node *vnode = dyn_cast <varpool_node> (ref->referred);
	  if (vnode
	      && (!DECL_EXTERNAL (ref->referred->symbol.decl)
		  || vnode->alias)
	      && vnode->analyzed)
	    enqueue_node (vnode, &first);
	}
    }
  if (cgraph_dump_file)
    fprintf (cgraph_dump_file, "\nRemoving variables:");
  for (node = varpool_first_defined_variable (); node; node = next)
    {
      next = varpool_next_defined_variable (node);
      if (!node->symbol.aux)
	{
          if (cgraph_dump_file)
	    fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node));
	  varpool_remove_node (node);
	}
    }
  if (cgraph_dump_file)
    fprintf (cgraph_dump_file, "\n");
}
Beispiel #13
0
int
cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
{
  int saved_stmts_are_full_exprs_p = 0;
  enum tree_code code = TREE_CODE (*expr_p);
  enum gimplify_status ret;

  if (STATEMENT_CODE_P (code))
    {
      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
      current_stmt_tree ()->stmts_are_full_exprs_p
	= STMT_IS_FULL_EXPR_P (*expr_p);
    }

  switch (code)
    {
    case PTRMEM_CST:
      *expr_p = cplus_expand_constant (*expr_p);
      ret = GS_OK;
      break;

    case AGGR_INIT_EXPR:
      simplify_aggr_init_expr (expr_p);
      ret = GS_OK;
      break;

    case VEC_INIT_EXPR:
      {
	location_t loc = input_location;
	tree init = VEC_INIT_EXPR_INIT (*expr_p);
	int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
	gcc_assert (EXPR_HAS_LOCATION (*expr_p));
	input_location = EXPR_LOCATION (*expr_p);
	*expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
				  init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
				  from_array,
				  tf_warning_or_error);
	cp_genericize_tree (expr_p);
	ret = GS_OK;
	input_location = loc;
      }
      break;

    case THROW_EXPR:
      /* FIXME communicate throw type to back end, probably by moving
	 THROW_EXPR into ../tree.def.  */
      *expr_p = TREE_OPERAND (*expr_p, 0);
      ret = GS_OK;
      break;

    case MUST_NOT_THROW_EXPR:
      ret = gimplify_must_not_throw_expr (expr_p, pre_p);
      break;

      /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
	 LHS of an assignment might also be involved in the RHS, as in bug
	 25979.  */
    case INIT_EXPR:
      if (fn_contains_cilk_spawn_p (cfun)
	  && cilk_detect_spawn_and_unwrap (expr_p)
	  && !seen_error ())
	return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
      cp_gimplify_init_expr (expr_p);
      if (TREE_CODE (*expr_p) != INIT_EXPR)
	return GS_OK;
      /* Otherwise fall through.  */
    case MODIFY_EXPR:
      {
	if (fn_contains_cilk_spawn_p (cfun)
	    && cilk_detect_spawn_and_unwrap (expr_p)
	    && !seen_error ())
	  return (enum gimplify_status) gimplify_cilk_spawn (expr_p);

	/* If the back end isn't clever enough to know that the lhs and rhs
	   types are the same, add an explicit conversion.  */
	tree op0 = TREE_OPERAND (*expr_p, 0);
	tree op1 = TREE_OPERAND (*expr_p, 1);

	if (!error_operand_p (op0)
	    && !error_operand_p (op1)
	    && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
		|| TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
	    && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
	  TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
					      TREE_TYPE (op0), op1);

	else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
		  || (TREE_CODE (op1) == CONSTRUCTOR
		      && CONSTRUCTOR_NELTS (op1) == 0
		      && !TREE_CLOBBER_P (op1))
		  || (TREE_CODE (op1) == CALL_EXPR
		      && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
		 && is_really_empty_class (TREE_TYPE (op0)))
	  {
	    /* Remove any copies of empty classes.  We check that the RHS
	       has a simple form so that TARGET_EXPRs and non-empty
	       CONSTRUCTORs get reduced properly, and we leave the return
	       slot optimization alone because it isn't a copy (FIXME so it
	       shouldn't be represented as one).

	       Also drop volatile variables on the RHS to avoid infinite
	       recursion from gimplify_expr trying to load the value.  */
	    if (!TREE_SIDE_EFFECTS (op1)
		|| (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
	      *expr_p = op0;
	    else if (TREE_CODE (op1) == MEM_REF
		     && TREE_THIS_VOLATILE (op1))
	      {
		/* Similarly for volatile MEM_REFs on the RHS.  */
		if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
		  *expr_p = op0;
		else
		  *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
				    TREE_OPERAND (op1, 0), op0);
	      }
	    else
	      *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
				op0, op1);
	  }
      }
      ret = GS_OK;
      break;

    case EMPTY_CLASS_EXPR:
      /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
      *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
      ret = GS_OK;
      break;

    case BASELINK:
      *expr_p = BASELINK_FUNCTIONS (*expr_p);
      ret = GS_OK;
      break;

    case TRY_BLOCK:
      genericize_try_block (expr_p);
      ret = GS_OK;
      break;

    case HANDLER:
      genericize_catch_block (expr_p);
      ret = GS_OK;
      break;

    case EH_SPEC_BLOCK:
      genericize_eh_spec_block (expr_p);
      ret = GS_OK;
      break;

    case USING_STMT:
      gcc_unreachable ();

    case FOR_STMT:
    case WHILE_STMT:
    case DO_STMT:
    case SWITCH_STMT:
    case CONTINUE_STMT:
    case BREAK_STMT:
      gcc_unreachable ();

    case OMP_FOR:
    case OMP_SIMD:
    case OMP_DISTRIBUTE:
      ret = cp_gimplify_omp_for (expr_p, pre_p);
      break;

    case EXPR_STMT:
      gimplify_expr_stmt (expr_p);
      ret = GS_OK;
      break;

    case UNARY_PLUS_EXPR:
      {
	tree arg = TREE_OPERAND (*expr_p, 0);
	tree type = TREE_TYPE (*expr_p);
	*expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
					    : arg;
	ret = GS_OK;
      }
      break;

    case CILK_SPAWN_STMT:
      gcc_assert 
	(fn_contains_cilk_spawn_p (cfun) 
	 && cilk_detect_spawn_and_unwrap (expr_p));

      /* If errors are seen, then just process it as a CALL_EXPR.  */
      if (!seen_error ())
	return (enum gimplify_status) gimplify_cilk_spawn (expr_p);
      
    case CALL_EXPR:
      if (fn_contains_cilk_spawn_p (cfun)
	  && cilk_detect_spawn_and_unwrap (expr_p)
	  && !seen_error ())
	return (enum gimplify_status) gimplify_cilk_spawn (expr_p);

    default:
      ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
      break;
    }

  /* Restore saved state.  */
  if (STATEMENT_CODE_P (code))
    current_stmt_tree ()->stmts_are_full_exprs_p
      = saved_stmts_are_full_exprs_p;

  return ret;
}