+static void turn_back_am(ir_node *node)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = get_nodes_block(node);
+ ir_node *base = get_irn_n(node, n_ia32_base);
+ ir_node *index = get_irn_n(node, n_ia32_index);
+ ir_node *mem = get_irn_n(node, n_ia32_mem);
+ ir_node *noreg = ia32_new_NoReg_gp(ia32_current_cg);
+ ir_node *load;
+ ir_node *load_res;
+ ir_node *mem_proj;
+ const ir_edge_t *edge;
+
+ load = new_rd_ia32_Load(dbgi, irg, block, base, index, mem);
+ load_res = new_rd_Proj(dbgi, irg, block, load, mode_Iu, pn_ia32_Load_res);
+
+ ia32_copy_am_attrs(load, node);
+ set_irn_n(node, n_ia32_mem, new_NoMem());
+
+ switch (get_ia32_am_arity(node)) {
+ case ia32_am_unary:
+ set_irn_n(node, n_ia32_unary_op, load_res);
+ break;
+
+ case ia32_am_binary:
+ if (is_ia32_Immediate(get_irn_n(node, n_ia32_Cmp_right))) {
+ assert(is_ia32_Cmp(node) || is_ia32_Cmp8Bit(node) ||
+ is_ia32_Test(node) || is_ia32_Test8Bit(node));
+ set_irn_n(node, n_ia32_binary_left, load_res);
+ } else {
+ set_irn_n(node, n_ia32_binary_right, load_res);
+ }
+ break;
+
+ case ia32_am_ternary:
+ set_irn_n(node, n_ia32_binary_right, load_res);
+ break;
+
+ default: break;
+ }
+ set_irn_n(node, n_ia32_base, noreg);
+ set_irn_n(node, n_ia32_index, noreg);
+ set_ia32_am_offs_int(node, 0);
+ set_ia32_am_sc(node, NULL);
+ set_ia32_am_scale(node, 0);
+ clear_ia32_am_sc_sign(node);
+
+ /* rewire mem-proj */
+ if (get_irn_mode(node) == mode_T) {
+ mem_proj = NULL;
+ foreach_out_edge(node, edge) {
+ ir_node *out = get_edge_src_irn(edge);
+ if(get_irn_mode(out) == mode_M) {
+ assert(mem_proj == NULL);
+ mem_proj = out;
+ }
+ }
+
+ if(mem_proj != NULL) {
+ set_Proj_pred(mem_proj, load);
+ set_Proj_proj(mem_proj, pn_ia32_Load_M);
+ }
+ }
+
+ set_ia32_op_type(node, ia32_Normal);
+ if (sched_is_scheduled(node))
+ sched_add_before(node, load);
+}
+
+static ir_node *flags_remat(ir_node *node, ir_node *after)
+{
+ /* we should turn back source address mode when rematerializing nodes */
+ ia32_op_type_t type;
+ ir_node *block;
+ ir_node *copy;
+
+ if (is_Block(after)) {
+ block = after;
+ } else {
+ block = get_nodes_block(after);
+ }
+
+ type = get_ia32_op_type(node);
+ switch (type) {
+ case ia32_AddrModeS:
+ turn_back_am(node);
+ break;
+
+ case ia32_AddrModeD:
+ /* TODO implement this later... */
+ panic("found DestAM with flag user %+F this should not happen", node);
+ break;
+
+ default: assert(type == ia32_Normal); break;
+ }
+
+ copy = exact_copy(node);
+ set_nodes_block(copy, block);
+ sched_add_after(after, copy);
+
+ return copy;
+}
+