/* Calculate branch probabilities, and basic block execution counts.
- Copyright (C) 1990, 91-94, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91-94, 96, 97, 1998 Free Software Foundation, Inc.
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.
achieve this, see Dain Sample's UC Berkeley thesis. */
#include "config.h"
-#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
+#include "system.h"
#include "rtl.h"
#include "flags.h"
#include "insn-flags.h"
#include "tree.h"
#include "output.h"
#include "gcov-io.h"
+#include "toplev.h"
extern char * xmalloc ();
-extern void free ();
/* One of these is dynamically created whenever we identify an arc in the
function. */
__write_long (delimiter, bb_file, 4);
}
\f
+/* Return TRUE if this insn must be a tablejump entry insn. This works for
+ the MIPS port, but may give false negatives for some targets. */
+
+int
+tablejump_entry_p (insn, label)
+ rtx insn, label;
+{
+ rtx next = next_active_insn (insn);
+ enum rtx_code code = GET_CODE (PATTERN (next));
+
+ if (code != ADDR_DIFF_VEC && code != ADDR_VEC)
+ return 0;
+
+ if (PREV_INSN (next) == XEXP (label, 0))
+ return 1;
+
+ return 0;
+}
+
/* 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.
register int i;
int fall_through = 0;
struct adj_list *arcptr;
- int dest;
+ int dest = 0;
/* Block 0 always falls through to block 1. */
num_arcs = 0;
We have to handle tablejumps and returns specially anyways, so
we don't check the JUMP_LABEL at all here. */
+ /* ??? This code should be rewritten. We need a more elegant way
+ to find the LABEL_REF. We need a more elegant way to
+ differentiate tablejump entries from computed gotos.
+ We should perhaps reuse code from flow to compute the CFG
+ instead of trying to compute it here.
+
+ We can't use current_function_has_computed_jump, because that
+ is calculated later by flow. We can't use computed_jump_p,
+ because that returns true for tablejump entry insns for some
+ targets, e.g. HPPA and MIPS. */
+
if (GET_CODE (pattern) == PARALLEL)
{
- /* This assumes that PARALLEL jumps are tablejump entry
- jumps. */
+ /* This assumes that PARALLEL jumps with a USE are
+ tablejump entry jumps. The same assumption can be found
+ in computed_jump_p. */
/* Make an arc from this jump to the label of the
jump table. This will instrument the number of
times the switch statement is executed. */
tablejump = pattern;
else if (GET_CODE (pattern) == RETURN)
dest = num_blocks - 1;
+ else if (GET_CODE (pattern) != SET)
+ abort ();
else if ((tem = SET_SRC (pattern))
&& GET_CODE (tem) == LABEL_REF)
dest = label_to_bb[CODE_LABEL_NUMBER (XEXP (tem, 0))];
+ /* Recognize HPPA table jump entry. This code is similar to
+ the code above in the PARALLEL case. */
+ else if (GET_CODE (tem) == PLUS
+ && GET_CODE (XEXP (tem, 0)) == MEM
+ && GET_CODE (XEXP (XEXP (tem, 0), 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (XEXP (tem, 0), 0), 0)) == PC
+ && GET_CODE (XEXP (tem, 1)) == LABEL_REF
+ && tablejump_entry_p (insn, XEXP (tem, 1)))
+ dest = label_to_bb[CODE_LABEL_NUMBER (XEXP (XEXP (tem, 1), 0))];
+ /* Recognize the MIPS table jump entry. */
+ else if (GET_CODE (tem) == PLUS
+ && GET_CODE (XEXP (tem, 0)) == REG
+ && GET_CODE (XEXP (tem, 1)) == LABEL_REF
+ && tablejump_entry_p (insn, XEXP (tem, 1)))
+ dest = label_to_bb[CODE_LABEL_NUMBER (XEXP (XEXP (tem, 1), 0))];
else
{
rtx label_ref;
/* For each arc not on the spanning tree, add counting code as rtl. */
if (profile_arc_flag)
- instrument_arcs (f, num_blocks, dump_file);
+ {
+ instrument_arcs (f, num_blocks, dump_file);
+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
+ }
/* Execute the rest only if doing branch probabilities. */
if (! flag_branch_probabilities)
/* Reset flag_inline_functions to its original value. */
flag_inline_functions = save_flag_inline_functions;
- fflush (asm_out_file);
+ if (! quiet_flag)
+ fflush (asm_out_file);
current_function_decl = NULL_TREE;
assemble_constructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));