profile.c 34.3 KB
Newer Older
1
/* Calculate branch probabilities, and basic block execution counts.
2 3
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
   2000, 2001  Free Software Foundation, Inc.
Doug Evans committed
4 5 6 7
   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
   based on some ideas from Dain Samples of UC Berkeley.
   Further mangling by Bob Manson, Cygnus Support.

8
This file is part of GCC.
Doug Evans committed
9

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

15 16 17 18
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.
Doug Evans committed
19 20

You should have received a copy of the GNU General Public License
21 22 23
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */
Doug Evans committed
24 25 26 27 28 29 30 31 32 33 34 35 36

/* ??? Register allocation should use basic block execution counts to
   give preference to the most commonly executed blocks.  */

/* ??? The .da files are not safe.  Changing the program after creating .da
   files or using different options when compiling with -fbranch-probabilities
   can result the arc data not matching the program.  Maybe add instrumented
   arc count to .bbg file?  Maybe check whether PFG matches the .bbg file?  */

/* ??? Should calculate branch probabilities before instrumenting code, since
   then we can use arc counts to help decide which arcs to instrument.  */

#include "config.h"
37
#include "system.h"
Doug Evans committed
38
#include "rtl.h"
39
#include "tree.h"
Doug Evans committed
40 41 42
#include "flags.h"
#include "insn-config.h"
#include "output.h"
43
#include "regs.h"
44
#include "expr.h"
45
#include "function.h"
Robert Lipe committed
46
#include "toplev.h"
47
#include "ggc.h"
48
#include "hard-reg-set.h"
49
#include "basic-block.h"
50
#include "gcov-io.h"
51
#include "target.h"
Doug Evans committed
52

53 54 55 56 57 58 59
/* Additional information about the edges we need.  */
struct edge_info
  {
    unsigned int count_valid : 1;
    unsigned int on_tree : 1;
    unsigned int ignore : 1;
  };
Doug Evans committed
60
struct bb_info
61 62
  {
    unsigned int count_valid : 1;
63 64
    gcov_type succ_count;
    gcov_type pred_count;
65 66 67 68 69 70
  };

#define EDGE_INFO(e)  ((struct edge_info *) (e)->aux)
#define BB_INFO(b)  ((struct bb_info *) (b)->aux)

/* Keep all basic block indexes nonnegative in the gcov output.  Index 0
Kazu Hirata committed
71
   is used for entry block, last block exit block.  */
72
#define GCOV_INDEX_TO_BB(i)  ((i) == 0 ? ENTRY_BLOCK_PTR		\
73
			      : (((i) == n_basic_blocks + 1)		\
74
			         ? EXIT_BLOCK_PTR : BASIC_BLOCK ((i)-1)))
75 76
#define BB_TO_GCOV_INDEX(bb)  ((bb) == ENTRY_BLOCK_PTR ? 0		\
			       : ((bb) == EXIT_BLOCK_PTR		\
77
				  ? n_basic_blocks + 1 : (bb)->index + 1))
Doug Evans committed
78 79 80 81 82 83 84 85 86

/* Name and file pointer of the output file for the basic block graph.  */

static FILE *bbg_file;

/* Name and file pointer of the input file for the arc count data.  */

static FILE *da_file;

87
/* Pointer of the output file for the basic block/line number map.  */
Doug Evans committed
88 89
static FILE *bb_file;

90
/* Last source file name written to bb_file.  */
Doug Evans committed
91 92 93 94 95 96

static char *last_bb_file_name;

/* Used by final, for allocating the proper amount of storage for the
   instrumented arc execution counts.  */

97
int count_instrumented_edges;
Doug Evans committed
98 99 100 101 102

/* Collect statistics on the performance of this pass for the entire source
   file.  */

static int total_num_blocks;
103
static int total_num_edges;
104
static int total_num_edges_ignored;
105
static int total_num_edges_instrumented;
Doug Evans committed
106 107 108 109 110 111 112 113
static int total_num_blocks_created;
static int total_num_passes;
static int total_num_times_called;
static int total_hist_br_prob[20];
static int total_num_never_executed;
static int total_num_branches;

/* Forward declarations.  */
114 115 116 117
static void find_spanning_tree PARAMS ((struct edge_list *));
static void init_edge_profiler PARAMS ((void));
static rtx gen_edge_profiler PARAMS ((int));
static void instrument_edges PARAMS ((struct edge_list *));
118
static void output_gcov_string PARAMS ((const char *, long));
119 120 121
static void compute_branch_probabilities PARAMS ((void));
static basic_block find_group PARAMS ((basic_block));
static void union_groups PARAMS ((basic_block, basic_block));
Doug Evans committed
122 123

/* If non-zero, we need to output a constructor to set up the
124
   per-object-file data.  */
Doug Evans committed
125 126
static int need_func_profiler = 0;

127
/* Add edge instrumentation code to the entire insn chain.
Doug Evans committed
128 129

   F is the first insn of the chain.
130
   NUM_BLOCKS is the number of basic blocks found in F.  */
Doug Evans committed
131 132

static void
133 134
instrument_edges (el)
     struct edge_list *el;
Doug Evans committed
135
{
136 137 138 139 140 141 142 143 144 145
  int i;
  int num_instr_edges = 0;
  int num_edges = NUM_EDGES (el);
  remove_fake_edges ();

  for (i = 0; i < n_basic_blocks + 2; i++)
    {
      basic_block bb = GCOV_INDEX_TO_BB (i);
      edge e = bb->succ;
      while (e)
Doug Evans committed
146
	{
147 148
	  struct edge_info *inf = EDGE_INFO (e);
	  if (!inf->ignore && !inf->on_tree)
Doug Evans committed
149
	    {
150
	      if (e->flags & EDGE_ABNORMAL)
Doug Evans committed
151
		abort ();
152 153 154
	      if (rtl_dump_file)
		fprintf (rtl_dump_file, "Edge %d to %d instrumented%s\n",
			 e->src->index, e->dest->index,
155
			 EDGE_CRITICAL_P (e) ? " (and split)" : "");
156 157 158 159
	      need_func_profiler = 1;
	      insert_insn_on_edge (
			 gen_edge_profiler (total_num_edges_instrumented
					    + num_instr_edges++), e);
Doug Evans committed
160
	    }
161
	  e = e->succ_next;
Doug Evans committed
162 163
	}
    }
164 165 166 167 168 169 170 171 172

  total_num_edges_instrumented += num_instr_edges;
  count_instrumented_edges = total_num_edges_instrumented;

  total_num_blocks_created += num_edges;
  if (rtl_dump_file)
    fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);

  commit_edge_insertions ();
Doug Evans committed
173 174 175 176 177 178
}

/* Output STRING to bb_file, surrounded by DELIMITER.  */

static void
output_gcov_string (string, delimiter)
179
     const char *string;
Doug Evans committed
180 181 182
     long delimiter;
{
  long temp;
183

Doug Evans committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
  /* Write a delimiter to indicate that a file name follows.  */
  __write_long (delimiter, bb_file, 4);

  /* Write the string.  */
  temp = strlen (string) + 1;
  fwrite (string, temp, 1, bb_file);

  /* Append a few zeros, to align the output to a 4 byte boundary.  */
  temp = temp & 0x3;
  if (temp)
    {
      char c[4];

      c[0] = c[1] = c[2] = c[3] = 0;
      fwrite (c, sizeof (char), 4 - temp, bb_file);
    }

201 202
  /* Store another delimiter in the .bb file, just to make it easy to find
     the end of the file name.  */
Doug Evans committed
203 204 205
  __write_long (delimiter, bb_file, 4);
}

206

207 208 209 210
/* Compute the branch probabilities for the various branches.
   Annotate them accordingly.  */

static void
211
compute_branch_probabilities ()
212 213
{
  int i;
214
  int num_edges = 0;
215 216 217
  int changes;
  int passes;
  int hist_br_prob[20];
218 219
  int num_never_executed;
  int num_branches;
220

221 222
  /* Attach extra info block to each bb.  */

223
  alloc_aux_for_blocks (sizeof (struct bb_info));
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
  for (i = 0; i < n_basic_blocks + 2; i++)
    {
      basic_block bb = GCOV_INDEX_TO_BB (i);
      edge e;

      for (e = bb->succ; e; e = e->succ_next)
	if (!EDGE_INFO (e)->ignore)
	  BB_INFO (bb)->succ_count++;
      for (e = bb->pred; e; e = e->pred_next)
	if (!EDGE_INFO (e)->ignore)
	  BB_INFO (bb)->pred_count++;
    }

  /* Avoid predicting entry on exit nodes.  */
  BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
  BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;

  /* For each edge not on the spanning tree, set its execution count from
242 243 244 245 246
     the .da file.  */

  /* The first count in the .da file is the number of times that the function
     was entered.  This is the exec_count for block zero.  */

247 248 249 250 251 252 253 254 255 256
  for (i = 0; i < n_basic_blocks + 2; i++)
    {
      basic_block bb = GCOV_INDEX_TO_BB (i);
      edge e;
      for (e = bb->succ; e; e = e->succ_next)
	if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
	  {
	    num_edges++;
	    if (da_file)
	      {
257 258
		gcov_type value;
		__read_gcov_type (&value, da_file, 8);
259 260 261 262 263 264 265
		e->count = value;
	      }
	    else
	      e->count = 0;
	    EDGE_INFO (e)->count_valid = 1;
	    BB_INFO (bb)->succ_count--;
	    BB_INFO (e->dest)->pred_count--;
266 267 268 269 270 271 272
	    if (rtl_dump_file)
	      {
		fprintf (rtl_dump_file, "\nRead edge from %i to %i, count:",
			 bb->index, e->dest->index);
		fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,
			 (HOST_WIDEST_INT) e->count);
	      }
273 274
	  }
    }
275

276
  if (rtl_dump_file)
277
    fprintf (rtl_dump_file, "\n%d edge counts read\n", num_edges);
278 279

  /* For every block in the file,
280 281 282
     - if every exit/entrance edge has a known count, then set the block count
     - if the block count is known, and every exit/entrance edge but one has
     a known execution count, then set the count of the remaining edge
283

284 285 286
     As edge counts are set, decrement the succ/pred count, but don't delete
     the edge, that way we can easily tell when all edges are known, or only
     one edge is unknown.  */
287 288 289

  /* The order that the basic blocks are iterated through is important.
     Since the code that finds spanning trees starts with block 0, low numbered
290 291
     edges are put on the spanning tree in preference to high numbered edges.
     Hence, most instrumented edges are at the end.  Graph solving works much
292
     faster if we propagate numbers from the end to the start.
293

294 295 296 297 298 299 300 301
     This takes an average of slightly more than 3 passes.  */

  changes = 1;
  passes = 0;
  while (changes)
    {
      passes++;
      changes = 0;
302
      for (i = n_basic_blocks + 1; i >= 0; i--)
303
	{
304 305 306
	  basic_block bb = GCOV_INDEX_TO_BB (i);
	  struct bb_info *bi = BB_INFO (bb);
	  if (! bi->count_valid)
307
	    {
308
	      if (bi->succ_count == 0)
309
		{
310
		  edge e;
311
		  gcov_type total = 0;
312 313 314 315 316

		  for (e = bb->succ; e; e = e->succ_next)
		    total += e->count;
		  bb->count = total;
		  bi->count_valid = 1;
317 318
		  changes = 1;
		}
319
	      else if (bi->pred_count == 0)
320
		{
321
		  edge e;
322
		  gcov_type total = 0;
323 324 325 326 327

		  for (e = bb->pred; e; e = e->pred_next)
		    total += e->count;
		  bb->count = total;
		  bi->count_valid = 1;
328 329 330
		  changes = 1;
		}
	    }
331
	  if (bi->count_valid)
332
	    {
333
	      if (bi->succ_count == 1)
334
		{
335
		  edge e;
336
		  gcov_type total = 0;
337

338 339
		  /* One of the counts will be invalid, but it is zero,
		     so adding it in also doesn't hurt.  */
340 341 342 343 344 345
		  for (e = bb->succ; e; e = e->succ_next)
		    total += e->count;

		  /* Seedgeh for the invalid edge, and set its count.  */
		  for (e = bb->succ; e; e = e->succ_next)
		    if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
346
		      break;
347 348 349 350 351

		  /* Calculate count for remaining edge by conservation.  */
		  total = bb->count - total;

		  if (! e)
352
		    abort ();
353 354 355
		  EDGE_INFO (e)->count_valid = 1;
		  e->count = total;
		  bi->succ_count--;
356

357
		  BB_INFO (e->dest)->pred_count--;
358 359
		  changes = 1;
		}
360
	      if (bi->pred_count == 1)
361
		{
362
		  edge e;
363
		  gcov_type total = 0;
364

365 366
		  /* One of the counts will be invalid, but it is zero,
		     so adding it in also doesn't hurt.  */
367 368 369 370 371 372
		  for (e = bb->pred; e; e = e->pred_next)
		    total += e->count;

		  /* Seedgeh for the invalid edge, and set its count.  */
		  for (e = bb->pred; e; e = e->pred_next)
		    if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
373
		      break;
374 375 376 377 378

		  /* Calculate count for remaining edge by conservation.  */
		  total = bb->count - total + e->count;

		  if (! e)
379
		    abort ();
380 381 382
		  EDGE_INFO (e)->count_valid = 1;
		  e->count = total;
		  bi->pred_count--;
383

384
		  BB_INFO (e->src)->succ_count--;
385 386 387 388 389
		  changes = 1;
		}
	    }
	}
    }
390 391
  if (rtl_dump_file)
    dump_flow_info (rtl_dump_file);
392 393

  total_num_passes += passes;
394 395
  if (rtl_dump_file)
    fprintf (rtl_dump_file, "Graph solving took %d passes.\n\n", passes);
396 397 398

  /* If the graph has been correctly solved, every block will have a
     succ and pred count of zero.  */
399
  for (i = 0; i < n_basic_blocks; i++)
400
    {
401 402
      basic_block bb = BASIC_BLOCK (i);
      if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
403 404 405
	abort ();
    }

406
  /* For every edge, calculate its branch probability and add a reg_note
407 408 409 410 411 412 413
     to the branch insn to indicate this.  */

  for (i = 0; i < 20; i++)
    hist_br_prob[i] = 0;
  num_never_executed = 0;
  num_branches = 0;

414
  for (i = 0; i <= n_basic_blocks + 1; i++)
415
    {
416
      basic_block bb = GCOV_INDEX_TO_BB (i);
417
      edge e;
418
      gcov_type total;
419 420 421
      rtx note;

      total = bb->count;
422 423
      if (total)
	{
424
	  for (e = bb->succ; e; e = e->succ_next)
425
	    {
426 427 428
		e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total;
		if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
		  {
429
		    error ("corrupted profile info: prob for %d-%d thought to be %d",
430 431 432 433 434 435 436 437 438 439
			   e->src->index, e->dest->index, e->probability);
		    e->probability = REG_BR_PROB_BASE / 2;
		  }
	    }
	  if (bb->index >= 0
	      && any_condjump_p (bb->end)
	      && bb->succ->succ_next)
	    {
	      int prob;
	      edge e;
440 441 442 443 444 445 446 447 448 449
	      int index;

	      /* Find the branch edge.  It is possible that we do have fake
		 edges here.  */
	      for (e = bb->succ; e->flags & (EDGE_FAKE | EDGE_FALLTHRU);
		   e = e->succ_next)
		continue; /* Loop body has been intentionally left blank.  */

	      prob = e->probability;
	      index = prob * 20 / REG_BR_PROB_BASE;
450

451 452 453 454 455
	      if (index == 20)
		index = 19;
	      hist_br_prob[index]++;

	      note = find_reg_note (bb->end, REG_BR_PROB, 0);
456
	      /* There may be already note put by some other pass, such
457
		 as builtin_expect expander.  */
458 459 460
	      if (note)
		XEXP (note, 0) = GEN_INT (prob);
	      else
461
		REG_NOTES (bb->end)
462
		  = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
463
				       REG_NOTES (bb->end));
464
	      num_branches++;
465
	    }
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
	}
      /* Otherwise distribute the probabilities evenly so we get sane sum.
	 Use simple heuristics that if there are normal edges, give all abnormals
	 frequency of 0, otherwise distribute the frequency over abnormals
	 (this is the case of noreturn calls).  */
      else
	{
	  for (e = bb->succ; e; e = e->succ_next)
	    if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
	      total ++;
	  if (total)
	    {
	      for (e = bb->succ; e; e = e->succ_next)
		if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
		  e->probability = REG_BR_PROB_BASE / total;
		else
		  e->probability = 0;
	    }
	  else
	    {
	      for (e = bb->succ; e; e = e->succ_next)
		total ++;
	      for (e = bb->succ; e; e = e->succ_next)
		e->probability = REG_BR_PROB_BASE / total;
	    }
	  if (bb->index >= 0
	      && any_condjump_p (bb->end)
	      && bb->succ->succ_next)
	    num_branches++, num_never_executed;
495 496 497
	}
    }

498
  if (rtl_dump_file)
499
    {
500 501
      fprintf (rtl_dump_file, "%d branches\n", num_branches);
      fprintf (rtl_dump_file, "%d branches never executed\n",
502 503 504
	       num_never_executed);
      if (num_branches)
	for (i = 0; i < 10; i++)
505 506 507
	  fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
		   (hist_br_prob[i] + hist_br_prob[19-i]) * 100 / num_branches,
		   5 * i, 5 * i + 5);
508 509 510 511 512

      total_num_branches += num_branches;
      total_num_never_executed += num_never_executed;
      for (i = 0; i < 20; i++)
	total_hist_br_prob[i] += hist_br_prob[i];
513 514 515

      fputc ('\n', rtl_dump_file);
      fputc ('\n', rtl_dump_file);
516
    }
517

518
  free_aux_for_blocks ();
519 520
}

Doug Evans committed
521 522 523 524
/* Instrument and/or analyze program behavior based on program flow graph.
   In either case, this function builds a flow graph for the function being
   compiled.  The flow graph is stored in BB_GRAPH.

525
   When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
Doug Evans committed
526 527 528
   the flow graph that are needed to reconstruct the dynamic behavior of the
   flow graph.

Jeff Law committed
529
   When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
530
   information from a data file containing edge count information from previous
Doug Evans committed
531 532 533 534 535 536 537
   executions of the function being compiled.  In this case, the flow graph is
   annotated with actual execution counts, which are later propagated into the
   rtl for optimization purposes.

   Main entry point of this file.  */

void
538
branch_prob ()
Doug Evans committed
539
{
540
  int i;
541
  int num_edges, ignored_edges;
542
  struct edge_list *el;
Doug Evans committed
543

544
  /* Start of a function.  */
Doug Evans committed
545 546 547 548 549
  if (flag_test_coverage)
    output_gcov_string (current_function_name, (long) -2);

  total_num_times_called++;

550
  flow_call_edges_add (NULL);
551
  add_noreturn_fake_exit_edges ();
552

553 554 555 556 557
  /* We can't handle cyclic regions constructed using abnormal edges.
     To avoid these we replace every source of abnormal edge by a fake
     edge from entry node and every destination by fake edge to exit.
     This keeps graph acyclic and our calculation exact for all normal
     edges except for exit and entrance ones.
558

559 560
     We also add fake exit edges for each call and asm statement in the
     basic, since it may not return.  */
Doug Evans committed
561

562 563 564 565 566
  for (i = 0; i < n_basic_blocks ; i++)
    {
      int need_exit_edge = 0, need_entry_edge = 0;
      int have_exit_edge = 0, have_entry_edge = 0;
      basic_block bb = BASIC_BLOCK (i);
567
      rtx insn;
568
      edge e;
Doug Evans committed
569

570 571 572 573 574 575 576 577 578 579 580 581 582 583
      /* Add fake edges from entry block to the call insns that may return
	 twice.  The CFG is not quite correct then, as call insn plays more
	 role of CODE_LABEL, but for our purposes, everything should be OK,
	 as we never insert code to the beggining of basic block.  */
      for (insn = bb->head; insn != NEXT_INSN (bb->end);
	   insn = NEXT_INSN (insn))
	{
	  if (GET_CODE (insn) == CALL_INSN
	      && find_reg_note (insn, REG_SETJMP, NULL))
	    {
	      if (GET_CODE (bb->head) == CODE_LABEL
		  || insn != NEXT_INSN (bb->head))
		{
		  e = split_block (bb, PREV_INSN (insn));
584
		  make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE);
585 586 587 588 589 590 591 592
		  break;
		}
	      else
		{
		  /* We should not get abort here, as call to setjmp should not
		     be the very first instruction of function.  */
		  if (!i)
		    abort ();
593
		  make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
594 595 596 597
		}
	    }
	}

598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
      for (e = bb->succ; e; e = e->succ_next)
	{
	  if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
	       && e->dest != EXIT_BLOCK_PTR)
	    need_exit_edge = 1;
	  if (e->dest == EXIT_BLOCK_PTR)
	    have_exit_edge = 1;
	}
      for (e = bb->pred; e; e = e->pred_next)
	{
	  if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
	       && e->src != ENTRY_BLOCK_PTR)
	    need_entry_edge = 1;
	  if (e->src == ENTRY_BLOCK_PTR)
	    have_entry_edge = 1;
	}
Doug Evans committed
614

615 616 617 618 619
      if (need_exit_edge && !have_exit_edge)
	{
	  if (rtl_dump_file)
	    fprintf (rtl_dump_file, "Adding fake exit edge to bb %i\n",
		     bb->index);
620
          make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
621 622 623 624 625 626
	}
      if (need_entry_edge && !have_entry_edge)
	{
	  if (rtl_dump_file)
	    fprintf (rtl_dump_file, "Adding fake entry edge to bb %i\n",
		     bb->index);
627
          make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
628 629
	}
    }
Doug Evans committed
630

631 632
  el = create_edge_list ();
  num_edges = NUM_EDGES (el);
633
  alloc_aux_for_edges (sizeof (struct edge_info));
Doug Evans committed
634

635
  ignored_edges = 0;
636 637 638 639 640 641 642 643
  for (i = 0 ; i < num_edges ; i++)
    {
      edge e = INDEX_EDGE (el, i);
      e->count = 0;

      /* Mark edges we've replaced by fake edges above as ignored.  */
      if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
	  && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
644 645 646 647
        {
	  EDGE_INFO (e)->ignore = 1;
	  ignored_edges++;
        }
648
    }
Doug Evans committed
649

650 651 652
#ifdef ENABLE_CHECKING
  verify_flow_info ();
#endif
Doug Evans committed
653

654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
  /* Output line number information about each basic block for
     GCOV utility.  */
  if (flag_test_coverage)
    {
      int i = 0;
      for (i = 0 ; i < n_basic_blocks; i++)
        {
	  basic_block bb = BASIC_BLOCK (i);
	  rtx insn = bb->head;
          static int ignore_next_note = 0;

	  /* We are looking for line number notes.  Search backward before
	     basic block to find correct ones.  */
	  insn = prev_nonnote_insn (insn);
	  if (!insn)
	    insn = get_insns ();
	  else
	    insn = NEXT_INSN (insn);
Doug Evans committed
672

673 674 675
	  /* Output a zero to the .bb file to indicate that a new
	     block list is starting.  */
	  __write_long (0, bb_file, 4);
Doug Evans committed
676

677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
	  while (insn != bb->end)
	    {
	      if (GET_CODE (insn) == NOTE)
		{
		  /* Must ignore the line number notes that immediately
		     follow the end of an inline function to avoid counting
		     it twice.  There is a note before the call, and one
		     after the call.  */
		  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_REPEATED_LINE_NUMBER)
		    ignore_next_note = 1;
		  else if (NOTE_LINE_NUMBER (insn) > 0)
		    {
		      if (ignore_next_note)
			ignore_next_note = 0;
		      else
			{
			  /* If this is a new source file, then output the
			     file's name to the .bb file.  */
			  if (! last_bb_file_name
			      || strcmp (NOTE_SOURCE_FILE (insn),
					 last_bb_file_name))
			    {
			      if (last_bb_file_name)
				free (last_bb_file_name);
			      last_bb_file_name
				= xstrdup (NOTE_SOURCE_FILE (insn));
			      output_gcov_string (NOTE_SOURCE_FILE (insn),
						  (long)-1);
			    }
			  /* Output the line number to the .bb file.  Must be
			     done after the output_bb_profile_data() call, and
			     after the file name is written, to ensure that it
			     is correctly handled by gcov.  */
			  __write_long (NOTE_LINE_NUMBER (insn), bb_file, 4);
			}
		    }
		}
	      insn = NEXT_INSN (insn);
	    }
        }
      __write_long (0, bb_file, 4);
    }
Doug Evans committed
719

720 721
  /* Create spanning tree from basic block graph, mark each edge that is
     on the spanning tree.  We insert as many abnormal and critical edges
722
     as possible to minimize number of edge splits necessary.  */
Doug Evans committed
723

724
  find_spanning_tree (el);
725

726
  /* Fake edges that are not on the tree will not be instrumented, so
727
     mark them ignored.  */
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
  for (i = 0; i < num_edges; i++)
    {
      edge e = INDEX_EDGE (el, i);
      struct edge_info *inf = EDGE_INFO (e);
      if ((e->flags & EDGE_FAKE) && !inf->ignore && !inf->on_tree)
        {
          inf->ignore = 1;
          ignored_edges++;
        }
    }

  total_num_blocks += n_basic_blocks + 2;
  if (rtl_dump_file)
    fprintf (rtl_dump_file, "%d basic blocks\n", n_basic_blocks);

  total_num_edges += num_edges;
  if (rtl_dump_file)
    fprintf (rtl_dump_file, "%d edges\n", num_edges);

  total_num_edges_ignored += ignored_edges;
  if (rtl_dump_file)
    fprintf (rtl_dump_file, "%d ignored edges\n", ignored_edges);

751 752
  /* Create a .bbg file from which gcov can reconstruct the basic block
     graph.  First output the number of basic blocks, and then for every
753
     edge output the source and target basic block numbers.
754 755 756
     NOTE: The format of this file must be compatible with gcov.  */

  if (flag_test_coverage)
Doug Evans committed
757
    {
758
      int flag_bits;
Doug Evans committed
759

760 761
      /* The plus 2 stands for entry and exit block.  */
      __write_long (n_basic_blocks + 2, bbg_file, 4);
762
      __write_long (num_edges - ignored_edges + 1, bbg_file, 4);
Doug Evans committed
763

764
      for (i = 0; i < n_basic_blocks + 1; i++)
765
	{
766 767
	  basic_block bb = GCOV_INDEX_TO_BB (i);
	  edge e;
768
	  long count = 0;
769 770 771 772

	  for (e = bb->succ; e; e = e->succ_next)
	    if (!EDGE_INFO (e)->ignore)
	      count++;
773
	  __write_long (count, bbg_file, 4);
Doug Evans committed
774

775
	  for (e = bb->succ; e; e = e->succ_next)
776
	    {
777 778 779 780 781 782
	      struct edge_info *i = EDGE_INFO (e);
	      if (!i->ignore)
		{
		  flag_bits = 0;
		  if (i->on_tree)
		    flag_bits |= 0x1;
783
		  if (e->flags & EDGE_FAKE)
784 785 786 787 788 789 790
		    flag_bits |= 0x2;
		  if (e->flags & EDGE_FALLTHRU)
		    flag_bits |= 0x4;

		  __write_long (BB_TO_GCOV_INDEX (e->dest), bbg_file, 4);
		  __write_long (flag_bits, bbg_file, 4);
	        }
Doug Evans committed
791 792
	    }
	}
793
      /* Emit fake loopback edge for EXIT block to maintain compatibility with
794 795 796 797
         old gcov format.  */
      __write_long (1, bbg_file, 4);
      __write_long (0, bbg_file, 4);
      __write_long (0x1, bbg_file, 4);
Doug Evans committed
798

799
      /* Emit a -1 to separate the list of all edges from the list of
800 801
	 loop back edges that follows.  */
      __write_long (-1, bbg_file, 4);
Doug Evans committed
802 803
    }

804 805 806 807
  if (flag_branch_probabilities)
    compute_branch_probabilities ();

  /* For each edge not on the spanning tree, add counting code as rtl.  */
Doug Evans committed
808

809 810
  if (profile_arc_flag)
    {
811
      instrument_edges (el);
812
      allocate_reg_info (max_reg_num (), FALSE, FALSE);
Doug Evans committed
813 814
    }

815
  remove_fake_edges ();
816 817 818 819 820 821
  /* Re-merge split basic blocks and the mess introduced by
     insert_insn_on_edge.  */
  cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
  if (rtl_dump_file)
    dump_flow_info (rtl_dump_file);

822
  free_aux_for_edges ();
823
  free_edge_list (el);
Doug Evans committed
824 825
}

826
/* Union find algorithm implementation for the basic blocks using
827
   aux fields.  */
Doug Evans committed
828

829 830 831
static basic_block
find_group (bb)
     basic_block bb;
Doug Evans committed
832
{
833
  basic_block group = bb, bb1;
Doug Evans committed
834

835 836
  while ((basic_block) group->aux != group)
    group = (basic_block) group->aux;
Doug Evans committed
837

838 839
  /* Compress path.  */
  while ((basic_block) bb->aux != group)
Doug Evans committed
840
    {
841 842 843
      bb1 = (basic_block) bb->aux;
      bb->aux = (void *) group;
      bb = bb1;
Doug Evans committed
844
    }
845 846
  return group;
}
Doug Evans committed
847

848 849 850 851 852 853
static void
union_groups (bb1, bb2)
     basic_block bb1, bb2;
{
  basic_block bb1g = find_group (bb1);
  basic_block bb2g = find_group (bb2);
Doug Evans committed
854

855 856 857 858
  /* ??? I don't have a place for the rank field.  OK.  Lets go w/o it,
     this code is unlikely going to be performance problem anyway.  */
  if (bb1g == bb2g)
    abort ();
Doug Evans committed
859

860
  bb1g->aux = bb2g;
Doug Evans committed
861
}
862 863 864 865 866 867 868

/* This function searches all of the edges in the program flow graph, and puts
   as many bad edges as possible onto the spanning tree.  Bad edges include
   abnormals edges, which can't be instrumented at the moment.  Since it is
   possible for fake edges to form an cycle, we will have to develop some
   better way in the future.  Also put critical edges to the tree, since they
   are more expensive to instrument.  */
Doug Evans committed
869 870

static void
871 872
find_spanning_tree (el)
     struct edge_list *el;
Doug Evans committed
873
{
874 875
  int i;
  int num_edges = NUM_EDGES (el);
Doug Evans committed
876

877 878 879 880 881
  /* We use aux field for standard union-find algorithm.  */
  EXIT_BLOCK_PTR->aux = EXIT_BLOCK_PTR;
  ENTRY_BLOCK_PTR->aux = ENTRY_BLOCK_PTR;
  for (i = 0; i < n_basic_blocks; i++)
    BASIC_BLOCK (i)->aux = BASIC_BLOCK (i);
Doug Evans committed
882

883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
  /* Add fake edge exit to entry we can't instrument.  */
  union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);

  /* First add all abnormal edges to the tree unless they form an cycle.  */
  for (i = 0; i < num_edges; i++)
    {
      edge e = INDEX_EDGE (el, i);
      if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
	  && !EDGE_INFO (e)->ignore
	  && (find_group (e->src) != find_group (e->dest)))
	{
	  EDGE_INFO (e)->on_tree = 1;
	  union_groups (e->src, e->dest);
	}
    }

  /* Now insert all critical edges to the tree unless they form an cycle.  */
  for (i = 0; i < num_edges; i++)
    {
      edge e = INDEX_EDGE (el, i);
903
      if ((EDGE_CRITICAL_P (e))
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
	  && !EDGE_INFO (e)->ignore
	  && (find_group (e->src) != find_group (e->dest)))
	{
	  EDGE_INFO (e)->on_tree = 1;
	  union_groups (e->src, e->dest);
	}
    }

  /* And now the rest.  */
  for (i = 0; i < num_edges; i++)
    {
      edge e = INDEX_EDGE (el, i);
      if (find_group (e->src) != find_group (e->dest)
	  && !EDGE_INFO (e)->ignore)
	{
	  EDGE_INFO (e)->on_tree = 1;
	  union_groups (e->src, e->dest);
	}
    }
923 924 925 926 927

  EXIT_BLOCK_PTR->aux = NULL;
  ENTRY_BLOCK_PTR->aux = NULL;
  for (i = 0; i < n_basic_blocks; i++)
    BASIC_BLOCK (i)->aux = NULL;
Doug Evans committed
928 929 930 931 932 933
}

/* Perform file-level initialization for branch-prob processing.  */

void
init_branch_prob (filename)
934
  const char *filename;
Doug Evans committed
935 936 937 938 939 940 941
{
  long len;
  int i;

  if (flag_test_coverage)
    {
      int len = strlen (filename);
942 943 944 945
      char *data_file, *bbg_file_name;

      /* Open an output file for the basic block/line number map.  */
      data_file = (char *) alloca (len + 4);
Doug Evans committed
946 947 948
      strcpy (data_file, filename);
      strip_off_ending (data_file, len);
      strcat (data_file, ".bb");
Richard Kenner committed
949
      if ((bb_file = fopen (data_file, "wb")) == 0)
950
	fatal_io_error ("can't open %s", data_file);
Doug Evans committed
951 952 953 954 955 956

      /* Open an output file for the program flow graph.  */
      bbg_file_name = (char *) alloca (len + 5);
      strcpy (bbg_file_name, filename);
      strip_off_ending (bbg_file_name, len);
      strcat (bbg_file_name, ".bbg");
Richard Kenner committed
957
      if ((bbg_file = fopen (bbg_file_name, "wb")) == 0)
958
	fatal_io_error ("can't open %s", bbg_file_name);
Doug Evans committed
959 960 961 962 963 964 965 966

      /* Initialize to zero, to ensure that the first file name will be
	 written to the .bb file.  */
      last_bb_file_name = 0;
    }

  if (flag_branch_probabilities)
    {
967 968
      char *da_file_name;

Doug Evans committed
969 970 971 972 973
      len = strlen (filename);
      da_file_name = (char *) alloca (len + 4);
      strcpy (da_file_name, filename);
      strip_off_ending (da_file_name, len);
      strcat (da_file_name, ".da");
Richard Kenner committed
974
      if ((da_file = fopen (da_file_name, "rb")) == 0)
975
	warning ("file %s not found, execution counts assumed to be zero",
Doug Evans committed
976 977
		 da_file_name);

978 979
      /* The first word in the .da file gives the number of instrumented
	 edges, which is not needed for our purposes.  */
Doug Evans committed
980 981 982 983 984 985

      if (da_file)
	__read_long (&len, da_file, 8);
    }

  if (profile_arc_flag)
986
    init_edge_profiler ();
Doug Evans committed
987 988

  total_num_blocks = 0;
989
  total_num_edges = 0;
990
  total_num_edges_ignored = 0;
991
  total_num_edges_instrumented = 0;
Doug Evans committed
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
  total_num_blocks_created = 0;
  total_num_passes = 0;
  total_num_times_called = 0;
  total_num_branches = 0;
  total_num_never_executed = 0;
  for (i = 0; i < 20; i++)
    total_hist_br_prob[i] = 0;
}

/* Performs file-level cleanup after branch-prob processing
   is completed.  */

void
1005
end_branch_prob ()
Doug Evans committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
{
  if (flag_test_coverage)
    {
      fclose (bb_file);
      fclose (bbg_file);
    }

  if (flag_branch_probabilities)
    {
      if (da_file)
	{
	  long temp;
	  /* This seems slightly dangerous, as it presumes the EOF
	     flag will not be set until an attempt is made to read
1020
	     past the end of the file.  */
Doug Evans committed
1021
	  if (feof (da_file))
1022
	    error (".da file contents exhausted too early");
Doug Evans committed
1023 1024
	  /* Should be at end of file now.  */
	  if (__read_long (&temp, da_file, 8) == 0)
1025
	    error (".da file contents not exhausted");
Doug Evans committed
1026 1027 1028 1029
	  fclose (da_file);
	}
    }

1030
  if (rtl_dump_file)
Doug Evans committed
1031
    {
1032 1033 1034 1035
      fprintf (rtl_dump_file, "\n");
      fprintf (rtl_dump_file, "Total number of blocks: %d\n",
	       total_num_blocks);
      fprintf (rtl_dump_file, "Total number of edges: %d\n", total_num_edges);
1036 1037
      fprintf (rtl_dump_file, "Total number of ignored edges: %d\n",
	       total_num_edges_ignored);
1038 1039 1040
      fprintf (rtl_dump_file, "Total number of instrumented edges: %d\n",
	       total_num_edges_instrumented);
      fprintf (rtl_dump_file, "Total number of blocks created: %d\n",
Doug Evans committed
1041
	       total_num_blocks_created);
1042
      fprintf (rtl_dump_file, "Total number of graph solution passes: %d\n",
Doug Evans committed
1043 1044
	       total_num_passes);
      if (total_num_times_called != 0)
1045
	fprintf (rtl_dump_file, "Average number of graph solution passes: %d\n",
Doug Evans committed
1046 1047
		 (total_num_passes + (total_num_times_called  >> 1))
		 / total_num_times_called);
1048 1049 1050
      fprintf (rtl_dump_file, "Total number of branches: %d\n",
	       total_num_branches);
      fprintf (rtl_dump_file, "Total number of branches never executed: %d\n",
Doug Evans committed
1051 1052 1053 1054 1055 1056
	       total_num_never_executed);
      if (total_num_branches)
	{
	  int i;

	  for (i = 0; i < 10; i++)
1057
	    fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
Doug Evans committed
1058 1059 1060 1061 1062 1063
		     (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100
		     / total_num_branches, 5*i, 5*i+5);
	}
    }
}

1064
/* The label used by the edge profiling code.  */
Doug Evans committed
1065 1066 1067 1068 1069 1070

static rtx profiler_label;

/* Initialize the profiler_label.  */

static void
1071
init_edge_profiler ()
Doug Evans committed
1072 1073
{
  /* Generate and save a copy of this so it can be shared.  */
Zack Weinberg committed
1074 1075
  char buf[20];
  ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
1076
  profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1077
  ggc_add_rtx_root (&profiler_label, 1);
Doug Evans committed
1078 1079
}

1080
/* Output instructions as RTL to increment the edge execution count.  */
Doug Evans committed
1081

1082 1083 1084
static rtx
gen_edge_profiler (edgeno)
     int edgeno;
Doug Evans committed
1085
{
1086
  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1087
  rtx mem_ref, tmp;
Doug Evans committed
1088 1089 1090 1091
  rtx sequence;

  start_sequence ();

1092
  tmp = force_reg (Pmode, profiler_label);
1093
  tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
1094
  mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
Doug Evans committed
1095

1096 1097
  tmp = expand_simple_binop (mode, PLUS, mem_ref, const1_rtx,
			     mem_ref, 0, OPTAB_WIDEN);
Doug Evans committed
1098

1099 1100
  if (tmp != mem_ref)
    emit_move_insn (copy_rtx (mem_ref), tmp);
Doug Evans committed
1101 1102 1103

  sequence = gen_sequence ();
  end_sequence ();
1104
  return sequence;
Doug Evans committed
1105 1106 1107
}

/* Output code for a constructor that will invoke __bb_init_func, if
1108
   this has not already been done.  */
Doug Evans committed
1109 1110 1111 1112 1113

void
output_func_start_profiler ()
{
  tree fnname, fndecl;
Zack Weinberg committed
1114
  char *name;
Zack Weinberg committed
1115
  char buf[20];
Zack Weinberg committed
1116
  const char *cfnname;
Doug Evans committed
1117
  rtx table_address;
1118
  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1119
  int save_flag_inline_functions = flag_inline_functions;
1120 1121 1122
  int save_flag_test_coverage = flag_test_coverage;
  int save_profile_arc_flag = profile_arc_flag;
  int save_flag_branch_probabilities = flag_branch_probabilities;
Doug Evans committed
1123 1124

  /* It's either already been output, or we don't need it because we're
1125
     not doing profile-edges.  */
Doug Evans committed
1126 1127 1128 1129 1130 1131
  if (! need_func_profiler)
    return;

  need_func_profiler = 0;

  /* Synthesize a constructor function to invoke __bb_init_func with a
1132
     pointer to this object file's profile block.  */
Doug Evans committed
1133 1134 1135

  /* Try and make a unique name given the "file function name".

1136
     And no, I don't like this either.  */
Doug Evans committed
1137 1138 1139

  fnname = get_file_function_name ('I');
  cfnname = IDENTIFIER_POINTER (fnname);
1140
  name = concat (cfnname, "GCOV", NULL);
Doug Evans committed
1141 1142 1143 1144 1145
  fnname = get_identifier (name);
  free (name);

  fndecl = build_decl (FUNCTION_DECL, fnname,
		       build_function_type (void_type_node, NULL_TREE));
1146
  DECL_EXTERNAL (fndecl) = 0;
1147 1148 1149

  /* It can be a static function as long as collect2 does not have
     to scan the object file to find its ctor/dtor routine.  */
1150 1151 1152
  TREE_PUBLIC (fndecl) = ! targetm.have_ctors_dtors;

  TREE_USED (fndecl) = 1;
1153

Doug Evans committed
1154
  DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1155 1156 1157 1158

  fndecl = pushdecl (fndecl);
  rest_of_decl_compilation (fndecl, 0, 1, 0);
  announce_function (fndecl);
Doug Evans committed
1159
  current_function_decl = fndecl;
1160
  DECL_INITIAL (fndecl) = error_mark_node;
1161
  make_decl_rtl (fndecl, NULL);
Doug Evans committed
1162
  init_function_start (fndecl, input_filename, lineno);
1163
  pushlevel (0);
Doug Evans committed
1164 1165
  expand_function_start (fndecl, 0);

1166
  /* Actually generate the code to call __bb_init_func.  */
Zack Weinberg committed
1167 1168
  ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 0);
  table_address = force_reg (Pmode,
1169
			     gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)));
1170
  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__bb_init_func"), LCT_NORMAL,
Doug Evans committed
1171 1172 1173 1174
		     mode, 1, table_address, Pmode);

  expand_function_end (input_filename, lineno, 0);
  poplevel (1, 0, 1);
1175 1176 1177 1178 1179 1180

  /* Since fndecl isn't in the list of globals, it would never be emitted
     when it's considered to be 'safe' for inlining, so turn off
     flag_inline_functions.  */
  flag_inline_functions = 0;

1181 1182 1183 1184 1185 1186 1187
  /* Don't instrument the function that turns on instrumentation.  Which
     is also handy since we'd get silly warnings about not consuming all
     of our da_file input.  */
  flag_test_coverage = 0;
  profile_arc_flag = 0;
  flag_branch_probabilities = 0;

Doug Evans committed
1188
  rest_of_compilation (fndecl);
1189 1190 1191

  /* Reset flag_inline_functions to its original value.  */
  flag_inline_functions = save_flag_inline_functions;
1192 1193 1194
  flag_test_coverage = save_flag_test_coverage;
  profile_arc_flag = save_profile_arc_flag;
  flag_branch_probabilities = save_flag_branch_probabilities;
1195

1196 1197
  if (! quiet_flag)
    fflush (asm_out_file);
Doug Evans committed
1198 1199
  current_function_decl = NULL_TREE;

1200 1201 1202
  if (targetm.have_ctors_dtors)
    (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
				     DEFAULT_INIT_PRIORITY);
Doug Evans committed
1203
}