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; ...@@ -49,9 +49,9 @@ static void * MARK = &MARK;
static eset * entities = NULL; static eset * entities = NULL;
/* Bestimmt die eindeutige Methode, die die Methode fr den /** Bestimmt die eindeutige Methode, die die Methode fr den
* bergebenene (dynamischen) Typ berschreibt. */ * bergebenen (dynamischen) Typ berschreibt. */
entity * get_implementation(type * class, entity * method) { static entity * get_implementation(type * class, entity * method) {
int i; int i;
if (get_entity_peculiarity(method) != peculiarity_description && if (get_entity_peculiarity(method) != peculiarity_description &&
get_entity_owner(method) == class) { get_entity_owner(method) == class) {
...@@ -73,9 +73,9 @@ entity * get_implementation(type * class, entity * method) { ...@@ -73,9 +73,9 @@ entity * get_implementation(type * class, entity * method) {
return NULL; 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 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; entity *impl_meth = NULL;
ir_node *addr = get_atomic_ent_value(inh_meth); ir_node *addr = get_atomic_ent_value(inh_meth);
assert(addr && "constant entity without value"); assert(addr && "constant entity without value");
...@@ -112,6 +112,7 @@ entity *get_inherited_methods_implementation(entity *inh_meth) { ...@@ -112,6 +112,7 @@ entity *get_inherited_methods_implementation(entity *inh_meth) {
*/ */
static void collect_impls(entity *method, eset *set, int *size, bool *open) { static void collect_impls(entity *method, eset *set, int *size, bool *open) {
int i; int i;
if (get_entity_peculiarity(method) == peculiarity_existent) { if (get_entity_peculiarity(method) == peculiarity_existent) {
if (get_entity_visibility(method) == visibility_external_allocated) { if (get_entity_visibility(method) == visibility_external_allocated) {
assert(get_entity_irg(method) == NULL); assert(get_entity_irg(method) == NULL);
...@@ -124,6 +125,7 @@ static void collect_impls(entity *method, eset *set, int *size, bool *open) { ...@@ -124,6 +125,7 @@ static void collect_impls(entity *method, eset *set, int *size, bool *open) {
} }
} }
} }
if (get_entity_peculiarity(method) == peculiarity_inherited) { if (get_entity_peculiarity(method) == peculiarity_inherited) {
entity *impl_ent = get_inherited_methods_implementation(method); entity *impl_ent = get_inherited_methods_implementation(method);
assert(impl_ent && "no implementation for inherited entity"); assert(impl_ent && "no implementation for inherited entity");
...@@ -200,15 +202,29 @@ static entity ** get_impl_methods(entity * method) { ...@@ -200,15 +202,29 @@ static entity ** get_impl_methods(entity * method) {
__dbg_info_merge_pair(new_node, node, dbg_rem_poly_call) __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) { static void sel_methods_walker(ir_node * node, pmap * ldname_map) {
if (get_irn_op(node) == op_SymConst) { if (get_irn_op(node) == op_SymConst) {
/* Wenn mglich SymConst-Operation durch Const-Operation /* Wenn mglich SymConst-Operation durch Const-Operation
* ersetzen. */ * ersetzen. */
if (get_SymConst_kind(node) == linkage_ptr_info) { 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 */ if (entry != NULL) { /* Method is declared in the compiled code */
entity * ent = entry->value; entity *ent = entry->value;
if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) { /* Meth. is defined */ if (get_opt_normalize() && (get_entity_visibility(ent) != visibility_external_allocated)) {
/* Meth. is defined */
ir_node *new_node; ir_node *new_node;
assert(get_entity_irg(ent)); assert(get_entity_irg(ent));
set_irg_current_block(current_ir_graph, get_nodes_Block(node)); 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) { ...@@ -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 * SymConst-Operationen, die auf interne Methoden verweisen, durch
* Const-Operationen ersetzt. */ * Const-Operationen ersetzt. */
static void sel_methods_init(void) { static void sel_methods_init(void) {
int i; 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); assert(entities == NULL);
entities = eset_create(); entities = eset_create();
for (i = get_irp_n_irgs() - 1; i >= 0; --i) { for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
......
...@@ -103,7 +103,7 @@ set_irn_uplink (ir_node *n, int uplink) { ...@@ -103,7 +103,7 @@ set_irn_uplink (ir_node *n, int uplink) {
((scc_info *)n->link)->uplink = uplink; ((scc_info *)n->link)->uplink = uplink;
} }
static INLINE int INLINE int
get_irn_uplink (ir_node *n) { get_irn_uplink (ir_node *n) {
assert(get_irn_link(n)); assert(get_irn_link(n));
/* from fast to slow */ /* from fast to slow */
...@@ -119,7 +119,7 @@ set_irn_dfn (ir_node *n, int dfn) { ...@@ -119,7 +119,7 @@ set_irn_dfn (ir_node *n, int dfn) {
((scc_info *)n->link)->dfn = dfn; ((scc_info *)n->link)->dfn = dfn;
} }
static INLINE int INLINE int
get_irn_dfn (ir_node *n) { get_irn_dfn (ir_node *n) {
assert(get_irn_link(n)); assert(get_irn_link(n));
/* to slow */ /* to slow */
...@@ -247,6 +247,9 @@ pop_scc_to_loop (ir_node *n) ...@@ -247,6 +247,9 @@ pop_scc_to_loop (ir_node *n)
do do
{ {
m = pop(); 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++; loop_node_cnt++;
set_irn_dfn(m, loop_node_cnt); set_irn_dfn(m, loop_node_cnt);
add_loop_node(current_loop, m); add_loop_node(current_loop, m);
...@@ -635,72 +638,6 @@ get_start_index(ir_node *n) { ...@@ -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 #if 0
static void test(ir_node *pred, ir_node *root, ir_node *this) { static void test(ir_node *pred, ir_node *root, ir_node *this) {
int i; int i;
...@@ -751,11 +688,10 @@ is_head (ir_node *n, ir_node *root) ...@@ -751,11 +688,10 @@ is_head (ir_node *n, ir_node *root)
if (!irn_is_in_stack(pred)) { if (!irn_is_in_stack(pred)) {
some_outof_loop = 1; some_outof_loop = 1;
} else { } else {
if(get_irn_uplink(pred) < get_irn_uplink(root)) if(get_irn_uplink(pred) < get_irn_uplink(root)) {
{ DDMN(n); DDMN(pred); DDMN(root);
DDMN(pred); DDMN(root); assert(get_irn_uplink(pred) >= get_irn_uplink(root));
} }
assert(get_irn_uplink(pred) >= get_irn_uplink(root));
some_in_loop = 1; some_in_loop = 1;
} }
} }
...@@ -763,6 +699,40 @@ is_head (ir_node *n, ir_node *root) ...@@ -763,6 +699,40 @@ is_head (ir_node *n, ir_node *root)
return some_outof_loop && some_in_loop; 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 /* Returns index of the predecessor with the smallest dfn number
greater-equal than limit. */ greater-equal than limit. */
static int static int
...@@ -805,11 +775,14 @@ largest_dfn_pred (ir_node *n) ...@@ -805,11 +775,14 @@ largest_dfn_pred (ir_node *n)
return index; 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 If it finds a head with an unmarked backedge it marks this edge and
returns the tail of the loop. returns the tail of the loop.
If it finds no backedge returns NULL. 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 * static ir_node *
find_tail (ir_node *n) { find_tail (ir_node *n) {
...@@ -819,7 +792,6 @@ 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; if (!icfg && rm_cyclic_phis && remove_cyclic_phis (n)) return NULL;
*/ */
m = stack[tos-1]; /* tos = top of stack */ m = stack[tos-1]; /* tos = top of stack */
if (is_head (m, n)) { if (is_head (m, n)) {
res_index = smallest_dfn_pred(m, 0); res_index = smallest_dfn_pred(m, 0);
...@@ -827,16 +799,45 @@ find_tail (ir_node *n) { ...@@ -827,16 +799,45 @@ find_tail (ir_node *n) {
(n == m)) (n == m))
return NULL; return NULL;
} else { } else {
if (m == n) return NULL; if (m == n) return NULL; // Is this to catch Phi - self loops?
for (i = tos-2; ; --i) { for (i = tos-2; i >= 0; --i) {
m = stack[i]; m = stack[i];
if (is_head (m, n)) { if (is_head (m, n)) {
res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1); res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
if (res_index == -2) /* no smallest dfn pred found. */ if (res_index == -2) /* no smallest dfn pred found. */
res_index = largest_dfn_pred (m); res_index = largest_dfn_pred (m);
if ((m == n) && (res_index == -2)) {
i = -1;
}
break; 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); assert (res_index > -2);
...@@ -986,7 +987,6 @@ static void scc (ir_node *n) { ...@@ -986,7 +987,6 @@ static void scc (ir_node *n) {
for (i = get_start_index(n); i < arity; i++) { for (i = get_start_index(n); i < arity; i++) {
ir_node *m; ir_node *m;
if (is_backedge(n, i)) continue; if (is_backedge(n, i)) continue;
/* printf("i: %d\n", i); */
m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */ m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
/* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */ /* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
scc (m); scc (m);
......
...@@ -13,7 +13,7 @@ ...@@ -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 * die Menge der instantiierten Klassen bestimmt, und daraus existierende Methoden
* bestimmt. * bestimmt.
*/ */
...@@ -87,7 +87,10 @@ static void rta_act (ir_node *node, void *env) ...@@ -87,7 +87,10 @@ static void rta_act (ir_node *node, void *env)
ent = get_tarval_entity (get_Const_tarval (ptr)); ent = get_tarval_entity (get_Const_tarval (ptr));
} else if (iro_SymConst == get_irn_opcode (ptr)) { /* CALL SYMCONST */ } 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) { if (ent) {
...@@ -285,7 +288,13 @@ static int has_live_call (entity *method, ir_graph *graph) ...@@ -285,7 +288,13 @@ static int has_live_call (entity *method, ir_graph *graph)
int i, n_over; int i, n_over;
/* stop searching if a overwriting method comes with a new graph */ /* 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); return (FALSE);
} }
...@@ -442,6 +451,8 @@ static void remove_irg (ir_graph *graph) ...@@ -442,6 +451,8 @@ static void remove_irg (ir_graph *graph)
{ {
entity *ent = get_irg_entity (graph); entity *ent = get_irg_entity (graph);
//DDMEO(get_irg_ent(graph));
/* delete the ir_graph data */ /* delete the ir_graph data */
remove_irp_irg (graph); remove_irp_irg (graph);
/* remove reference to the graph */ /* remove reference to the graph */
...@@ -534,7 +545,14 @@ void rta_delete_dead_graphs () ...@@ -534,7 +545,14 @@ void rta_delete_dead_graphs ()
eset_insert (dead_graphs, graph); 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. */ /* now delete the graphs. */
for (graph = eset_first (dead_graphs); for (graph = eset_first (dead_graphs);
graph; graph;
...@@ -620,6 +638,11 @@ int rta_is_alive_field (entity *field) ...@@ -620,6 +638,11 @@ int rta_is_alive_field (entity *field)
/* /*
* $Log$ * $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 * Revision 1.9 2004/06/17 08:56:03 liekweg
* Fixed typos in comments * Fixed typos in comments
* *
......
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