tree-optimize.c 12.7 KB
Newer Older
1
/* Top-level control of tree optimizations.
Joseph Myers committed
2
   Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Diego Novillo <dnovillo@redhat.com>
5 6 7 8 9

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
11 12 13 14 15 16 17 18
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
19 20
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
21 22 23 24

#include "config.h"
#include "system.h"
#include "coretypes.h"
25
#include "tm.h"
26
#include "tree.h"
27 28 29
#include "tm_p.h"
#include "basic-block.h"
#include "output.h"
30
#include "flags.h"
31 32
#include "tree-flow.h"
#include "tree-dump.h"
33 34
#include "timevar.h"
#include "function.h"
35
#include "langhooks.h"
36
#include "diagnostic-core.h"
37 38 39 40 41 42
#include "toplev.h"
#include "flags.h"
#include "cgraph.h"
#include "tree-inline.h"
#include "tree-mudflap.h"
#include "tree-pass.h"
43
#include "ggc.h"
44
#include "cgraph.h"
45
#include "graph.h"
46
#include "cfgloop.h"
47
#include "except.h"
48
#include "plugin.h"
49
#include "regset.h"	/* FIXME: For reg_obstack.  */
50 51 52 53 54 55 56

/* Gate: execute, or not, all of the non-trivial optimizations.  */

static bool
gate_all_optimizations (void)
{
  return (optimize >= 1
H.J. Lu committed
57
	  /* Don't bother doing anything if the program has errors.
58
	     We have to pass down the queue if we already went into SSA */
Joseph Myers committed
59
	  && (!seen_error () || gimple_in_ssa_p (cfun)));
60 61
}

62
struct gimple_opt_pass pass_all_optimizations =
63
{
64 65
 {
  GIMPLE_PASS,
66
  "*all_optimizations",			/* name */
67 68 69 70 71
  gate_all_optimizations,		/* gate */
  NULL,					/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
72
  TV_OPTIMIZE,				/* tv_id */
73 74 75 76
  0,					/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
77 78
  0					/* todo_flags_finish */
 }
79 80
};

81 82 83 84 85 86
/* Gate: execute, or not, all of the non-trivial optimizations.  */

static bool
gate_all_early_local_passes (void)
{
	  /* Don't bother doing anything if the program has errors.  */
Joseph Myers committed
87
  return (!seen_error () && !in_lto_p);
88 89
}

90 91 92 93 94 95 96 97 98 99 100 101 102 103
static unsigned int
execute_all_early_local_passes (void)
{
  /* Once this pass (and its sub-passes) are complete, all functions
     will be in SSA form.  Technically this state change is happening
     a tad early, since the sub-passes have not yet run, but since
     none of the sub-passes are IPA passes and do not create new
     functions, this is ok.  We're setting this value for the benefit
     of IPA passes that follow.  */
  if (cgraph_state < CGRAPH_STATE_IPA_SSA)
    cgraph_state = CGRAPH_STATE_IPA_SSA;
  return 0;
}

104
struct simple_ipa_opt_pass pass_early_local_passes =
105
{
106 107
 {
  SIMPLE_IPA_PASS,
108 109
  "early_local_cleanups",		/* name */
  gate_all_early_local_passes,		/* gate */
110
  execute_all_early_local_passes,	/* execute */
111 112 113
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
114
  TV_EARLY_LOCAL,			/* tv_id */
115 116 117 118
  0,					/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
119 120
  TODO_remove_functions	 		/* todo_flags_finish */
 }
121 122
};

123 124 125 126 127 128 129
/* Gate: execute, or not, all of the non-trivial optimizations.  */

static bool
gate_all_early_optimizations (void)
{
  return (optimize >= 1
	  /* Don't bother doing anything if the program has errors.  */
Joseph Myers committed
130
	  && !seen_error ());
131 132
}

133
struct gimple_opt_pass pass_all_early_optimizations =
134
{
135 136
 {
  GIMPLE_PASS,
137 138
  "early_optimizations",		/* name */
  gate_all_early_optimizations,		/* gate */
139
  NULL,					/* execute */
140 141 142
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
143
  TV_NONE,				/* tv_id */
144 145 146 147
  0,					/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
148 149
  0					/* todo_flags_finish */
 }
150 151
};

152

153 154 155 156 157
/* Pass: cleanup the CFG just before expanding trees to RTL.
   This is just a round of label cleanups and case node grouping
   because after the tree optimizers have run such cleanups may
   be necessary.  */

158
static unsigned int
159 160 161 162 163
execute_cleanup_cfg_post_optimizing (void)
{
  cleanup_tree_cfg ();
  cleanup_dead_labels ();
  group_case_labels ();
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
  if ((flag_compare_debug_opt || flag_compare_debug)
      && flag_dump_final_insns)
    {
      FILE *final_output = fopen (flag_dump_final_insns, "a");

      if (!final_output)
	{
	  error ("could not open final insn dump file %qs: %m",
		 flag_dump_final_insns);
	  flag_dump_final_insns = NULL;
	}
      else
	{
	  int save_unnumbered = flag_dump_unnumbered;
	  int save_noaddr = flag_dump_noaddr;

	  flag_dump_noaddr = flag_dump_unnumbered = 1;
	  fprintf (final_output, "\n");
	  dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
	  flag_dump_noaddr = save_noaddr;
	  flag_dump_unnumbered = save_unnumbered;
	  if (fclose (final_output))
	    {
	      error ("could not close final insn dump file %qs: %m",
		     flag_dump_final_insns);
	      flag_dump_final_insns = NULL;
	    }
	}
    }
193
  return 0;
194 195
}

196
struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
197
{
198 199
 {
  GIMPLE_PASS,
200
  "optimized",				/* name */
201 202 203 204 205
  NULL,					/* gate */
  execute_cleanup_cfg_post_optimizing,	/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
206
  TV_TREE_CLEANUP_CFG,			/* tv_id */
207 208 209 210
  PROP_cfg,				/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
211
  TODO_remove_unused_locals             /* todo_flags_finish */
212
 }
213 214
};

215 216 217
/* Pass: do the actions required to finish with tree-ssa optimization
   passes.  */

Michael Matz committed
218
unsigned int
219
execute_free_datastructures (void)
220 221
{
  free_dominance_info (CDI_DOMINATORS);
222
  free_dominance_info (CDI_POST_DOMINATORS);
223

Michael Matz committed
224 225 226
  /* And get rid of annotations we no longer need.  */
  delete_tree_cfg_annotations ();

227
  return 0;
228
}
229

230
/* IPA passes, compilation of earlier functions or inlining
231 232
   might have changed some properties, such as marked functions nothrow,
   pure, const or noreturn.
233
   Remove redundant edges and basic blocks, and create new ones if necessary.
234

235 236 237 238
   This pass can't be executed as stand alone pass from pass manager, because
   in between inlining and this fixup the verify_flow_info would fail.  */

unsigned int
239 240 241
execute_fixup_cfg (void)
{
  basic_block bb;
242
  gimple_stmt_iterator gsi;
243
  int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
244 245 246 247 248
  gcov_type count_scale;
  edge e;
  edge_iterator ei;

  if (ENTRY_BLOCK_PTR->count)
249 250 251
    count_scale = ((cgraph_get_node (current_function_decl)->count
		    * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2)
		   / ENTRY_BLOCK_PTR->count);
252 253 254
  else
    count_scale = REG_BR_PROB_BASE;

255
  ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
256 257 258
  EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
  			   + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;

259 260 261 262 263 264 265 266 267 268
  FOR_EACH_BB (bb)
    {
      bb->count = (bb->count * count_scale
		   + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
	{
	  gimple stmt = gsi_stmt (gsi);
	  tree decl = is_gimple_call (stmt)
		      ? gimple_call_fndecl (stmt)
		      : NULL;
269
	  if (decl)
270
	    {
271 272
	      int flags = gimple_call_flags (stmt);
	      if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
273
		{
274 275 276
		  if (gimple_purge_dead_abnormal_call_edges (bb))
		    todo |= TODO_cleanup_cfg;

277 278 279 280 281
		  if (gimple_in_ssa_p (cfun))
		    {
		      todo |= TODO_update_ssa | TODO_cleanup_cfg;
		      update_stmt (stmt);
		    }
282
		}
283

284 285 286 287
	      if (flags & ECF_NORETURN
		  && fixup_noreturn_call (stmt))
		todo |= TODO_cleanup_cfg;
	     }
288

289 290 291
	  if (maybe_clean_eh_stmt (stmt)
	      && gimple_purge_dead_eh_edges (bb))
	    todo |= TODO_cleanup_cfg;
292 293 294 295 296 297 298 299
	}

      FOR_EACH_EDGE (e, ei, bb->succs)
        e->count = (e->count * count_scale
		    + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
    }
  if (count_scale != REG_BR_PROB_BASE)
    compute_function_frequency ();
300

301 302 303 304 305 306 307
  /* We just processed all calls.  */
  if (cfun->gimple_df)
    {
      VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun));
      MODIFIED_NORETURN_CALLS (cfun) = NULL;
    }

308 309
  /* Dump a textual representation of the flowgraph.  */
  if (dump_file)
310
    gimple_dump_cfg (dump_file, dump_flags);
311

312
  return todo;
313 314
}

315 316 317 318
struct gimple_opt_pass pass_fixup_cfg =
{
 {
  GIMPLE_PASS,
319
  "*free_cfg_annotations",		/* name */
320
  NULL,					/* gate */
321
  execute_fixup_cfg,			/* execute */
322 323 324
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
325
  TV_NONE,				/* tv_id */
326 327 328 329 330 331 332 333
  PROP_cfg,				/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
  0					/* todo_flags_finish */
 }
};

334 335 336
/* Do the actions required to initialize internal data structures used
   in tree-ssa optimization passes.  */

337
static unsigned int
338 339 340
execute_init_datastructures (void)
{
  /* Allocate hash tables, arrays and other structures.  */
341
  init_tree_ssa (cfun);
342
  return 0;
343 344
}

345
struct gimple_opt_pass pass_init_datastructures =
346
{
347 348
 {
  GIMPLE_PASS,
349
  "*init_datastructures",		/* name */
350
  NULL,					/* gate */
351 352 353 354
  execute_init_datastructures,		/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
355
  TV_NONE,				/* tv_id */
356 357 358 359
  PROP_cfg,				/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
360 361
  0					/* todo_flags_finish */
 }
362 363
};

364 365 366 367 368 369 370
void
tree_lowering_passes (tree fn)
{
  tree saved_current_function_decl = current_function_decl;

  current_function_decl = fn;
  push_cfun (DECL_STRUCT_FUNCTION (fn));
371
  gimple_register_cfg_hooks ();
372 373
  bitmap_obstack_initialize (NULL);
  execute_pass_list (all_lowering_passes);
374
  if (optimize && cgraph_global_info_ready)
375
    execute_pass_list (pass_early_local_passes.pass.sub);
376
  free_dominance_info (CDI_POST_DOMINATORS);
377
  free_dominance_info (CDI_DOMINATORS);
378 379 380 381 382
  compact_blocks ();
  current_function_decl = saved_current_function_decl;
  bitmap_obstack_release (NULL);
  pop_cfun ();
}
383

384 385 386 387
/* For functions-as-trees languages, this performs all optimization and
   compilation for FNDECL.  */

void
388
tree_rest_of_compilation (tree fndecl)
389
{
390 391
  location_t saved_loc;

392
  timevar_push (TV_REST_OF_COMPILATION);
393

394
  gcc_assert (cgraph_global_info_ready);
395

396 397 398
  /* Initialize the default bitmap obstack.  */
  bitmap_obstack_initialize (NULL);

399 400
  /* Initialize the RTL code for the function.  */
  current_function_decl = fndecl;
401
  saved_loc = input_location;
402
  input_location = DECL_SOURCE_LOCATION (fndecl);
403 404
  init_function_start (fndecl);

405
  gimple_register_cfg_hooks ();
406

407
  bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
408 409 410

  execute_all_ipa_transforms ();

411
  /* Perform all tree transforms and optimizations.  */
412 413 414 415

  /* Signal the start of passes.  */
  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);

416
  execute_pass_list (all_passes);
H.J. Lu committed
417

418 419 420
  /* Signal the end of passes.  */
  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);

421
  bitmap_obstack_release (&reg_obstack);
422

423 424
  /* Release the default bitmap obstack.  */
  bitmap_obstack_release (NULL);
H.J. Lu committed
425

426
  set_cfun (NULL);
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443

  /* If requested, warn about function definitions where the function will
     return a value (usually of some struct or union type) which itself will
     take up a lot of stack space.  */
  if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
    {
      tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));

      if (ret_type && TYPE_SIZE_UNIT (ret_type)
	  && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
	  && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
				   larger_than_size))
	{
	  unsigned int size_as_int
	    = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));

	  if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
444
	    warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
445
                     fndecl, size_as_int);
446
	  else
447
	    warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes",
448
                     fndecl, larger_than_size);
449 450 451
	}
    }

452
  gimple_set_body (fndecl, NULL);
453
  if (DECL_STRUCT_FUNCTION (fndecl) == 0
454
      && !cgraph_get_node (fndecl)->origin)
455
    {
456 457 458 459 460 461 462
      /* Stop pointing to the local nodes about to be freed.
	 But DECL_INITIAL must remain nonzero so we know this
	 was an actual function definition.
	 For a nested function, this is done in c_pop_function_context.
	 If rest_of_compilation set this to 0, leave it 0.  */
      if (DECL_INITIAL (fndecl) != 0)
	DECL_INITIAL (fndecl) = error_mark_node;
463 464
    }

465 466
  input_location = saved_loc;

467
  ggc_collect ();
468
  timevar_pop (TV_REST_OF_COMPILATION);
469
}