Commit ce280749 authored by Götz Lindenmaier's avatar Götz Lindenmaier
Browse files

mode loop analyses

[r3795]
parent 90e75f9f
This diff is collapsed.
......@@ -14,42 +14,77 @@
#define _CALLGRAPH_H_
/**
* @file callgraph.h
*
* This file contains defines the representation of the callgraph.
* The nodes of the call graph are ir_graphs. The edges between
* The nodes are calling relation. I.e., if method a calls method
* b at some point, there is an edge between a and b.
*
* Further this file contains an algorithm to construct the call
* graph. The construction of the callgraph uses the callee
* information in Call nodes to determine which methods are called.
*
* Finally this file contains an algorithm that computes backedges
* in the callgraph, i.e., the algorithm finds possibly recursive calls.
* The algorithm computes an upper bound of all recursive calls.
*
*/
* @file callgraph.h
*
* This file contains the representation of the callgraph.
* The nodes of the call graph are ir_graphs. The edges between
* ghe nodes are calling relations. I.e., if method a calls method
* b at some point, there is an edge between a and b.
*
* Further this file contains an algorithm to construct the call
* graph. The construction of the callgraph uses the callee
* information in Call nodes to determine which methods are called.
*
* Finally this file contains an algorithm that computes backedges
* in the callgraph, i.e., the algorithm finds possibly recursive calls.
* The algorithm computes an upper bound of all recursive calls.
*
*/
#include "irgraph.h"
/** Flag to indicate state of callgraph. */
typedef enum {
irp_callgraph_none,
irp_callgraph_consistent, /* calltree is inconsistent */
irp_callgraph_inconsistent,
irp_callgraph_and_calltree_consistent
} irp_callgraph_state;
irp_callgraph_state get_irp_callgraph_state(void);
void set_irp_callgraph_state(irp_callgraph_state s);
/** The functions that call irg. */
int get_irg_n_callers(ir_graph *irg);
ir_graph *get_irg_caller(ir_graph *irg, int pos);
/* int is_irg_caller_backedge(ir_graph *irg, int pos); not implemented */
int is_irg_caller_backedge(ir_graph *irg, int pos);
int has_irg_caller_backedge(ir_graph *irg);
/** maximal loop depth of call nodes that call along this edge. */
int get_irg_caller_loop_depth(ir_graph *irg, int pos);
/** The functions called by irg. */
int get_irg_n_callees(ir_graph *irg);
ir_graph *get_irg_callee(ir_graph *irg, int pos);
int is_irg_callee_backedge(ir_graph *irg, int pos);
int has_irg_callee_backedge(ir_graph *irg);
/** maximal loop depth of call nodes that call along this edge. */
int get_irg_callee_loop_depth(ir_graph *irg, int pos);
/** Maximal loop depth of all paths from an external visible method to
this irg. */
int get_irg_loop_depth(ir_graph *irg);
/** Maximal recursion depth of all paths from an external visible method to
this irg. */
int get_irg_recursion_depth(ir_graph *irg);
/** Construct and destruct the callgraph. */
void compute_callgraph(void);
void free_callgraph(void);
/** A function type for fuctions passed to the callgraph walker. */
typedef void callgraph_walk_func(ir_graph *g, void *env);
void callgraph_walk(callgraph_walk_func *pre, callgraph_walk_func *post, void *env);
/** Compute the backedges that represent recursions. */
void find_callgraph_recursions(void);
#endif /* _CALLGRAPH_H_ */
......@@ -568,7 +568,7 @@ static void callee_ana(void) {
irg_walk_graph(get_irp_irg(i), callee_walker, remove_Tuples, NULL);
set_irg_callee_info_state(get_irp_irg(i), irg_callee_info_consistent);
}
//set_irp_callee_info_state(irg_callee_info_consistent);
set_irp_callee_info_state(irg_callee_info_consistent);
}
......
......@@ -28,6 +28,8 @@
#include "irprog_t.h"
#include "irdump.h"
#define NO_CFLOOPS_WITHOUT_HEAD 1
static ir_graph *outermost_ir_graph; /* The outermost graph the scc is computed
for */
static ir_loop *current_loop; /* Current cfloop construction is working
......@@ -312,6 +314,39 @@ is_head (ir_node *n, ir_node *root)
return some_outof_loop && some_in_loop;
}
/* Returns true if n is possible loop head of an endless loop.
I.e., it is a Block, Phi or Filter node and has only predecessors
within the loop.
@arg root: only needed for assertion. */
static bool
is_endless_head (ir_node *n, ir_node *root)
{
int i, arity;
int some_outof_loop = 0, some_in_loop = 0;
assert(is_Block(n));
/* Test for legal loop header: Block, Phi, ... */
if (!is_outermost_StartBlock(n)) {
arity = get_irn_arity(n);
for (i = 0; i < arity; i++) {
ir_node *pred = get_nodes_block(skip_Proj(get_irn_n(n, i)));
assert(pred);
if (is_backedge(n, i)) { continue; }
if (!irn_is_in_stack(pred)) {
some_outof_loop = 1; //printf(" some out of loop ");
} else {
if(get_irn_uplink(pred) < get_irn_uplink(root)) {
DDMN(pred); DDMN(root);
assert(get_irn_uplink(pred) >= get_irn_uplink(root));
}
some_in_loop = 1;
}
}
}
return !some_outof_loop && some_in_loop;
}
/* Returns index of the predecessor with the smallest dfn number
greater-equal than limit. */
static int
......@@ -356,8 +391,7 @@ largest_dfn_pred (ir_node *n)
/* Searches the stack for possible loop heads. Tests these for backedges.
If it finds a head with an unmarked backedge it marks this edge and
returns the tail of the loop.
If it finds no backedge returns NULL.
("disable_backedge" in fiasco) */
If it finds no backedge returns NULL. */
static ir_node *
find_tail (ir_node *n) {
ir_node *m;
......@@ -371,15 +405,46 @@ find_tail (ir_node *n) {
return NULL;
} else {
if (m == n) return NULL;
for (i = tos-2; ; --i) {
for (i = tos-2; i >= 0; --i) {
m = stack[i];
if (is_head (m, n)) {
res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
if (res_index == -2) /* no smallest dfn pred found. */
res_index = largest_dfn_pred (m);
if ((m == n) && (res_index == -2)) {
i = -1;
}
break;
}
/* We should not walk past our selves on the stack: The upcoming nodes
are not in this loop. We assume a loop not reachable from Start. */
if (m == n) {
i = -1;
break;
}
}
if (i < 0) {
/* A dead loop not reachable from Start. */
for (i = tos-2; i >= 0; --i) {
m = stack[i];
if (is_endless_head (m, n)) {
res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
if (res_index == -2) /* no smallest dfn pred found. */
res_index = largest_dfn_pred (m);
break;
}
if (m == n) { break; } /* It's not an unreachable loop, either. */
}
//assert(0 && "no head found on stack");
}
}
assert (res_index > -2);
......@@ -387,6 +452,11 @@ find_tail (ir_node *n) {
return is_outermost_StartBlock(n) ? NULL : get_nodes_block(skip_Proj(get_irn_n(m, res_index)));
}
INLINE static int
is_outermost_loop(ir_loop *l) {
return l == get_loop_outer_loop(l);
}
/*-----------------------------------------------------------*
* The core algorithm. *
*-----------------------------------------------------------*/
......@@ -448,8 +518,6 @@ static void cfscc (ir_node *n) {
Next actions: Open a new cfloop on the cfloop tree and
try to find inner cfloops */
#define NO_CFLOOPS_WITHOUT_HEAD 1
#if NO_CFLOOPS_WITHOUT_HEAD
/* This is an adaption of the algorithm from fiasco / optscc to
......@@ -461,7 +529,7 @@ static void cfscc (ir_node *n) {
ir_loop *l;
int close;
if (get_loop_n_elements(current_loop) > 0) {
if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
l = new_loop();
close = 1;
} else {
......
......@@ -30,6 +30,11 @@
#include "irdump.h"
/* A variant of the loop tree that avoids loops without head.
This reduces the depth of the loop tree. */
#define NO_LOOPS_WITHOUT_HEAD 1
INLINE void add_loop_son(ir_loop *loop, ir_loop *son);
INLINE void add_loop_node(ir_loop *loop, ir_node *n);
......@@ -788,7 +793,7 @@ find_tail (ir_node *n) {
if (res_index == -2) /* no smallest dfn pred found. */
res_index = largest_dfn_pred (m);
if ((m == n) && (res_index == -2)) {
if ((m == n) && (res_index == -2)) { /* dont walk past loop head. */
i = -1;
}
break;
......@@ -867,7 +872,8 @@ int search_endproj_in_stack(ir_node *start_block)
int arity = get_irn_arity(start_block);
for(j = 0; j < arity; j++)
{
ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)), get_Proj_proj(end_projx));
ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)),
get_Proj_proj(end_projx));
DDMN(begin_projx);
if(get_irn_n(start_block, j) == begin_projx)
{
......@@ -884,11 +890,13 @@ int search_endproj_in_stack(ir_node *start_block)
static pmap *projx_link = NULL;
void link_to_reg_end (ir_node *n, void *env) {
if(get_irn_op(n) == op_Proj && get_irn_mode(n) == mode_X && get_irn_op(get_irn_n(n, 0)) == op_EndReg)
{
if(get_irn_op(n) == op_Proj &&
get_irn_mode(n) == mode_X &&
get_irn_op(get_irn_n(n, 0)) == op_EndReg) {
/* Reg End Projx -> Find the CallBegin Projx and hash it */
ir_node *end_projx = n;
ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)), get_Proj_proj(end_projx));
ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)),
get_Proj_proj(end_projx));
printf("Linked the following ProjxNodes:\n");
DDMN(begin_projx);
DDMN(end_projx);
......@@ -910,6 +918,10 @@ ir_node *get_projx_link(ir_node *cb_projx)
#endif
INLINE static int
is_outermost_loop(ir_loop *l) {
return l == get_loop_outer_loop(l);
}
/*-----------------------------------------------------------*
......@@ -970,18 +982,20 @@ static void scc (ir_node *n) {
Next actions: Open a new loop on the loop tree and
try to find inner loops */
#define NO_LOOPS_WITHOUT_HEAD 1
#if NO_LOOPS_WITHOUT_HEAD
/* This is an adaption of the algorithm from fiasco / optscc to
* avoid loops without Block or Phi as first node. This should
* severely reduce the number of evaluations of nodes to detect
* a fixpoint in the heap analysis.
* Further it avoids loops without firm nodes that cause errors
* in the heap analyses. */
* in the heap analyses.
* But attention: don't do it for the outermost loop: This loop
* is not iterated. A first block can be a loop head in case of
* an endless recursion. */
ir_loop *l;
int close;
if (get_loop_n_elements(current_loop) > 0) {
if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
l = new_loop();
close = 1;
} else {
......@@ -1069,7 +1083,6 @@ static void my_scc (ir_node *n) {
Next actions: Open a new loop on the loop tree and
try to find inner loops */
#define NO_LOOPS_WITHOUT_HEAD 1
#if NO_LOOPS_WITHOUT_HEAD
/* This is an adaption of the algorithm from fiasco / optscc to
* avoid loops without Block or Phi as first node. This should
......@@ -1080,7 +1093,7 @@ static void my_scc (ir_node *n) {
ir_loop *l;
int close;
if (get_loop_n_elements(current_loop) > 0) {
if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
l = new_loop();
close = 1;
} else {
......@@ -1133,17 +1146,10 @@ void construct_backedges(ir_graph *irg) {
new_loop(); /* sets current_loop */
head_rem = current_loop; /* Just for assertion */
if (interprocedural_view) {
set_irg_visited(current_ir_graph, inc_max_irg_visited());
init_ip_walk ();
} else {
inc_irg_visited(current_ir_graph);
}
inc_irg_visited(current_ir_graph);
scc(get_irg_end(current_ir_graph));
if (interprocedural_view) finish_ip_walk();
assert(head_rem == current_loop);
set_irg_loop(current_ir_graph, current_loop);
set_irg_loopinfo_state(current_ir_graph, loopinfo_consistent);
......
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