-static void handle_first(ir_node *node, void *ctx)
-{
- env_t *env = ctx;
- ir_op *op = get_irn_op(node);
- ir_node *adr, *block, *mem, *unk, **value_arr, **in;
- unsigned vnum;
- int i, j, n;
- list_entry_t *l;
-
- if (op == op_Load) {
- /* a load, check if we can resolve it */
- adr = get_Load_ptr(node);
-
- if (! is_Sel(adr))
- return;
-
- if (! pset_find_ptr(env->sels, adr))
- return;
-
- /* ok, we have a Load that will be replaced */
- vnum = GET_VNUM(adr);
-
- assert(vnum < (unsigned)env->nvals);
-
- block = get_nodes_block(node);
- value_arr = get_irn_link(block);
-
- /* check, if we can replace this Load */
- if (value_arr[vnum]) {
- mem = get_Load_mem(node);
-
- turn_into_tuple(node, pn_Load_max);
- set_Tuple_pred(node, pn_Load_M, mem);
- set_Tuple_pred(node, pn_Load_res, value_arr[vnum]);
- set_Tuple_pred(node, pn_Load_X_except, new_Bad());
- }
- else {
- l = obstack_alloc(&env->obst, sizeof(*l));
- l->node = node;
- l->vnum = vnum;
+static void topologic_walker(ir_node *node, void *ctx) {
+ env_t *env = ctx;
+ ir_op *op = get_irn_op(node);
+ ir_node *adr, *block, *mem, *unk, **value_arr, **in, *val;
+ ir_mode *mode;
+ unsigned vnum;
+ int i, j, n;
+ list_entry_t *l;
+
+ if (op == op_Load) {
+ /* a load, check if we can resolve it */
+ adr = get_Load_ptr(node);
+
+ if (! is_Sel(adr))
+ return;
+
+ if (! pset_find_ptr(env->sels, adr))
+ return;
+
+ /* ok, we have a Load that will be replaced */
+ vnum = GET_VNUM(adr);
+
+ assert(vnum < (unsigned)env->nvals);
+
+ block = get_nodes_block(node);
+ value_arr = get_irn_link(block);
+
+ /* check, if we can replace this Load */
+ if (value_arr[vnum]) {
+ mem = get_Load_mem(node);
+
+ /* Beware: A Load can contain a hidden conversion in Firm.
+ This happens for instance in the following code:
+
+ int i;
+ unsigned j = *(unsigned *)&i;
+
+ Handle this here. */
+ val = value_arr[vnum];
+ mode = get_Load_mode(node);
+ if (mode != get_irn_mode(val))
+ val = new_d_Conv(get_irn_dbg_info(node), val, mode);
+
+ turn_into_tuple(node, pn_Load_max);
+ set_Tuple_pred(node, pn_Load_M, mem);
+ set_Tuple_pred(node, pn_Load_res, val);
+ set_Tuple_pred(node, pn_Load_X_regular, new_r_Jmp(current_ir_graph, block));
+ set_Tuple_pred(node, pn_Load_X_except, new_Bad());
+ } else {
+ l = obstack_alloc(&env->obst, sizeof(*l));
+ l->node = node;
+ l->vnum = vnum;
+
+ set_irn_link(node, env->fix_loads);
+ env->fix_loads = l;
+ }
+ } else if (op == op_Store) {
+ /* a Store always can be replaced */
+ adr = get_Store_ptr(node);
+
+ if (! is_Sel(adr))
+ return;
+
+ if (! pset_find_ptr(env->sels, adr))
+ return;
+
+ vnum = GET_VNUM(adr);
+
+ assert(vnum < (unsigned)env->nvals);
+
+ block = get_nodes_block(node);
+ value_arr = get_irn_link(block);
+
+ /* Beware: A Store can contain a hidden conversion in Firm. */
+ val = get_Store_value(node);
+ if (get_irn_mode(val) != env->modes[vnum])
+ val = new_d_Conv(get_irn_dbg_info(node), val, env->modes[vnum]);
+ value_arr[vnum] = val;
+
+ mem = get_Store_mem(node);
+ block = get_nodes_block(node);
+
+ turn_into_tuple(node, pn_Store_max);
+ set_Tuple_pred(node, pn_Store_M, mem);
+ set_Tuple_pred(node, pn_Store_X_regular, new_r_Jmp(current_ir_graph, block));
+ set_Tuple_pred(node, pn_Store_X_except, new_Bad());
+ } else if (op == op_Phi && get_irn_mode(node) == mode_M) {
+ /*
+ * found a memory Phi: Here, we must create new Phi nodes
+ */
+ block = get_nodes_block(node);
+ value_arr = get_irn_link(block);
+
+ n = get_Block_n_cfgpreds(block);
+
+ in = alloca(sizeof(*in) * n);
+
+ for (i = env->nvals - 1; i >= 0; --i) {
+ unk = new_Unknown(env->modes[i]);
+ for (j = n - 1; j >= 0; --j)
+ in[j] = unk;
+
+ value_arr[i] = new_r_Phi(current_ir_graph, block, n, in, env->modes[i]);
+
+ l = obstack_alloc(&env->obst, sizeof(*l));
+ l->node = value_arr[i];
+ l->vnum = i;