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

Extended semantics of Cond node. There are two flavors now.

Optimizations during construction are save.  For others first
transform to standard flavor.  Optimization of Cond is
turned of for new flavor.

parent ababa4c9
......@@ -141,6 +141,17 @@ new_r_Proj (ir_graph *irg, ir_node *block, ir_node *arg, ir_mode *mode,
ir_node *
new_r_defaultProj (ir_graph *irg, ir_node *block, ir_node *arg,
long max_proj)
ir_node *res;
assert((arg->op==op_Cond) && (get_irn_mode(arg->in[1]) == mode_I));
arg->attr.c = fragmentary;
res = new_r_Proj (irg, block, arg, mode_X, max_proj);
return res;
ir_node *
new_r_Conv (ir_graph *irg, ir_node *block, ir_node *op, ir_mode *mode)
......@@ -397,6 +408,7 @@ new_r_Cond (ir_graph *irg, ir_node *block, ir_node *c)
ir_node *in[1] = {c};
ir_node *res;
res = new_ir_node (irg, block, op_Cond, mode_T, 1, in);
res->attr.c = dense;
res = optimize (res);
irn_vrfy (res);
return res;
......@@ -1288,6 +1300,16 @@ new_Proj (ir_node *arg, ir_mode *mode, long proj)
arg, mode, proj);
ir_node *
new_defaultProj (ir_node *arg, long max_proj)
ir_node *res;
assert((arg->op==op_Cond) && (get_irn_mode(arg->in[1]) == mode_I));
arg->attr.c = fragmentary;
res = new_Proj (arg, mode_X, max_proj);
return res;
ir_node *
new_Conv (ir_node *op, ir_mode *mode)
......@@ -1141,6 +1141,8 @@ ir_node *new_r_Free (ir_graph *irg, ir_node *block, ir_node *store,
ir_node *new_r_Sync (ir_graph *irg, ir_node *block, int arity, ir_node **in);
ir_node *new_r_Proj (ir_graph *irg, ir_node *block, ir_node *arg,
ir_mode *mode, long proj);
ir_node *new_r_defaultProj (ir_graph *irg, ir_node *block, ir_node *arg,
long max_proj);
ir_node *new_r_Tuple (ir_graph *irg, ir_node *block,
int arity, ir_node **in);
ir_node *new_r_Id (ir_graph *irg, ir_node *block,
......@@ -1201,6 +1203,7 @@ ir_node *new_Free (ir_node *store, ir_node *ptr, ir_node *size,
type *free_type);
ir_node *new_Sync (int arity, ir_node **in);
ir_node *new_Proj (ir_node *arg, ir_mode *mode, long proj);
ir_node *new_defaultProj (ir_node *arg, long max_proj);
ir_node *new_Tuple (int arity, ir_node **in);
ir_node *new_Id (ir_node *val, ir_mode *mode);
ir_node *new_Bad (void);
......@@ -491,6 +491,18 @@ set_Cond_selector (ir_node *node, ir_node *selector) {
set_irn_n(node, 0, selector);
inline cond_kind
get_Cond_kind (ir_node *node) {
assert (node->op == op_Cond);
return node->attr.c;
inline void
set_Cond_kind (ir_node *node, cond_kind kind) {
assert (node->op == op_Cond);
node->attr.c = kind;
inline ir_node *
get_Return_mem (ir_node *node) {
assert (node->op == op_Return);
......@@ -136,8 +136,37 @@ inline void set_Block_block_visited (ir_node *node, unsigned long visit);
inline ir_node *get_Block_graph_arr (ir_node *node, int pos);
inline void set_Block_graph_arr (ir_node *node, int pos, ir_node *value);
/* We distinguish three kinds of Cond nodes. These can be distinguished
by the mode of the selector operand and an internal flag of type cond_kind.
First we distinguish binary Conds and switch Conds.
A binary Cond has as selector a boolean value. Proj(0) projects the control
flow for case "False", Proj(1) the control flow for "True". A binary Cond
is recognized by the boolean selector.
The switch Cond has as selector an unsigned integer. It produces as result
an n+1 Tuple (cf0, ... , cfn) of control flows.
We differ two flavours of this Cond. The first, the dense Cond, passes
control along output i if the selector value is i, 0 <= i <= n. If the
selector value is >n it passes control along output n.
The second Cond flavor differes in the treatment of cases not specified in
the source program. It magically knows about the existence of Proj nodes.
It only passes control along output i, 0 <= i <= n, if a node Proj(Cond, i)
exists. Else it passes control along output n (even if this Proj does not
exist.) This Cond we call "fragmentary". There is a special constructor
new_defaultProj that automatically sets the flavor.
The two switch flavors are distinguished by a flag of type cond_kind. Default
flavor is "dense"
typedef enum {
dense, /* Default. Missing Proj nodes are dead control flow. */
fragmentary /* Special. No control flow optimizations allowed. Missing
Proj nodes mean default control flow, i.e., Proj(n). */
} cond_kind;
inline ir_node *get_Cond_selector (ir_node *node);
inline void set_Cond_selector (ir_node *node, ir_node *selector);
inline cond_kind get_Cond_kind (ir_node *node);
inline void set_Cond_kind (ir_node *node, cond_kind kind);
inline ir_node *get_Return_mem (ir_node *node);
inline void set_Return_mem (ir_node *node, ir_node *mem);
......@@ -57,6 +57,7 @@ typedef union {
long proj; /* For Proj: contains the result position to project */
alloc_attr a; /* For Alloc. */
type *f; /* For Free. */
cond_kind c; /* For Cond. */
int phi0_pos; /* For Phi. Used to remember the value defined by
this Phi node. Needed when the Phi is completed
to call get_r_internal_value to find the
......@@ -86,7 +86,7 @@ init_op(void)
op_Start = new_ir_op (iro_Start, id_from_str ("Start", 5), sizeof (block_attr), 1);
op_End = new_ir_op (iro_End, id_from_str ("End", 3), sizeof (block_attr), 1);
op_Jmp = new_ir_op (iro_Jmp, id_from_str ("Jmp", 3), 0, 0);
op_Cond = new_ir_op (iro_Cond, id_from_str ("Cond", 4), 0, 1);
op_Cond = new_ir_op (iro_Cond, id_from_str ("Cond", 4), sizeof(cond_kind), 1);
op_Return = new_ir_op (iro_Return, id_from_str ("Return", 6), 0, 1);
op_Raise = new_ir_op (iro_Raise, id_from_str ("Raise", 5), 0, 1);
......@@ -654,7 +654,7 @@ transform_node (ir_node *n)
set_Tuple_pred(n, 0, jmp);
set_Tuple_pred(n, 1, new_Bad());
} else if (ta && (get_irn_mode(a) == mode_I)) {
} else if (ta && (get_irn_mode(a) == mode_I) && (get_Cond_kind(n) == dense)) {
/* I don't want to allow Tuples smaller than the biggest Proj.
Also this tuple might get really big...
I generate the Jmp here, and remember it in link. Link is used
......@@ -698,7 +698,8 @@ transform_node (ir_node *n)
set_Proj_proj(n, 0);
} else if ( (get_irn_op(a) == op_Cond)
&& (get_irn_mode(get_Cond_selector(a)) == mode_I)
&& value_of(a)) {
&& value_of(a)
&& (get_Cond_kind(a) == dense)) {
/* The Cond is a Switch on a Constant */
if (get_Proj_proj(n) == tv_val_CHIL(value_of(a))) {
/* The always taken branch, reuse the existing Jmp. */
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