2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Lower small CopyB nodes into a series of Load/store
23 * @author Michael Beck, Matthias Braun
41 typedef struct entry entry_t;
43 struct list_head list;
47 typedef struct walk_env {
49 struct obstack obst; /**< the obstack where data is allocated on */
50 struct list_head list; /**< the list of copyb nodes */
53 static ir_mode *get_ir_mode(unsigned bytes)
56 case 1: return mode_Bu;
57 case 2: return mode_Hu;
58 case 4: return mode_Iu;
59 case 8: return mode_Lu;
60 case 16: return mode_LLu;
62 panic("unexpected mode size requested in copyb lowering");
69 static void lower_copyb_nodes(ir_node *irn, unsigned mode_bytes) {
70 ir_graph *irg = current_ir_graph;
81 addr_src = get_CopyB_src(irn);
82 addr_dst = get_CopyB_dst(irn);
83 mem = get_CopyB_mem(irn);
84 addr_mode = get_irn_mode(addr_src);
85 block = get_nodes_block(irn);
87 tp = get_CopyB_type(irn);
88 size = get_type_size_bytes(tp);
91 while (offset < size) {
92 mode = get_ir_mode(mode_bytes);
93 for (; offset + mode_bytes <= size; offset += mode_bytes) {
94 /* construct offset */
103 addr_const = new_r_Const_long(irg, block, mode_Iu, offset);
104 add = new_r_Add(irg, block, addr_src, addr_const, addr_mode);
106 load = new_r_Load(irg, block, mem, add, mode);
107 load_res = new_r_Proj(irg, block, load, mode, pn_Load_res);
108 load_mem = new_r_Proj(irg, block, load, mode_M, pn_Load_M);
110 addr_const = new_r_Const_long(irg, block, mode_Iu, offset);
111 add = new_r_Add(irg, block, addr_dst, addr_const, addr_mode);
113 store = new_r_Store(irg, block, mem, add, load_res);
114 store_mem = new_r_Proj(irg, block, store, mode_M, pn_Store_M);
122 turn_into_tuple(irn, pn_CopyB_max);
123 set_Tuple_pred(irn, pn_CopyB_M_regular, mem);
124 set_Tuple_pred(irn, pn_CopyB_X_regular, get_irg_bad(irg));
125 set_Tuple_pred(irn, pn_CopyB_X_except, get_irg_bad(irg));
126 set_Tuple_pred(irn, pn_CopyB_M_except, get_irg_bad(irg));
130 * Post-Walker: find small CopyB nodes.
132 static void find_copyb_nodes(ir_node *irn, void *ctx) {
133 walk_env_t *env = ctx;
139 ir_node *pred = get_Proj_pred(irn);
141 if (is_CopyB(pred) && get_Proj_proj(irn) != pn_CopyB_M_regular) {
142 /* found an exception Proj: remove it from the list again */
143 entry = get_irn_link(pred);
144 list_del(&entry->list);
152 tp = get_CopyB_type(irn);
153 if (get_type_state(tp) != layout_fixed)
156 size = get_type_size_bytes(tp);
157 if (size > env->max_size)
161 entry = obstack_alloc(&env->obst, sizeof(*entry));
163 INIT_LIST_HEAD(&entry->list);
164 set_irn_link(irn, entry);
165 list_add_tail(&entry->list, &env->list);
168 void lower_CopyB(ir_graph *irg, unsigned max_size, unsigned native_mode_bytes)
172 ir_graph *rem = current_ir_graph;
174 current_ir_graph = irg;
176 obstack_init(&env.obst);
177 env.max_size = max_size;
178 INIT_LIST_HEAD(&env.list);
179 irg_walk_graph(irg, NULL, find_copyb_nodes, &env);
181 list_for_each_entry(entry_t, entry, &env.list, list) {
182 lower_copyb_nodes(entry->copyb, native_mode_bytes);
185 obstack_free(&env.obst, NULL);
186 current_ir_graph = rem;