⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profile.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
     a predecessor of the last node, or from the last node to node 0.  */  for (arcptr = bb_graph[0].succ; arcptr; arcptr = arcptr->succ_next)    if (arcptr->fake)      {	/* Adding this arc should never cause a cycle.  This is a fatal 	   error if it would.  */	if (bb_graph[ARC_TARGET (arcptr)].on_tree && binfo->on_tree)	  abort();	else	  {	    arcptr->on_tree = 1;	    bb_graph[ARC_TARGET (arcptr)].on_tree = 1;	    binfo->on_tree = 1;	  }      }  binfo = &bb_graph[num_blocks-1];  for (arcptr = binfo->pred; arcptr; arcptr = arcptr->pred_next)    if (arcptr->fake)      {	/* Adding this arc should never cause a cycle.  This is a fatal 	   error if it would.  */	if (bb_graph[ARC_SOURCE (arcptr)].on_tree && binfo->on_tree)	  abort();	else	  {	    arcptr->on_tree = 1;	    bb_graph[ARC_SOURCE (arcptr)].on_tree = 1;	    binfo->on_tree = 1;	  }      }  /* The only entrace to node zero is a fake arc.  */  bb_graph[0].pred->on_tree = 1;    /* Arcs which are crowded at both the source and target should be put on     the spanning tree if possible, except for fall_throuch arcs which never     require adding a new block even if crowded, add arcs with the same source     and dest which must always be instrumented.  */  for (i = 0; i < num_blocks; i++)    {      binfo = &bb_graph[i];      for (arcptr = binfo->succ; arcptr; arcptr = arcptr->succ_next)	if (! ((binfo->succ == arcptr && arcptr->succ_next == 0)	       || (bb_graph[ARC_TARGET (arcptr)].pred		   && arcptr->pred_next == 0))	    && ! arcptr->fall_through	    && ARC_TARGET (arcptr) != i)	  {	    /* This is a crowded arc at both source and target.  Try to put	       in on the spanning tree.  Can do this if either the source or	       target block is not yet on the tree.  */	    if (! bb_graph[ARC_TARGET (arcptr)].on_tree	|| ! binfo->on_tree)	      {		arcptr->on_tree = 1;		bb_graph[ARC_TARGET (arcptr)].on_tree = 1;		binfo->on_tree = 1;	      }	  }    }  /* Clear all of the basic block on_tree bits, so that we can use them to     create the spanning tree.  */  for (i = 0; i < num_blocks; i++)    bb_graph[i].on_tree = 0;  /* Now fill in the spanning tree until every basic block is on it.     Don't put the 0 to 1 fall through arc on the tree, since it is      always cheap to instrument, so start filling the tree from node 1.  */  for (i = 1; i < num_blocks; i++)    for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)      if (! arcptr->on_tree	  && ! bb_graph[ARC_TARGET (arcptr)].on_tree)	{	  fill_spanning_tree (i);	  break;	}}/* Add arcs reached from BLOCK to the spanning tree if they are needed and   not already there.  */static voidfill_spanning_tree (block)     int block;{  struct adj_list *arcptr;    expand_spanning_tree (block);  for (arcptr = bb_graph[block].succ; arcptr; arcptr = arcptr->succ_next)    if (! arcptr->on_tree	&& ! bb_graph[ARC_TARGET (arcptr)].on_tree)      {	arcptr->on_tree = 1;	fill_spanning_tree (ARC_TARGET (arcptr));      }}/* When first visit a block, must add all blocks that are already connected   to this block via tree arcs to the spanning tree.  */static voidexpand_spanning_tree (block)     int block;{  struct adj_list *arcptr;  bb_graph[block].on_tree = 1;  for (arcptr = bb_graph[block].succ; arcptr; arcptr = arcptr->succ_next)    if (arcptr->on_tree && ! bb_graph[ARC_TARGET (arcptr)].on_tree)      expand_spanning_tree (ARC_TARGET (arcptr));      for (arcptr = bb_graph[block].pred;       arcptr; arcptr = arcptr->pred_next)    if (arcptr->on_tree && ! bb_graph[ARC_SOURCE (arcptr)].on_tree)      expand_spanning_tree (ARC_SOURCE (arcptr));}/* Perform file-level initialization for branch-prob processing.  */voidinit_branch_prob (filename)     char *filename;{  long len;  int i;  if (flag_test_coverage)    {      /* Open an output file for the basic block/line number map.  */      int len = strlen (filename);      char *data_file = (char *) alloca (len + 4);      strcpy (data_file, filename);      strip_off_ending (data_file, len);      strcat (data_file, ".bb");      if ((bb_file = fopen (data_file, "w")) == 0)	pfatal_with_name (data_file);      /* Open an output file for the program flow graph.  */      len = strlen (filename);      bbg_file_name = (char *) alloca (len + 5);      strcpy (bbg_file_name, filename);      strip_off_ending (bbg_file_name, len);      strcat (bbg_file_name, ".bbg");      if ((bbg_file = fopen (bbg_file_name, "w")) == 0)	pfatal_with_name (bbg_file_name);      /* 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)    {      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");      if ((da_file = fopen (da_file_name, "r")) == 0)	warning ("file %s not found, execution counts assumed to be zero.",		 da_file_name);      /* The first word in the .da file gives the number of instrumented arcs,	 which is not needed for our purposes.  */      if (da_file)	__read_long (&len, da_file, 8);    }  if (profile_arc_flag)    init_arc_profiler ();  total_num_blocks = 0;  total_num_arcs = 0;  total_num_arcs_instrumented = 0;  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.  */voidend_branch_prob (dump_file)     FILE *dump_file;{  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	     past the end of the file. */	  if (feof (da_file))	    warning (".da file contents exhausted too early\n");	  /* Should be at end of file now.  */	  if (__read_long (&temp, da_file, 8) == 0)	    warning (".da file contents not exhausted\n");	  fclose (da_file);	}    }  if (dump_file)    {      fprintf (dump_file, "\n");      fprintf (dump_file, "Total number of blocks: %d\n", total_num_blocks);      fprintf (dump_file, "Total number of arcs: %d\n", total_num_arcs);      fprintf (dump_file, "Total number of instrumented arcs: %d\n",	       total_num_arcs_instrumented);      fprintf (dump_file, "Total number of blocks created: %d\n",	       total_num_blocks_created);      fprintf (dump_file, "Total number of graph solution passes: %d\n",	       total_num_passes);      if (total_num_times_called != 0)	fprintf (dump_file, "Average number of graph solution passes: %d\n",		 (total_num_passes + (total_num_times_called  >> 1))		 / total_num_times_called);      fprintf (dump_file, "Total number of branches: %d\n", total_num_branches);      fprintf (dump_file, "Total number of branches never executed: %d\n",	       total_num_never_executed);      if (total_num_branches)	{	  int i;	  for (i = 0; i < 10; i++)	    fprintf (dump_file, "%d%% branches in range %d-%d%%\n",		     (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100		     / total_num_branches, 5*i, 5*i+5);	}    }}/* The label used by the arc profiling code.  */static rtx profiler_label;/* Initialize the profiler_label.  */static voidinit_arc_profiler (){  /* Generate and save a copy of this so it can be shared.  */  char *name = xmalloc (20);  ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);  profiler_label = gen_rtx (SYMBOL_REF, Pmode, name);}/* Output instructions as RTL to increment the arc execution count.  */static voidoutput_arc_profiler (arcno, insert_after)     int arcno;     rtx insert_after;{  rtx profiler_target_addr    = (arcno       ? gen_rtx (CONST, Pmode,		  gen_rtx (PLUS, Pmode, profiler_label,			   gen_rtx (CONST_INT, VOIDmode,				    LONG_TYPE_SIZE / BITS_PER_UNIT * arcno)))       : profiler_label);  enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0);  rtx profiler_reg = gen_reg_rtx (mode);  rtx address_reg = gen_reg_rtx (Pmode);  rtx mem_ref, add_ref;  rtx sequence;  /* In this case, reload can use explicitly mentioned hard registers for     reloads.  It is not safe to output profiling code between a call     and the instruction that copies the result to a pseudo-reg.  This     is because reload may allocate one of the profiling code pseudo-regs     to the return value reg, thus clobbering the return value.  So we     must check for calls here, and emit the profiling code after the     instruction that uses the return value, if any.     ??? The code here performs the same tests that reload does so hopefully     all the bases are covered.  */  if (SMALL_REGISTER_CLASSES      && GET_CODE (insert_after) == CALL_INSN      && (GET_CODE (PATTERN (insert_after)) == SET	  || (GET_CODE (PATTERN (insert_after)) == PARALLEL	      && GET_CODE (XVECEXP (PATTERN (insert_after), 0, 0)) == SET)))    {      rtx return_reg;      rtx next_insert_after = next_nonnote_insn (insert_after);      /* The first insn after the call may be a stack pop, skip it.  */      if (next_insert_after	  && GET_CODE (next_insert_after) == INSN	  && GET_CODE (PATTERN (next_insert_after)) == SET	  && SET_DEST (PATTERN (next_insert_after)) == stack_pointer_rtx)	next_insert_after = next_nonnote_insn (next_insert_after);      if (next_insert_after	  && GET_CODE (next_insert_after) == INSN)	{	  if (GET_CODE (PATTERN (insert_after)) == SET)	    return_reg = SET_DEST (PATTERN (insert_after));	  else	    return_reg = SET_DEST (XVECEXP (PATTERN (insert_after), 0, 0));	  /* Now, NEXT_INSERT_AFTER may be an instruction that uses the	     return value.  However, it could also be something else,	     like a CODE_LABEL, so check that the code is INSN.  */	  if (next_insert_after != 0	      && GET_RTX_CLASS (GET_CODE (next_insert_after)) == 'i'	      && reg_referenced_p (return_reg, PATTERN (next_insert_after)))	    insert_after = next_insert_after;	}    }  start_sequence ();  emit_move_insn (address_reg, profiler_target_addr);  mem_ref = gen_rtx (MEM, mode, address_reg);  emit_move_insn (profiler_reg, mem_ref);  add_ref = gen_rtx (PLUS, mode, profiler_reg, GEN_INT (1));  emit_move_insn (profiler_reg, add_ref);  /* This is the same rtx as above, but it is not legal to share this rtx.  */  mem_ref = gen_rtx (MEM, mode, address_reg);  emit_move_insn (mem_ref, profiler_reg);  sequence = gen_sequence ();  end_sequence ();  emit_insn_after (sequence, insert_after);}/* Output code for a constructor that will invoke __bb_init_func, if   this has not already been done. */voidoutput_func_start_profiler (){  tree fnname, fndecl;  char *name, *cfnname;  rtx table_address;  enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0);  /* It's either already been output, or we don't need it because we're     not doing profile-arcs. */  if (! need_func_profiler)    return;  need_func_profiler = 0;  /* Synthesize a constructor function to invoke __bb_init_func with a     pointer to this object file's profile block. */  start_sequence ();  /* Try and make a unique name given the "file function name".     And no, I don't like this either. */  fnname = get_file_function_name ('I');  cfnname = IDENTIFIER_POINTER (fnname);  name = xmalloc (strlen (cfnname) + 5);  sprintf (name, "%sGCOV",cfnname);  fnname = get_identifier (name);  free (name);  fndecl = build_decl (FUNCTION_DECL, fnname,		       build_function_type (void_type_node, NULL_TREE));  DECL_EXTERNAL (fndecl) = 0;  TREE_PUBLIC (fndecl) = 1;  DECL_ASSEMBLER_NAME (fndecl) = fnname;  DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);  current_function_decl = fndecl;  pushlevel (0);  make_function_rtl (fndecl);  init_function_start (fndecl, input_filename, lineno);  expand_function_start (fndecl, 0);  /* Actually generate the code to call __bb_init_func. */  name = xmalloc (20);  ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);  table_address = force_reg (Pmode, gen_rtx (SYMBOL_REF, Pmode, name));  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__bb_init_func"), 0,		     mode, 1, table_address, Pmode);  expand_function_end (input_filename, lineno, 0);  poplevel (1, 0, 1);  rest_of_compilation (fndecl);  fflush (asm_out_file);  current_function_decl = NULL_TREE;  assemble_constructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -