Commit 6946b3f7 by Jan Hubicka Committed by Jan Hubicka

Makefile.in: Add dependencies.

	
	* Makefile.in: Add dependencies.
	* tree-pretty-print.c: Include value-prof.h
	(dump_generic_bb_buff): Dump histograms
	* value-prof.c: Include pointer-set.h
	(gimple_alloc_histogram_value, histogram_hash, histogram_eq,
	set_histogram_value, gimple_histogram_value,
	gimple_add_histogram_value, gimple_remove_histogram_value,
	gimple_histogram_value_of_type, dump_histogram_value,
	dump_histograms_for_stmt, gimple_remove_stmt_histograms,
	gimple_duplicate_stmt_histograms, visit_hist,
	verify_histograms): New functions.
	(tree_value_profile_transformations): Update for new histogram API.
	(tree_divmod_fixed_value): Update for new histogram API.
	(tree_divmod_fixed_value_transform): Update for new histogram API.
	(tree_mod_pow2): Update for new histogram API.
	(tree_mod_pow2_value_transform): Update for new histogram API.
	(tree_mod_subtract): Update for new histogram API.
	(tree_mod_subtract_transform): Update for new histogram API.
	(tree_stringops_transform): Update for new histogram API.
	(tree_divmod_values_to_profile): Update for new histogram API.
	(tree_stringops_values_to_profile): Update for new histogram API.
	(tree_find_values_to_profile): Update for new histogram API.
	* value-prof.h (gimple_histogram_value): Declare.
	(gimple_histogram_value_of_type): Declare.
	(gimple_add_histogram_value): Declare.
	(gimple_remove_histogram_value): Declare.
	(dump_histograms_for_stmt): Declare.
	(gimple_remove_histogram_value): Declare.
	(gimple_remove_stmt_histograms): Declare.
	(gimple_duplicate_stmt_histograms): Declare.
	(verify_histograms): Declare.
	* function.h
	(struct funrction): Add value_histograms hash.
	(VALUE_HISTOGRAMS): New macro.
	* profile.c (compute_value_histograms): update for new API.
	* tree-inline.c: Include value-prof.h
	(copy_bb): Update histograms.
	* tree-flow.h (struct stmt_ann_d): Do not contain pointer to histograms;
	reorder to get smaller memory layout.
	* tree-cfg.c: Include value-prof.h
	(bsi_remove): Update histograms.
	(bsi_replace): Update histograms.
	(verify_stmts): Call histogram verifier.
	(tree_duplicate_bb): Update histograms.
	(move_block_to_fn): Update histograms.

From-SVN: r119829
parent a22831b1
2006-12-13 Jan Hubicka <jh@suse.cz>
* Makefile.in: Add dependencies.
* tree-pretty-print.c: Include value-prof.h
(dump_generic_bb_buff): Dump histograms
* value-prof.c: Include pointer-set.h
(gimple_alloc_histogram_value, histogram_hash, histogram_eq,
set_histogram_value, gimple_histogram_value,
gimple_add_histogram_value, gimple_remove_histogram_value,
gimple_histogram_value_of_type, dump_histogram_value,
dump_histograms_for_stmt, gimple_remove_stmt_histograms,
gimple_duplicate_stmt_histograms, visit_hist,
verify_histograms): New functions.
(tree_value_profile_transformations): Update for new histogram API.
(tree_divmod_fixed_value): Update for new histogram API.
(tree_divmod_fixed_value_transform): Update for new histogram API.
(tree_mod_pow2): Update for new histogram API.
(tree_mod_pow2_value_transform): Update for new histogram API.
(tree_mod_subtract): Update for new histogram API.
(tree_mod_subtract_transform): Update for new histogram API.
(tree_stringops_transform): Update for new histogram API.
(tree_divmod_values_to_profile): Update for new histogram API.
(tree_stringops_values_to_profile): Update for new histogram API.
(tree_find_values_to_profile): Update for new histogram API.
* value-prof.h (gimple_histogram_value): Declare.
(gimple_histogram_value_of_type): Declare.
(gimple_add_histogram_value): Declare.
(gimple_remove_histogram_value): Declare.
(dump_histograms_for_stmt): Declare.
(gimple_remove_histogram_value): Declare.
(gimple_remove_stmt_histograms): Declare.
(gimple_duplicate_stmt_histograms): Declare.
(verify_histograms): Declare.
* function.h
(struct funrction): Add value_histograms hash.
(VALUE_HISTOGRAMS): New macro.
* profile.c (compute_value_histograms): update for new API.
* tree-inline.c: Include value-prof.h
(copy_bb): Update histograms.
* tree-flow.h (struct stmt_ann_d): Do not contain pointer to histograms;
reorder to get smaller memory layout.
* tree-cfg.c: Include value-prof.h
(bsi_remove): Update histograms.
(bsi_replace): Update histograms.
(verify_stmts): Call histogram verifier.
(tree_duplicate_bb): Update histograms.
(move_block_to_fn): Update histograms.
2006-12-13 Richard Guenther <rguenther@suse.de> 2006-12-13 Richard Guenther <rguenther@suse.de>
* ipa-inline.c (cgraph_flatten_node): Replace leafify with * ipa-inline.c (cgraph_flatten_node): Replace leafify with
......
...@@ -1828,7 +1828,7 @@ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ ...@@ -1828,7 +1828,7 @@ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \ $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
langhooks.h $(TREE_INLINE_H) $(CGRAPH_H) intl.h $(FUNCTION_H) $(TREE_GIMPLE_H) \ langhooks.h $(TREE_INLINE_H) $(CGRAPH_H) intl.h $(FUNCTION_H) $(TREE_GIMPLE_H) \
debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \ debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \
ipa-prop.h ipa-prop.h value-prof.h
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) langhooks.h $(REAL_H) tree-iterator.h $(GGC_H) langhooks.h $(REAL_H) tree-iterator.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
...@@ -2127,7 +2127,8 @@ tree-nomudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \ ...@@ -2127,7 +2127,8 @@ tree-nomudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
$(GGC_H) gt-tree-mudflap.h tree-pass.h toplev.h $(GGC_H) gt-tree-mudflap.h tree-pass.h toplev.h
tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \ tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(DIAGNOSTIC_H) $(REAL_H) $(HASHTAB_H) $(TREE_FLOW_H) \ $(TREE_H) $(DIAGNOSTIC_H) $(REAL_H) $(HASHTAB_H) $(TREE_FLOW_H) \
$(TM_H) coretypes.h tree-iterator.h tree-chrec.h langhooks.h tree-pass.h $(TM_H) coretypes.h tree-iterator.h tree-chrec.h langhooks.h tree-pass.h \
value-prof.h
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(FLAGS_H) $(REAL_H) toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) $(REAL_H) toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
$(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H)
...@@ -2438,7 +2439,8 @@ cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ ...@@ -2438,7 +2439,8 @@ cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) \
coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \ coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \
$(DIAGNOSTIC_H) toplev.h $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) $(DIAGNOSTIC_H) toplev.h $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \
value-prof.h
cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \ $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
output.h toplev.h $(FUNCTION_H) except.h $(TM_P_H) insn-config.h $(EXPR_H) \ output.h toplev.h $(FUNCTION_H) except.h $(TM_P_H) insn-config.h $(EXPR_H) \
......
...@@ -40,6 +40,7 @@ Boston, MA 02110-1301, USA. */ ...@@ -40,6 +40,7 @@ Boston, MA 02110-1301, USA. */
#include "debug.h" #include "debug.h"
#include "params.h" #include "params.h"
#include "tree-inline.h" #include "tree-inline.h"
#include "value-prof.h"
/* Verify that there is exactly single jump instruction since last and attach /* Verify that there is exactly single jump instruction since last and attach
REG_BR_PROB note specifying probability. REG_BR_PROB note specifying probability.
...@@ -1860,6 +1861,7 @@ tree_expand_cfg (void) ...@@ -1860,6 +1861,7 @@ tree_expand_cfg (void)
/* After expanding, the return labels are no longer needed. */ /* After expanding, the return labels are no longer needed. */
return_label = NULL; return_label = NULL;
naked_return_label = NULL; naked_return_label = NULL;
free_histograms ();
return 0; return 0;
} }
......
...@@ -195,6 +195,9 @@ struct function GTY(()) ...@@ -195,6 +195,9 @@ struct function GTY(())
/* The loops in this function. */ /* The loops in this function. */
struct loops * GTY((skip)) x_current_loops; struct loops * GTY((skip)) x_current_loops;
/* Value histograms attached to particular statements. */
htab_t GTY((skip)) value_histograms;
/* For function.c. */ /* For function.c. */
/* Points to the FUNCTION_DECL of this function. */ /* Points to the FUNCTION_DECL of this function. */
...@@ -532,6 +535,7 @@ extern int trampolines_created; ...@@ -532,6 +535,7 @@ extern int trampolines_created;
#define temp_slot_level (cfun->x_temp_slot_level) #define temp_slot_level (cfun->x_temp_slot_level)
#define nonlocal_goto_handler_labels (cfun->x_nonlocal_goto_handler_labels) #define nonlocal_goto_handler_labels (cfun->x_nonlocal_goto_handler_labels)
#define current_loops (cfun->x_current_loops) #define current_loops (cfun->x_current_loops)
#define VALUE_HISTOGRAMS(fun) (fun)->value_histograms
/* Given a function decl for a containing function, /* Given a function decl for a containing function,
return the `struct function' for it. */ return the `struct function' for it. */
......
...@@ -648,15 +648,13 @@ compute_value_histograms (histogram_values values) ...@@ -648,15 +648,13 @@ compute_value_histograms (histogram_values values)
{ {
histogram_value hist = VEC_index (histogram_value, values, i); histogram_value hist = VEC_index (histogram_value, values, i);
tree stmt = hist->hvalue.stmt; tree stmt = hist->hvalue.stmt;
stmt_ann_t ann = get_stmt_ann (stmt);
t = (int) hist->type; t = (int) hist->type;
aact_count = act_count[t]; aact_count = act_count[t];
act_count[t] += hist->n_counters; act_count[t] += hist->n_counters;
hist->hvalue.next = ann->histograms; gimple_add_histogram_value (cfun, stmt, hist);
ann->histograms = hist;
hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters); hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters);
for (j = 0; j < hist->n_counters; j++) for (j = 0; j < hist->n_counters; j++)
hist->hvalue.counters[j] = aact_count[j]; hist->hvalue.counters[j] = aact_count[j];
......
...@@ -46,6 +46,7 @@ Boston, MA 02110-1301, USA. */ ...@@ -46,6 +46,7 @@ Boston, MA 02110-1301, USA. */
#include "cfglayout.h" #include "cfglayout.h"
#include "hashtab.h" #include "hashtab.h"
#include "tree-ssa-propagate.h" #include "tree-ssa-propagate.h"
#include "value-prof.h"
/* This file contains functions for building the Control Flow Graph (CFG) /* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */ for a function tree. */
...@@ -2871,7 +2872,10 @@ bsi_remove (block_stmt_iterator *i, bool remove_eh_info) ...@@ -2871,7 +2872,10 @@ bsi_remove (block_stmt_iterator *i, bool remove_eh_info)
tsi_delink (&i->tsi); tsi_delink (&i->tsi);
mark_stmt_modified (t); mark_stmt_modified (t);
if (remove_eh_info) if (remove_eh_info)
remove_stmt_from_eh_region (t); {
remove_stmt_from_eh_region (t);
gimple_remove_stmt_histograms (cfun, t);
}
} }
...@@ -2934,6 +2938,8 @@ bsi_replace (const block_stmt_iterator *bsi, tree stmt, bool update_eh_info) ...@@ -2934,6 +2938,8 @@ bsi_replace (const block_stmt_iterator *bsi, tree stmt, bool update_eh_info)
{ {
remove_stmt_from_eh_region (orig_stmt); remove_stmt_from_eh_region (orig_stmt);
add_stmt_to_eh_region (stmt, eh_region); add_stmt_to_eh_region (stmt, eh_region);
gimple_duplicate_stmt_histograms (cfun, stmt, cfun, orig_stmt);
gimple_remove_stmt_histograms (cfun, orig_stmt);
} }
} }
...@@ -3671,6 +3677,7 @@ verify_stmts (void) ...@@ -3671,6 +3677,7 @@ verify_stmts (void)
internal_error ("verify_stmts failed"); internal_error ("verify_stmts failed");
htab_delete (htab); htab_delete (htab);
verify_histograms ();
timevar_pop (TV_TREE_STMT_VERIFY); timevar_pop (TV_TREE_STMT_VERIFY);
} }
...@@ -4342,6 +4349,7 @@ tree_duplicate_bb (basic_block bb) ...@@ -4342,6 +4349,7 @@ tree_duplicate_bb (basic_block bb)
region = lookup_stmt_eh_region (stmt); region = lookup_stmt_eh_region (stmt);
if (region >= 0) if (region >= 0)
add_stmt_to_eh_region (copy, region); add_stmt_to_eh_region (copy, region);
gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
/* Create new names for all the definitions created by COPY and /* Create new names for all the definitions created by COPY and
add replacement mappings for each new name. */ add replacement mappings for each new name. */
...@@ -4785,6 +4793,8 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, ...@@ -4785,6 +4793,8 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
{ {
add_stmt_to_eh_region_fn (dest_cfun, stmt, region + eh_offset); add_stmt_to_eh_region_fn (dest_cfun, stmt, region + eh_offset);
remove_stmt_from_eh_region (stmt); remove_stmt_from_eh_region (stmt);
gimple_duplicate_stmt_histograms (dest_cfun, stmt, cfun, stmt);
gimple_remove_stmt_histograms (cfun, stmt);
} }
} }
} }
......
...@@ -356,17 +356,6 @@ struct stmt_ann_d GTY(()) ...@@ -356,17 +356,6 @@ struct stmt_ann_d GTY(())
{ {
struct tree_ann_common_d common; struct tree_ann_common_d common;
/* Nonzero if the statement has been modified (meaning that the operands
need to be scanned again). */
unsigned modified : 1;
/* Nonzero if the statement makes references to volatile storage. */
unsigned has_volatile_ops : 1;
/* Nonzero if the statement makes a function call that may clobber global
and local addressable variables. */
unsigned makes_clobbering_call : 1;
/* Nonzero if the statement references memory (at least one of its /* Nonzero if the statement references memory (at least one of its
expressions contains a non-register operand). */ expressions contains a non-register operand). */
unsigned references_memory : 1; unsigned references_memory : 1;
...@@ -385,11 +374,16 @@ struct stmt_ann_d GTY(()) ...@@ -385,11 +374,16 @@ struct stmt_ann_d GTY(())
pass which needs statement UIDs. */ pass which needs statement UIDs. */
unsigned int uid; unsigned int uid;
/* Linked list of histograms for value-based profiling. This is really a /* Nonzero if the statement has been modified (meaning that the operands
struct histogram_value*. We use void* to avoid having to export that need to be scanned again). */
everywhere, and to avoid having to put it in GC memory. */ unsigned modified : 1;
void * GTY ((skip (""))) histograms; /* Nonzero if the statement makes references to volatile storage. */
unsigned has_volatile_ops : 1;
/* Nonzero if the statement makes a function call that may clobber global
and local addressable variables. */
unsigned makes_clobbering_call : 1;
}; };
union tree_ann_d GTY((desc ("ann_type ((tree_ann_t)&%h)"))) union tree_ann_d GTY((desc ("ann_type ((tree_ann_t)&%h)")))
......
...@@ -49,6 +49,7 @@ Boston, MA 02110-1301, USA. */ ...@@ -49,6 +49,7 @@ Boston, MA 02110-1301, USA. */
#include "debug.h" #include "debug.h"
#include "pointer-set.h" #include "pointer-set.h"
#include "ipa-prop.h" #include "ipa-prop.h"
#include "value-prof.h"
/* I'm not real happy about this, but we need to handle gimple and /* I'm not real happy about this, but we need to handle gimple and
non-gimple trees. */ non-gimple trees. */
...@@ -707,6 +708,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal ...@@ -707,6 +708,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int count_scal
{ {
tree call, decl; tree call, decl;
gimple_duplicate_stmt_histograms (cfun, stmt, id->src_cfun, orig_stmt);
/* With return slot optimization we can end up with /* With return slot optimization we can end up with
non-gimple (foo *)&this->m, fix that here. */ non-gimple (foo *)&this->m, fix that here. */
if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
......
...@@ -33,6 +33,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -33,6 +33,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "tree-iterator.h" #include "tree-iterator.h"
#include "tree-chrec.h" #include "tree-chrec.h"
#include "tree-pass.h" #include "tree-pass.h"
#include "value-prof.h"
/* Local functions, macros and variables. */ /* Local functions, macros and variables. */
static int op_prio (tree); static int op_prio (tree);
...@@ -3000,6 +3001,7 @@ dump_generic_bb_buff (pretty_printer *buffer, basic_block bb, ...@@ -3000,6 +3001,7 @@ dump_generic_bb_buff (pretty_printer *buffer, basic_block bb,
INDENT (curr_indent); INDENT (curr_indent);
dump_generic_node (buffer, stmt, curr_indent, flags, true); dump_generic_node (buffer, stmt, curr_indent, flags, true);
pp_newline (buffer); pp_newline (buffer);
dump_histograms_for_stmt (cfun, buffer->buffer->stream, stmt);
} }
dump_implicit_edges (buffer, bb, indent, flags); dump_implicit_edges (buffer, bb, indent, flags);
......
...@@ -43,6 +43,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -43,6 +43,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "timevar.h" #include "timevar.h"
#include "tree-pass.h" #include "tree-pass.h"
#include "toplev.h" #include "toplev.h"
#include "pointer-set.h"
static struct value_prof_hooks *value_prof_hooks; static struct value_prof_hooks *value_prof_hooks;
...@@ -81,6 +82,302 @@ static bool tree_mod_pow2_value_transform (tree); ...@@ -81,6 +82,302 @@ static bool tree_mod_pow2_value_transform (tree);
static bool tree_mod_subtract_transform (tree); static bool tree_mod_subtract_transform (tree);
static bool tree_stringops_transform (block_stmt_iterator *); static bool tree_stringops_transform (block_stmt_iterator *);
/* Allocate histogram value. */
static histogram_value
gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
enum hist_type type, tree stmt, tree value)
{
histogram_value hist = (histogram_value) xcalloc (1, sizeof (*hist));
hist->hvalue.value = value;
hist->hvalue.stmt = stmt;
hist->type = type;
return hist;
}
/* Hash value for histogram. */
static hashval_t
histogram_hash (const void *x)
{
return htab_hash_pointer (((histogram_value)x)->hvalue.stmt);
}
/* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
static int
histogram_eq (const void *x, const void *y)
{
return ((histogram_value) x)->hvalue.stmt == (tree)y;
}
/* Set histogram for STMT. */
static void
set_histogram_value (struct function *fun, tree stmt, histogram_value hist)
{
void **loc;
if (!hist && !VALUE_HISTOGRAMS (fun))
return;
if (!VALUE_HISTOGRAMS (fun))
VALUE_HISTOGRAMS (fun) = htab_create (1, histogram_hash,
histogram_eq, NULL);
loc = htab_find_slot_with_hash (VALUE_HISTOGRAMS (fun), stmt,
htab_hash_pointer (stmt),
hist ? INSERT : NO_INSERT);
if (!hist)
{
if (loc)
htab_clear_slot (VALUE_HISTOGRAMS (fun), loc);
return;
}
*loc = hist;
}
/* Get histogram list for STMT. */
histogram_value
gimple_histogram_value (struct function *fun, tree stmt)
{
if (!VALUE_HISTOGRAMS (fun))
return NULL;
return htab_find_with_hash (VALUE_HISTOGRAMS (fun), stmt,
htab_hash_pointer (stmt));
}
/* Add histogram for STMT. */
void
gimple_add_histogram_value (struct function *fun, tree stmt, histogram_value hist)
{
hist->hvalue.next = gimple_histogram_value (fun, stmt);
set_histogram_value (fun, stmt, hist);
}
/* Remove histogram HIST from STMT's histogram list. */
void
gimple_remove_histogram_value (struct function *fun, tree stmt, histogram_value hist)
{
histogram_value hist2 = gimple_histogram_value (fun, stmt);
if (hist == hist2)
{
set_histogram_value (fun, stmt, hist->hvalue.next);
}
else
{
while (hist2->hvalue.next != hist)
hist2 = hist2->hvalue.next;
hist2->hvalue.next = hist->hvalue.next;
}
free (hist->hvalue.counters);
#ifdef ENABLE_CHECKING
memset (hist, 0xab, sizeof (*hist));
#endif
free (hist);
}
/* Lookup histogram of type TYPE in the STMT. */
histogram_value
gimple_histogram_value_of_type (struct function *fun, tree stmt, enum hist_type type)
{
histogram_value hist;
for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
if (hist->type == type)
return hist;
return NULL;
}
/* Dump information about HIST to DUMP_FILE. */
static void
dump_histogram_value (FILE *dump_file, histogram_value hist)
{
switch (hist->type)
{
case HIST_TYPE_INTERVAL:
fprintf (dump_file, "Interval counter range %d -- %d",
hist->hdata.intvl.int_start,
(hist->hdata.intvl.int_start
+ hist->hdata.intvl.steps - 1));
if (hist->hvalue.counters)
{
unsigned int i;
fprintf(dump_file, " [");
for (i = 0; i < hist->hdata.intvl.steps; i++)
fprintf (dump_file, " %d:"HOST_WIDEST_INT_PRINT_DEC,
hist->hdata.intvl.int_start + i,
(HOST_WIDEST_INT) hist->hvalue.counters[i]);
fprintf (dump_file, " ] outside range:"HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) hist->hvalue.counters[i]);
}
fprintf (dump_file, ".\n");
break;
case HIST_TYPE_POW2:
fprintf (dump_file, "Pow2 counter ");
if (hist->hvalue.counters)
{
fprintf (dump_file, "pow2:"HOST_WIDEST_INT_PRINT_DEC
" nonpow2:"HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) hist->hvalue.counters[0],
(HOST_WIDEST_INT) hist->hvalue.counters[1]);
}
fprintf (dump_file, ".\n");
break;
case HIST_TYPE_SINGLE_VALUE:
fprintf (dump_file, "Single value ");
if (hist->hvalue.counters)
{
fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
" match:"HOST_WIDEST_INT_PRINT_DEC
" wrong:"HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) hist->hvalue.counters[0],
(HOST_WIDEST_INT) hist->hvalue.counters[1],
(HOST_WIDEST_INT) hist->hvalue.counters[2]);
}
fprintf (dump_file, ".\n");
break;
case HIST_TYPE_CONST_DELTA:
fprintf (dump_file, "Constant delta ");
if (hist->hvalue.counters)
{
fprintf (dump_file, "value:"HOST_WIDEST_INT_PRINT_DEC
" match:"HOST_WIDEST_INT_PRINT_DEC
" wrong:"HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) hist->hvalue.counters[0],
(HOST_WIDEST_INT) hist->hvalue.counters[1],
(HOST_WIDEST_INT) hist->hvalue.counters[2]);
}
fprintf (dump_file, ".\n");
break;
}
}
/* Dump all histograms attached to STMT to DUMP_FILE. */
void
dump_histograms_for_stmt (struct function *fun, FILE *dump_file, tree stmt)
{
histogram_value hist;
for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
dump_histogram_value (dump_file, hist);
}
/* Remove all histograms associated with STMT. */
void
gimple_remove_stmt_histograms (struct function *fun, tree stmt)
{
histogram_value val;
while ((val = gimple_histogram_value (fun, stmt)) != NULL)
gimple_remove_histogram_value (fun, stmt, val);
}
/* Duplicate all histograms associates with OSTMT to STMT. */
void
gimple_duplicate_stmt_histograms (struct function *fun, tree stmt,
struct function *ofun, tree ostmt)
{
histogram_value val;
for (val = gimple_histogram_value (ofun, ostmt); val != NULL; val = val->hvalue.next)
{
histogram_value new = gimple_alloc_histogram_value (fun, val->type, NULL, NULL);
memcpy (new, val, sizeof (*val));
new->hvalue.stmt = stmt;
new->hvalue.counters = xmalloc (sizeof (*new->hvalue.counters) * new->n_counters);
memcpy (new->hvalue.counters, val->hvalue.counters, sizeof (*new->hvalue.counters) * new->n_counters);
gimple_add_histogram_value (fun, stmt, new);
}
}
static bool error_found = false;
/* Helper function for verify_histograms. For each histogram reachable via htab
walk verify that it was reached via statement walk. */
static int
visit_hist (void **slot, void *data)
{
struct pointer_set_t *visited = (struct pointer_set_t *) data;
histogram_value hist = *(histogram_value *) slot;
if (!pointer_set_contains (visited, hist))
{
error ("Dead histogram");
dump_histogram_value (stderr, hist);
debug_generic_stmt (hist->hvalue.stmt);
error_found = true;
}
return 0;
}
/* Verify sanity of the histograms. */
void
verify_histograms (void)
{
basic_block bb;
block_stmt_iterator bsi;
histogram_value hist;
struct pointer_set_t *visited_hists;
error_found = false;
visited_hists = pointer_set_create ();
FOR_EACH_BB (bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
for (hist = gimple_histogram_value (cfun, stmt); hist; hist = hist->hvalue.next)
{
if (hist->hvalue.stmt != stmt)
{
error ("Histogram value statement does not correspond to statement"
" it is associated with");
debug_generic_stmt (stmt);
dump_histogram_value (stderr, hist);
error_found = true;
}
pointer_set_insert (visited_hists, hist);
}
}
if (VALUE_HISTOGRAMS (cfun))
htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, visited_hists);
pointer_set_destroy (visited_hists);
if (error_found)
internal_error ("verify_histograms failed");
}
/* Helper function for verify_histograms. For each histogram reachable via htab
walk verify that it was reached via statement walk. */
static int
free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
{
histogram_value hist = *(histogram_value *) slot;
free (hist->hvalue.counters);
#ifdef ENABLE_CHECKING
memset (hist, 0xab, sizeof (*hist));
#endif
free (hist);
return 0;
}
void
free_histograms (void)
{
if (VALUE_HISTOGRAMS (cfun))
{
htab_traverse (VALUE_HISTOGRAMS (cfun), free_hist, NULL);
htab_delete (VALUE_HISTOGRAMS (cfun));
VALUE_HISTOGRAMS (cfun) = NULL;
}
}
/* The overall number of invocations of the counter should match execution count /* The overall number of invocations of the counter should match execution count
of basic block. Report it as error rather than internal error as it might of basic block. Report it as error rather than internal error as it might
mean that user has misused the profile somehow. */ mean that user has misused the profile somehow. */
...@@ -110,22 +407,18 @@ tree_value_profile_transformations (void) ...@@ -110,22 +407,18 @@ tree_value_profile_transformations (void)
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
/* Ignore cold areas -- we are enlarging the code. */
if (!bb->count || !maybe_hot_bb_p (bb))
continue;
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 stmt = bsi_stmt (bsi); tree stmt = bsi_stmt (bsi);
stmt_ann_t ann = get_stmt_ann (stmt); histogram_value th = gimple_histogram_value (cfun, stmt);
histogram_value th = ann->histograms;
if (!th) if (!th)
continue; continue;
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "Trying transformations on insn "); fprintf (dump_file, "Trying transformations on stmt ");
print_generic_stmt (dump_file, stmt, TDF_SLIM); print_generic_stmt (dump_file, stmt, TDF_SLIM);
dump_histograms_for_stmt (cfun, dump_file, stmt);
} }
/* Transformations: */ /* Transformations: */
...@@ -150,14 +443,6 @@ tree_value_profile_transformations (void) ...@@ -150,14 +443,6 @@ tree_value_profile_transformations (void)
bsi = bsi_for_stmt (stmt); bsi = bsi_for_stmt (stmt);
} }
} }
/* Free extra storage from compute_value_histograms. */
while (th)
{
free (th->hvalue.counters);
th = th->hvalue.next;
}
ann->histograms = 0;
} }
} }
...@@ -259,7 +544,6 @@ tree_divmod_fixed_value (tree stmt, tree operation, ...@@ -259,7 +544,6 @@ tree_divmod_fixed_value (tree stmt, tree operation,
static bool static bool
tree_divmod_fixed_value_transform (tree stmt) tree_divmod_fixed_value_transform (tree stmt)
{ {
stmt_ann_t ann = get_stmt_ann (stmt);
histogram_value histogram; histogram_value histogram;
enum tree_code code; enum tree_code code;
gcov_type val, count, all; gcov_type val, count, all;
...@@ -283,13 +567,8 @@ tree_divmod_fixed_value_transform (tree stmt) ...@@ -283,13 +567,8 @@ tree_divmod_fixed_value_transform (tree stmt)
op1 = TREE_OPERAND (op, 0); op1 = TREE_OPERAND (op, 0);
op2 = TREE_OPERAND (op, 1); op2 = TREE_OPERAND (op, 1);
if (!ann->histograms)
return false;
for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
if (histogram->type == HIST_TYPE_SINGLE_VALUE)
break;
histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
if (!histogram) if (!histogram)
return false; return false;
...@@ -297,11 +576,13 @@ tree_divmod_fixed_value_transform (tree stmt) ...@@ -297,11 +576,13 @@ tree_divmod_fixed_value_transform (tree stmt)
val = histogram->hvalue.counters[0]; val = histogram->hvalue.counters[0];
count = histogram->hvalue.counters[1]; count = histogram->hvalue.counters[1];
all = histogram->hvalue.counters[2]; all = histogram->hvalue.counters[2];
gimple_remove_histogram_value (cfun, stmt, histogram);
/* We require that count is at least half of all; this means /* We require that count is at least half of all; this means
that for the transformation to fire the value must be constant that for the transformation to fire the value must be constant
at least 50% of time (and 75% gives the guarantee of usage). */ at least 50% of time (and 75% gives the guarantee of usage). */
if (simple_cst_equal (op2, value) != 1 || 2 * count < all) if (simple_cst_equal (op2, value) != 1 || 2 * count < all
|| !maybe_hot_bb_p (bb_for_stmt (stmt)))
return false; return false;
if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count)) if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
...@@ -422,7 +703,6 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob, ...@@ -422,7 +703,6 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
static bool static bool
tree_mod_pow2_value_transform (tree stmt) tree_mod_pow2_value_transform (tree stmt)
{ {
stmt_ann_t ann = get_stmt_ann (stmt);
histogram_value histogram; histogram_value histogram;
enum tree_code code; enum tree_code code;
gcov_type count, wrong_values, all; gcov_type count, wrong_values, all;
...@@ -446,13 +726,8 @@ tree_mod_pow2_value_transform (tree stmt) ...@@ -446,13 +726,8 @@ tree_mod_pow2_value_transform (tree stmt)
op1 = TREE_OPERAND (op, 0); op1 = TREE_OPERAND (op, 0);
op2 = TREE_OPERAND (op, 1); op2 = TREE_OPERAND (op, 1);
if (!ann->histograms)
return false;
for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
if (histogram->type == HIST_TYPE_POW2)
break;
histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_POW2);
if (!histogram) if (!histogram)
return false; return false;
...@@ -460,8 +735,11 @@ tree_mod_pow2_value_transform (tree stmt) ...@@ -460,8 +735,11 @@ tree_mod_pow2_value_transform (tree stmt)
wrong_values = histogram->hvalue.counters[0]; wrong_values = histogram->hvalue.counters[0];
count = histogram->hvalue.counters[1]; count = histogram->hvalue.counters[1];
gimple_remove_histogram_value (cfun, stmt, histogram);
/* 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
|| !maybe_hot_bb_p (bb_for_stmt (stmt)))
return false; return false;
if (dump_file) if (dump_file)
...@@ -472,6 +750,7 @@ tree_mod_pow2_value_transform (tree stmt) ...@@ -472,6 +750,7 @@ tree_mod_pow2_value_transform (tree stmt)
/* Compute probability of taking the optimal path. */ /* Compute probability of taking the optimal path. */
all = count + wrong_values; all = count + wrong_values;
if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count)) if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
return false; return false;
...@@ -604,13 +883,13 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2, ...@@ -604,13 +883,13 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
static bool static bool
tree_mod_subtract_transform (tree stmt) tree_mod_subtract_transform (tree stmt)
{ {
stmt_ann_t ann = get_stmt_ann (stmt);
histogram_value histogram; histogram_value histogram;
enum tree_code code; enum tree_code code;
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 prob1, prob2; int prob1, prob2;
unsigned int i; unsigned int i, steps;
gcov_type count1, count2;
modify = stmt; modify = stmt;
if (TREE_CODE (stmt) == RETURN_EXPR if (TREE_CODE (stmt) == RETURN_EXPR
...@@ -629,13 +908,8 @@ tree_mod_subtract_transform (tree stmt) ...@@ -629,13 +908,8 @@ tree_mod_subtract_transform (tree stmt)
op1 = TREE_OPERAND (op, 0); op1 = TREE_OPERAND (op, 0);
op2 = TREE_OPERAND (op, 1); op2 = TREE_OPERAND (op, 1);
if (!ann->histograms)
return false;
for (histogram = ann->histograms; histogram; histogram = histogram->hvalue.next)
if (histogram->type == HIST_TYPE_INTERVAL)
break;
histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INTERVAL);
if (!histogram) if (!histogram)
return false; return false;
...@@ -647,11 +921,17 @@ tree_mod_subtract_transform (tree stmt) ...@@ -647,11 +921,17 @@ tree_mod_subtract_transform (tree stmt)
wrong_values += histogram->hvalue.counters[i]; wrong_values += histogram->hvalue.counters[i];
wrong_values += histogram->hvalue.counters[i+1]; wrong_values += histogram->hvalue.counters[i+1];
steps = histogram->hdata.intvl.steps;
all += wrong_values; all += wrong_values;
count1 = histogram->hvalue.counters[0];
count2 = histogram->hvalue.counters[1];
/* Compute probability of taking the optimal path. */ /* Compute probability of taking the optimal path. */
if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count)) if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
return false; {
gimple_remove_histogram_value (cfun, stmt, histogram);
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. */
...@@ -662,9 +942,11 @@ tree_mod_subtract_transform (tree stmt) ...@@ -662,9 +942,11 @@ tree_mod_subtract_transform (tree stmt)
if (count * 2 >= all) if (count * 2 >= all)
break; break;
} }
if (i == histogram->hdata.intvl.steps) if (i == steps
|| !maybe_hot_bb_p (bb_for_stmt (stmt)))
return false; return false;
gimple_remove_histogram_value (cfun, stmt, histogram);
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "Mod subtract transformation on insn "); fprintf (dump_file, "Mod subtract transformation on insn ");
...@@ -672,14 +954,13 @@ tree_mod_subtract_transform (tree stmt) ...@@ -672,14 +954,13 @@ tree_mod_subtract_transform (tree stmt)
} }
/* Compute probability of taking the optimal path(s). */ /* Compute probability of taking the optimal path(s). */
prob1 = (histogram->hvalue.counters[0] * REG_BR_PROB_BASE + all / 2) / all; prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all;
prob2 = (histogram->hvalue.counters[1] * REG_BR_PROB_BASE + all / 2) / all; prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all;
/* In practice, "steps" is always 2. This interface reflects this, /* In practice, "steps" is always 2. This interface reflects this,
and will need to be changed if "steps" can change. */ and will need to be changed if "steps" can change. */
result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i, result = tree_mod_subtract (stmt, op, op1, op2, prob1, prob2, i,
histogram->hvalue.counters[0], count1, count2, all);
histogram->hvalue.counters[1], all);
GIMPLE_STMT_OPERAND (modify, 1) = result; GIMPLE_STMT_OPERAND (modify, 1) = result;
...@@ -826,7 +1107,6 @@ tree_stringops_transform (block_stmt_iterator *bsi) ...@@ -826,7 +1107,6 @@ tree_stringops_transform (block_stmt_iterator *bsi)
tree arglist; tree arglist;
tree blck_size; tree blck_size;
enum built_in_function fcode; enum built_in_function fcode;
stmt_ann_t ann = get_stmt_ann (stmt);
histogram_value histogram; histogram_value histogram;
gcov_type count, all, val; gcov_type count, all, val;
tree value; tree value;
...@@ -852,26 +1132,18 @@ tree_stringops_transform (block_stmt_iterator *bsi) ...@@ -852,26 +1132,18 @@ tree_stringops_transform (block_stmt_iterator *bsi)
if (TREE_CODE (blck_size) == INTEGER_CST) if (TREE_CODE (blck_size) == INTEGER_CST)
return false; return false;
if (!ann->histograms) histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
return false;
all = bb_for_stmt (stmt)->count;
if (!all)
return false;
for (histogram = ann->histograms; histogram;
histogram = histogram->hvalue.next)
if (histogram->type == HIST_TYPE_SINGLE_VALUE)
break;
if (!histogram) if (!histogram)
return false; return false;
value = histogram->hvalue.value; value = histogram->hvalue.value;
val = histogram->hvalue.counters[0]; val = histogram->hvalue.counters[0];
count = histogram->hvalue.counters[1]; count = histogram->hvalue.counters[1];
all = histogram->hvalue.counters[2]; all = histogram->hvalue.counters[2];
gimple_remove_histogram_value (cfun, stmt, histogram);
/* We require that count is at least half of all; this means /* We require that count is at least half of all; this means
that for the transformation to fire the value must be constant that for the transformation to fire the value must be constant
at least 80% of time. */ at least 80% of time. */
if ((6 * count / 5) < all) if ((6 * count / 5) < all || !maybe_hot_bb_p (bb_for_stmt (stmt)))
return false; return false;
if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count)) if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
return false; return false;
...@@ -957,33 +1229,26 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values) ...@@ -957,33 +1229,26 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values)
VEC_reserve (histogram_value, heap, *values, 3); VEC_reserve (histogram_value, heap, *values, 3);
if (is_gimple_reg (divisor)) if (is_gimple_reg (divisor))
{ /* 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. */ VEC_quick_push (histogram_value, *values,
hist = ggc_alloc (sizeof (*hist)); gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
hist->hvalue.value = divisor; stmt, divisor));
hist->hvalue.stmt = stmt;
hist->type = HIST_TYPE_SINGLE_VALUE;
VEC_quick_push (histogram_value, *values, hist);
}
/* 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 (rhs) == TRUNC_MOD_EXPR if (TREE_CODE (rhs) == TRUNC_MOD_EXPR
&& TYPE_UNSIGNED (type)) && TYPE_UNSIGNED (type))
{ {
tree val;
/* Check for a special case where the divisor is power of 2. */ /* Check for a special case where the divisor is power of 2. */
hist = ggc_alloc (sizeof (*hist)); VEC_quick_push (histogram_value, *values,
hist->hvalue.value = divisor; gimple_alloc_histogram_value (cfun, HIST_TYPE_POW2,
hist->hvalue.stmt = stmt; stmt, divisor));
hist->type = HIST_TYPE_POW2;
VEC_quick_push (histogram_value, *values, hist);
hist = ggc_alloc (sizeof (*hist)); val = build2 (TRUNC_DIV_EXPR, type, op0, divisor);
hist->hvalue.stmt = stmt; hist = gimple_alloc_histogram_value (cfun, HIST_TYPE_INTERVAL,
hist->hvalue.value stmt, val);
= build2 (TRUNC_DIV_EXPR, type, op0, divisor);
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;
VEC_quick_push (histogram_value, *values, hist); VEC_quick_push (histogram_value, *values, hist);
...@@ -996,7 +1261,7 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values) ...@@ -996,7 +1261,7 @@ tree_divmod_values_to_profile (tree stmt, histogram_values *values)
} }
/* Find values inside STMT for that we want to measure histograms for /* Find values inside STMT for that we want to measure histograms for
division/modulo optimization. */ string operations. */
static void static void
tree_stringops_values_to_profile (tree stmt, histogram_values *values) tree_stringops_values_to_profile (tree stmt, histogram_values *values)
{ {
...@@ -1005,7 +1270,6 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values) ...@@ -1005,7 +1270,6 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values)
tree arglist; tree arglist;
tree blck_size; tree blck_size;
enum built_in_function fcode; enum built_in_function fcode;
histogram_value hist;
if (!call) if (!call)
return; return;
...@@ -1024,14 +1288,9 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values) ...@@ -1024,14 +1288,9 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values)
blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
if (TREE_CODE (blck_size) != INTEGER_CST) if (TREE_CODE (blck_size) != INTEGER_CST)
{ VEC_safe_push (histogram_value, heap, *values,
VEC_reserve (histogram_value, heap, *values, 3); gimple_alloc_histogram_value (cfun, HIST_TYPE_SINGLE_VALUE,
hist = ggc_alloc (sizeof (*hist)); stmt, blck_size));
hist->hvalue.value = blck_size;
hist->hvalue.stmt = stmt;
hist->type = HIST_TYPE_SINGLE_VALUE;
VEC_quick_push (histogram_value, *values, hist);
}
} }
/* Find values inside STMT for that we want to measure histograms and adds /* Find values inside STMT for that we want to measure histograms and adds
...@@ -1053,7 +1312,7 @@ tree_find_values_to_profile (histogram_values *values) ...@@ -1053,7 +1312,7 @@ tree_find_values_to_profile (histogram_values *values)
basic_block bb; basic_block bb;
block_stmt_iterator bsi; block_stmt_iterator bsi;
unsigned i; unsigned i;
histogram_value hist; histogram_value hist = NULL;
*values = NULL; *values = NULL;
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
...@@ -1065,52 +1324,30 @@ tree_find_values_to_profile (histogram_values *values) ...@@ -1065,52 +1324,30 @@ tree_find_values_to_profile (histogram_values *values)
switch (hist->type) switch (hist->type)
{ {
case HIST_TYPE_INTERVAL: case HIST_TYPE_INTERVAL:
if (dump_file)
{
fprintf (dump_file, "Interval counter for tree ");
print_generic_expr (dump_file, hist->hvalue.stmt,
TDF_SLIM);
fprintf (dump_file, ", range %d -- %d.\n",
hist->hdata.intvl.int_start,
(hist->hdata.intvl.int_start
+ hist->hdata.intvl.steps - 1));
}
hist->n_counters = hist->hdata.intvl.steps + 2; hist->n_counters = hist->hdata.intvl.steps + 2;
break; break;
case HIST_TYPE_POW2: case HIST_TYPE_POW2:
if (dump_file)
{
fprintf (dump_file, "Pow2 counter for tree ");
print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
fprintf (dump_file, ".\n");
}
hist->n_counters = 2; hist->n_counters = 2;
break; break;
case HIST_TYPE_SINGLE_VALUE: case HIST_TYPE_SINGLE_VALUE:
if (dump_file)
{
fprintf (dump_file, "Single value counter for tree ");
print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
fprintf (dump_file, ".\n");
}
hist->n_counters = 3; hist->n_counters = 3;
break; break;
case HIST_TYPE_CONST_DELTA: case HIST_TYPE_CONST_DELTA:
if (dump_file)
{
fprintf (dump_file, "Constant delta counter for tree ");
print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
fprintf (dump_file, ".\n");
}
hist->n_counters = 4; hist->n_counters = 4;
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
if (dump_file)
{
fprintf (dump_file, "Stmt ");
print_generic_expr (dump_file, hist->hvalue.stmt, TDF_SLIM);
dump_histogram_value (dump_file, hist);
}
} }
} }
......
...@@ -96,6 +96,17 @@ struct profile_hooks { ...@@ -96,6 +96,17 @@ struct profile_hooks {
void (*gen_const_delta_profiler) (histogram_value, unsigned, unsigned); void (*gen_const_delta_profiler) (histogram_value, unsigned, unsigned);
}; };
histogram_value gimple_histogram_value (struct function *, tree);
histogram_value gimple_histogram_value_of_type (struct function *, tree, enum hist_type);
void gimple_add_histogram_value (struct function *, tree, histogram_value);
void gimple_remove_histogram_value (struct function *, tree, histogram_value);
void dump_histograms_for_stmt (struct function *, FILE *, tree);
void gimple_remove_histogram_value (struct function *, tree, histogram_value);
void gimple_remove_stmt_histograms (struct function *, tree);
void gimple_duplicate_stmt_histograms (struct function *, tree, struct function *, tree);
void verify_histograms (void);
void free_histograms (void);
/* In profile.c. */ /* In profile.c. */
extern void init_branch_prob (void); extern void init_branch_prob (void);
extern void branch_prob (void); extern void branch_prob (void);
......
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