*/
FIRM_API void find_callgraph_recursions(void);
-/** Compute interprocedural performance estimates.
- *
- * Computes
- * - the loop depth of the method.
- * The loop depth of an edge between two methods is the
- * maximal loop depth of the Call nodes that call along this edge.
- * The loop depth of the method is the loop depth of the most expensive
- * path from main().
- * - The recursion depth. The maximal number of recursions passed
- * on all paths reaching this method.
- * - The execution frequency. As loop depth, but the edge weight is the sum
- * of the execution frequencies of all Calls along the edge.
- *
- * Expects the main irg is set, see set_irp_main_irg();
- **/
-FIRM_API void compute_performance_estimates(void);
-
/** Computes the interprocedural loop nesting information.
*
* Computes two numbers for each irg: the depth it is called in 'normal'
+++ /dev/null
-/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief Compute an estimate of basic block executions.
- * @author Goetz Lindenmaier
- * @date 5.11.2004
- * @version $Id$
- * @brief
- * We assume the start block of a procedure is executed once. Based on this we
- * compute the execution freqency of all blocks.
- *
- * The computation of the frequencies depends on the count of exception control
- * flow computed during the interval analysis. The interval analysis again
- * depends on stuff computed here.
- */
-#ifndef FIRM_ANA_EXECUTION_FREQUENCY_H
-#define FIRM_ANA_EXECUTION_FREQUENCY_H
-
-#include "firm_types.h"
-#include "begin.h"
-
-/** A proj from a Cond that goes to an exception handler. */
-FIRM_API int is_fragile_Proj(ir_node *n);
-
-/** Returns the number of times the block/region is executed according to
- * our estimate. Gives a number relative to the Start node of the procedure
- * the block is in, which is weighted with 1. */
-FIRM_API double get_irn_exec_freq(ir_node *n);
-FIRM_API double get_Block_exec_freq(ir_node *b);
-FIRM_API double get_region_exec_freq(void *reg);
-
-/** Compute the execution frequency for all blocks in the given
- * graph.
- *
- * @param irg The graph to be analyzed.
- * @param default_loop_weight The default number of executions of a loop.
- * @param exception_probability The probability that a fragile operation causes an exception.
- *
- * Uses link field.
- */
-FIRM_API void compute_execution_frequency(ir_graph *irg, int default_loop_weight, double exception_probability);
-
-/** Compute the execution frequency for all graphs.
- *
- * @param default_loop_weight The default number of executions of a loop.
- * @param exception_probability The probability that a fragile operation causes an exception.
- *
- */
-FIRM_API void compute_execution_frequencies(int default_loop_weight, double exception_probability);
-
-/** Free occupied memory, reset for all graphs. */
-FIRM_API void free_execution_frequency(void);
-
-/** State of execution frequencies for graphs and the whole program.
- *
- * The exec_freq_state in irp is consistent, if the state of all graphs is consistent.
- * It is none, if the state of all graphs is none. Else it is inconsistent. */
-typedef enum {
- exec_freq_none, /**< Execution frequencies are not computed, no
- memory is allocaaccess fails. */
- exec_freq_consistent, /**< Execution frequency information is computed and
- correct. */
- exec_freq_inconsistent /**< Execution frequency is computed but the graph
- has been changed since. */
-} exec_freq_state;
-
-FIRM_API exec_freq_state get_irg_exec_freq_state(ir_graph *irg);
-FIRM_API void set_irg_exec_freq_state(ir_graph *irg,
- exec_freq_state s);
-/**
- * Sets irg and irp exec freq state to inconsistent if it is set to consistent.
- */
-FIRM_API void set_irg_exec_freq_state_inconsistent(ir_graph *irg);
-
-FIRM_API exec_freq_state get_irp_exec_freq_state(void);
-/**
- * Sets irp and all irg exec freq states to inconsistent if it is set to
- * consistent.
- */
-FIRM_API void set_irp_exec_freq_state_inconsistent(void);
-
-#include "end.h"
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief Compute an estimate of field temperature, i.e., field access heuristic.
- * @author Goetz Lindenmaier
- * @date 21.7.2004
- * @version $Id$
- * @note
- * Watch it! This is highly java dependent.
- *
- * - All Sel nodes get an array with possibly accessed entities.
- * (resolve polymorphy on base of inherited entities.)
- * (the mentioned entity in first approximation.)
- *
- * - We compute a value for the entity based on the Sel nodes.
- */
-#ifndef FIRM_ANA_FIELD_TEMPERATURE_H
-#define FIRM_ANA_FIELD_TEMPERATURE_H
-
-#include "firm_types.h"
-
-#include "begin.h"
-
-/** The number of array elements we assume if not both bounds are given. */
-#define DEFAULT_N_ARRAY_ELEMENTS 1
-
-FIRM_API int get_irn_loop_call_depth(ir_node *n);
-/** Return loop depth of node.
- *
- * Returns the loop depth of n in the control flow. I.e., we
- * go from the node to the block to the loop the block is in,
- * and return its depth. */
-FIRM_API int get_irn_cfloop_depth(ir_node *n);
-FIRM_API int get_irn_recursion_depth(ir_node *n);
-
-/**
- * Get the weighted interprocedural loop depth of the node.
- * The depth is estimated by a heuristic. The heuristic considers
- * loop and recursion depth.
- */
-FIRM_API int get_weighted_loop_depth(ir_node *n);
-
-/** Heuristic merging recursion and loop depth. */
-FIRM_API double get_irn_final_cost(ir_node *n);
-
-/** Get accumulated(really?) execution frequencies.
- * A heuristic weights the recursions. */
-FIRM_API double get_type_estimated_n_instances(ir_type *clss);
-FIRM_API double get_type_estimated_mem_consumption_bytes(ir_type *tp);
-
-/** Estimates the size of an object.
- *
- * The heuristic mainly affects array sizes.
- * Further this ignores padding for alignment, especially of small fields. */
-FIRM_API int get_type_estimated_size_bytes(ir_type *tp);
-/** Estimates the number of fields of a single Object.
- * The heuristic mainly affects array sizes.
- * @@@ Misses inherited fields! */
-FIRM_API int get_type_estimated_n_fields(ir_type *tp);
-FIRM_API double get_type_estimated_n_casts(ir_type *clss);
-
-FIRM_API double get_class_estimated_n_upcasts(ir_type *clss);
-FIRM_API double get_class_estimated_n_downcasts(ir_type *clss);
-
-/**
- * Returns the number of accesses to the dispatch table.
- *
- * This includes the initialization of the pointer field, and accesses
- * to virtual fields (as instance marker in Java). Certainly this
- * includes virtual method calls.
- */
-FIRM_API double get_class_estimated_n_dyncalls(ir_type *clss);
-/** Returns the number of writes to the dispatch pointer.
- * This is the same as the number of allocations. */
-FIRM_API double get_class_estimated_dispatch_writes(ir_type *clss);
-/** Returns the number of reads of the dispatch pointer. */
-FIRM_API double get_class_estimated_dispatch_reads (ir_type *clss);
-
-FIRM_API double get_entity_estimated_n_loads(ir_entity *ent);
-FIRM_API double get_entity_estimated_n_stores(ir_entity *ent);
-FIRM_API double get_entity_estimated_n_calls(ir_entity *ent);
-
-/**
- * The number of accesses to dynamically called methods and
- * to other static fields that overwrite/are overwritten.
- */
-FIRM_API double get_entity_estimated_n_dyncalls(ir_entity *ent);
-
-typedef enum {
- temperature_none,
- temperature_consistent,
- temperature_inconsistent
-} irp_temperature_state;
-
-#include "end.h"
-
-#endif
#include "cgana.h"
#include "dbginfo.h"
#include "execfreq.h"
-#include "execution_frequency.h"
-#include "field_temperature.h"
#include "firm_common.h"
#include "firmstat.h"
#include "firm_types.h"
#include "irnode_t.h"
#include "cgana.h"
-#include "execution_frequency.h"
#include "array.h"
#include "pmap.h"
return irg->callees ? irg->callees[pos]->max_depth : 0;
}
-static double get_irg_callee_execution_frequency(const ir_graph *irg, size_t pos)
-{
- ir_node **arr = irg->callees[pos]->call_list;
- size_t i, n_Calls = ARR_LEN(arr);
- double freq = 0.0;
-
- for (i = 0; i < n_Calls; ++i) {
- freq += get_irn_exec_freq(arr[i]);
- }
- return freq;
-}
-
-static double get_irg_callee_method_execution_frequency(const ir_graph *irg,
- size_t pos)
-{
- double call_freq = get_irg_callee_execution_frequency(irg, pos);
- double meth_freq = get_irg_method_execution_frequency(irg);
- return call_freq * meth_freq;
-}
-
-static double get_irg_caller_method_execution_frequency(const ir_graph *irg,
- size_t pos)
-{
- ir_graph *caller = get_irg_caller(irg, pos);
- size_t pos_callee = reverse_pos(irg, pos);
-
- return get_irg_callee_method_execution_frequency(caller, pos_callee);
-}
-
/* --------------------- Compute the callgraph ------------------------ */
}
}
-/* ----------------------------------------------------------------------------------- */
-/* Another algorithm to compute recursion nesting depth */
-/* Walk the callgraph. For each crossed edge increase the loop depth by the edge */
-/* weight. Assign graphs the maximal depth. */
-/* ----------------------------------------------------------------------------------- */
-
-static void compute_loop_depth(ir_graph *irg, void *env)
-{
- size_t current_nesting = *(size_t *) env;
- size_t old_nesting = irg->callgraph_loop_depth;
- ir_visited_t old_visited = get_cg_irg_visited(irg);
-
- if (cg_irg_visited(irg)) return;
-
- mark_cg_irg_visited(irg);
-
- if (old_nesting < current_nesting)
- irg->callgraph_loop_depth = current_nesting;
-
- if (current_nesting > irp->max_callgraph_loop_depth)
- irp->max_callgraph_loop_depth = current_nesting;
-
- if ((old_visited +1 < get_cg_irg_visited(irg)) || /* not yet visited */
- (old_nesting < current_nesting)) { /* propagate larger nesting */
- size_t i, n_callees;
-
- /* Don't walk the graph, but a tree that is an unfolded graph. */
- n_callees = get_irg_n_callees(irg);
- for (i = 0; i < n_callees; ++i) {
- ir_graph *m = get_irg_callee(irg, i);
- *(size_t *)env += get_irg_callee_loop_depth(irg, i);
- compute_loop_depth(m, env);
- *(size_t *)env -= get_irg_callee_loop_depth(irg, i);
- }
- }
-
- set_cg_irg_visited(irg, master_cg_visited-1);
-}
-
-/* ------------------------------------------------------------------------------------ */
-/* Another algorithm to compute recursion nesting depth */
-/* Walk the callgraph. For each crossed loop increase the nesting depth by one. */
-/* Assign graphs the maximal nesting depth. Don't increase if passing loops more than */
-/* once. */
-/* ------------------------------------------------------------------------------------ */
-
-
-/* For callees, we want to remember the Call nodes, too. */
-typedef struct ana_entry2 {
- ir_loop **loop_stack; /**< a stack of ir_loop entries */
- size_t tos; /**< the top of stack entry */
- size_t recursion_nesting;
-} ana_entry2;
-
-/**
- * push a loop entry on the stack
- */
-static void push2(ana_entry2 *e, ir_loop *g)
-{
- if (ARR_LEN(e->loop_stack) == e->tos) {
- ARR_APP1(ir_loop *, e->loop_stack, g);
- } else {
- e->loop_stack[e->tos] = g;
- }
- ++e->tos;
-}
-
-/**
- * returns the top of stack and pop it
- */
-static ir_loop *pop2(ana_entry2 *e)
-{
- return e->loop_stack[--e->tos];
-}
-
-/**
- * check if a loop g in on the stack. Did not check the TOS.
- */
-static int in_stack(ana_entry2 *e, ir_loop *g)
-{
- size_t i;
- for (i = e->tos; i != 0;) {
- if (e->loop_stack[--i] == g) return 1;
- }
- return 0;
-}
-
-static void compute_rec_depth(ir_graph *irg, void *env)
-{
- ana_entry2 *e = (ana_entry2 *)env;
- ir_loop *l = irg->l;
- size_t depth, old_depth = irg->callgraph_recursion_depth;
- int pushed = 0;
-
- if (cg_irg_visited(irg))
- return;
- mark_cg_irg_visited(irg);
-
- /* -- compute and set the new nesting value -- */
- if ((l != irp->outermost_cg_loop) && !in_stack(e, l)) {
- push2(e, l);
- ++e->recursion_nesting;
- pushed = 1;
- }
- depth = e->recursion_nesting;
-
- if (old_depth < depth)
- irg->callgraph_recursion_depth = depth;
-
- if (depth > irp->max_callgraph_recursion_depth)
- irp->max_callgraph_recursion_depth = depth;
-
- /* -- spread the nesting value -- */
- if (depth == 0 || old_depth < depth) {
- size_t i, n_callees;
-
- /* Don't walk the graph, but a tree that is an unfolded graph.
- Therefore we unset the visited flag at the end. */
- n_callees = get_irg_n_callees(irg);
- for (i = 0; i < n_callees; ++i) {
- ir_graph *m = get_irg_callee(irg, i);
- compute_rec_depth(m, env);
- }
- }
-
- /* -- clean up -- */
- if (pushed) {
- pop2(e);
- --e->recursion_nesting;
- }
- set_cg_irg_visited(irg, master_cg_visited-1);
-}
-
-
-/* ----------------------------------------------------------------------------------- */
-/* Another algorithm to compute the execution frequency of methods ignoring recursions. */
-/* Walk the callgraph. Ignore backedges. Use sum of execution frequencies of Call */
-/* nodes to evaluate a callgraph edge. */
-/* ----------------------------------------------------------------------------------- */
-
-/* Returns the method execution frequency of a graph. */
-double get_irg_method_execution_frequency(const ir_graph *irg)
-{
- return irg->method_execution_frequency;
-}
-
-/**
- * Increase the method execution frequency to freq if its current value is
- * smaller then this.
- */
-static void set_irg_method_execution_frequency(ir_graph *irg, double freq)
-{
- irg->method_execution_frequency = freq;
-
- if (irp->max_method_execution_frequency < freq)
- irp->max_method_execution_frequency = freq;
-}
-
-static void compute_method_execution_frequency(ir_graph *irg, void *env)
-{
- size_t i, n_callers;
- double freq;
- int found_edge;
- size_t n_callees;
- (void) env;
-
- if (cg_irg_visited(irg))
- return;
-
- /* We need the values of all predecessors (except backedges).
- So they must be marked. Else we will reach the node through
- one of the unmarked ones. */
- n_callers = get_irg_n_callers(irg);
- for (i = 0; i < n_callers; ++i) {
- ir_graph *m = get_irg_caller(irg, i);
- if (is_irg_caller_backedge(irg, i))
- continue;
- if (!cg_irg_visited(m)) {
- return;
- }
- }
- mark_cg_irg_visited(irg);
-
- /* Compute the new frequency. */
- freq = 0;
- found_edge = 0;
- for (i = 0; i < n_callers; ++i) {
- if (! is_irg_caller_backedge(irg, i)) {
- double edge_freq = get_irg_caller_method_execution_frequency(irg, i);
- assert(edge_freq >= 0);
- freq += edge_freq;
- found_edge = 1;
- }
- }
-
- if (!found_edge) {
- /* A starting point: method only called from outside,
- or only backedges as predecessors. */
- freq = 1;
- }
-
- set_irg_method_execution_frequency(irg, freq);
-
- /* recur */
- n_callees = get_irg_n_callees(irg);
- for (i = 0; i < n_callees; ++i) {
- compute_method_execution_frequency(get_irg_callee(irg, i), NULL);
- }
-}
-
-
/* ----------------------------------------------------------------------------------- */
/* The recursion stuff driver. */
/* ----------------------------------------------------------------------------------- */
irp->callgraph_state = irp_callgraph_and_calltree_consistent;
}
-/* Compute interprocedural performance estimates. */
-void compute_performance_estimates(void)
-{
- size_t i, n_irgs = get_irp_n_irgs();
- size_t current_nesting;
- ana_entry2 e;
-
- assert(get_irp_exec_freq_state() != exec_freq_none && "execution frequency not calculated");
-
- /* -- compute the loop depth -- */
- current_nesting = 0;
- irp->max_callgraph_loop_depth = 0;
- master_cg_visited += 2;
- compute_loop_depth(get_irp_main_irg(), ¤t_nesting);
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if ((get_cg_irg_visited(irg) < master_cg_visited-1) &&
- get_irg_n_callers(irg) == 0) {
- compute_loop_depth(irg, ¤t_nesting);
- }
- }
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if (get_cg_irg_visited(irg) < master_cg_visited-1) {
- compute_loop_depth(irg, ¤t_nesting);
- }
- }
-
-
- /* -- compute the recursion depth -- */
- e.loop_stack = NEW_ARR_F(ir_loop *, 0);
- e.tos = 0;
- e.recursion_nesting = 0;
-
- irp->max_callgraph_recursion_depth = 0;
-
- master_cg_visited += 2;
- compute_rec_depth(get_irp_main_irg(), &e);
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if ((get_cg_irg_visited(irg) < master_cg_visited-1) &&
- get_irg_n_callers(irg) == 0) {
- compute_rec_depth(irg, &e);
- }
- }
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if (get_cg_irg_visited(irg) < master_cg_visited-1) {
- compute_rec_depth(irg, &e);
- }
- }
-
- DEL_ARR_F(e.loop_stack);
-
- /* -- compute the execution frequency -- */
- irp->max_method_execution_frequency = 0;
- master_cg_visited += 2;
- assert(get_irg_n_callers(get_irp_main_irg()) == 0);
- compute_method_execution_frequency(get_irp_main_irg(), NULL);
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if ((get_cg_irg_visited(irg) < master_cg_visited-1) &&
- get_irg_n_callers(irg) == 0) {
- compute_method_execution_frequency(irg, NULL);
- }
- }
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if (get_cg_irg_visited(irg) < master_cg_visited-1) {
- compute_method_execution_frequency(irg, NULL);
- }
- }
-}
-
/* Returns the maximal loop depth of all paths from an external visible method to
this irg. */
size_t get_irg_loop_depth(const ir_graph *irg)
find_callgraph_recursions();
- compute_performance_estimates();
-
set_irp_loop_nesting_depth_state(loop_nesting_depth_consistent);
}
+++ /dev/null
-/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief Compute an estimate of basic block executions.
- * @author Goetz Lindenmaier
- * @date 5.11.2004
- * @version $Id$
- */
-#include "config.h"
-
-#include "execution_frequency.h"
-
-#include "set.h"
-#include "pdeq.h"
-#include "hashptr.h"
-#include "error.h"
-
-#include "irprog_t.h"
-#include "irgraph_t.h"
-#include "irnode_t.h"
-#include "irloop.h"
-#include "irgwalk.h"
-
-#include "interval_analysis.h"
-
-void set_irp_exec_freq_state(exec_freq_state s);
-
-/*------------------------------------------------------------------*/
-/* A hashmap mapping the frequency to block and loop nodes. Block
- * and loop nodes are regions. */
-/*------------------------------------------------------------------*/
-
-typedef struct {
- void *reg;
- double freq;
- int prob;
-} reg_exec_freq;
-
-/* We use this set for all nodes in all irgraphs. */
-static set *exec_freq_set = NULL;
-
-static int exec_freq_cmp(const void *e1, const void *e2, size_t size)
-{
- reg_exec_freq *ef1 = (reg_exec_freq *)e1;
- reg_exec_freq *ef2 = (reg_exec_freq *)e2;
- (void) size;
-
- return (ef1->reg != ef2->reg);
-}
-
-static inline unsigned int exec_freq_hash(reg_exec_freq *e)
-{
- return HASH_PTR(e->reg);
-}
-
-static inline void set_region_exec_freq(void *reg, double freq)
-{
- reg_exec_freq ef;
- ef.reg = reg;
- ef.freq = freq;
- set_insert(exec_freq_set, &ef, sizeof(ef), exec_freq_hash(&ef));
-}
-
-double get_region_exec_freq(void *reg)
-{
- reg_exec_freq ef, *found;
- ef.reg = reg;
- assert(exec_freq_set);
-
- found = (reg_exec_freq*) set_find(exec_freq_set, &ef, sizeof(ef), exec_freq_hash(&ef));
-
- /* Not found if information is invalid. */
- if (found)
- return found->freq;
- else
- return 0;
-}
-
-/* Returns the number of times the block is executed. */
-double get_Block_exec_freq(ir_node *b)
-{
- return get_region_exec_freq((void *)b);
-}
-
-double get_irn_exec_freq(ir_node *n)
-{
- if (!is_Block(n)) n = get_nodes_block(n);
- return get_Block_exec_freq(n);
-}
-
-
-/*------------------------------------------------------------------*/
-/* A algorithm that precomputes whether Conds lead to an exception.
- * Computes a field for all Projs from Conds that says the following:
- * - The Proj projs from a normal dual Cond with probability 50:50
- * - This Proj of the Cond leads to an exception, i.e., a raise node.
- * It is taken with exception probability.
- * - The Proj of the Cond avoids an exception. It is taken with
- * 1 - exception probability. */
-/*------------------------------------------------------------------*/
-
-#include "irouts.h"
-
-typedef enum {
- Cond_prob_none,
- Cond_prob_normal,
- Cond_prob_avoid_exception,
- Cond_prob_exception_taken,
- Cond_prob_was_exception_taken,
-} Cond_prob;
-
-static int just_passed_a_Raise = 0;
-static ir_node *Cond_list = NULL;
-
-/* We do not use an extra set, as Projs are not yet in the existing one. */
-static void set_ProjX_probability(ir_node *n, Cond_prob prob)
-{
- reg_exec_freq ef;
- ef.reg = n;
- ef.prob = prob;
- set_insert(exec_freq_set, &ef, sizeof(ef), exec_freq_hash(&ef));
-}
-
-static Cond_prob get_ProjX_probability(ir_node *n)
-{
- reg_exec_freq ef, *found;
- ef.reg = n;
-
- found = (reg_exec_freq*) set_find(exec_freq_set, &ef, sizeof(ef), exec_freq_hash(&ef));
-
- if (found)
- return (Cond_prob)found->prob;
- else
- return Cond_prob_none;
-}
-
-/* A walker that only visits the nodes we want to see. */
-
-static void my_irg_walk_2_both(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void * env)
-{
- int i;
- set_irn_visited(node, current_ir_graph->visited);
-
- pre(node, env);
-
- if (!is_Block(node)) {
- ir_node *pred;
- if (is_Proj(node))
- pred = get_irn_n(node, 0);
- else
- pred = get_irn_n(node, -1);
- if (pred->visited < current_ir_graph->visited)
- my_irg_walk_2_both(pred, pre, post, env);
- }
-
- else { /* a Block */
- for (i = get_irn_arity(node) - 1; i >= 0; --i) {
- ir_node *pred = get_irn_n(node, i);
- if (pred->visited < current_ir_graph->visited)
- my_irg_walk_2_both(pred, pre, post, env);
- }
- }
-
- if (is_End(node)) {
- for (i = get_irn_arity(node) - 1; i >= 0; --i) {
- ir_node *pred = get_irn_n(node, i);
- if ((pred->op == op_Block) && (pred->visited < current_ir_graph->visited))
- my_irg_walk_2_both(pred, pre, post, env);
- }
- }
-
- post(node, env);
-}
-static void my_irg_walk_current_graph(irg_walk_func *pre, irg_walk_func *post, void *env)
-{
- inc_irg_visited(current_ir_graph);
- my_irg_walk_2_both(get_irg_end(current_ir_graph), pre, post, env);
-}
-
-
-static void walk_pre(ir_node *n, void *env)
-{
- (void) env;
- if (is_Raise(n))
- just_passed_a_Raise = 1;
-
- if (get_irn_op(n) == op_Proj &&
- is_Cond(get_Proj_pred(n)) &&
- just_passed_a_Raise) {
- ir_node *other_proj;
- ir_node *c = get_Proj_pred(n);
-
- /* If we already visited the other Proj, and it also leads to a Raise,
- we are in the middle of something. Continue searching. */
- assert(get_irn_n_outs(c) == 2 && "encountered a switch cond");
- other_proj = get_irn_out(c, 0);
- if (other_proj == n) other_proj = get_irn_out(c, 1);
- if (get_ProjX_probability(other_proj) == Cond_prob_exception_taken) {
- set_ProjX_probability(other_proj, Cond_prob_was_exception_taken);
- /* Keep searching for the Proj, so keep just_passed_a_Raise. */
- } else {
- set_ProjX_probability(n, Cond_prob_exception_taken);
- just_passed_a_Raise = 0;
- }
- }
-
- if (is_Cond(n)) {
- set_irn_link(n, Cond_list);
- Cond_list = n;
- }
-}
-
-static void walk_post(ir_node *n, void *env)
-{
- (void) env;
- if (is_Raise(n))
- just_passed_a_Raise = 0;
-
- if (get_irn_op(n) == op_Proj &&
- is_Cond(get_Proj_pred(n)) && (
- get_ProjX_probability(n) == Cond_prob_exception_taken ||
- get_ProjX_probability(n) == Cond_prob_was_exception_taken
- )) {
- just_passed_a_Raise = 1;
- }
-}
-
-/** Precompute which Conds test for an exception.
- *
- * Operates on current_ir_graph. */
-static void precompute_cond_evaluation(void)
-{
- ir_node *c;
-
- compute_irg_outs(current_ir_graph);
-
- just_passed_a_Raise = 0;
- Cond_list = NULL;
- my_irg_walk_current_graph(walk_pre, walk_post, NULL);
-
- for (c = Cond_list; c; c = (ir_node*)get_irn_link(c)) {
- ir_node *p0, *p1;
-
- assert(get_irn_n_outs(c) == 2 && "encountered a switch cond");
- p0 = get_irn_out(c, 0);
- p1 = get_irn_out(c, 1);
-
- /* both are exceptions */
- if ((get_ProjX_probability(p0) == Cond_prob_exception_taken) &&
- (get_ProjX_probability(p1) == Cond_prob_exception_taken) ) {
- panic("I tried to avoid these!");
-#if 0
- /* It's a */
- set_ProjX_probability(p0, Cond_prob_normal);
- set_ProjX_probability(p1, Cond_prob_normal);
-#endif
- }
-
- /* p0 is exception */
- else if (get_ProjX_probability(p0) == Cond_prob_exception_taken) {
- set_ProjX_probability(p1, Cond_prob_avoid_exception);
- }
-
- /* p1 is exception */
- else if (get_ProjX_probability(p1) == Cond_prob_exception_taken) {
- set_ProjX_probability(p0, Cond_prob_avoid_exception);
- }
-
- /* none is exception */
- else {
- set_ProjX_probability(p0, Cond_prob_normal);
- set_ProjX_probability(p1, Cond_prob_normal);
- }
- }
-}
-
-int is_fragile_Proj(ir_node *n)
-{
- return is_Proj(n) && (get_ProjX_probability(n) == Cond_prob_exception_taken);
-}
-
-/*------------------------------------------------------------------*/
-/* The algorithm to compute the execution frequencies.
- *
- * Walk the control flow loop tree which we consider the interval
- * tree. Compute the execution for the lowest loop, add inner loops
- * to worklist. Consider the inner loops as simple nodes. Check that
- * there is only one loop header in each loop. */
-/*------------------------------------------------------------------*/
-
-static double exception_prob = 0.001;
-
-static inline int is_loop_head(ir_node *cond)
-{
- (void) cond;
- return 0;
-}
-
-/** Weight a single region in edge.
- *
- * Given all outs of the predecessor region, we can compute the weight of
- * this single edge. */
-static inline double get_weighted_region_exec_freq(void *reg, int pos)
-{
- void *pred_reg = get_region_in(reg, pos);
- double res, full_freq = get_region_exec_freq (pred_reg);
- int n_outs = get_region_n_outs (pred_reg);
- int n_exc_outs = get_region_n_exc_outs(pred_reg);
-
- ir_node *cfop;
- if (is_ir_node(reg)) {
- cfop = get_Block_cfgpred((ir_node *)reg, pos);
- if (is_Proj(cfop) && !is_Cond(get_Proj_pred(cfop)))
- cfop = skip_Proj(cfop);
- } else {
- assert(is_ir_loop(reg));
- cfop = (ir_node*)get_loop_cfop(reg, pos);
- }
-
- if (is_fragile_op(cfop) || is_fragile_Proj(cfop)) {
- res = full_freq * exception_prob;
- } else {
-
- /* Equally distribute the weight after exceptions to the left over outs. */
- res = (full_freq *(1 - exception_prob * n_exc_outs)) / (n_outs - n_exc_outs);
- }
-
- return res;
-}
-
-static inline void compute_region_freqency(void *reg, double head_weight)
-{
- int i, n_ins = get_region_n_ins(reg);
- double my_freq = 0;
-
- for (i = 0; i < n_ins; ++i) {
- void *pred_reg = get_region_in(reg, i);
- if (pred_reg) {
- my_freq += get_weighted_region_exec_freq(reg, i);
- }
- }
-
- if (my_freq == 0.0) {
- /* All preds are from outer loop. We are a head or so. */
- my_freq = head_weight;
- }
- set_region_exec_freq(reg, my_freq);
-}
-
-static void check_proper_head(ir_loop *l, void *reg)
-{
- int i, n_ins = get_region_n_ins(reg);
- (void) l;
- for (i = 0; i < n_ins; ++i) {
- assert(!get_region_in(reg, i));
- }
-}
-
-/* Compute the ex freq for current_ir_graph */
-static void compute_frequency(int default_loop_weight)
-{
- ir_loop *outermost_l = get_irg_loop(current_ir_graph);
- pdeq *block_worklist = new_pdeq1(outermost_l);
-
- /* Outermost start is considered a loop head. We will soon multiply
- by default_loop_weight. */
- set_region_exec_freq(outermost_l, 1.0/default_loop_weight);
-
- while (!pdeq_empty(block_worklist)) {
- ir_loop *l = (ir_loop *)pdeq_getl(block_worklist);
- size_t i, n_elems = get_loop_n_elements(l);
-
- /* The header is initialized with the frequency of the full loop times the iteration weight. */
- check_proper_head(l, get_loop_element(l, 0).son);
-
- for (i = 0; i < n_elems; ++i) {
- loop_element e = get_loop_element(l, i);
- if (is_ir_loop(e.son)) pdeq_putr(block_worklist, e.son);
- compute_region_freqency(e.son, default_loop_weight * get_region_exec_freq(l));
- }
- }
- del_pdeq(block_worklist);
-}
-
-/* Compute the execution frequency for all blocks in the given
- * graph.
- *
- * irg: The graph to be analyzed.
- * default_loop_weight: The number of executions of a loop.
- */
-void compute_execution_frequency(ir_graph *irg, int default_loop_weight, double exception_probability)
-{
- ir_graph *rem = current_ir_graph;
- current_ir_graph = irg;
- exception_prob = exception_probability;
- if (!exec_freq_set) exec_freq_set = new_set(exec_freq_cmp, 256);
-
- precompute_cond_evaluation();
- construct_intervals(current_ir_graph);
- compute_frequency(default_loop_weight);
-
- set_irg_exec_freq_state(irg, exec_freq_consistent);
- if (get_irp_exec_freq_state() == exec_freq_none)
- set_irp_exec_freq_state(exec_freq_inconsistent);
-
- /*
- dump_loop_tree (current_ir_graph, "-execfreq");
- dump_ir_block_graph(current_ir_graph, "-execfreq");
- dump_interval_graph(current_ir_graph, "-execfreq");
- */
-
- current_ir_graph = rem;
-}
-
-
-void compute_execution_frequencies(int default_loop_weight, double exception_probability)
-{
- size_t i, n_irgs = get_irp_n_irgs();
- free_intervals();
- for (i = 0; i < n_irgs; ++i) {
- compute_execution_frequency(get_irp_irg(i), default_loop_weight, exception_probability);
- }
- set_irp_exec_freq_state(exec_freq_consistent);
-}
-
-/** free occupied memory, reset */
-void free_execution_frequency(void)
-{
- size_t i, n_irgs = get_irp_n_irgs();
- free_intervals();
- del_set(exec_freq_set);
-
- for (i = 0; i < n_irgs; ++i)
- set_irg_exec_freq_state(get_irp_irg(i), exec_freq_none);
- set_irp_exec_freq_state(exec_freq_none);
-}
-
-exec_freq_state get_irg_exec_freq_state(ir_graph *irg)
-{
- return irg->execfreq_state;
-}
-void set_irg_exec_freq_state(ir_graph *irg, exec_freq_state s)
-{
- if ((get_irp_exec_freq_state() == exec_freq_consistent && s != exec_freq_consistent) ||
- (get_irp_exec_freq_state() == exec_freq_none && s != exec_freq_none))
- irp->execfreq_state = exec_freq_inconsistent;
- irg->execfreq_state = s;
-}
-
-/* Sets irg and irp exec freq state to inconsistent if it is set to consistent. */
-void set_irg_exec_freq_state_inconsistent(ir_graph *irg)
-{
- if (get_irg_exec_freq_state(irg) == exec_freq_consistent)
- set_irg_exec_freq_state(irg, exec_freq_inconsistent);
-}
-
-void set_irp_exec_freq_state(exec_freq_state s)
-{
- irp->execfreq_state = s;
-}
-
-exec_freq_state get_irp_exec_freq_state(void)
-{
- return irp->execfreq_state;
-}
-
-/* Sets irp and all irg exec freq states to inconsistent if it is set to consistent. */
-void set_irp_exec_freq_state_inconsistent(void)
-{
- if (get_irp_exec_freq_state() != exec_freq_none) {
- size_t i, n_irgs = get_irp_n_irgs();
- set_irp_exec_freq_state(exec_freq_inconsistent);
- for (i = 0; i < n_irgs; ++i) {
- ir_graph *irg = get_irp_irg(i);
- if (get_irg_exec_freq_state(irg) != exec_freq_none)
- irg->execfreq_state = exec_freq_inconsistent;
- }
- }
-}
#include "debug.h"
#include "interval_analysis.h"
-#include "execution_frequency.h"
#include "set.h"
#include "array.h"
*/
static inline void exc_outs(void *reg, ir_node *cfop)
{
- if (is_fragile_op(cfop) || is_fragile_Proj(cfop))
+ if (is_fragile_op(cfop))
inc_region_n_exc_outs(reg);
}
}
}
-#include "execution_frequency.h"
-
static void dump_interval_block(FILE *F, ir_node *block)
{
int i, fl;
fprintf(F, "%s ", get_op_name(get_irn_op(block)));
PRINT_NODEID(block);
- fprintf(F, " freq: %9.4lf", get_region_exec_freq(block));
+ //fprintf(F, " freq: %9.4lf", get_region_exec_freq(block));
fprintf(F, " n_outs: %d", get_region_n_outs(block));
fprintf(F, " n_exc_outs: %d", get_region_n_exc_outs(block));
fprintf(F, "\" ");
fprintf(F, "graph: { title: \"");
PRINT_LOOPID(l);
fprintf(F, "\" label: \"loop %ld", get_loop_loop_nr(l));
- fprintf(F, " freq: %9.4lf", get_region_exec_freq(l));
+ //fprintf(F, " freq: %9.4lf", get_region_exec_freq(l));
fprintf(F, " n_outs: %d", get_region_n_outs(l));
fprintf(F, " n_exc_outs: %d", get_region_n_exc_outs(l));
fprintf(F, "\" status:clustered color:white \n");
} /* end switch */
}
-#include <math.h>
-#include "execution_frequency.h"
-
static void dump_node_ana_vals(FILE *F, ir_node *n)
{
(void) F;
#include "error.h"
#include "irdom.h"
-#include "field_temperature.h"
static ir_dump_verbosity_t verbosity = dump_verbosity_max;
fprintf(F, " max pdomsubtree pre num %u\n", get_Block_pdom_max_subtree_pre_num(n));
}
- fprintf(F, " Execution frequency statistics:\n");
- if (get_irg_exec_freq_state(get_irn_irg(n)) != exec_freq_none)
- fprintf(F, " procedure local evaluation: %8.2lf\n", get_irn_exec_freq(n));
-
/* not dumped: graph_arr */
/* not dumped: mature */
} break;
set_irp_typeinfo_inconsistent(); /* there is a new graph with typeinfo_none. */
res->callee_info_state = irg_callee_info_none;
res->class_cast_state = ir_class_casts_transitive;
- res->execfreq_state = exec_freq_none;
res->fp_model = fp_model_precise;
res->mem_disambig_opt = aa_opt_inherited;
#include "irmemory.h"
#include "callgraph.h"
-#include "field_temperature.h"
-#include "execution_frequency.h"
#include "array.h"
#include "iredgekinds.h"
#include "irtypeinfo.h"
#include "irextbb.h"
-#include "execution_frequency.h"
#include "irmemory.h"
#include "callgraph.h"
#include "irprog.h"
-#include "field_temperature.h"
#include "irphase.h"
#include "bitset.h"
ir_typeinfo_state typeinfo_state; /**< Validity of type information. */
irg_callee_info_state callee_info_state; /**< Validity of callee information. */
ir_class_cast_state class_cast_state; /**< Kind of cast operations in code. */
- exec_freq_state execfreq_state; /**< Execution frequency state. */
unsigned mem_disambig_opt; /**< Options for the memory disambiguator. */
unsigned fp_model; /**< floating point model of the graph. */
size_t max_callgraph_loop_depth; /**< needed in callgraph. */
size_t max_callgraph_recursion_depth; /**< needed in callgraph. */
double max_method_execution_frequency; /**< needed in callgraph. */
- irp_temperature_state temperature_state; /**< accumulated temperatures computed? */
- exec_freq_state execfreq_state; /**< The state of execution frequency information */
loop_nesting_depth_state lnd_state; /**< The state of loop nesting depth information. */
ir_class_cast_state class_cast_state; /**< The state of cast operations in code. */
ir_entity_usage_computed_state globals_entity_usage_state;