Commit 9885da8e by Zdenek Dvorak Committed by Zdenek Dvorak

Makefile.in (LIBGCOV): Add _gcov_interval_profiler, _gcov_pow2_profiler and…

Makefile.in (LIBGCOV): Add _gcov_interval_profiler, _gcov_pow2_profiler and _gcov_one_value_profiler.

	* Makefile.in (LIBGCOV): Add _gcov_interval_profiler,
	_gcov_pow2_profiler and _gcov_one_value_profiler.
	(tree-profile.o): Add GGC_H and gt-tree-profile.h dependency.
	(GTFILES): Add $(srcdir)/tree-profile.c.
	* gcov-io.h (__gcov_interval_profiler, __gcov_pow2_profiler,
	__gcov_one_value_profiler): Declare.
	* gimplify.c (force_gimple_operand): Check whether the statements
	should be produced in ssa form.
	(force_gimple_operand_bsi): New function.
	* libgcov.c (__gcov_interval_profiler, __gcov_pow2_profiler,
	__gcov_one_value_profiler): New functions.
	* rtl-profile.c (rtl_gen_pow2_profiler): Only measure whether
	the profiled value is a power of two or not.
	* tree-cfg.c (tree_block_ends_with_condjump_p): Handle empty blocks.
	* tree-flow.h (in_ssa_p): Declare.
	(force_gimple_operand_bsi): Declare.
	* tree-into-ssa.c (in_ssa_p): New variable.
	(rewrite_into_ssa): Set in_ssa_p.
	* tree-outof-ssa.c (rewrite_out_of_ssa): Set in_ssa_p.
	* tree-profile.c: Include ggc.h and gt-tree-profile.h.
	(gcov_type_node, tree_interval_profiler_fn, tree_pow2_profiler_fn,
	tree_one_value_profiler_fn): New variables.
	(tree_init_edge_profiler): Initialize the profiler function decls.
	(tree_gen_edge_profiler): Use global gcov_type_node.
	(prepare_instrumented_value): New function.
	(tree_gen_interval_profiler, tree_gen_interval_profiler,
	tree_gen_one_value_profiler): Call the library functions instead of
	creating instrumentation code.
	* tree.c (build_fn_decl): New function.
	* tree.h (build_fn_decl): Declare.
	* value-prof.c (rtl_divmod_values_to_profile,
	rtl_find_values_to_profile, rtl_mod_pow2_value_transform,
	tree_mod_pow2_value_transform, tree_find_values_to_profile):
	Do not handle may_be_other and precise values of exponents at pow2
	profiler.
	(tree_mod_subtract_transform): Reflect that value field of
	histogram has changed meaning.
	(tree_divmod_values_to_profile): Record the values correctly.
	(tree_values_to_profile): Update comment.
	* value-prof.h (struct histogram_value_t): Remove pow2 data.

From-SVN: r98555
parent ebccb65d
2005-04-22 Zdenek Dvorak <dvorakz@suse.cz>
* Makefile.in (LIBGCOV): Add _gcov_interval_profiler,
_gcov_pow2_profiler and _gcov_one_value_profiler.
(tree-profile.o): Add GGC_H and gt-tree-profile.h dependency.
(GTFILES): Add $(srcdir)/tree-profile.c.
* gcov-io.h (__gcov_interval_profiler, __gcov_pow2_profiler,
__gcov_one_value_profiler): Declare.
* gimplify.c (force_gimple_operand): Check whether the statements
should be produced in ssa form.
(force_gimple_operand_bsi): New function.
* libgcov.c (__gcov_interval_profiler, __gcov_pow2_profiler,
__gcov_one_value_profiler): New functions.
* rtl-profile.c (rtl_gen_pow2_profiler): Only measure whether
the profiled value is a power of two or not.
* tree-cfg.c (tree_block_ends_with_condjump_p): Handle empty blocks.
* tree-flow.h (in_ssa_p): Declare.
(force_gimple_operand_bsi): Declare.
* tree-into-ssa.c (in_ssa_p): New variable.
(rewrite_into_ssa): Set in_ssa_p.
* tree-outof-ssa.c (rewrite_out_of_ssa): Set in_ssa_p.
* tree-profile.c: Include ggc.h and gt-tree-profile.h.
(gcov_type_node, tree_interval_profiler_fn, tree_pow2_profiler_fn,
tree_one_value_profiler_fn): New variables.
(tree_init_edge_profiler): Initialize the profiler function decls.
(tree_gen_edge_profiler): Use global gcov_type_node.
(prepare_instrumented_value): New function.
(tree_gen_interval_profiler, tree_gen_interval_profiler,
tree_gen_one_value_profiler): Call the library functions instead of
creating instrumentation code.
* tree.c (build_fn_decl): New function.
* tree.h (build_fn_decl): Declare.
* value-prof.c (rtl_divmod_values_to_profile,
rtl_find_values_to_profile, rtl_mod_pow2_value_transform,
tree_mod_pow2_value_transform, tree_find_values_to_profile):
Do not handle may_be_other and precise values of exponents at pow2
profiler.
(tree_mod_subtract_transform): Reflect that value field of
histogram has changed meaning.
(tree_divmod_values_to_profile): Record the values correctly.
(tree_values_to_profile): Update comment.
* value-prof.h (struct histogram_value_t): Remove pow2 data.
2005-04-22 Joseph S. Myers <joseph@codesourcery.com> 2005-04-22 Joseph S. Myers <joseph@codesourcery.com>
* varasm.c (do_assemble_alias): Return early if TREE_ASM_WRITTEN * varasm.c (do_assemble_alias): Return early if TREE_ASM_WRITTEN
......
...@@ -995,7 +995,8 @@ LIB2FUNCS_ST = _eprintf __gcc_bcmp ...@@ -995,7 +995,8 @@ LIB2FUNCS_ST = _eprintf __gcc_bcmp
# Defined in libgcov.c, included only in gcov library # Defined in libgcov.c, included only in gcov library
LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \ LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
_gcov_fork _gcov_execl _gcov_execlp _gcov_execle \ _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
_gcov_execv _gcov_execvp _gcov_execve _gcov_execv _gcov_execvp _gcov_execve \
_gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler
FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \ FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
_fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \ _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
...@@ -2034,7 +2035,7 @@ profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ ...@@ -2034,7 +2035,7 @@ profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
tree-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ tree-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) function.h \ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) function.h \
toplev.h $(BASIC_BLOCK_H) $(COVERAGE_H) $(TREE_H) value-prof.h \ toplev.h $(BASIC_BLOCK_H) $(COVERAGE_H) $(TREE_H) value-prof.h \
tree-pass.h $(TREE_FLOW_H) $(TIMEVAR_H) tree-pass.h $(TREE_FLOW_H) $(TIMEVAR_H) $(GGC_H) gt-tree-profile.h
rtl-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ rtl-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) function.h \ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) function.h \
toplev.h $(BASIC_BLOCK_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h $(GGC_H) toplev.h $(BASIC_BLOCK_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h $(GGC_H)
...@@ -2466,7 +2467,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \ ...@@ -2466,7 +2467,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \ $(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
$(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \ $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
$(srcdir)/dojump.c \ $(srcdir)/dojump.c $(srcdir)/tree-profile.c \
$(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \ $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
$(srcdir)/function.c \ $(srcdir)/function.c \
$(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \ $(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
...@@ -2500,7 +2501,7 @@ gt-dwarf2out.h gt-reg-stack.h gt-dwarf2asm.h \ ...@@ -2500,7 +2501,7 @@ gt-dwarf2out.h gt-reg-stack.h gt-dwarf2asm.h \
gt-dbxout.h gt-c-common.h gt-c-decl.h gt-c-parser.h \ gt-dbxout.h gt-c-common.h gt-c-decl.h gt-c-parser.h \
gt-c-pragma.h gtype-c.h gt-cfglayout.h \ gt-c-pragma.h gtype-c.h gt-cfglayout.h \
gt-tree-mudflap.h gt-tree-complex.h \ gt-tree-mudflap.h gt-tree-complex.h \
gt-tree-eh.h \ gt-tree-eh.h gt-tree-profile.h \
gt-tree-ssanames.h gt-tree-iterator.h gt-gimplify.h \ gt-tree-ssanames.h gt-tree-iterator.h gt-gimplify.h \
gt-tree-phinodes.h gt-tree-nested.h \ gt-tree-phinodes.h gt-tree-nested.h \
gt-tree-ssa-operands.h gt-tree-ssa-propagate.h \ gt-tree-ssa-operands.h gt-tree-ssa-propagate.h \
......
...@@ -443,6 +443,11 @@ extern void __gcov_merge_single (gcov_type *, unsigned); ...@@ -443,6 +443,11 @@ extern void __gcov_merge_single (gcov_type *, unsigned);
consecutive values. */ consecutive values. */
extern void __gcov_merge_delta (gcov_type *, unsigned); extern void __gcov_merge_delta (gcov_type *, unsigned);
/* The profiler functions. */
extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned);
extern void __gcov_pow2_profiler (gcov_type *, gcov_type);
extern void __gcov_one_value_profiler (gcov_type *, gcov_type);
#ifndef inhibit_libc #ifndef inhibit_libc
/* The wrappers around some library functions.. */ /* The wrappers around some library functions.. */
extern pid_t __gcov_fork (void); extern pid_t __gcov_fork (void);
......
...@@ -4662,7 +4662,7 @@ force_gimple_operand (tree expr, tree *stmts, bool simple, tree var) ...@@ -4662,7 +4662,7 @@ force_gimple_operand (tree expr, tree *stmts, bool simple, tree var)
gimple_test_f = simple ? is_gimple_val : is_gimple_reg_rhs; gimple_test_f = simple ? is_gimple_val : is_gimple_reg_rhs;
push_gimplify_context (); push_gimplify_context ();
gimplify_ctxp->into_ssa = true; gimplify_ctxp->into_ssa = in_ssa_p;
if (var) if (var)
expr = build (MODIFY_EXPR, TREE_TYPE (var), var, expr); expr = build (MODIFY_EXPR, TREE_TYPE (var), var, expr);
...@@ -4671,12 +4671,31 @@ force_gimple_operand (tree expr, tree *stmts, bool simple, tree var) ...@@ -4671,12 +4671,31 @@ force_gimple_operand (tree expr, tree *stmts, bool simple, tree var)
gimple_test_f, fb_rvalue); gimple_test_f, fb_rvalue);
gcc_assert (ret != GS_ERROR); gcc_assert (ret != GS_ERROR);
if (referenced_vars)
{
for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t)) for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
add_referenced_tmp_var (t); add_referenced_tmp_var (t);
}
pop_gimplify_context (NULL); pop_gimplify_context (NULL);
return expr; return expr;
} }
/* Invokes force_gimple_operand for EXPR with parameters SIMPLE_P and VAR. If
some statements are produced, emits them before BSI. */
tree
force_gimple_operand_bsi (block_stmt_iterator *bsi, tree expr,
bool simple_p, tree var)
{
tree stmts;
expr = force_gimple_operand (expr, &stmts, simple_p, var);
if (stmts)
bsi_insert_before (bsi, stmts, BSI_SAME_STMT);
return expr;
}
#include "gt-gimplify.h" #include "gt-gimplify.h"
...@@ -581,6 +581,67 @@ __gcov_merge_delta (gcov_type *counters, unsigned n_counters) ...@@ -581,6 +581,67 @@ __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
} }
#endif /* L_gcov_merge_delta */ #endif /* L_gcov_merge_delta */
#ifdef L_gcov_interval_profiler
/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
corresponding counter in COUNTERS. If the VALUE is above or below
the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased
instead. */
void
__gcov_interval_profiler (gcov_type *counters, gcov_type value,
int start, unsigned steps)
{
gcov_type delta = value - start;
if (delta < 0)
counters[steps + 1]++;
else if (delta >= steps)
counters[steps]++;
else
counters[delta]++;
}
#endif
#ifdef L_gcov_pow2_profiler
/* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise
COUNTERS[0] is incremented. */
void
__gcov_pow2_profiler (gcov_type *counters, gcov_type value)
{
if (value & (value - 1))
counters[0]++;
else
counters[1]++;
}
#endif
#ifdef L_gcov_one_value_profiler
/* Tries to determine the most common value among its inputs. Checks if the
value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1]
is incremented. If this is not the case and COUNTERS[1] is not zero,
COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and
VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this
function is called more than 50% of the time with one value, this value
will be in COUNTERS[0] in the end.
In any case, COUNTERS[2] is incremented. */
void
__gcov_one_value_profiler (gcov_type *counters, gcov_type value)
{
if (value == counters[0])
counters[1]++;
else if (counters[1] == 0)
{
counters[1] = 1;
counters[0] = value;
}
else
counters[1]--;
counters[2]++;
}
#endif
#ifdef L_gcov_fork #ifdef L_gcov_fork
/* A wrapper for the fork function. Flushes the accumulated profiling data, so /* A wrapper for the fork function. Flushes the accumulated profiling data, so
that they are not counted twice. */ that they are not counted twice. */
......
...@@ -172,7 +172,6 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) ...@@ -172,7 +172,6 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
rtx mem_ref, tmp, mr, uval; rtx mem_ref, tmp, mr, uval;
rtx sequence; rtx sequence;
rtx end_of_code_label = gen_label_rtx (); rtx end_of_code_label = gen_label_rtx ();
rtx loop_label = gen_label_rtx ();
int per_counter = GCOV_TYPE_SIZE / BITS_PER_UNIT; int per_counter = GCOV_TYPE_SIZE / BITS_PER_UNIT;
edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn), edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
PREV_INSN (value->hvalue.rtl.insn)); PREV_INSN (value->hvalue.rtl.insn));
...@@ -191,8 +190,6 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) ...@@ -191,8 +190,6 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
emit_move_insn (uval, copy_rtx (value->hvalue.rtl.value)); emit_move_insn (uval, copy_rtx (value->hvalue.rtl.value));
/* Check for non-power of 2. */ /* Check for non-power of 2. */
if (value->hdata.pow2.may_be_other)
{
do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->hvalue.rtl.mode, do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->hvalue.rtl.mode,
NULL_RTX, NULL_RTX, end_of_code_label); NULL_RTX, NULL_RTX, end_of_code_label);
tmp = expand_simple_binop (value->hvalue.rtl.mode, PLUS, copy_rtx (uval), tmp = expand_simple_binop (value->hvalue.rtl.mode, PLUS, copy_rtx (uval),
...@@ -201,23 +198,12 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base) ...@@ -201,23 +198,12 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
NULL_RTX, 0, OPTAB_WIDEN); NULL_RTX, 0, OPTAB_WIDEN);
do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->hvalue.rtl.mode, NULL_RTX, do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->hvalue.rtl.mode, NULL_RTX,
NULL_RTX, end_of_code_label); NULL_RTX, end_of_code_label);
}
/* Count log_2(value). */ tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter),
emit_label (loop_label); mr, 0, OPTAB_WIDEN);
tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter), mr, 0, OPTAB_WIDEN);
if (tmp != mr) if (tmp != mr)
emit_move_insn (copy_rtx (mr), tmp); emit_move_insn (copy_rtx (mr), tmp);
tmp = expand_simple_binop (value->hvalue.rtl.mode, ASHIFTRT, copy_rtx (uval), const1_rtx,
uval, 0, OPTAB_WIDEN);
if (tmp != uval)
emit_move_insn (copy_rtx (uval), tmp);
do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, NE, 0, value->hvalue.rtl.mode,
NULL_RTX, NULL_RTX, loop_label);
/* Increase the counter. */ /* Increase the counter. */
emit_label (end_of_code_label); emit_label (end_of_code_label);
......
...@@ -5350,8 +5350,8 @@ tree_block_ends_with_call_p (basic_block bb) ...@@ -5350,8 +5350,8 @@ tree_block_ends_with_call_p (basic_block bb)
static bool static bool
tree_block_ends_with_condjump_p (basic_block bb) tree_block_ends_with_condjump_p (basic_block bb)
{ {
tree stmt = tsi_stmt (bsi_last (bb).tsi); tree stmt = last_stmt (bb);
return (TREE_CODE (stmt) == COND_EXPR); return (stmt && TREE_CODE (stmt) == COND_EXPR);
} }
......
...@@ -38,6 +38,9 @@ struct basic_block_def; ...@@ -38,6 +38,9 @@ struct basic_block_def;
typedef struct basic_block_def *basic_block; typedef struct basic_block_def *basic_block;
#endif #endif
/* True if the code is in ssa form. */
extern bool in_ssa_p;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Attributes for SSA_NAMEs. Attributes for SSA_NAMEs.
...@@ -796,9 +799,10 @@ extern void linear_transform_loops (struct loops *); ...@@ -796,9 +799,10 @@ extern void linear_transform_loops (struct loops *);
/* In tree-ssa-loop-ivopts.c */ /* In tree-ssa-loop-ivopts.c */
extern bool expr_invariant_in_loop_p (struct loop *, tree); extern bool expr_invariant_in_loop_p (struct loop *, tree);
/* In gimplify.c */
/* In gimplify.c */
tree force_gimple_operand (tree, tree *, bool, tree); tree force_gimple_operand (tree, tree *, bool, tree);
tree force_gimple_operand_bsi (block_stmt_iterator *, tree, bool, tree);
#include "tree-flow-inline.h" #include "tree-flow-inline.h"
......
...@@ -54,6 +54,9 @@ Boston, MA 02111-1307, USA. */ ...@@ -54,6 +54,9 @@ Boston, MA 02111-1307, USA. */
Graph. ACM Transactions on Programming Languages and Systems, Graph. ACM Transactions on Programming Languages and Systems,
13(4):451-490, October 1991. */ 13(4):451-490, October 1991. */
/* True if the code is in ssa form. */
bool in_ssa_p;
/* Structure to map a variable VAR to the set of blocks that contain /* Structure to map a variable VAR to the set of blocks that contain
definitions for VAR. */ definitions for VAR. */
struct def_blocks_d struct def_blocks_d
...@@ -1773,6 +1776,7 @@ rewrite_into_ssa (void) ...@@ -1773,6 +1776,7 @@ rewrite_into_ssa (void)
sbitmap_free (interesting_blocks); sbitmap_free (interesting_blocks);
timevar_pop (TV_TREE_SSA_OTHER); timevar_pop (TV_TREE_SSA_OTHER);
in_ssa_p = true;
} }
......
...@@ -2511,6 +2511,8 @@ rewrite_out_of_ssa (void) ...@@ -2511,6 +2511,8 @@ rewrite_out_of_ssa (void)
/* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE. */ /* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE. */
discover_nonconstant_array_refs (); discover_nonconstant_array_refs ();
in_ssa_p = false;
} }
......
...@@ -2808,6 +2808,23 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) ...@@ -2808,6 +2808,23 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
return t; return t;
} }
/* Builds and returns function declaration with NAME and TYPE. */
tree
build_fn_decl (const char *name, tree type)
{
tree id = get_identifier (name);
tree decl = build_decl (FUNCTION_DECL, id, type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
TREE_NOTHROW (decl) = 1;
return decl;
}
/* BLOCK nodes are used to represent the structure of binding contours /* BLOCK nodes are used to represent the structure of binding contours
and declarations, once those contours have been exited and their contents and declarations, once those contours have been exited and their contents
compiled. This information is used for outputting debugging info. */ compiled. This information is used for outputting debugging info. */
......
...@@ -2905,6 +2905,7 @@ extern tree build_string (int, const char *); ...@@ -2905,6 +2905,7 @@ extern tree build_string (int, const char *);
extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL); extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
#define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO) #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL); extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL);
extern tree build_fn_decl (const char *, tree);
#define build_decl(c,t,q) build_decl_stat (c,t,q MEM_STAT_INFO) #define build_decl(c,t,q) build_decl_stat (c,t,q MEM_STAT_INFO)
extern tree build_block (tree, tree, tree, tree, tree); extern tree build_block (tree, tree, tree, tree, tree);
#ifndef USE_MAPPED_LOCATION #ifndef USE_MAPPED_LOCATION
......
...@@ -128,8 +128,6 @@ static bool rtl_mod_subtract_transform (rtx); ...@@ -128,8 +128,6 @@ static bool rtl_mod_subtract_transform (rtx);
#ifdef HAVE_prefetch #ifdef HAVE_prefetch
static bool speculative_prefetching_transform (rtx); static bool speculative_prefetching_transform (rtx);
#endif #endif
static void tree_divmod_values_to_profile (tree, histogram_values *);
static void tree_values_to_profile (tree, histogram_values *);
static tree tree_divmod_fixed_value (tree, tree, tree, tree, static tree tree_divmod_fixed_value (tree, tree, tree, tree,
tree, int, gcov_type, gcov_type); tree, int, gcov_type, gcov_type);
static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type); static tree tree_mod_pow2 (tree, tree, tree, tree, int, gcov_type, gcov_type);
...@@ -181,7 +179,6 @@ rtl_divmod_values_to_profile (rtx insn, histogram_values *values) ...@@ -181,7 +179,6 @@ rtl_divmod_values_to_profile (rtx insn, histogram_values *values)
hist->hvalue.rtl.mode = mode; hist->hvalue.rtl.mode = mode;
hist->hvalue.rtl.insn = insn; hist->hvalue.rtl.insn = insn;
hist->type = HIST_TYPE_POW2; hist->type = HIST_TYPE_POW2;
hist->hdata.pow2.may_be_other = 1;
VEC_safe_push (histogram_value, heap, *values, hist); VEC_safe_push (histogram_value, heap, *values, hist);
} }
...@@ -360,9 +357,7 @@ rtl_find_values_to_profile (histogram_values *values) ...@@ -360,9 +357,7 @@ rtl_find_values_to_profile (histogram_values *values)
fprintf (dump_file, fprintf (dump_file,
"Pow2 counter for insn %d.\n", "Pow2 counter for insn %d.\n",
INSN_UID ((rtx)hist->hvalue.rtl.insn)); INSN_UID ((rtx)hist->hvalue.rtl.insn));
hist->n_counters hist->n_counters = 2;
= GET_MODE_BITSIZE (hist->hvalue.rtl.mode)
+ (hist->hdata.pow2.may_be_other ? 1 : 0);
break; break;
case HIST_TYPE_SINGLE_VALUE: case HIST_TYPE_SINGLE_VALUE:
...@@ -722,7 +717,7 @@ rtl_mod_pow2_value_transform (rtx insn) ...@@ -722,7 +717,7 @@ rtl_mod_pow2_value_transform (rtx insn)
enum machine_mode mode; enum machine_mode mode;
gcov_type wrong_values, count; gcov_type wrong_values, count;
edge e; edge e;
int i, all, prob; int all, prob;
set = single_set (insn); set = single_set (insn);
if (!set) if (!set)
...@@ -751,15 +746,9 @@ rtl_mod_pow2_value_transform (rtx insn) ...@@ -751,15 +746,9 @@ rtl_mod_pow2_value_transform (rtx insn)
histogram = XEXP (XEXP (histogram, 0), 1); histogram = XEXP (XEXP (histogram, 0), 1);
value = XEXP (histogram, 0); value = XEXP (histogram, 0);
histogram = XEXP (histogram, 1); histogram = XEXP (histogram, 1);
wrong_values =INTVAL (XEXP (histogram, 0)); wrong_values = INTVAL (XEXP (histogram, 0));
histogram = XEXP (histogram, 1);
count = 0;
for (i = 0; i < GET_MODE_BITSIZE (mode); i++)
{
count += INTVAL (XEXP (histogram, 0));
histogram = XEXP (histogram, 1); histogram = XEXP (histogram, 1);
} count = INTVAL (XEXP (histogram, 0));
if (!rtx_equal_p (op2, value)) if (!rtx_equal_p (op2, value))
return false; return false;
...@@ -1355,7 +1344,6 @@ tree_mod_pow2_value_transform (tree stmt) ...@@ -1355,7 +1344,6 @@ tree_mod_pow2_value_transform (tree stmt)
gcov_type count, wrong_values, all; gcov_type count, wrong_values, all;
tree modify, op, op1, op2, result, value; tree modify, op, op1, op2, result, value;
int prob; int prob;
unsigned int i;
modify = stmt; modify = stmt;
if (TREE_CODE (stmt) == RETURN_EXPR if (TREE_CODE (stmt) == RETURN_EXPR
...@@ -1386,9 +1374,7 @@ tree_mod_pow2_value_transform (tree stmt) ...@@ -1386,9 +1374,7 @@ tree_mod_pow2_value_transform (tree stmt)
value = histogram->hvalue.tree.value; value = histogram->hvalue.tree.value;
wrong_values = histogram->hvalue.tree.counters[0]; wrong_values = histogram->hvalue.tree.counters[0];
count = 0; count = histogram->hvalue.tree.counters[1];
for (i = 1; i <= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (stmt))); i++)
count += histogram->hvalue.tree.counters[i];
/* We require that we hit a power of 2 at least half of all evaluations. */ /* We require that we hit a power of 2 at least half of all evaluations. */
if (simple_cst_equal (op2, value) != 1 || count < wrong_values) if (simple_cst_equal (op2, value) != 1 || count < wrong_values)
...@@ -1576,10 +1562,6 @@ tree_mod_subtract_transform (tree stmt) ...@@ -1576,10 +1562,6 @@ tree_mod_subtract_transform (tree stmt)
wrong_values += histogram->hvalue.tree.counters[i+1]; wrong_values += histogram->hvalue.tree.counters[i+1];
all += wrong_values; all += wrong_values;
/* Sanity check. */
if (simple_cst_equal (op2, value) != 1)
return false;
/* We require that we use just subtractions in at least 50% of all /* We require that we use just subtractions in at least 50% of all
evaluations. */ evaluations. */
count = 0; count = 0;
...@@ -1638,54 +1620,53 @@ rtl_register_value_prof_hooks (void) ...@@ -1638,54 +1620,53 @@ rtl_register_value_prof_hooks (void)
gcc_assert (!ir_type ()); gcc_assert (!ir_type ());
} }
/* Find values inside INSN for that we want to measure histograms for /* Find values inside STMT for that we want to measure histograms for
division/modulo optimization. */ division/modulo optimization. */
static void static void
tree_divmod_values_to_profile (tree stmt, histogram_values *values) tree_divmod_values_to_profile (tree stmt, histogram_values *values)
{ {
tree op, op1, op2; tree assign, lhs, rhs, divisor, op0, type;
histogram_value hist; histogram_value hist;
op = stmt; if (TREE_CODE (stmt) == RETURN_EXPR)
if (TREE_CODE (stmt) == RETURN_EXPR assign = TREE_OPERAND (stmt, 0);
&& TREE_OPERAND (stmt, 0) else
&& TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR) assign = stmt;
op = TREE_OPERAND (stmt, 0);
if (TREE_CODE (op) != MODIFY_EXPR) if (!assign
|| TREE_CODE (assign) != MODIFY_EXPR)
return; return;
if (!INTEGRAL_TYPE_P (TREE_TYPE (op))) lhs = TREE_OPERAND (assign, 0);
type = TREE_TYPE (lhs);
if (!INTEGRAL_TYPE_P (type))
return; return;
op = TREE_OPERAND (op, 1);
switch (TREE_CODE (op)) rhs = TREE_OPERAND (assign, 1);
switch (TREE_CODE (rhs))
{ {
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR: case TRUNC_MOD_EXPR:
op1 = TREE_OPERAND (op, 0); divisor = TREE_OPERAND (rhs, 1);
op2 = TREE_OPERAND (op, 1); op0 = TREE_OPERAND (rhs, 0);
VEC_reserve (histogram_value, heap, *values, 3); VEC_reserve (histogram_value, heap, *values, 3);
if (is_gimple_reg (divisor))
{
/* Check for a special case where the divisor is power(s) of 2. /* Check for a special case where the divisor is power(s) of 2.
This is more aggressive than the RTL version, under the This is more aggressive than the RTL version, under the
assumption that later phases will reduce / or % by power of 2 assumption that later phases will reduce / or % by power of 2
to something clever most of the time. Signed or unsigned. */ to something clever most of the time. Signed or unsigned. */
if (TREE_CODE (op2) != INTEGER_CST)
{
hist = ggc_alloc (sizeof (*hist)); hist = ggc_alloc (sizeof (*hist));
hist->hvalue.tree.value = op2; hist->hvalue.tree.value = divisor;
hist->hvalue.tree.stmt = stmt; hist->hvalue.tree.stmt = stmt;
hist->type = HIST_TYPE_POW2; hist->type = HIST_TYPE_POW2;
hist->hdata.pow2.may_be_other = 1;
VEC_quick_push (histogram_value, *values, hist); VEC_quick_push (histogram_value, *values, hist);
}
/* Check for the case where the divisor is the same value most /* Check for the case where the divisor is the same value most
of the time. */ of the time. */
if (TREE_CODE (op2) != INTEGER_CST)
{
hist = ggc_alloc (sizeof (*hist)); hist = ggc_alloc (sizeof (*hist));
hist->hvalue.tree.value = op2; hist->hvalue.tree.value = divisor;
hist->hvalue.tree.stmt = stmt; hist->hvalue.tree.stmt = stmt;
hist->type = HIST_TYPE_SINGLE_VALUE; hist->type = HIST_TYPE_SINGLE_VALUE;
VEC_quick_push (histogram_value, *values, hist); VEC_quick_push (histogram_value, *values, hist);
...@@ -1693,11 +1674,13 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values) ...@@ -1693,11 +1674,13 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values)
/* For mod, check whether it is not often a noop (or replaceable by /* For mod, check whether it is not often a noop (or replaceable by
a few subtractions). */ a few subtractions). */
if (TREE_CODE (op) == TRUNC_MOD_EXPR && TYPE_UNSIGNED (TREE_TYPE (op))) if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
&& TYPE_UNSIGNED (type))
{ {
hist = ggc_alloc (sizeof (*hist)); hist = ggc_alloc (sizeof (*hist));
hist->hvalue.tree.stmt = stmt; hist->hvalue.tree.stmt = stmt;
hist->hvalue.tree.value = op2; hist->hvalue.tree.value
= build2 (TRUNC_DIV_EXPR, type, op0, divisor);
hist->type = HIST_TYPE_INTERVAL; hist->type = HIST_TYPE_INTERVAL;
hist->hdata.intvl.int_start = 0; hist->hdata.intvl.int_start = 0;
hist->hdata.intvl.steps = 2; hist->hdata.intvl.steps = 2;
...@@ -1710,8 +1693,9 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values) ...@@ -1710,8 +1693,9 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values)
} }
} }
/* Find values inside INSN for that we want to measure histograms and adds /* Find values inside STMT for that we want to measure histograms and adds
them to list VALUES (increasing the record of its length in N_VALUES). */ them to list VALUES. */
static void static void
tree_values_to_profile (tree stmt, histogram_values *values) tree_values_to_profile (tree stmt, histogram_values *values)
{ {
...@@ -1724,17 +1708,13 @@ tree_find_values_to_profile (histogram_values *values) ...@@ -1724,17 +1708,13 @@ tree_find_values_to_profile (histogram_values *values)
{ {
basic_block bb; basic_block bb;
block_stmt_iterator bsi; block_stmt_iterator bsi;
tree stmt; unsigned i;
unsigned int i;
histogram_value hist; histogram_value hist;
*values = NULL; *values = NULL;
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{ tree_values_to_profile (bsi_stmt (bsi), values);
tree stmt = bsi_stmt (bsi);
tree_values_to_profile (stmt, values);
}
static_values = *values; static_values = *values;
for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++) for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
...@@ -1758,20 +1738,17 @@ tree_find_values_to_profile (histogram_values *values) ...@@ -1758,20 +1738,17 @@ tree_find_values_to_profile (histogram_values *values)
case HIST_TYPE_POW2: case HIST_TYPE_POW2:
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "Pow2 counter for insn "); fprintf (dump_file, "Pow2 counter for tree ");
print_generic_expr (dump_file, hist->hvalue.tree.stmt, TDF_SLIM); print_generic_expr (dump_file, hist->hvalue.tree.stmt, TDF_SLIM);
fprintf (dump_file, ".\n"); fprintf (dump_file, ".\n");
} }
stmt = hist->hvalue.tree.stmt; hist->n_counters = 2;
hist->n_counters
= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (stmt)))
+ (hist->hdata.pow2.may_be_other ? 1 : 0);
break; break;
case HIST_TYPE_SINGLE_VALUE: case HIST_TYPE_SINGLE_VALUE:
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "Single value counter for insn "); fprintf (dump_file, "Single value counter for tree ");
print_generic_expr (dump_file, hist->hvalue.tree.stmt, TDF_SLIM); print_generic_expr (dump_file, hist->hvalue.tree.stmt, TDF_SLIM);
fprintf (dump_file, ".\n"); fprintf (dump_file, ".\n");
} }
...@@ -1781,7 +1758,7 @@ tree_find_values_to_profile (histogram_values *values) ...@@ -1781,7 +1758,7 @@ tree_find_values_to_profile (histogram_values *values)
case HIST_TYPE_CONST_DELTA: case HIST_TYPE_CONST_DELTA:
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "Constant delta counter for insn "); fprintf (dump_file, "Constant delta counter for tree ");
print_generic_expr (dump_file, hist->hvalue.tree.stmt, TDF_SLIM); print_generic_expr (dump_file, hist->hvalue.tree.stmt, TDF_SLIM);
fprintf (dump_file, ".\n"); fprintf (dump_file, ".\n");
} }
......
...@@ -66,10 +66,6 @@ struct histogram_value_t ...@@ -66,10 +66,6 @@ struct histogram_value_t
int int_start; /* First value in interval. */ int int_start; /* First value in interval. */
unsigned int steps; /* Number of values in it. */ unsigned int steps; /* Number of values in it. */
} intvl; /* Interval histogram data. */ } intvl; /* Interval histogram data. */
struct
{
int may_be_other; /* If the value may be non-positive or not 2^k. */
} pow2; /* Power of 2 histogram data. */
} hdata; /* Profiled information specific data. */ } hdata; /* Profiled information specific data. */
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment