tree-optimize.c 13.8 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_NONE,				/* 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_NONE,				/* 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
/* 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.  */

157
static unsigned int
158 159 160
execute_cleanup_cfg_pre_ipa (void)
{
  cleanup_tree_cfg ();
161
  return 0;
162 163
}

164
struct gimple_opt_pass pass_cleanup_cfg =
165
{
166 167
 {
  GIMPLE_PASS,
168 169 170 171 172 173
  "cleanup_cfg",			/* name */
  NULL,					/* gate */
  execute_cleanup_cfg_pre_ipa,		/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
174
  TV_NONE,				/* tv_id */
175 176 177 178
  PROP_cfg,				/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
179 180
  TODO_dump_func			/* todo_flags_finish */
 }
181 182 183
};


184 185 186 187 188
/* 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.  */

189
static unsigned int
190 191
execute_cleanup_cfg_post_optimizing (void)
{
192
  fold_cond_expr_cond ();
193 194 195
  cleanup_tree_cfg ();
  cleanup_dead_labels ();
  group_case_labels ();
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
  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;
	    }
	}
    }
225
  return 0;
226 227
}

228
struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
229
{
230 231
 {
  GIMPLE_PASS,
232
  "optimized",				/* name */
233 234 235 236 237
  NULL,					/* gate */
  execute_cleanup_cfg_post_optimizing,	/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
238
  TV_NONE,				/* tv_id */
239 240 241 242
  PROP_cfg,				/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
243
  TODO_dump_func			/* todo_flags_finish */
Michael Matz committed
244
    | TODO_remove_unused_locals
245
 }
246 247
};

248 249 250
/* Pass: do the actions required to finish with tree-ssa optimization
   passes.  */

Michael Matz committed
251
unsigned int
252
execute_free_datastructures (void)
253 254
{
  free_dominance_info (CDI_DOMINATORS);
255
  free_dominance_info (CDI_POST_DOMINATORS);
256

Michael Matz committed
257 258 259
  /* And get rid of annotations we no longer need.  */
  delete_tree_cfg_annotations ();

260
  return 0;
261
}
262

263
/* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
264 265
   might have changed some properties, such as marked functions nothrow,
   pure, const or noreturn.
266
   Remove redundant edges and basic blocks, and create new ones if necessary.
267

268 269 270 271
   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
272 273 274
execute_fixup_cfg (void)
{
  basic_block bb;
275
  gimple_stmt_iterator gsi;
276
  int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
277 278 279 280 281 282 283 284 285 286
  gcov_type count_scale;
  edge e;
  edge_iterator ei;

  if (ENTRY_BLOCK_PTR->count)
    count_scale = (cgraph_node (current_function_decl)->count * REG_BR_PROB_BASE
    		   + ENTRY_BLOCK_PTR->count / 2) / ENTRY_BLOCK_PTR->count;
  else
    count_scale = REG_BR_PROB_BASE;

287 288 289 290
  ENTRY_BLOCK_PTR->count = cgraph_node (current_function_decl)->count;
  EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
  			   + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;

291 292 293 294 295 296 297 298 299 300
  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;
301
	  if (decl)
302
	    {
303 304
	      int flags = gimple_call_flags (stmt);
	      if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
305
		{
306 307 308 309 310 311
		  if (gimple_in_ssa_p (cfun))
		    {
		      todo |= TODO_update_ssa | TODO_cleanup_cfg;
		      mark_symbols_for_renaming (stmt);
		      update_stmt (stmt);
		    }
312
		}
313 314 315 316 317
	      
	      if (flags & ECF_NORETURN
		  && fixup_noreturn_call (stmt))
		todo |= TODO_cleanup_cfg;
	     }
318 319 320 321 322 323 324 325 326 327 328 329

	  maybe_clean_eh_stmt (stmt);
	}

      if (gimple_purge_dead_eh_edges (bb))
	todo |= TODO_cleanup_cfg;
      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 ();
330

331 332 333 334 335 336 337
  /* We just processed all calls.  */
  if (cfun->gimple_df)
    {
      VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun));
      MODIFIED_NORETURN_CALLS (cfun) = NULL;
    }

338 339
  /* Dump a textual representation of the flowgraph.  */
  if (dump_file)
340
    gimple_dump_cfg (dump_file, dump_flags);
341

342
  return todo;
343 344
}

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

364 365 366
/* Do the actions required to initialize internal data structures used
   in tree-ssa optimization passes.  */

367
static unsigned int
368 369 370
execute_init_datastructures (void)
{
  /* Allocate hash tables, arrays and other structures.  */
371
  init_tree_ssa (cfun);
372
  return 0;
373 374
}

375
struct gimple_opt_pass pass_init_datastructures =
376
{
377 378
 {
  GIMPLE_PASS,
379
  "*init_datastructures",		/* name */
380
  NULL,					/* gate */
381 382 383 384
  execute_init_datastructures,		/* execute */
  NULL,					/* sub */
  NULL,					/* next */
  0,					/* static_pass_number */
385
  TV_NONE,				/* tv_id */
386 387 388 389
  PROP_cfg,				/* properties_required */
  0,					/* properties_provided */
  0,					/* properties_destroyed */
  0,					/* todo_flags_start */
390 391
  0					/* todo_flags_finish */
 }
392 393
};

394 395 396 397 398 399 400
void
tree_lowering_passes (tree fn)
{
  tree saved_current_function_decl = current_function_decl;

  current_function_decl = fn;
  push_cfun (DECL_STRUCT_FUNCTION (fn));
401
  gimple_register_cfg_hooks ();
402 403
  bitmap_obstack_initialize (NULL);
  execute_pass_list (all_lowering_passes);
404
  if (optimize && cgraph_global_info_ready)
405
    execute_pass_list (pass_early_local_passes.pass.sub);
406
  free_dominance_info (CDI_POST_DOMINATORS);
407
  free_dominance_info (CDI_DOMINATORS);
408 409 410 411 412
  compact_blocks ();
  current_function_decl = saved_current_function_decl;
  bitmap_obstack_release (NULL);
  pop_cfun ();
}
413

414 415 416 417
/* For functions-as-trees languages, this performs all optimization and
   compilation for FNDECL.  */

void
418
tree_rest_of_compilation (tree fndecl)
419
{
420 421
  location_t saved_loc;

422 423
  timevar_push (TV_EXPAND);

424
  gcc_assert (cgraph_global_info_ready);
425

426 427 428
  /* Initialize the default bitmap obstack.  */
  bitmap_obstack_initialize (NULL);

429 430
  /* Initialize the RTL code for the function.  */
  current_function_decl = fndecl;
431
  saved_loc = input_location;
432
  input_location = DECL_SOURCE_LOCATION (fndecl);
433 434 435 436 437 438
  init_function_start (fndecl);

  /* Even though we're inside a function body, we still don't want to
     call expand_expr to calculate the size of a variable-sized array.
     We haven't necessarily assigned RTL to all variables yet, so it's
     not safe to try to expand expressions involving them.  */
439
  cfun->dont_save_pending_sizes_p = 1;
H.J. Lu committed
440

441
  gimple_register_cfg_hooks ();
442

443
  bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
444 445 446

  execute_all_ipa_transforms ();

447
  /* Perform all tree transforms and optimizations.  */
448 449 450 451

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

452
  execute_pass_list (all_passes);
H.J. Lu committed
453

454 455 456
  /* Signal the end of passes.  */
  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);

457
  bitmap_obstack_release (&reg_obstack);
458

459 460
  /* Release the default bitmap obstack.  */
  bitmap_obstack_release (NULL);
H.J. Lu committed
461

462
  set_cfun (NULL);
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479

  /* 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)
480
	    warning (OPT_Wlarger_than_eq, "size of return value of %q+D is %u bytes",
481
                     fndecl, size_as_int);
482
	  else
483
	    warning (OPT_Wlarger_than_eq, "size of return value of %q+D is larger than %wd bytes",
484
                     fndecl, larger_than_size);
485 486 487
	}
    }

488
  gimple_set_body (fndecl, NULL);
489 490
  if (DECL_STRUCT_FUNCTION (fndecl) == 0
      && !cgraph_node (fndecl)->origin)
491
    {
492 493 494 495 496 497 498
      /* 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;
499 500
    }

501 502
  input_location = saved_loc;

503
  ggc_collect ();
504 505
  timevar_pop (TV_EXPAND);
}