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

irscc: bugfix, can now deal with loops not reachable from start

cgana: bugfix, skip_Tuple
rta: improved

[r3133]
parent 4e530c4a
......@@ -49,9 +49,9 @@ static void * MARK = &MARK;
static eset * entities = NULL;
/* Bestimmt die eindeutige Methode, die die Methode fr den
* bergebenene (dynamischen) Typ berschreibt. */
entity * get_implementation(type * class, entity * method) {
/** Bestimmt die eindeutige Methode, die die Methode fr den
* bergebenen (dynamischen) Typ berschreibt. */
static entity * get_implementation(type * class, entity * method) {
int i;
if (get_entity_peculiarity(method) != peculiarity_description &&
get_entity_owner(method) == class) {
......@@ -73,9 +73,9 @@ entity * get_implementation(type * class, entity * method) {
return NULL;
}
/* Returns the entity that contains the implementation of the inherited
/** Returns the entity that contains the implementation of the inherited
entity if available, else returns the entity passed. */
entity *get_inherited_methods_implementation(entity *inh_meth) {
static entity *get_inherited_methods_implementation(entity *inh_meth) {
entity *impl_meth = NULL;
ir_node *addr = get_atomic_ent_value(inh_meth);
assert(addr && "constant entity without value");
......@@ -112,6 +112,7 @@ entity *get_inherited_methods_implementation(entity *inh_meth) {
*/
static void collect_impls(entity *method, eset *set, int *size, bool *open) {
int i;
if (get_entity_peculiarity(method) == peculiarity_existent) {
if (get_entity_visibility(method) == visibility_external_allocated) {
assert(get_entity_irg(method) == NULL);
......@@ -124,6 +125,7 @@ static void collect_impls(entity *method, eset *set, int *size, bool *open) {
}
}
}
if (get_entity_peculiarity(method) == peculiarity_inherited) {
entity *impl_ent = get_inherited_methods_implementation(method);
assert(impl_ent && "no implementation for inherited entity");
......@@ -200,15 +202,29 @@ static entity ** get_impl_methods(entity * method) {
__dbg_info_merge_pair(new_node, node, dbg_rem_poly_call)
/** Analyse address computations.
*
* - If the node is a SymConst replace it by Const(ent) if possible.
* - If the node is a Sel:
* * If the pointer to the Sel comes directly from an Alloc node
* replace the Sel by a Const(ent).
*
*
* @param node The node to analyze
* @param ldname_map A map that mapps names of entities to the entities.
*/
static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
if (get_irn_op(node) == op_SymConst) {
/* Wenn mglich SymConst-Operation durch Const-Operation
* ersetzen. */
if (get_SymConst_kind(node) == linkage_ptr_info) {
pmap_entry * entry = pmap_find(ldname_map, (void *) get_SymConst_ptrinfo(node));
pmap_entry *entry = pmap_find(ldname_map, (void *) get_SymConst_ptrinfo(node));
if (entry != NULL) { /* Method is declared in the compiled code */
entity * ent = entry->value;
if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */
entity *ent = entry->value;
if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) {
/* Meth. is defined */
ir_node *new_node;
assert(get_entity_irg(ent));
set_irg_current_block(current_ir_graph, get_nodes_Block(node));
......@@ -300,12 +316,12 @@ static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
}
/* Datenstruktur initialisieren. Zustzlich werden alle
/** Datenstruktur initialisieren. Zustzlich werden alle
* SymConst-Operationen, die auf interne Methoden verweisen, durch
* Const-Operationen ersetzt. */
static void sel_methods_init(void) {
int i;
pmap * ldname_map = pmap_create();
pmap * ldname_map = pmap_create(); /* Map entitiy names to entities: to replace SymConst by Const(ent). */
assert(entities == NULL);
entities = eset_create();
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
......
......@@ -103,7 +103,7 @@ set_irn_uplink (ir_node *n, int uplink) {
((scc_info *)n->link)->uplink = uplink;
}
static INLINE int
INLINE int
get_irn_uplink (ir_node *n) {
assert(get_irn_link(n));
/* from fast to slow */
......@@ -119,7 +119,7 @@ set_irn_dfn (ir_node *n, int dfn) {
((scc_info *)n->link)->dfn = dfn;
}
static INLINE int
INLINE int
get_irn_dfn (ir_node *n) {
assert(get_irn_link(n));
/* to slow */
......@@ -247,6 +247,9 @@ pop_scc_to_loop (ir_node *n)
do
{
m = pop();
//printf(" dfn: %d, upl %d upl-new %d ", get_irn_dfn(m), get_irn_uplink(m), loop_node_cnt+1); DDMN(m);
loop_node_cnt++;
set_irn_dfn(m, loop_node_cnt);
add_loop_node(current_loop, m);
......@@ -635,72 +638,6 @@ get_start_index(ir_node *n) {
}
#if 0
/* Returns current_ir_graph and set it to the irg of predecessor index
of node n. */
static INLINE ir_graph *
switch_irg (ir_node *n, int index) {
ir_graph *old_current = current_ir_graph;
if (interprocedural_view) {
/* Only Filter and Block nodes can have predecessors in other graphs. */
if (get_irn_op(n) == op_Filter)
n = get_nodes_Block(n);
if (get_irn_op(n) == op_Block) {
ir_node *cfop = skip_Proj(get_Block_cfgpred(n, index));
if (is_ip_cfop(cfop)) {
current_ir_graph = get_irn_irg(cfop);
set_irg_visited(current_ir_graph, get_max_irg_visited());
}
}
}
return old_current;
}
/* Walks up the stack passing n and then finding the node
where we walked into the irg n is contained in.
Here we switch the irg. */
static ir_graph *
find_irg_on_stack (ir_node *n) {
ir_node *m;
ir_graph *old_current = current_ir_graph;
int i;
if (interprocedural_view) {
for (i = tos; i >= 0; i--) {
if (stack[i] == n) break;
}
if (i < 0) i = tos;
assert (i >= 0);
for (; i >= 0; i--) {
m = stack[i];
/*printf(" Visiting %d ", i); DDMN(m);*/
if (is_ip_cfop(m)) {
current_ir_graph = get_irn_irg(m);
break;
}
if (get_irn_op(m) == op_Filter) {
/* Find the corresponding ip_cfop */
ir_node *pred = stack[i+1];
int j;
for (j = 0; j < get_Filter_n_cg_preds(m); j++)
if (get_Filter_cg_pred(m, j) == pred) break;
if (j >= get_Filter_n_cg_preds(m))
/* It is a filter we didn't pass as the predecessors are marked. */
continue;
assert(get_Filter_cg_pred(m, j) == pred);
switch_irg(m, j);
break;
}
}
}
return old_current;
}
#endif
#if 0
static void test(ir_node *pred, ir_node *root, ir_node *this) {
int i;
......@@ -751,11 +688,10 @@ is_head (ir_node *n, ir_node *root)
if (!irn_is_in_stack(pred)) {
some_outof_loop = 1;
} else {
if(get_irn_uplink(pred) < get_irn_uplink(root))
{
DDMN(pred); DDMN(root);
}
if(get_irn_uplink(pred) < get_irn_uplink(root)) {
DDMN(n); DDMN(pred); DDMN(root);
assert(get_irn_uplink(pred) >= get_irn_uplink(root));
}
some_in_loop = 1;
}
}
......@@ -763,6 +699,40 @@ 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;
/* Test for legal loop header: Block, Phi, ... */
if (!is_possible_loop_head(n))
return false;
if (!is_outermost_Start(n)) {
arity = get_irn_arity(n);
for (i = get_start_index(n); i < arity; i++) {
ir_node *pred = 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
......@@ -805,11 +775,14 @@ largest_dfn_pred (ir_node *n)
return index;
}
/* Searches the stack for possible loop heads. Tests these for backedges.
/** 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) */
("disable_backedge" in fiasco)
*
* @param n A node where uplink == dfn.
**/
static ir_node *
find_tail (ir_node *n) {
......@@ -819,7 +792,6 @@ find_tail (ir_node *n) {
/*
if (!icfg && rm_cyclic_phis && remove_cyclic_phis (n)) return NULL;
*/
m = stack[tos-1]; /* tos = top of stack */
if (is_head (m, n)) {
res_index = smallest_dfn_pred(m, 0);
......@@ -827,16 +799,45 @@ find_tail (ir_node *n) {
(n == m))
return NULL;
} else {
if (m == n) return NULL;
for (i = tos-2; ; --i) {
if (m == n) return NULL; // Is this to catch Phi - self loops?
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);
......@@ -986,7 +987,6 @@ static void scc (ir_node *n) {
for (i = get_start_index(n); i < arity; i++) {
ir_node *m;
if (is_backedge(n, i)) continue;
/* printf("i: %d\n", i); */
m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
/* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
scc (m);
......
......@@ -13,7 +13,7 @@
*/
/**
* Intraprozedurale Analyse zur Abschtzung der Aufrufrelation. Es
nn * Intraprozedurale Analyse zur Abschtzung der Aufrufrelation. Es
* die Menge der instantiierten Klassen bestimmt, und daraus existierende Methoden
* bestimmt.
*/
......@@ -87,7 +87,10 @@ static void rta_act (ir_node *node, void *env)
ent = get_tarval_entity (get_Const_tarval (ptr));
} else if (iro_SymConst == get_irn_opcode (ptr)) { /* CALL SYMCONST */
assert (ent && "couldn't determine entity of call to symConst");
/* If this SymConst refers to a method the method is external_visible
and therefore must be considered executed anyways. */
//dump_ir_block_graph(get_irn_irg(ptr));
//assert (ent && "couldn't determine entity of call to symConst");
}
if (ent) {
......@@ -285,7 +288,13 @@ static int has_live_call (entity *method, ir_graph *graph)
int i, n_over;
/* stop searching if a overwriting method comes with a new graph */
if (get_irg_ent (graph) != method) { /* shouldn't we compare GRAPHS here????? */
/* if (get_irg_ent (graph) != method) *
{ /* shouldn't we compare GRAPHS here????? *
return (FALSE);
}
*/
if (graph != get_entity_irg (method)) {
return (FALSE);
}
......@@ -442,6 +451,8 @@ static void remove_irg (ir_graph *graph)
{
entity *ent = get_irg_entity (graph);
//DDMEO(get_irg_ent(graph));
/* delete the ir_graph data */
remove_irp_irg (graph);
/* remove reference to the graph */
......@@ -534,7 +545,14 @@ void rta_delete_dead_graphs ()
eset_insert (dead_graphs, graph);
}
}
/*
for (i = 0; i < get_irp_n_types(); ++i) {
type *tp = get_irp_type(i);
if (is_class_type(tp) && !rta_is_alive_class(tp)) {
printf(" never allocated: "); DDMT(tp);
}
}
*/
/* now delete the graphs. */
for (graph = eset_first (dead_graphs);
graph;
......@@ -620,6 +638,11 @@ int rta_is_alive_field (entity *field)
/*
* $Log$
* Revision 1.10 2004/06/17 10:31:41 goetz
* irscc: bugfix, can now deal with loops not reachable from start
* cgana: bugfix, skip_Tuple
* rta: improved
*
* Revision 1.9 2004/06/17 08:56:03 liekweg
* Fixed typos in comments
*
......
Supports Markdown
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