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

New directory: ana for analyses. Adapted configure/makefiles

  implemented irout: backedges.  Added one field to ir_graph, one to ir_node.
  Implemented state management for irgraphs:  see irgraph.h.
  Must now call finalize_cons() after graph construction!!C

[r304]
parent f062f87d
......@@ -27,7 +27,7 @@ include $(topdir)/MakeRules
CPPFLAGS += -I$(top_srcdir)/ir/adt -I$(top_srcdir)/ir/ir -I$(top_srcdir)/ir/common \
-I$(top_srcdir)/ir/ident -I$(top_srcdir)/ir/tr -I$(top_srcdir)/ir/tv \
-I$(top_srcdir)/ir/debug
-I$(top_srcdir)/ir/debug -I$(top_srcdir)/ir/ana
include $(top_srcdir)/MakeTargets
......
......@@ -22,7 +22,7 @@
# include "common.h"
# include "irvrfy.h"
# include "irop.h"
# include "iropt.h"
# include "iropt_t.h"
# include "irgmod.h"
# include "array.h"
/* memset belongs to string.h */
......@@ -636,10 +636,8 @@ ir_node *
new_End (void)
{
ir_node *res;
res = new_ir_node (current_ir_graph, current_ir_graph->current_block,
op_End, mode_X, -1, NULL);
res = optimize (res);
irn_vrfy (res);
......@@ -1373,8 +1371,9 @@ mature_block (ir_node *block)
we can not free the node on the obstack. Therefore we have to call
optimize_in_place.
Unfortunately the optimization does not change a lot, as all allocated
nodes refer to the unoptimized node. */
block = optimize_in_place(block);
nodes refer to the unoptimized node.
We can call _2, as global cse has no effect on blocks. */
block = optimize_in_place_2(block);
irn_vrfy(block);
}
}
......@@ -1717,6 +1716,7 @@ new_Bad (void)
ir_node *new_immBlock (void) {
ir_node *res;
assert(get_irg_phase_state (current_ir_graph) == phase_building);
/* creates a new dynamic in-array as length of in is -1 */
res = new_ir_node (current_ir_graph, NULL, op_Block, mode_R, -1, NULL);
current_ir_graph->current_block = res;
......@@ -1761,6 +1761,7 @@ switch_block (ir_node *target)
ir_node *
get_value (int pos, ir_mode *mode)
{
assert(get_irg_phase_state (current_ir_graph) == phase_building);
inc_irg_visited(current_ir_graph);
return get_r_value_internal (current_ir_graph->current_block, pos + 1, mode);
}
......@@ -1770,6 +1771,7 @@ get_value (int pos, ir_mode *mode)
inline void
set_value (int pos, ir_node *value)
{
assert(get_irg_phase_state (current_ir_graph) == phase_building);
current_ir_graph->current_block->attr.block.graph_arr[pos + 1] = value;
}
......@@ -1777,6 +1779,7 @@ set_value (int pos, ir_node *value)
inline ir_node *
get_store (void)
{
assert(get_irg_phase_state (current_ir_graph) == phase_building);
/* GL: one could call get_value instead */
inc_irg_visited(current_ir_graph);
return get_r_value_internal (current_ir_graph->current_block, 0, mode_M);
......@@ -1786,6 +1789,7 @@ get_store (void)
inline void
set_store (ir_node *store)
{
assert(get_irg_phase_state (current_ir_graph) == phase_building);
/* GL: one could call set_value instead */
current_ir_graph->current_block->attr.block.graph_arr[0] = store;
}
......@@ -1817,3 +1821,9 @@ void
init_cons (void)
{
}
/* call for each graph */
void
finalize_cons (ir_graph *irg) {
irg->phase_state = phase_high;
}
......@@ -1267,9 +1267,11 @@ type *get_cur_frame_type();
/***********************************************************************/
/* initialize ir construction */
/* initialize and finalize ir construction */
/***********************************************************************/
void init_cons (void);
/* Puts the graph into state "phase_high" */
void finalize_cons (ir_graph *irg);
# endif /* _IRCONS_H_ */
......@@ -26,6 +26,7 @@
# include "type_or_entity.h"
# include "irgwalk.h"
# include "typewalk.h"
# include "irouts.h"
/* Attributes of nodes */
#define DEFAULT_NODE_ATTR ""
......@@ -72,7 +73,10 @@ int edge_label = 1;
/* A compiler option to turn off dumping values of constant entities */
int const_entities = 1;
/* A compiler option to dump the keep alive edges */
int dump_keepalive = 1;
int dump_keepalive = 0;
/* A compiler option to dump the out edges in dump_ir_graph */
int dump_out_edge_flag = 0;
/* A global variable to record output of the Bad node. */
int Bad_dumped;
......@@ -479,6 +483,22 @@ dump_ir_data_edges(ir_node *n) {
}
}
/* dump out edges */
void
dump_out_edge (ir_node *n, void* env) {
int i;
for (i = 0; i < get_irn_n_outs(n); i++) {
assert(get_irn_out(n, i));
fprintf (F, "edge: {sourcename: \"");
PRINT_NODEID(n);
fprintf (F, "\" targetname: \"");
PRINT_NODEID(get_irn_out(n, i));
fprintf (F, "\" color: red linestyle: dashed");
fprintf (F, "}\n");
}
}
/* dumps the edges between nodes and their type or entity attributes. */
void dump_node2type_edges (ir_node *n, void *env)
{
......@@ -851,7 +871,7 @@ vcg_close () {
void
dump_whole_node (ir_node *n, void* env) {
dump_node(n);
dump_ir_block_edge(n);
if (!node_floats(n)) dump_ir_block_edge(n);
dump_ir_data_edges(n);
}
......@@ -867,6 +887,11 @@ dump_ir_graph (ir_graph *irg)
/* walk over the graph */
irg_walk(irg->end, dump_whole_node, NULL, NULL);
/* dump the out edges in a separate walk */
if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
}
vcg_close();
current_ir_graph = rem;
......@@ -876,11 +901,16 @@ dump_ir_graph (ir_graph *irg)
/* the following routines dump the nodes as attached to the blocks. */
/***********************************************************************/
int node_floats(ir_node *n) {
return ((get_op_pinned(get_irn_op(n)) == floats) &&
(get_irg_pinned(current_ir_graph) == floats));
}
void
dump_ir_blocks_nodes (ir_node *n, void *env) {
ir_node *block = (ir_node *)env;
if (is_no_Block(n) && get_nodes_Block(n) == block) {
if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
dump_node(n);
dump_ir_data_edges(n);
}
......@@ -920,9 +950,14 @@ dump_blockless_nodes (ir_node *n, void *env) {
dump_node(n);
dump_ir_data_edges(n);
dump_ir_block_edge(n);
if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
return;
}
if (node_floats(n)) {
dump_node(n);
dump_ir_data_edges(n);
if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
}
if (get_irn_op(n) == op_Bad)
Bad_dumped = 1;
}
void dump_ir_block_graph_2 (ir_graph *irg)
......@@ -1110,3 +1145,7 @@ void dump_constant_entity_values() {
void dump_keepalive_edges() {
dump_keepalive = 1;
}
void dump_out_edges() {
dump_out_edge_flag = 1;
}
......@@ -276,4 +276,21 @@ void dump_constant_entity_values();
void dump_keepalive_edges();
/****m* irdump/dump_constant_entity_values
*
* NAME
* dump_out_edges
* SYNOPSIS
* void dump_out_edges()
* FUNCTION
* Turns on dumping the out edges starting from the Start block in
* dump_ir_graph. To test the consistency of the out datastructure.
* INPUTS
* No inputs
* RESULT
* SEE ALSO
*
***
*/
void dump_out_edges();
# endif /* _IRDUMP_H_ */
......@@ -15,15 +15,18 @@
/* 0 - don't do this optimization
1 - lets see, if there is a better graph */
int optimized = 1; /* Turn off all optimizations */
int opt_cse = 1; /* Hash the nodes */
int opt_global_cse = 0; /* Don't use block predecessor for comparison */
/* @@@ 0 solage code placement fehlt */
int opt_constant_folding = 1; /* Evaluate operations */
int opt_unreachable_code = 1; /* Bad node propagation */
int opt_dead_node_elimination = 1; /* Reclaim memory */
int optimized = 1;
int opt_inline = 1;
int opt_reassociation = 1; /* Reassociate nodes */
int opt_inline = 1; /* Do inlining transformation */
/* set the flags with set_flagname, get the flag with get_flagname */
inline void
set_opt_cse (int value)
{
......@@ -36,6 +39,16 @@ get_opt_cse (void)
return opt_cse;
}
void set_opt_global_cse (int value)
{
opt_global_cse = value;
}
int get_opt_global_cse (void)
{
return opt_global_cse;
}
inline void
set_opt_constant_folding (int value)
{
......@@ -60,6 +73,17 @@ get_opt_unreachable_code(void)
return opt_unreachable_code;
}
inline void
set_opt_reassociation(int value)
{
opt_reassociation = value;
}
inline int
get_opt_reassociation(void)
{
return opt_reassociation;
}
inline void
set_opt_dead_node_elimination (int value)
......
......@@ -28,19 +28,30 @@ int get_optimize (void);
void set_opt_constant_folding (int value);
int get_opt_constant_folding (void);
/* If opt_cse == 1 perfor constant subexpression elimination
(and, if implemented, global code motion. @@@ Right now
cse only within blocks.
/* If opt_cse == 1 perform constant subexpression elimination.
Default: opt_cse == 1. */
void set_opt_cse (int value);
int get_opt_cse (void);
/* If opt_global_cse == 1 and opt_cse == 1 perform intra procedure
constant subexpression elimination for floating nodes. Intra
procedure cse gets the graph into state "floating". It is necessary
to run pre/code motion to get the graph back into state "pinned".
Default: opt_global_cse == 1. */
void set_opt_global_cse (int value);
int get_opt_global_cse (void);
/* If opt_unreachable_code == 1 replace nodes (except Block,
Phi and Tuple) with a Bad predecessor by the Bad node.
Default: opt_unreachable_code == 1. */
inline void set_opt_unreachable_code(int value);
inline int get_opt_unreachable_code(void);
/* If opt_reassociation == 1 reassociation is performed.
Default: opt_reassociation == 1. */
inline void set_opt_reassociation(int value);
inline int get_opt_reassociation(void);
/* If opt_dead_node_elimination == 1 deallocate all dead nodes
by copying the firm graph.
Default: opt_dead_node_elimination == 0. @@@ as buggy, else 1. */
......
/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
/* Coyright (C) 1998 - 2000 by Universitaet Karlsruhe
** All rights reserved.
**
** Author: Christian Schaefer
......@@ -17,7 +17,7 @@
# include "irgopt.h"
# include "irnode_t.h"
# include "irgraph_t.h"
# include "iropt.h"
# include "iropt_t.h"
# include "irgwalk.h"
# include "ircons.h"
# include "misc.h"
......@@ -55,7 +55,7 @@ optimize_in_place_wrapper (ir_node *n, void *env) {
/* optimize all sons after recursion, i.e., the sons' sons are
optimized already. */
for (i = -1; i < get_irn_arity(n); i++) {
optimized = optimize_in_place(get_irn_n(n, i));
optimized = optimize_in_place_2(get_irn_n(n, i));
set_irn_n(n, i, optimized);
}
}
......@@ -65,7 +65,14 @@ local_optimize_graph (ir_graph *irg) {
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
/* Should we clean the value_table in irg for the cse? Better do so... */
/* Handle graph state */
assert(get_irg_phase_state(irg) != phase_building);
if (get_opt_global_cse())
set_irg_pinned(current_ir_graph, floats);
if (get_irg_outs_state(current_ir_graph) == outs_consistent)
set_irg_outs_inconsistent(current_ir_graph);
/* Clean the value_table in irg for the cse. */
del_identities(irg->value_table);
irg->value_table = new_identities();
......@@ -189,7 +196,7 @@ copy_preds (ir_node *n, void *env) {
set_Block_block_visited(n, 0);
/* Local optimization could not merge two subsequent blocks if
in array contained Bads. Now it's possible.
@@@ I removed the call to optimize_in_place as it requires
We don't call optimize_in_place as it requires
that the fields in ir_graph are set properly. */
if (get_Block_n_cfgpreds(nn) == 1
&& get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)
......@@ -292,6 +299,7 @@ copy_graph_env () {
copy_graph();
/* fix the fields in current_ir_graph */
free_End(get_irg_end(current_ir_graph));
set_irg_end (current_ir_graph, get_new_node(get_irg_end(current_ir_graph)));
set_irg_end_block (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
......@@ -337,6 +345,10 @@ dead_node_elimination(ir_graph *irg) {
rem = current_ir_graph;
current_ir_graph = irg;
/* Handle graph state */
assert(get_irg_phase_state(current_ir_graph) != phase_building);
free_outs(current_ir_graph);
if (get_optimize() && get_opt_dead_node_elimination()) {
/* A quiet place, where the old obstack can rest in peace,
......@@ -400,6 +412,11 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
if (!get_opt_inline()) return;
/* Handle graph state */
assert(get_irg_phase_state(current_ir_graph) != phase_building);
if (get_irg_outs_state(current_ir_graph) == outs_consistent)
set_irg_outs_inconsistent(current_ir_graph);
/** Check preconditions **/
assert(get_irn_op(call) == op_Call);
assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
......@@ -505,6 +522,8 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
/** archive keepalives **/
for (i = 0; i < get_irn_arity(end); i++)
add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
/* The new end node will die, but the in array is not on the obstack ... */
free_End(end);
/** Collect control flow from Return blocks to post_calls block. Replace
Return nodes by Jump nodes. **/
......
......@@ -19,6 +19,9 @@ void local_optimize_graph (ir_graph *irg);
/* Performs dead node elimination by copying the ir graph to a new obstack.
Further removes Bad predecesors from Blocks and the corresponding
inputs to Phi nodes.
The graph may not be in state phase_building. The outs datasturcture
is freed, the outs state set to no_outs. (@@@ Change this? -> inconsistent.)
Removes old attributes of nodes.
Attention: the numbers assigned to nodes if the library is compiled for
development/debugging are not conserved by copying. */
void dead_node_elimination(ir_graph *irg);
......
......@@ -76,6 +76,11 @@ new_ir_graph (entity *ent, int n_loc)
res->value_table = new_identities (); /* value table for global value
numbering for optimizing use in
iropt.c */
res->outs = NULL;
res->phase_state = phase_building;
res->pinned = pinned;
res->outs_state = no_outs;
/** Type inforamtion for the procedure of the graph **/
res->ent = ent;
......@@ -132,6 +137,7 @@ ir_graph *new_const_code_irg() {
#endif
res->obst = (struct obstack *) xmalloc (sizeof (struct obstack));
obstack_init (res->obst);
res->pinned = pinned;
res->value_table = new_identities (); /* value table for global value
numbering for optimizing use in
iropt.c */
......@@ -157,8 +163,6 @@ ir_graph *new_const_code_irg() {
return res;
}
/* Frees the passed irgraph.
Deallocates all nodes in this graph and the ir_graph structure.
Sets the field irgraph in the corresponding entity to NULL.
......@@ -338,6 +342,33 @@ set_irg_n_loc (ir_graph *irg, int n_loc)
irg->n_loc = n_loc;
}
irg_phase_state get_irg_phase_state (ir_graph *irg) {
return irg->phase_state;
}
void set_irg_phase_low(ir_graph *irg) {
irg->phase_state = phase_low;
}
op_pinned
get_irg_pinned (ir_graph *irg) {
return irg->pinned;
}
irg_outs_state get_irg_outs_state(ir_graph *irg) {
return irg->outs_state;
}
void set_irg_outs_inconsistent(ir_graph *irg) {
irg->outs_state = outs_inconsistent;
}
inline void
set_irg_pinned (ir_graph *irg, op_pinned p)
{
irg->pinned = p;
}
unsigned long
get_irg_visited (ir_graph *irg)
{
......
......@@ -8,6 +8,8 @@
/* $Id$ */
#include "irop.h"
# ifndef _IRGRAPH_H_
# define _IRGRAPH_H_
# include "tv.h"
......@@ -58,6 +60,10 @@ typedef struct ir_graph ir_graph;
* datastructure is used to build the Phi nodes and removed after
* completion of the graph. There is no path from end to start in the
* graph after calling ir_graph.
* FIELDS
* pinned set to "pinned" if no global cse was performed on the graph.
* set to "floats" if global cse was performed (and during construction:
* did actually change something). Code placement is necessary.
* SOURCE
*/
......@@ -71,7 +77,8 @@ extern ir_graph *current_ir_graph;
entity must be of a method type. The constructor automatically sets the
field irg of the entity as well as current_ir_graph to the new ir graph.
n_loc is the number of local variables in this procedure including
the procedure parameters. */
the procedure parameters.
The state of the ir graph is: phase_building, pinned, no_outs. */
ir_graph *new_ir_graph (entity *ent, int n_loc);
/* Frees the passed irgraph.
......@@ -125,6 +132,55 @@ void set_irg_frame_type (ir_graph *irg, type *ftp);
int get_irg_n_loc (ir_graph *irg);
void set_irg_n_loc (ir_graph *irg, int n_loc);
/********************************************************************************/
/* States of an ir_graph. */
/********************************************************************************/
/* An ir_graph can have different states. These states represent the analysis
information associated with the graph. Optimizations invalidate these
states. */
/* state: phase
values: phase_building, phase_high, phase_low
The irg is in phase_building during construction of the irgraph.
It is in phase_high after construction. All nodes are allowed.
To get the irgraph into phase_low all Sel nodes must be removed
and replaced by explicit address computations. @@@ More conditions? */
typedef enum {
phase_building,
phase_high,
phase_low
} irg_phase_state;
irg_phase_state get_irg_phase_state (ir_graph *irg);
void set_irg_phase_low(ir_graph *irg);
/* state: pinned
The graph is "pinned" if all nodes are accosiated with a basic block.
It is in state "floats" if nodes are in arbitrary blocks. In state
"floats" the block predecessor is set in all nodes, but this can be an
invalid block, i.e., the block is not a dominator of all the uses of
the node.
The enum op_pinned is defined in irop.h. */
op_pinned get_irg_pinned (ir_graph *irg);
/* state: outs_state
Outs are the back edges or def-use edges.
Values: no_outs, outs_consistent, outs_inconsistent
no_outs: outs are not computed, no memory is allocated.
outs_consistent: outs are computed and correct,
outs_inconsistent: outs have been computed, memory is still allocated,
but the graph has been changed since. */
typedef enum {
no_outs,
outs_consistent,
outs_inconsistent
} irg_outs_state;
irg_outs_state get_irg_outs_state(ir_graph *irg);
void set_irg_outs_inconsistent(ir_graph *irg);
/* increments visited by one */
void inc_irg_visited(ir_graph *irg);
unsigned long get_irg_visited (ir_graph *irg);
......
......@@ -16,6 +16,7 @@
/* ir_graph holds all information for a procedure */
struct ir_graph {
/** Basics of the representation **/
struct entity *ent; /* The entity of this procedure, i.e.,
the type of the procedure and the
class it belongs to. */
......@@ -33,26 +34,39 @@ struct ir_graph {
struct ir_node *bad; /* bad node of this ir_graph, the one and
only in this graph */
struct obstack *obst; /* obstack where all of the ir_nodes live */
struct ir_node *current_block; /* block for newly gen_*()-erated
ir_nodes */
/** Fields indicating different states of irgraph **/
irg_phase_state phase_state; /* compiler phase */
op_pinned pinned; /* Flag for status of nodes */
irg_outs_state outs_state; /* Out edges. */
/** Fields for construction **/
#if USE_EXPICIT_PHI_IN_STACK
struct Phi_in_stack *Phi_in_stack; /* needed for automatic Phi construction */
#endif
struct ir_node *current_block; /* block for newly gen_*()-erated
ir_nodes */
int n_loc; /* number of local variable in this
procedure including procedure parameters. */
pset *value_table; /* value table for global value numbering
/** Fields for optimizations / analysis information **/
pset *value_table; /* hash table for global value numbering (cse)
for optimizing use in iropt.c */
struct ir_node **outs; /* Space for the out arrays. */
/** Fields for Walking the graph **/
unsigned long visited; /* this flag is an identifier for
ir walk. it will be incremented,
every time, someone walk through
ir walk. it will be incremented
every time someone walks through
the graph */
unsigned long block_visited; /* same as visited, for a
complete block */
unsigned long block_visited; /* same as visited, for a complete block */
};
/* Make a rudimentary ir graph for the constant code.
Must look like a correct irg, spare everything else. */
ir_graph *new_const_code_irg();
inline void
set_irg_pinned (ir_graph *irg, op_pinned p);
# endif /* _IRGRAPH_T_H_ */
......@@ -96,6 +96,7 @@ new_ir_node (ir_graph *irg, ir_node *block, ir_op *op, ir_mode *mode,
memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
}
res->in[0] = block;
res->out = NULL;
#ifdef DEBUG_libfirm
res->node_nr = get_irp_new_node_nr();
......@@ -208,9 +209,12 @@ set_irn_in (ir_node *node, int arity, ir_node **in) {
inline ir_node *
get_irn_n (ir_node *node, int n)
{
ir_node *res;
assert (node);
assert (get_irn_arity (node) > n);
return skip_nop(node->in[n+1]);
assert ((get_irn_arity (node) > n) && (-1 <= n));
res = skip_nop(node->in[n+1]);
if (res != node->in[n+1]) node->in[n+1] = res;
return res;
}