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

*** empty log message ***

[r58]
parent b629f9f2
15.8.2000 Goetz
looking at bug in dead_node_elimination.
Following fixes:
irnode: all get_..._arr functions changed
ircons: new_r_Block: set matured flag.
ircons: new_r_SymConst: needs mode_p for linkage_ptr_info.
adapted call_str_example to new concepts.
2.8.2000 Goetz
Implemented simpler Phi construction algorithm that constructs
correct code for three_cfpred_example in ircons. This algorithm
......
......@@ -15,13 +15,13 @@
The second works always but is slower and causes more unnecessary Phi
nodes.
Select the implementations by the following preprocessor flag: */
#define USE_FAST_PHI_CONSTRUCTION 1
#define USE_FAST_PHI_CONSTRUCTION 0
/* Further there are two versions of the fast Phi node construction.
If the following flag is set, new_r_Phi_in uses an explicit stack for
allocating and deallocating Phi nodes. Else it uses the obstack
as a stack! */
#define USE_EXPICIT_PHI_IN_STACK 0
#define USE_EXPICIT_PHI_IN_STACK 1
/* a list of firm kinds */
typedef enum {
......
......@@ -40,7 +40,8 @@ new_r_Block (ir_graph *irg, int arity, ir_node **in)
{
ir_node *res;
res = new_ir_node (current_ir_graph, NULL, op_Block, mode_R, arity, in);
res = new_ir_node (irg, NULL, op_Block, mode_R, arity, in);
set_Block_matured(res, 1);
irn_vrfy (res);
return res;
......@@ -531,7 +532,12 @@ new_r_SymConst (ir_graph *irg, ir_node *block, type_or_id *value,
{
ir_node *in[0] = {};
ir_node *res;
res = new_ir_node (irg, block, op_SymConst, mode_I, 0, in);
ir_mode *mode;
if (symkind == linkage_ptr_info)
mode = mode_p;
else
mode = mode_I;
res = new_ir_node (irg, block, op_SymConst, mode, 0, in);
res->attr.i.num = symkind;
if (symkind == linkage_ptr_info) {
......
......@@ -618,9 +618,10 @@
variable.
Parameters
kind The kind of the symbolic constant: type_tag, size or link_info.
*type Points to the type the tag stands for or to the type
whose size is represented by the constant.
kind The kind of the symbolic constant: type_tag, size or link_info.
*type_or_id Points to the type the tag stands for or to the type
whose size is represented by the constant or to an ident
representing the linkage info.
Inputs:
No inputs except the block it belogns to.
......@@ -635,7 +636,7 @@
If the attr.i.num is type_tag or size, the node contains an attribute
attr.i.*type A pointer to a type_class.
if it is linkage_ptr_info it contains
attr.i.*ptrinfo A ident holding information for the linker.
attr.i.*ptrinfo An ident holding information for the linker.
THE SELECT NODE
---------------
......
......@@ -577,11 +577,12 @@ dump_ir_block (ir_node *block, void *env) {
ir_graph *irg = (ir_graph *)env;
if (get_irn_opcode(block) == iro_Block) {
/* This is a block. So dump the vcg information to make a block. */
xfprintf(F, "graph: { title: \"%p\" label: \"", block);
#ifdef DEBUG_libfirm
xfprintf (F, "%ld", get_irn_node_nr(block));
#elif
#else
xfprintf (F, "%I", block->op->name);
#endif
xfprintf(F, "\" status:clustered color:lightyellow \n");
......
......@@ -3,9 +3,7 @@
**
** Author: Christian Schaefer
**
** dead node elimination
** walks one time through the whole graph and copies it into another graph,
** so unreachable nodes will be lost.
** Optimizations for a whole ir graph, i.e., a procedure.
*/
# include "irgopt.h"
......@@ -17,6 +15,7 @@
/********************************************************************/
/* apply optimizations of iropt to all nodes. */
void
optimize_in_place_wrapper (ir_node *n, void *env) {
int i;
......@@ -30,7 +29,6 @@ optimize_in_place_wrapper (ir_node *n, void *env) {
}
}
void
local_optimize_graph (ir_graph *irg) {
ir_graph *rem = current_ir_graph;
......@@ -51,9 +49,11 @@ local_optimize_graph (ir_graph *irg) {
void *
set_new_node (ir_node *old, ir_node *new)
{
old->in[0] = new; /* Hi Chris: Benutze old->link, ich hab mich vergewissert dass
assert(old != new);
/* old->in[0] = new; Hi Chris: Benutze old->link, ich hab mich vergewissert dass
das hier ueberschrieben werden kann, das erspaart eine
indirektion --> schneller. */
old->link = new;
return old;
}
......@@ -62,8 +62,9 @@ ir_node *
get_new_node (ir_node * n)
{
ir_node *new;
new = n->in[0];
new = n->link;
assert(new);
assert(new != n);
return new;
}
......@@ -74,7 +75,7 @@ copy_node (ir_node *n, void *env) {
ir_node *res = NULL;
ir_node *a = NULL;
ir_node *b = NULL;
int i;
int i = 0;
assert (n);
DDMSG2(n);
......@@ -88,10 +89,10 @@ copy_node (ir_node *n, void *env) {
switch (get_irn_opcode(n)) {
case iro_Block:
{
ir_node **in = get_Block_cfgpred_arr(n);
for (i = 0; i < get_Block_n_cfgpreds(n); i++)
{ ir_node **in = get_Block_cfgpred_arr(n);
for (i = 0; i < get_Block_n_cfgpreds(n); i++) {
set_Block_cfgpred(n, i, get_new_node(get_Block_cfgpred(n, i)));
}
res = new_r_Block (current_ir_graph, get_Block_n_cfgpreds(n), in);
}
break;
......@@ -107,7 +108,6 @@ copy_node (ir_node *n, void *env) {
res = new_r_Jmp (current_ir_graph, get_new_node(get_nodes_Block(n)));
break;
case iro_Cond:
DDMSG;
res = new_r_Cond (current_ir_graph, get_new_node(get_nodes_Block(n)),
get_new_node(get_Cond_selector(n)));
break;
......@@ -115,16 +115,24 @@ copy_node (ir_node *n, void *env) {
{
ir_node **in;
in = get_Return_res_arr(n);
/* printf("1. n: %p, in: %p, in[0]: %p, in[1]: %p, in[2]: %p in[3] %p \n", */
/* n, in, in[0], in[1], in[2], in[3]); */
for (i = 0; i < get_Return_n_res(n); i++) {
/* printf(" old: %p, new: %p \n", get_Return_res(n, i), get_new_node(get_Return_res(n, i))); */
set_Return_res(n, i, get_new_node(get_Return_res(n, i)));
}
res = new_r_Return (current_ir_graph, get_new_node(get_nodes_Block(n)),
res = new_r_Return (current_ir_graph,
get_new_node(get_nodes_Block(n)),
get_new_node(get_Return_mem(n)),
get_Return_n_res(n), in);
}
break;
case iro_Raise:
res = new_r_Raise (current_ir_graph, get_new_node(get_nodes_Block(n)),
res = new_r_Raise (current_ir_graph,
get_new_node(get_nodes_Block(n)),
get_new_node(get_Raise_mem(n)),
get_new_node(get_Raise_exo_ptr(n)));
break;
......@@ -165,13 +173,17 @@ copy_node (ir_node *n, void *env) {
break;
case iro_Call:
{
ir_node **in = get_Call_param_arr(n);
ir_node **in;
in = get_Call_param_arr(n);
for (i = 0; i < get_Call_arity(n); i++)
set_Call_param(n, i, get_new_node(get_Call_param(n, i)));
res = new_r_Call (current_ir_graph, get_new_node(get_nodes_Block(n)),
res = new_r_Call (current_ir_graph,
get_new_node(get_nodes_Block(n)),
get_new_node(get_Call_mem(n)),
get_new_node(get_Call_ptr(n)), get_Call_arity(n),
in, get_Call_type (n));
get_new_node(get_Call_ptr(n)),
get_Call_arity(n), in,
get_Call_type (n));
}
break;
case iro_Add:
......@@ -232,10 +244,16 @@ copy_node (ir_node *n, void *env) {
res = new_r_Not (current_ir_graph, get_new_node(get_nodes_Block(n)),
get_new_node(get_Not_op(n)), get_irn_mode(n));
break;
case iro_Cmp:
res = new_r_Cmp (current_ir_graph, get_new_node(get_nodes_Block(n)),
case iro_Cmp: {
DDMSG2(get_new_node(get_Cmp_left(n)));
DDMSG2(get_new_node(get_Cmp_right(n)));
DDMSG2(get_new_node(get_nodes_Block(n)));
DDMSG;
res = new_r_Cmp (current_ir_graph,
get_new_node(get_nodes_Block(n)),
get_new_node(get_Cmp_left(n)),
get_new_node(get_Cmp_right(n)));
}
break;
case iro_Shl:
res = new_r_Shl (current_ir_graph, get_new_node(get_nodes_Block(n)),
......@@ -326,7 +344,7 @@ copy_node (ir_node *n, void *env) {
res = new_r_Bad ();
break;
}
/* @@@ Here we could call optimize()!! */
/* @@@ Here we could call optimize()!! Not necessary, called in constructor anyways. */
set_new_node(n, res);
printf(" "); DDMSG2(res);
......@@ -342,7 +360,7 @@ dead_node_elimination(ir_graph *irg) {
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
if (get_opt_dead_node_elimination()) {
if (get_optimize() && get_opt_dead_node_elimination()) {
/* A quiet place, where the old obstack can rest in peace,
until it will be cremated. */
......@@ -353,6 +371,9 @@ dead_node_elimination(ir_graph *irg) {
current_ir_graph->obst = rebirth_obst;
obstack_init (current_ir_graph->obst);
/* @@@@@ Do we need to do something about cse? */
set_opt_cse(0);
/*CS*/
printf("Before starting the DEAD NODE ELIMINATION !\n");
......@@ -368,37 +389,42 @@ dead_node_elimination(ir_graph *irg) {
new_node = new_r_Block (current_ir_graph, 0, NULL); /* new_r_Block calls
no optimization --> save */
irg->start_block = new_node;
DDMSG2(new_node);
set_new_node (old_node, new_node);
set_irn_visited (old_node, get_irg_visited(current_ir_graph)+1);
/* Copy the Start node */
old_node = irg->start;
new_node = new_r_Start (current_ir_graph, irg->start_block);
irg->start = new_node;
DDMSG2(new_node);
DDMSG2(new_node);
set_new_node (old_node, new_node);
set_irn_visited (old_node, get_irg_visited(current_ir_graph)+1);
/* Copy the Bad node */
old_node = irg->bad;
new_node = new_ir_node (irg, irg->start_block, op_Bad, mode_T, 0, NULL);
irg->bad = new_node;
DDMSG2(new_node);
set_new_node (old_node, new_node);
set_irn_visited (old_node, get_irg_visited(current_ir_graph)+1);
/* Copy the Projs for the Start's results. */
old_node = irg->frame;
new_node = new_r_Proj (irg, irg->start_block, irg->start, mode_p, pns_frame_base);
irg->frame = new_node;
DDMSG2(new_node);
set_new_node (old_node, new_node);
set_irn_visited (old_node, get_irg_visited(current_ir_graph)+1);
old_node = irg->globals;
new_node = new_r_Proj (irg, irg->start_block, irg->start, mode_p, pns_globals);
irg->globals = new_node;
DDMSG2(new_node);
set_new_node (old_node, new_node);
set_irn_visited (old_node, get_irg_visited(current_ir_graph)+1);
old_node = irg->args;
new_node = new_r_Proj (irg, irg->start_block, irg->start, mode_T, pns_args);
irg->args = new_node;
DDMSG2(new_node);
set_new_node (old_node, new_node);
set_irn_visited (old_node, get_irg_visited(current_ir_graph)+1);
......@@ -410,7 +436,8 @@ dead_node_elimination(ir_graph *irg) {
printf("After the DEAD NODE ELIMINATION !\n");
/* Free memory from old unoptimized obstack */
xfree (graveyard_obst);
obstack_free(graveyard_obst, 0); /* First empty the obstack ... */
xfree (graveyard_obst); /* ... then free it. */
}
current_ir_graph = rem;
......
......@@ -3,9 +3,7 @@
**
** Author: Christian Schaefer
**
** dead node elimination
** walks one time through the whole graph and copies it into another graph,
** so unreachable nodes will be lost.
** Optimizations for a whole ir graph, i.e., a procedure.
*/
# ifndef _IRGOPT_H_
......
......@@ -25,8 +25,9 @@ void irg_walk_2(ir_node *node,
pre(node, env);
}
if (is_no_Block(node))
if (is_no_Block(node)) {
irg_walk_2(get_nodes_Block(node), pre, post, env);
}
for(i = get_irn_arity(node) - 1; i >= 0; --i) {
irg_walk_2(get_irn_n(node, i), pre, post, env);
}
......
......@@ -8,6 +8,12 @@
#include "irnode.h"
#include "array.h"
/* some constants fixing the positions of nodes predecessors
in the in array */
#define CALL_PARAM_OFFSET 2
#define SEL_INDEX_OFFSET 2
#define RETURN_RESULT_OFFSET 1 /* mem is not a result */
static char *pnc_name_arr [] = {"False", "Eq", "Lt", "Le",
"Gt", "Ge", "Lg", "Leg", "Uo",
"Ue", "Ul", "Ule", "Ug", "Uge",
......@@ -168,12 +174,10 @@ get_irn_in (ir_node *node)
to iterate includind the Block predecessor iterate from i = -1 to
i < get_irn_arity.
If it is a block, the entry -1 is NULL. */
inline ir_node *
get_irn_n (ir_node *node, int n)
{
assert (node);
/* GL commented the assert in, 12.7.00, let's see whether it works */
assert (get_irn_arity (node) > n);
return skip_nop(node->in[n+1]);
}
......@@ -357,7 +361,7 @@ inline ir_node **
get_Block_cfgpred_arr (ir_node *node)
{
assert ((node->op == op_Block));
return (ir_node **)get_Block_cfgpred(node, 0);
return (ir_node **)&(get_irn_in(node)[1]);
}
......@@ -450,7 +454,7 @@ get_Return_res_arr (ir_node *node)
{
assert ((node->op == op_Return));
if (get_Return_n_res(node) > 0)
return ((ir_node **)get_Return_res(node, 0));
return (ir_node **)&(get_irn_in(node)[1 + RETURN_RESULT_OFFSET]);
else
return NULL;
}
......@@ -458,7 +462,7 @@ get_Return_res_arr (ir_node *node)
inline int
get_Return_n_res (ir_node *node) {
assert (node->op == op_Return);
return (get_irn_arity(node) - 1);
return (get_irn_arity(node) - RETURN_RESULT_OFFSET);
}
/*
......@@ -472,13 +476,13 @@ inline ir_node *
get_Return_res (ir_node *node, int pos) {
assert (node->op == op_Return);
assert (get_Return_n_res(node) > pos);
return get_irn_n(node, pos+1);
return get_irn_n(node, pos + RETURN_RESULT_OFFSET);
}
inline void
set_Return_res (ir_node *node, int pos, ir_node *res){
assert (node->op == op_Return);
set_irn_n(node, pos+1, res);
set_irn_n(node, pos + RETURN_RESULT_OFFSET, res);
}
inline ir_node *
......@@ -589,7 +593,7 @@ get_Sel_index_arr (ir_node *node)
{
assert ((node->op == op_Sel));
if (get_Sel_n_index(node) > 0)
return (ir_node **)get_Sel_index(node, 0);
return (ir_node **)& get_irn_in(node)[SEL_INDEX_OFFSET + 1];
else
return NULL;
}
......@@ -597,7 +601,7 @@ get_Sel_index_arr (ir_node *node)
inline int
get_Sel_n_index (ir_node *node) {
assert (node->op == op_Sel);
return (get_irn_arity(node) - 2);
return (get_irn_arity(node) - SEL_INDEX_OFFSET);
}
/*
......@@ -610,13 +614,13 @@ set_Sel_n_index (ir_node *node, int n_index) {
inline ir_node *
get_Sel_index (ir_node *node, int pos) {
assert (node->op == op_Sel);
return get_irn_n(node, pos+2);
return get_irn_n(node, pos + SEL_INDEX_OFFSET);
}
inline void
set_Sel_index (ir_node *node, int pos, ir_node *index) {
assert (node->op == op_Sel);
set_irn_n(node, pos+2, index);
set_irn_n(node, pos + SEL_INDEX_OFFSET, index);
}
inline entity *
......@@ -670,16 +674,13 @@ set_Call_ptr (ir_node *node, ir_node *ptr) {
inline ir_node **
get_Call_param_arr (ir_node *node) {
assert (node->op == op_Call);
if (get_Call_arity(node) > 0)
return ((ir_node **)get_Call_param (node, 0));
else
return NULL;
return (ir_node **)&get_irn_in(node)[CALL_PARAM_OFFSET + 1];
}
inline int
get_Call_arity (ir_node *node) {
assert (node->op == op_Call);
return (get_irn_arity(node) - 2);
return (get_irn_arity(node) - CALL_PARAM_OFFSET);
}
/* inline void
......@@ -691,13 +692,13 @@ set_Call_arity (ir_node *node, ir_node *arity) {
inline ir_node *
get_Call_param (ir_node *node, int pos) {
assert (node->op == op_Call);
return get_irn_n(node, pos+1);
return get_irn_n(node, pos + CALL_PARAM_OFFSET);
}
inline void
set_Call_param (ir_node *node, int pos, ir_node *param) {
assert (node->op == op_Call);
set_irn_n(node, pos+1, param);
set_irn_n(node, pos + CALL_PARAM_OFFSET, param);
}
inline type_method *
......@@ -1392,7 +1393,7 @@ set_Conv_op (ir_node *node, ir_node *op) {
inline ir_node **
get_Phi_preds_arr (ir_node *node) {
assert (node->op == op_Phi);
return ((ir_node **)get_Phi_pred(node, 0));
return (ir_node **)&(get_irn_in(node)[1]);
}
inline int
......@@ -1580,7 +1581,7 @@ set_Free_type (ir_node *node, type *type) {
inline ir_node **
get_Sync_preds_arr (ir_node *node) {
assert (node->op == op_Sync);
return ((ir_node **)get_Sync_pred(node, 0));
return (ir_node **)&(get_irn_in(node)[1]);
}
inline int
......@@ -1635,7 +1636,7 @@ set_Proj_proj (ir_node *node, long proj) {
inline ir_node **
get_Tuple_preds_arr (ir_node *node) {
assert (node->op == op_Tuple);
return ((ir_node **)get_Tuple_pred(node, 0));
return (ir_node **)&(get_irn_in(node)[1]);
}
inline int
......
......@@ -144,6 +144,8 @@ main(void)
/* verify the graph */
irg_vrfy(main_irg);
dead_node_elimination(main_irg);
printf("\nDone building the graph.\n");
printf("Dumping the graph and a type graph.\n");
dump_ir_block_graph (main_irg);
......
......@@ -130,6 +130,8 @@ main(void)
/* verify the graph */
irg_vrfy(main_irg);
dead_node_elimination(main_irg);
printf("\nDone building the graph.\n");
printf("Dumping the graph and a type graph.\n");
dump_ir_block_graph (main_irg);
......
......@@ -25,6 +25,8 @@ int main(int argc, char **argv)
{
ir_graph *irg; /* this variable contains the irgraph */
type_class *owner; /* the class in which this method is defined */
type_method *proc_main; /* type information for the method main */
type_method *proc_called; /* type information for called method f */
entity *ent; /* represents this method as entity of owner */
ir_node *x, *const_str, *proc_ptr, *call;
......@@ -34,55 +36,64 @@ int main(int argc, char **argv)
init_firm ();
/* FIRM was designed for oo languages where all methods belong to a class.
* For imperative languages like C we view a file as a large class containing
* all functions as methods in this file.
* Therefore we define a class "CALL_STR_EXAMPLE" with a method main as
* an entity.
* For imperative languages like C we view a program as a large class containing
* all functions of the program as methods in this class. This class is
* automatically generated.
* We use the same name for the method type as for the method entity.
*/
#define CLASSNAME "CALL_STR_EXAMPLE"
#define METHODNAME "main"
#define NRARGS 0
#define NRES 0
owner = get_glob_type();
proc_main = new_type_method(id_from_str(METHODNAME, strlen(METHODNAME)),
NRARGS, NRES);
/* Make type information for called method which also belongs to the
global type. */
#define F_METHODNAME "f"
#define F_NRARGS 1
#define F_NRES 0
owner = get_glob_type();
proc_called = new_type_method(id_from_str(F_METHODNAME, strlen(F_METHODNAME)),
F_NRARGS, F_NRES);
/* Make the entity for main needed for a correct ir_graph. */
#define ENTITYNAME "main"
owner = new_type_class (id_from_str (CLASSNAME, strlen(CLASSNAME)));
ent = new_entity ((type *)owner, id_from_str (ENTITYNAME, strlen(ENTITYNAME)), NULL);
ent = new_entity ((type *)owner, id_from_str (ENTITYNAME, strlen(ENTITYNAME)),
(type *)proc_main);
/* Generates the basic graph for the method represented by entity ent, that
* is, generates start and end blocks and nodes and a first, initial block.
* The constructor needs to know how many local variables the method has.
*/
#define NUM_OF_LOCAL_VARS 0
irg = new_ir_graph (ent, NUM_OF_LOCAL_VARS);
/* the string is enterd in the constant table. const_str is a pointer to the string */
/* the string is entered in the constant table. const_str is a pointer to the string */
const_str = new_Const (mode_p, tarval_p_from_str ("Hello world!"));
/* get the pointer to the procedure from the class type */
/* this is how a pointer to be fixed by the linker is represented after
lowering a Sel node. */
#define FUNCTIONNAME "f"
proc_ptr = new_Const (mode_p, tarval_p_from_str (FUNCTIONNAME));
proc_ptr = new_SymConst ((type_or_id *)ID_FROM_STR (FUNCTIONNAME, strlen(FUNCTIONNAME)),
linkage_ptr_info);
/* call procedure set_a, first built array with parameters */
{
ir_node *in[1];
in[0] = const_str;
call = new_Call(get_store(), proc_ptr, 1, in, NULL);
call = new_Call(get_store(), proc_ptr, 1, in, proc_called);
}
/* make the possible change of call to memory visible */
/* make the possible changes by the called method to memory visible */
set_store(new_Proj(call, mode_M, 0));
/* The constructor new_ir_graph() generated a region to place nodes in.
* This region is accessible via the attribut current_block of irg and
* it is not matured.
* Generate the return node into this region. The Return node is needed to
* return at least the store. */
/* Make the return node returning the memory. */
{
ir_node *in[0]; /* this is the array containing the return parameters */
x = new_Return (get_store(), 0, in);
}
/* Now generate all instructions for this block and all its predecessor blocks
/* Now we generated all instructions for this block and all its predecessor blocks
* so we can mature it. */
mature_block (irg->current_block);
......@@ -92,10 +103,13 @@ int main(int argc, char **argv)
/* Now we can mature the end block as all it's predecessors are known. */
mature_block (irg->end_block);
printf("\nDone building the graph. Dumping it.\n");
/* verify the graph */
irg_vrfy(irg);
printf("\nDone building the graph. Dumping it.\n");
set_opt_dead_node_elimination(1);
dead_node_elimination(irg);
dump_ir_block_graph (irg);