3 * File name: ir/arch/modeconv.c
4 * Purpose: integer mode conversion
8 * Copyright: (c) 1998-2004 Universität Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
15 * Contains the mode conversion for architectures that did not support lesser
16 * integer modes. Converts all Op(mode_l) into Op(mode) operations by adding
17 * conversions were needed. These Conv operations must be implemented in the backend
18 * as bit-reducing ops.
25 # include "irnode_t.h"
26 # include "irgraph_t.h"
27 # include "irmode_t.h"
29 # include "ircons_t.h"
32 # include "iropt_dbg.h"
33 # include "irflag_t.h"
35 # include "modeconv.h"
36 # include "firmstat.h"
38 typedef struct _walker_t {
39 int bits; /**< number of bits in the destination mode */
40 ir_mode *s_mode; /**< signed destination mode */
41 ir_mode *u_mode; /**< unsigned destination mode */
42 int changes; /**< non-zero if the graph was changed */
46 * Add a Conv node where needed on output
48 static ir_node *fix_irn_output(ir_node *node, ir_mode *mode)
50 switch (get_irn_opcode(node)) {
52 /* Args, Load, Div, Mod */
54 /* Hmm, maybe the Conv should be replaced */
56 ir_node *block = get_nodes_block(node);
58 if (get_irn_mode(node) != mode)
59 return new_r_Conv(current_ir_graph, block, node, mode);
69 * Add a Conv node where needed on input
71 static ir_node *fix_irn_input(opcode code, ir_node *block, ir_node *pred, ir_mode *mode)
82 ir_mode *p_mode = get_irn_mode(pred);
84 if (p_mode != mode && mode_is_int(p_mode))
85 return new_r_Conv(current_ir_graph, block, pred, mode);
94 * fix the mode of the operations if possible
96 static void fix_mode(ir_node *n, ir_mode *mode)
98 opcode code = get_irn_opcode(n);
100 if (code == iro_Proj) {
101 code = get_irn_opcode(get_Proj_pred(n));
112 set_irn_mode(n, mode);
117 * walker for the mode conversion
119 static void do_mode_conv(ir_node *n, void *env)
121 walker_t *wenv = env;
122 ir_mode *mode = get_irn_mode(n);
126 /* save the old mode, we need this info later */
127 set_irn_link(n, mode);
129 /* special case: fix the Return */
131 entity *ent = get_irg_entity(current_ir_graph);
132 ir_type *mt = get_entity_type(ent);
133 int i, n_ress = get_method_n_ress(mt);
135 mode = mode_is_signed(mode) ? wenv->s_mode : wenv->u_mode;
136 block = get_nodes_block(n);
137 for (i = 0; i < n_ress; ++i) {
138 ir_node *pred = get_irn_n(n, i + 1);
139 ir_type *rt = get_method_res_type(mt, i);
141 if (is_atomic_type(rt)) {
142 mode = get_type_mode(rt);
144 if (mode != get_irn_mode(pred)) {
145 pred = fix_irn_input(iro_Return, block, pred, mode);
147 set_irn_n(n, i + 1, pred);
155 /* convert only integer modes with less than 'bits' bits */
156 if (mode_is_int(mode) && get_mode_size_bits(mode) < wenv->bits && get_irn_op(n) != op_Conv) {
157 mode = mode_is_signed(mode) ? wenv->s_mode : wenv->u_mode;
159 code = get_irn_opcode(n);
161 if (code == iro_Conv) {
162 /* formally, the was a convert from modeA to modeB here.
163 * So, the expression before the conv must have modeA. */
164 ir_node *pred = get_Conv_op(n);
165 ir_mode *modeA = get_irn_link(pred);
167 if (modeA != get_irn_mode(pred)) {
168 pred = new_r_Conv(current_ir_graph, get_nodes_block(pred), pred, modeA);
169 set_Conv_op(n, pred);
172 else if (code == iro_Proj) {
173 /* special case for Proj: we must fix it's pred */
174 ir_node *oper = get_Proj_pred(n);
175 int i, arity = get_irn_arity(oper);
177 code = get_irn_opcode(oper);
178 block = get_nodes_block(oper);
180 for (i = 0; i < arity; ++i) {
181 ir_node *pred = get_irn_n(oper, i);
183 pred = fix_irn_input(code, block, pred, mode);
185 set_irn_n(oper, i, pred);
190 int i, arity = get_irn_arity(n);
192 block = get_nodes_block(n);
193 for (i = 0; i < arity; ++i) {
194 ir_node *pred = get_irn_n(n, i);
196 pred = fix_irn_output(pred, mode);
197 pred = fix_irn_input(code, block, pred, mode);
199 set_irn_n(n, i, pred);
207 if (get_irn_op(n) == op_Conv) {
208 /* formally, the was a convert from modeA to modeB here.
209 * So, the expression before the conv must have modeA. */
210 ir_node *pred = get_Conv_op(n);
211 ir_mode *modeA = get_irn_link(pred);
213 if (modeA != get_irn_mode(pred)) {
214 pred = new_r_Conv(current_ir_graph, get_nodes_block(pred), pred, modeA);
215 set_Conv_op(n, pred);
218 /* old conv may now get useless */
219 if (get_irn_mode(n) == get_irn_mode(pred)) {
220 exchange(n, get_Conv_op(n));
227 * do the integer mode conversion
229 void arch_mode_conversion(ir_graph *irg, ir_mode *mode)
233 assert(get_irg_phase_state(irg) != phase_building);
235 assert(mode_is_int(mode));
237 env.s_mode = mode_is_signed(mode) ? mode: find_signed_mode(mode) ;
238 env.u_mode = mode_is_signed(mode) ? find_unsigned_mode(mode) : mode;
239 env.bits = get_mode_size_bits(mode);
242 assert(env.s_mode && env.u_mode && "Could not find modes");
244 irg_walk_graph(irg, NULL, do_mode_conv, &env);
246 /* Handle graph state. We never change control flow. */
248 set_irg_outs_inconsistent(current_ir_graph);