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>
* varasm.c (do_assemble_alias): Return early if TREE_ASM_WRITTEN
......
......@@ -995,7 +995,8 @@ LIB2FUNCS_ST = _eprintf __gcc_bcmp
# Defined in libgcov.c, included only in gcov library
LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
_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 \
_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) \
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 \
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 \
$(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)
......@@ -2466,7 +2467,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.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)/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)/function.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 \
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-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-phinodes.h gt-tree-nested.h \
gt-tree-ssa-operands.h gt-tree-ssa-propagate.h \
......
......@@ -443,6 +443,11 @@ extern void __gcov_merge_single (gcov_type *, unsigned);
consecutive values. */
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
/* The wrappers around some library functions.. */
extern pid_t __gcov_fork (void);
......
......@@ -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;
push_gimplify_context ();
gimplify_ctxp->into_ssa = true;
gimplify_ctxp->into_ssa = in_ssa_p;
if (var)
expr = build (MODIFY_EXPR, TREE_TYPE (var), var, expr);
......@@ -4671,12 +4671,31 @@ force_gimple_operand (tree expr, tree *stmts, bool simple, tree var)
gimple_test_f, fb_rvalue);
gcc_assert (ret != GS_ERROR);
for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
add_referenced_tmp_var (t);
if (referenced_vars)
{
for (t = gimplify_ctxp->temps; t ; t = TREE_CHAIN (t))
add_referenced_tmp_var (t);
}
pop_gimplify_context (NULL);
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"
......@@ -581,6 +581,67 @@ __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
}
#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
/* A wrapper for the fork function. Flushes the accumulated profiling data, so
that they are not counted twice. */
......
......@@ -172,10 +172,9 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
rtx mem_ref, tmp, mr, uval;
rtx sequence;
rtx end_of_code_label = gen_label_rtx ();
rtx loop_label = gen_label_rtx ();
int per_counter = GCOV_TYPE_SIZE / BITS_PER_UNIT;
edge e = split_block (BLOCK_FOR_INSN (value->hvalue.rtl.insn),
PREV_INSN (value->hvalue.rtl.insn));
PREV_INSN (value->hvalue.rtl.insn));
start_sequence ();
......@@ -191,33 +190,20 @@ rtl_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
emit_move_insn (uval, copy_rtx (value->hvalue.rtl.value));
/* 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,
NULL_RTX, NULL_RTX, end_of_code_label);
tmp = expand_simple_binop (value->hvalue.rtl.mode, PLUS, copy_rtx (uval),
constm1_rtx, NULL_RTX, 0, OPTAB_WIDEN);
tmp = expand_simple_binop (value->hvalue.rtl.mode, AND, copy_rtx (uval), tmp,
NULL_RTX, 0, OPTAB_WIDEN);
do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->hvalue.rtl.mode, NULL_RTX,
NULL_RTX, end_of_code_label);
}
/* Count log_2(value). */
emit_label (loop_label);
tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter), mr, 0, OPTAB_WIDEN);
do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->hvalue.rtl.mode,
NULL_RTX, NULL_RTX, end_of_code_label);
tmp = expand_simple_binop (value->hvalue.rtl.mode, PLUS, copy_rtx (uval),
constm1_rtx, NULL_RTX, 0, OPTAB_WIDEN);
tmp = expand_simple_binop (value->hvalue.rtl.mode, AND, copy_rtx (uval), tmp,
NULL_RTX, 0, OPTAB_WIDEN);
do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->hvalue.rtl.mode, NULL_RTX,
NULL_RTX, end_of_code_label);
tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter),
mr, 0, OPTAB_WIDEN);
if (tmp != mr)
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. */
emit_label (end_of_code_label);
......
......@@ -5350,8 +5350,8 @@ tree_block_ends_with_call_p (basic_block bb)
static bool
tree_block_ends_with_condjump_p (basic_block bb)
{
tree stmt = tsi_stmt (bsi_last (bb).tsi);
return (TREE_CODE (stmt) == COND_EXPR);
tree stmt = last_stmt (bb);
return (stmt && TREE_CODE (stmt) == COND_EXPR);
}
......
......@@ -38,6 +38,9 @@ struct basic_block_def;
typedef struct basic_block_def *basic_block;
#endif
/* True if the code is in ssa form. */
extern bool in_ssa_p;
/*---------------------------------------------------------------------------
Attributes for SSA_NAMEs.
......@@ -796,9 +799,10 @@ extern void linear_transform_loops (struct loops *);
/* In tree-ssa-loop-ivopts.c */
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_bsi (block_stmt_iterator *, tree, bool, tree);
#include "tree-flow-inline.h"
......
......@@ -54,6 +54,9 @@ Boston, MA 02111-1307, USA. */
Graph. ACM Transactions on Programming Languages and Systems,
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
definitions for VAR. */
struct def_blocks_d
......@@ -1773,6 +1776,7 @@ rewrite_into_ssa (void)
sbitmap_free (interesting_blocks);
timevar_pop (TV_TREE_SSA_OTHER);
in_ssa_p = true;
}
......
......@@ -2511,6 +2511,8 @@ rewrite_out_of_ssa (void)
/* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE. */
discover_nonconstant_array_refs ();
in_ssa_p = false;
}
......
......@@ -2807,6 +2807,23 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
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
and declarations, once those contours have been exited and their contents
......
......@@ -2905,6 +2905,7 @@ extern tree build_string (int, const char *);
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)
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)
extern tree build_block (tree, tree, tree, tree, tree);
#ifndef USE_MAPPED_LOCATION
......
......@@ -128,8 +128,6 @@ static bool rtl_mod_subtract_transform (rtx);
#ifdef HAVE_prefetch
static bool speculative_prefetching_transform (rtx);
#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,
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)
hist->hvalue.rtl.mode = mode;
hist->hvalue.rtl.insn = insn;
hist->type = HIST_TYPE_POW2;
hist->hdata.pow2.may_be_other = 1;
VEC_safe_push (histogram_value, heap, *values, hist);
}
......@@ -360,9 +357,7 @@ rtl_find_values_to_profile (histogram_values *values)
fprintf (dump_file,
"Pow2 counter for insn %d.\n",
INSN_UID ((rtx)hist->hvalue.rtl.insn));
hist->n_counters
= GET_MODE_BITSIZE (hist->hvalue.rtl.mode)
+ (hist->hdata.pow2.may_be_other ? 1 : 0);
hist->n_counters = 2;
break;
case HIST_TYPE_SINGLE_VALUE:
......@@ -722,7 +717,7 @@ rtl_mod_pow2_value_transform (rtx insn)
enum machine_mode mode;
gcov_type wrong_values, count;
edge e;
int i, all, prob;
int all, prob;
set = single_set (insn);
if (!set)
......@@ -751,15 +746,9 @@ rtl_mod_pow2_value_transform (rtx insn)
histogram = XEXP (XEXP (histogram, 0), 1);
value = XEXP (histogram, 0);
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);
}
count = INTVAL (XEXP (histogram, 0));
if (!rtx_equal_p (op2, value))
return false;
......@@ -1355,7 +1344,6 @@ tree_mod_pow2_value_transform (tree stmt)
gcov_type count, wrong_values, all;
tree modify, op, op1, op2, result, value;
int prob;
unsigned int i;
modify = stmt;
if (TREE_CODE (stmt) == RETURN_EXPR
......@@ -1386,9 +1374,7 @@ tree_mod_pow2_value_transform (tree stmt)
value = histogram->hvalue.tree.value;
wrong_values = histogram->hvalue.tree.counters[0];
count = 0;
for (i = 1; i <= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (stmt))); i++)
count += histogram->hvalue.tree.counters[i];
count = histogram->hvalue.tree.counters[1];
/* 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)
......@@ -1576,10 +1562,6 @@ tree_mod_subtract_transform (tree stmt)
wrong_values += histogram->hvalue.tree.counters[i+1];
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
evaluations. */
count = 0;
......@@ -1638,54 +1620,53 @@ rtl_register_value_prof_hooks (void)
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. */
static void
tree_divmod_values_to_profile (tree stmt, histogram_values *values)
{
tree op, op1, op2;
tree assign, lhs, rhs, divisor, op0, type;
histogram_value hist;
op = stmt;
if (TREE_CODE (stmt) == RETURN_EXPR
&& TREE_OPERAND (stmt, 0)
&& TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR)
op = TREE_OPERAND (stmt, 0);
if (TREE_CODE (stmt) == RETURN_EXPR)
assign = TREE_OPERAND (stmt, 0);
else
assign = stmt;
if (TREE_CODE (op) != MODIFY_EXPR)
if (!assign
|| TREE_CODE (assign) != MODIFY_EXPR)
return;
if (!INTEGRAL_TYPE_P (TREE_TYPE (op)))
lhs = TREE_OPERAND (assign, 0);
type = TREE_TYPE (lhs);
if (!INTEGRAL_TYPE_P (type))
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_MOD_EXPR:
op1 = TREE_OPERAND (op, 0);
op2 = TREE_OPERAND (op, 1);
divisor = TREE_OPERAND (rhs, 1);
op0 = TREE_OPERAND (rhs, 0);
VEC_reserve (histogram_value, heap, *values, 3);
/* Check for a special case where the divisor is power(s) of 2.
This is more aggressive than the RTL version, under the
assumption that later phases will reduce / or % by power of 2
to something clever most of the time. Signed or unsigned. */
if (TREE_CODE (op2) != INTEGER_CST)
if (is_gimple_reg (divisor))
{
/* Check for a special case where the divisor is power(s) of 2.
This is more aggressive than the RTL version, under the
assumption that later phases will reduce / or % by power of 2
to something clever most of the time. Signed or unsigned. */
hist = ggc_alloc (sizeof (*hist));
hist->hvalue.tree.value = op2;
hist->hvalue.tree.value = divisor;
hist->hvalue.tree.stmt = stmt;
hist->type = HIST_TYPE_POW2;
hist->hdata.pow2.may_be_other = 1;
VEC_quick_push (histogram_value, *values, hist);
}
/* Check for the case where the divisor is the same value most
of the time. */
if (TREE_CODE (op2) != INTEGER_CST)
{
/* Check for the case where the divisor is the same value most
of the time. */
hist = ggc_alloc (sizeof (*hist));
hist->hvalue.tree.value = op2;
hist->hvalue.tree.value = divisor;
hist->hvalue.tree.stmt = stmt;
hist->type = HIST_TYPE_SINGLE_VALUE;
VEC_quick_push (histogram_value, *values, hist);
......@@ -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
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->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->hdata.intvl.int_start = 0;
hist->hdata.intvl.steps = 2;
......@@ -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
them to list VALUES (increasing the record of its length in N_VALUES). */
/* Find values inside STMT for that we want to measure histograms and adds
them to list VALUES. */
static void
tree_values_to_profile (tree stmt, histogram_values *values)
{
......@@ -1724,17 +1708,13 @@ tree_find_values_to_profile (histogram_values *values)
{
basic_block bb;
block_stmt_iterator bsi;
tree stmt;
unsigned int i;
unsigned i;
histogram_value hist;
*values = NULL;
FOR_EACH_BB (bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
tree_values_to_profile (stmt, values);
}
tree_values_to_profile (bsi_stmt (bsi), values);
static_values = *values;
for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
......@@ -1758,20 +1738,17 @@ tree_find_values_to_profile (histogram_values *values)
case HIST_TYPE_POW2:
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);
fprintf (dump_file, ".\n");
}
stmt = hist->hvalue.tree.stmt;
hist->n_counters
= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (stmt)))
+ (hist->hdata.pow2.may_be_other ? 1 : 0);
hist->n_counters = 2;
break;
case HIST_TYPE_SINGLE_VALUE:
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);
fprintf (dump_file, ".\n");
}
......@@ -1781,7 +1758,7 @@ tree_find_values_to_profile (histogram_values *values)
case HIST_TYPE_CONST_DELTA:
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);
fprintf (dump_file, ".\n");
}
......
......@@ -66,10 +66,6 @@ struct histogram_value_t
int int_start; /* First value in interval. */
unsigned int steps; /* Number of values in it. */
} 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. */
};
......
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