2 * Copyright (C) 1995-2008 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 Double word operations, ie 64bit -> 32bit, 32bit -> 16bit etc.
24 * @author Michael Beck
36 #include "irgraph_t.h"
41 #include "dbginfo_t.h"
42 #include "iropt_dbg.h"
56 /** A map from mode to a primitive type. */
57 static pmap *prim_types;
59 /** A map from (op, imode, omode) to Intrinsic functions entities. */
60 static set *intrinsic_fkt;
62 /** A map from (imode, omode) to conv function types. */
63 static set *conv_types;
65 /** A map from a method type to its lowered type. */
66 static pmap *lowered_type;
68 /** The types for the binop and unop intrinsics. */
69 static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *shiftop_tp_u, *shiftop_tp_s, *tp_s, *tp_u;
71 /** the debug handle */
72 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
75 * An entry in the (op, imode, omode) -> entity map.
77 typedef struct _op_mode_entry {
78 const ir_op *op; /**< the op */
79 const ir_mode *imode; /**< the input mode */
80 const ir_mode *omode; /**< the output mode */
81 ir_entity *ent; /**< the associated entity of this (op, imode, omode) triple */
85 * An entry in the (imode, omode) -> tp map.
87 typedef struct _conv_tp_entry {
88 const ir_mode *imode; /**< the input mode */
89 const ir_mode *omode; /**< the output mode */
90 ir_type *mtd; /**< the associated method type of this (imode, omode) pair */
94 * Every double word node will be replaced,
95 * we need some store to hold the replacement:
97 typedef struct _node_entry_t {
98 ir_node *low_word; /**< the low word */
99 ir_node *high_word; /**< the high word */
103 MUST_BE_LOWERED = 1, /**< graph must be lowered */
104 CF_CHANGED = 2, /**< control flow was changed */
108 * The lower environment.
110 typedef struct _lower_env_t {
111 node_entry_t **entries; /**< entries per node */
112 struct obstack obst; /**< an obstack holding the temporary data */
113 ir_type *l_mtp; /**< lowered method type of the current method */
114 tarval *tv_mode_bytes; /**< a tarval containing the number of bytes in the lowered modes */
115 tarval *tv_mode_bits; /**< a tarval containing the number of bits in the lowered modes */
116 pdeq *waitq; /**< a wait queue of all nodes that must be handled later */
117 pmap *proj_2_block; /**< a map from ProjX to its destination blocks */
118 ident *first_id; /**< .l for little and .h for big endian */
119 ident *next_id; /**< .h for little and .l for big endian */
120 const lwrdw_param_t *params; /**< transformation parameter */
121 unsigned flags; /**< some flags */
122 int n_entries; /**< number of entries */
124 ir_type *value_param_tp; /**< the old value param type */
129 * Get a primitive mode for a mode.
131 static ir_type *get_primitive_type(ir_mode *mode) {
132 pmap_entry *entry = pmap_find(prim_types, mode);
139 snprintf(buf, sizeof(buf), "_prim_%s", get_mode_name(mode));
140 tp = new_type_primitive(new_id_from_str(buf), mode);
142 pmap_insert(prim_types, mode, tp);
144 } /* get_primitive_type */
147 * Create a method type for a Conv emulation from imode to omode.
149 static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env) {
150 conv_tp_entry_t key, *entry;
157 entry = set_insert(conv_types, &key, sizeof(key), HASH_PTR(imode) ^ HASH_PTR(omode));
159 int n_param = 1, n_res = 1;
162 if (imode == env->params->high_signed || imode == env->params->high_unsigned)
164 if (omode == env->params->high_signed || omode == env->params->high_unsigned)
167 /* create a new one */
168 snprintf(buf, sizeof(buf), "LConv%s%s", get_mode_name(imode), get_mode_name(omode));
169 mtd = new_type_method(new_id_from_str(buf), n_param, n_res);
171 /* set param types and result types */
173 if (imode == env->params->high_signed) {
174 set_method_param_type(mtd, n_param++, tp_u);
175 set_method_param_type(mtd, n_param++, tp_s);
176 } else if (imode == env->params->high_unsigned) {
177 set_method_param_type(mtd, n_param++, tp_u);
178 set_method_param_type(mtd, n_param++, tp_u);
180 ir_type *tp = get_primitive_type(imode);
181 set_method_param_type(mtd, n_param++, tp);
185 if (omode == env->params->high_signed) {
186 set_method_res_type(mtd, n_res++, tp_u);
187 set_method_res_type(mtd, n_res++, tp_s);
188 } else if (omode == env->params->high_unsigned) {
189 set_method_res_type(mtd, n_res++, tp_u);
190 set_method_res_type(mtd, n_res++, tp_u);
192 ir_type *tp = get_primitive_type(omode);
193 set_method_res_type(mtd, n_res++, tp);
200 } /* get_conv_type */
203 * Add an additional control flow input to a block.
204 * Patch all Phi nodes. The new Phi inputs are copied from
205 * old input number nr.
207 static void add_block_cf_input_nr(ir_node *block, int nr, ir_node *cf)
209 int i, arity = get_irn_arity(block);
214 NEW_ARR_A(ir_node *, in, arity + 1);
215 for (i = 0; i < arity; ++i)
216 in[i] = get_irn_n(block, i);
219 set_irn_in(block, i + 1, in);
221 for (phi = get_Block_phis(block); phi != NULL; phi = get_Phi_next(phi)) {
222 for (i = 0; i < arity; ++i)
223 in[i] = get_irn_n(phi, i);
225 set_irn_in(phi, i + 1, in);
227 } /* add_block_cf_input_nr */
230 * Add an additional control flow input to a block.
231 * Patch all Phi nodes. The new Phi inputs are copied from
232 * old input from cf tmpl.
234 static void add_block_cf_input(ir_node *block, ir_node *tmpl, ir_node *cf)
236 int i, arity = get_irn_arity(block);
239 for (i = 0; i < arity; ++i) {
240 if (get_irn_n(block, i) == tmpl) {
246 add_block_cf_input_nr(block, nr, cf);
247 } /* add_block_cf_input */
250 * Return the "operational" mode of a Firm node.
252 static ir_mode *get_irn_op_mode(ir_node *node)
254 switch (get_irn_opcode(node)) {
256 return get_Load_mode(node);
258 return get_irn_mode(get_Store_value(node));
260 return get_irn_mode(get_DivMod_left(node));
262 return get_irn_mode(get_Div_left(node));
264 return get_irn_mode(get_Mod_left(node));
266 return get_irn_mode(get_Cmp_left(node));
268 return get_irn_mode(node);
270 } /* get_irn_op_mode */
273 * Walker, prepare the node links.
275 static void prepare_links(ir_node *node, void *env)
277 lower_env_t *lenv = env;
278 ir_mode *mode = get_irn_op_mode(node);
282 if (mode == lenv->params->high_signed ||
283 mode == lenv->params->high_unsigned) {
284 /* ok, found a node that will be lowered */
285 link = obstack_alloc(&lenv->obst, sizeof(*link));
287 memset(link, 0, sizeof(*link));
289 idx = get_irn_idx(node);
290 if (idx >= lenv->n_entries) {
291 /* enlarge: this happens only for Rotl nodes which is RARELY */
292 int old = lenv->n_entries;
293 int n_idx = idx + (idx >> 3);
295 ARR_RESIZE(node_entry_t *, lenv->entries, n_idx);
296 memset(&lenv->entries[old], 0, (n_idx - old) * sizeof(lenv->entries[0]));
297 lenv->n_entries = n_idx;
299 lenv->entries[idx] = link;
300 lenv->flags |= MUST_BE_LOWERED;
301 } else if (is_Conv(node)) {
302 /* Conv nodes have two modes */
303 ir_node *pred = get_Conv_op(node);
304 mode = get_irn_mode(pred);
306 if (mode == lenv->params->high_signed ||
307 mode == lenv->params->high_unsigned) {
308 /* must lower this node either but don't need a link */
309 lenv->flags |= MUST_BE_LOWERED;
315 /* link all Proj nodes to its predecessor:
316 Note that Tuple Proj's and its Projs are linked either. */
317 ir_node *pred = get_Proj_pred(node);
319 set_irn_link(node, get_irn_link(pred));
320 set_irn_link(pred, node);
321 } else if (is_Phi(node)) {
322 /* link all Phi nodes to its block */
323 ir_node *block = get_nodes_block(node);
324 add_Block_phi(block, node);
325 } else if (is_Block(node)) {
326 /* fill the Proj -> Block map */
327 for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
328 ir_node *pred = get_Block_cfgpred(node, i);
331 pmap_insert(lenv->proj_2_block, pred, node);
334 } /* prepare_links */
337 * Translate a Constant: create two.
339 static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env) {
340 tarval *tv, *tv_l, *tv_h;
342 dbg_info *dbg = get_irn_dbg_info(node);
344 ir_graph *irg = current_ir_graph;
345 ir_mode *low_mode = env->params->low_unsigned;
347 tv = get_Const_tarval(node);
349 tv_l = tarval_convert_to(tv, low_mode);
350 low = new_rd_Const(dbg, irg, tv_l);
352 tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
353 high = new_rd_Const(dbg, irg, tv_h);
355 idx = get_irn_idx(node);
356 assert(idx < env->n_entries);
357 env->entries[idx]->low_word = low;
358 env->entries[idx]->high_word = high;
362 * Translate a Load: create two.
364 static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) {
365 ir_mode *low_mode = env->params->low_unsigned;
366 ir_graph *irg = current_ir_graph;
367 ir_node *adr = get_Load_ptr(node);
368 ir_node *mem = get_Load_mem(node);
369 ir_node *low, *high, *proj;
371 ir_node *block = get_nodes_block(node);
373 ir_cons_flags volatility = get_Load_volatility(node) == volatility_is_volatile
376 if (env->params->little_endian) {
378 high = new_r_Add(irg, block, adr,
379 new_r_Const(irg, env->tv_mode_bytes),
382 low = new_r_Add(irg, block, adr,
383 new_r_Const(irg, env->tv_mode_bytes),
388 /* create two loads */
389 dbg = get_irn_dbg_info(node);
390 low = new_rd_Load(dbg, irg, block, mem, low, low_mode, volatility);
391 proj = new_r_Proj(irg, block, low, mode_M, pn_Load_M);
392 high = new_rd_Load(dbg, irg, block, proj, high, mode, volatility);
394 idx = get_irn_idx(node);
395 assert(idx < env->n_entries);
396 env->entries[idx]->low_word = low;
397 env->entries[idx]->high_word = high;
399 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
400 idx = get_irn_idx(proj);
402 switch (get_Proj_proj(proj)) {
403 case pn_Load_M: /* Memory result. */
404 /* put it to the second one */
405 set_Proj_pred(proj, high);
407 case pn_Load_X_except: /* Execution result if exception occurred. */
408 /* put it to the first one */
409 set_Proj_pred(proj, low);
411 case pn_Load_res: /* Result of load operation. */
412 assert(idx < env->n_entries);
413 env->entries[idx]->low_word = new_r_Proj(irg, block, low, low_mode, pn_Load_res);
414 env->entries[idx]->high_word = new_r_Proj(irg, block, high, mode, pn_Load_res);
417 assert(0 && "unexpected Proj number");
419 /* mark this proj: we have handled it already, otherwise we might fall into
421 mark_irn_visited(proj);
426 * Translate a Store: create two.
428 static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) {
430 ir_node *block, *adr, *mem;
431 ir_node *low, *high, *irn, *proj;
435 ir_cons_flags volatility = get_Store_volatility(node) == volatility_is_volatile
439 irn = get_Store_value(node);
440 entry = env->entries[get_irn_idx(irn)];
443 if (! entry->low_word) {
444 /* not ready yet, wait */
445 pdeq_putr(env->waitq, node);
449 irg = current_ir_graph;
450 adr = get_Store_ptr(node);
451 mem = get_Store_mem(node);
452 block = get_nodes_block(node);
454 if (env->params->little_endian) {
456 high = new_r_Add(irg, block, adr,
457 new_r_Const(irg, env->tv_mode_bytes),
460 low = new_r_Add(irg, block, adr,
461 new_r_Const(irg, env->tv_mode_bytes),
466 /* create two Stores */
467 dbg = get_irn_dbg_info(node);
468 low = new_rd_Store(dbg, irg, block, mem, low, entry->low_word, volatility);
469 proj = new_r_Proj(irg, block, low, mode_M, pn_Store_M);
470 high = new_rd_Store(dbg, irg, block, proj, high, entry->high_word, volatility);
472 idx = get_irn_idx(node);
473 assert(idx < env->n_entries);
474 env->entries[idx]->low_word = low;
475 env->entries[idx]->high_word = high;
477 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
478 idx = get_irn_idx(proj);
480 switch (get_Proj_proj(proj)) {
481 case pn_Store_M: /* Memory result. */
482 /* put it to the second one */
483 set_Proj_pred(proj, high);
485 case pn_Store_X_except: /* Execution result if exception occurred. */
486 /* put it to the first one */
487 set_Proj_pred(proj, low);
490 assert(0 && "unexpected Proj number");
492 /* mark this proj: we have handled it already, otherwise we might fall into
494 mark_irn_visited(proj);
499 * Return a node containing the address of the intrinsic emulation function.
501 * @param method the method type of the emulation function
502 * @param op the emulated ir_op
503 * @param imode the input mode of the emulated opcode
504 * @param omode the output mode of the emulated opcode
505 * @param block where the new mode is created
506 * @param env the lower environment
508 static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
509 ir_mode *imode, ir_mode *omode,
510 ir_node *block, lower_env_t *env) {
513 op_mode_entry_t key, *entry;
520 entry = set_insert(intrinsic_fkt, &key, sizeof(key),
521 HASH_PTR(op) ^ HASH_PTR(imode) ^ (HASH_PTR(omode) << 8));
523 /* create a new one */
524 ent = env->params->create_intrinsic(method, op, imode, omode, env->params->ctx);
526 assert(ent && "Intrinsic creator must return an entity");
532 return new_r_SymConst(current_ir_graph, block, mode_P_code, sym, symconst_addr_ent);
533 } /* get_intrinsic_address */
538 * Create an intrinsic Call.
540 static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) {
541 ir_node *block, *irn, *call, *proj;
550 irn = get_Div_left(node);
551 entry = env->entries[get_irn_idx(irn)];
554 if (! entry->low_word) {
555 /* not ready yet, wait */
556 pdeq_putr(env->waitq, node);
560 in[0] = entry->low_word;
561 in[1] = entry->high_word;
563 irn = get_Div_right(node);
564 entry = env->entries[get_irn_idx(irn)];
567 if (! entry->low_word) {
568 /* not ready yet, wait */
569 pdeq_putr(env->waitq, node);
573 in[2] = entry->low_word;
574 in[3] = entry->high_word;
576 dbg = get_irn_dbg_info(node);
577 block = get_nodes_block(node);
578 irg = current_ir_graph;
580 mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
581 opmode = get_irn_op_mode(node);
582 irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
583 call = new_rd_Call(dbg, irg, block, get_Div_mem(node),
585 set_irn_pinned(call, get_irn_pinned(node));
586 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
588 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
589 switch (get_Proj_proj(proj)) {
590 case pn_Div_M: /* Memory result. */
591 /* reroute to the call */
592 set_Proj_pred(proj, call);
593 set_Proj_proj(proj, pn_Call_M_except);
595 case pn_Div_X_except: /* Execution result if exception occurred. */
596 /* reroute to the call */
597 set_Proj_pred(proj, call);
598 set_Proj_proj(proj, pn_Call_X_except);
600 case pn_Div_res: /* Result of computation. */
601 idx = get_irn_idx(proj);
602 assert(idx < env->n_entries);
603 env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, irn, env->params->low_unsigned, 0);
604 env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1);
607 assert(0 && "unexpected Proj number");
609 /* mark this proj: we have handled it already, otherwise we might fall into
611 mark_irn_visited(proj);
618 * Create an intrinsic Call.
620 static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) {
621 ir_node *block, *proj, *irn, *call;
630 irn = get_Mod_left(node);
631 entry = env->entries[get_irn_idx(irn)];
634 if (! entry->low_word) {
635 /* not ready yet, wait */
636 pdeq_putr(env->waitq, node);
640 in[0] = entry->low_word;
641 in[1] = entry->high_word;
643 irn = get_Mod_right(node);
644 entry = env->entries[get_irn_idx(irn)];
647 if (! entry->low_word) {
648 /* not ready yet, wait */
649 pdeq_putr(env->waitq, node);
653 in[2] = entry->low_word;
654 in[3] = entry->high_word;
656 dbg = get_irn_dbg_info(node);
657 block = get_nodes_block(node);
658 irg = current_ir_graph;
660 mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
661 opmode = get_irn_op_mode(node);
662 irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
663 call = new_rd_Call(dbg, irg, block, get_Mod_mem(node),
665 set_irn_pinned(call, get_irn_pinned(node));
666 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
668 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
669 switch (get_Proj_proj(proj)) {
670 case pn_Mod_M: /* Memory result. */
671 /* reroute to the call */
672 set_Proj_pred(proj, call);
673 set_Proj_proj(proj, pn_Call_M_except);
675 case pn_Mod_X_except: /* Execution result if exception occurred. */
676 /* reroute to the call */
677 set_Proj_pred(proj, call);
678 set_Proj_proj(proj, pn_Call_X_except);
680 case pn_Mod_res: /* Result of computation. */
681 idx = get_irn_idx(proj);
682 assert(idx < env->n_entries);
683 env->entries[idx]->low_word = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
684 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1);
687 assert(0 && "unexpected Proj number");
689 /* mark this proj: we have handled it already, otherwise we might fall into
691 mark_irn_visited(proj);
696 * Translate a DivMod.
698 * Create two intrinsic Calls.
700 static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) {
701 ir_node *block, *proj, *irn, *mem, *callDiv, *callMod;
702 ir_node *resDiv = NULL;
703 ir_node *resMod = NULL;
713 /* check if both results are needed */
714 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
715 switch (get_Proj_proj(proj)) {
716 case pn_DivMod_res_div: flags |= 1; break;
717 case pn_DivMod_res_mod: flags |= 2; break;
722 irn = get_DivMod_left(node);
723 entry = env->entries[get_irn_idx(irn)];
726 if (! entry->low_word) {
727 /* not ready yet, wait */
728 pdeq_putr(env->waitq, node);
732 in[0] = entry->low_word;
733 in[1] = entry->high_word;
735 irn = get_DivMod_right(node);
736 entry = env->entries[get_irn_idx(irn)];
739 if (! entry->low_word) {
740 /* not ready yet, wait */
741 pdeq_putr(env->waitq, node);
745 in[2] = entry->low_word;
746 in[3] = entry->high_word;
748 dbg = get_irn_dbg_info(node);
749 block = get_nodes_block(node);
750 irg = current_ir_graph;
752 mem = get_DivMod_mem(node);
754 callDiv = callMod = NULL;
755 mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
757 opmode = get_irn_op_mode(node);
758 irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, block, env);
759 callDiv = new_rd_Call(dbg, irg, block, mem,
761 set_irn_pinned(callDiv, get_irn_pinned(node));
762 resDiv = new_r_Proj(irg, block, callDiv, mode_T, pn_Call_T_result);
766 mem = new_r_Proj(irg, block, callDiv, mode_M, pn_Call_M);
767 opmode = get_irn_op_mode(node);
768 irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, block, env);
769 callMod = new_rd_Call(dbg, irg, block, mem,
771 set_irn_pinned(callMod, get_irn_pinned(node));
772 resMod = new_r_Proj(irg, block, callMod, mode_T, pn_Call_T_result);
775 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
776 switch (get_Proj_proj(proj)) {
777 case pn_DivMod_M: /* Memory result. */
778 /* reroute to the first call */
779 set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
780 set_Proj_proj(proj, pn_Call_M_except);
782 case pn_DivMod_X_except: /* Execution result if exception occurred. */
783 /* reroute to the first call */
784 set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
785 set_Proj_proj(proj, pn_Call_X_except);
787 case pn_DivMod_res_div: /* Result of Div. */
788 idx = get_irn_idx(proj);
789 assert(idx < env->n_entries);
790 env->entries[idx]->low_word = new_r_Proj(irg, block, resDiv, env->params->low_unsigned, 0);
791 env->entries[idx]->high_word = new_r_Proj(irg, block, resDiv, mode, 1);
793 case pn_DivMod_res_mod: /* Result of Mod. */
794 idx = get_irn_idx(proj);
795 env->entries[idx]->low_word = new_r_Proj(irg, block, resMod, env->params->low_unsigned, 0);
796 env->entries[idx]->high_word = new_r_Proj(irg, block, resMod, mode, 1);
799 assert(0 && "unexpected Proj number");
801 /* mark this proj: we have handled it already, otherwise we might fall into
803 mark_irn_visited(proj);
810 * Create an intrinsic Call.
812 static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) {
813 ir_node *block, *irn;
821 irn = get_binop_left(node);
822 entry = env->entries[get_irn_idx(irn)];
825 if (! entry->low_word) {
826 /* not ready yet, wait */
827 pdeq_putr(env->waitq, node);
831 in[0] = entry->low_word;
832 in[1] = entry->high_word;
834 irn = get_binop_right(node);
835 entry = env->entries[get_irn_idx(irn)];
838 if (! entry->low_word) {
839 /* not ready yet, wait */
840 pdeq_putr(env->waitq, node);
844 in[2] = entry->low_word;
845 in[3] = entry->high_word;
847 dbg = get_irn_dbg_info(node);
848 block = get_nodes_block(node);
849 irg = current_ir_graph;
851 mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
852 irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
853 irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
855 set_irn_pinned(irn, get_irn_pinned(node));
856 irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
858 idx = get_irn_idx(node);
859 assert(idx < env->n_entries);
860 env->entries[idx]->low_word = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
861 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1);
865 * Translate a Shiftop.
867 * Create an intrinsic Call.
869 static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) {
870 ir_node *block, *irn;
878 irn = get_binop_left(node);
879 entry = env->entries[get_irn_idx(irn)];
882 if (! entry->low_word) {
883 /* not ready yet, wait */
884 pdeq_putr(env->waitq, node);
888 in[0] = entry->low_word;
889 in[1] = entry->high_word;
891 /* The shift count is always mode_Iu in firm, so there is no need for lowering */
892 in[2] = get_binop_right(node);
894 dbg = get_irn_dbg_info(node);
895 block = get_nodes_block(node);
896 irg = current_ir_graph;
898 mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u;
899 irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
900 irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
902 set_irn_pinned(irn, get_irn_pinned(node));
903 irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
905 idx = get_irn_idx(node);
906 assert(idx < env->n_entries);
907 env->entries[idx]->low_word = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
908 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1);
909 } /* lower_Shiftop */
912 * Translate a Shr and handle special cases.
914 static void lower_Shr(ir_node *node, ir_mode *mode, lower_env_t *env) {
915 ir_node *right = get_Shr_right(node);
916 ir_graph *irg = current_ir_graph;
918 if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
919 tarval *tv = get_Const_tarval(right);
921 if (tarval_is_long(tv) &&
922 get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
923 ir_node *block = get_nodes_block(node);
924 ir_node *left = get_Shr_left(node);
926 long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
927 int idx = get_irn_idx(left);
929 left = env->entries[idx]->high_word;
930 idx = get_irn_idx(node);
933 c = new_r_Const_long(irg, env->params->low_unsigned, shf_cnt);
934 env->entries[idx]->low_word = new_r_Shr(irg, block, left, c, mode);
936 env->entries[idx]->low_word = left;
938 env->entries[idx]->high_word = new_r_Const(irg, get_mode_null(mode));
943 lower_Shiftop(node, mode, env);
947 * Translate a Shl and handle special cases.
949 static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env) {
950 ir_node *right = get_Shl_right(node);
951 ir_graph *irg = current_ir_graph;
953 if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
954 tarval *tv = get_Const_tarval(right);
956 if (tarval_is_long(tv) &&
957 get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
959 ir_node *block = get_nodes_block(node);
960 ir_node *left = get_Shl_left(node);
962 long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
963 int idx = get_irn_idx(left);
965 left = new_r_Conv(irg, block, env->entries[idx]->low_word, mode);
966 idx = get_irn_idx(node);
968 mode_l = env->params->low_unsigned;
970 c = new_r_Const_long(irg, mode_l, shf_cnt);
971 env->entries[idx]->high_word = new_r_Shl(irg, block, left, c, mode);
973 env->entries[idx]->high_word = left;
975 env->entries[idx]->low_word = new_r_Const(irg, get_mode_null(mode_l));
980 lower_Shiftop(node, mode, env);
984 * Translate a Shrs and handle special cases.
986 static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env) {
987 ir_node *right = get_Shrs_right(node);
988 ir_graph *irg = current_ir_graph;
990 if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
991 tarval *tv = get_Const_tarval(right);
993 if (tarval_is_long(tv) &&
994 get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
995 ir_node *block = get_nodes_block(node);
996 ir_node *left = get_Shrs_left(node);
997 long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
998 int idx = get_irn_idx(left);
1003 left = env->entries[idx]->high_word;
1004 idx = get_irn_idx(node);
1006 mode_l = env->params->low_unsigned;
1008 c = new_r_Const_long(irg, mode_l, shf_cnt);
1009 low = new_r_Shrs(irg, block, left, c, mode);
1013 /* low word is expected to have mode_l */
1014 env->entries[idx]->low_word = new_r_Conv(irg, block, low, mode_l);
1016 c = new_r_Const_long(irg, mode_l, get_mode_size_bits(mode) - 1);
1017 env->entries[idx]->high_word = new_r_Shrs(irg, block, left, c, mode);
1022 lower_Shiftop(node, mode, env);
1026 * Rebuild Rotl nodes into Or(Shl, Shr) and prepare all nodes.
1028 static void prepare_links_and_handle_rotl(ir_node *node, void *env) {
1029 lower_env_t *lenv = env;
1031 if (is_Rotl(node)) {
1032 ir_mode *mode = get_irn_op_mode(node);
1033 if (mode == lenv->params->high_signed ||
1034 mode == lenv->params->high_unsigned) {
1035 ir_node *right = get_Rotl_right(node);
1036 ir_node *left, *shl, *shr, *or, *block, *sub, *c;
1037 ir_mode *omode, *rmode;
1040 optimization_state_t state;
1042 if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
1043 tarval *tv = get_Const_tarval(right);
1045 if (tarval_is_long(tv) &&
1046 get_tarval_long(tv) == (long)get_mode_size_bits(mode)) {
1047 /* will be optimized in lower_Rotl() */
1052 /* replace the Rotl(x,y) by an Or(Shl(x,y), Shr(x,64-y)) and lower those */
1053 dbg = get_irn_dbg_info(node);
1054 omode = get_irn_mode(node);
1055 left = get_Rotl_left(node);
1056 irg = current_ir_graph;
1057 block = get_nodes_block(node);
1058 shl = new_rd_Shl(dbg, irg, block, left, right, omode);
1059 rmode = get_irn_mode(right);
1060 c = new_Const_long(rmode, get_mode_size_bits(omode));
1061 sub = new_rd_Sub(dbg, irg, block, c, right, rmode);
1062 shr = new_rd_Shr(dbg, irg, block, left, sub, omode);
1064 /* optimization must be switched off here, or we will get the Rotl back */
1065 save_optimization_state(&state);
1066 set_opt_algebraic_simplification(0);
1067 or = new_rd_Or(dbg, irg, block, shl, shr, omode);
1068 restore_optimization_state(&state);
1072 /* do lowering on the new nodes */
1073 prepare_links(shl, env);
1074 prepare_links(c, env);
1075 prepare_links(sub, env);
1076 prepare_links(shr, env);
1077 prepare_links(or, env);
1080 prepare_links(node, env);
1085 * Translate a special case Rotl(x, sizeof(w)).
1087 static void lower_Rotl(ir_node *node, ir_mode *mode, lower_env_t *env) {
1088 ir_node *right = get_Rotl_right(node);
1089 ir_node *left = get_Rotl_left(node);
1091 int idx = get_irn_idx(left);
1095 assert(get_mode_arithmetic(mode) == irma_twos_complement &&
1096 is_Const(right) && tarval_is_long(get_Const_tarval(right)) &&
1097 get_tarval_long(get_Const_tarval(right)) == (long)get_mode_size_bits(mode));
1099 l = env->entries[idx]->low_word;
1100 h = env->entries[idx]->high_word;
1101 idx = get_irn_idx(node);
1103 env->entries[idx]->low_word = h;
1104 env->entries[idx]->high_word = l;
1108 * Translate an Unop.
1110 * Create an intrinsic Call.
1112 static void lower_Unop(ir_node *node, ir_mode *mode, lower_env_t *env) {
1113 ir_node *block, *irn;
1119 node_entry_t *entry;
1121 irn = get_unop_op(node);
1122 entry = env->entries[get_irn_idx(irn)];
1125 if (! entry->low_word) {
1126 /* not ready yet, wait */
1127 pdeq_putr(env->waitq, node);
1131 in[0] = entry->low_word;
1132 in[1] = entry->high_word;
1134 dbg = get_irn_dbg_info(node);
1135 block = get_nodes_block(node);
1136 irg = current_ir_graph;
1138 mtp = mode_is_signed(mode) ? unop_tp_s : unop_tp_u;
1139 irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
1140 irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
1142 set_irn_pinned(irn, get_irn_pinned(node));
1143 irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
1145 idx = get_irn_idx(node);
1146 assert(idx < env->n_entries);
1147 env->entries[idx]->low_word = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
1148 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1);
1152 * Translate a logical Binop.
1154 * Create two logical Binops.
1156 static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env,
1157 ir_node *(*constr_rd)(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) ) {
1158 ir_node *block, *irn;
1159 ir_node *lop_l, *lop_h, *rop_l, *rop_h;
1163 node_entry_t *entry;
1165 irn = get_binop_left(node);
1166 entry = env->entries[get_irn_idx(irn)];
1169 if (! entry->low_word) {
1170 /* not ready yet, wait */
1171 pdeq_putr(env->waitq, node);
1175 lop_l = entry->low_word;
1176 lop_h = entry->high_word;
1178 irn = get_binop_right(node);
1179 entry = env->entries[get_irn_idx(irn)];
1182 if (! entry->low_word) {
1183 /* not ready yet, wait */
1184 pdeq_putr(env->waitq, node);
1188 rop_l = entry->low_word;
1189 rop_h = entry->high_word;
1191 dbg = get_irn_dbg_info(node);
1192 block = get_nodes_block(node);
1194 idx = get_irn_idx(node);
1195 assert(idx < env->n_entries);
1196 irg = current_ir_graph;
1197 env->entries[idx]->low_word = constr_rd(dbg, irg, block, lop_l, rop_l, env->params->low_unsigned);
1198 env->entries[idx]->high_word = constr_rd(dbg, irg, block, lop_h, rop_h, mode);
1199 } /* lower_Binop_logical */
1201 /** create a logical operation transformation */
1202 #define lower_logical(op) \
1203 static void lower_##op(ir_node *node, ir_mode *mode, lower_env_t *env) { \
1204 lower_Binop_logical(node, mode, env, new_rd_##op); \
1214 * Create two logical Nots.
1216 static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) {
1217 ir_node *block, *irn;
1218 ir_node *op_l, *op_h;
1222 node_entry_t *entry;
1224 irn = get_Not_op(node);
1225 entry = env->entries[get_irn_idx(irn)];
1228 if (! entry->low_word) {
1229 /* not ready yet, wait */
1230 pdeq_putr(env->waitq, node);
1234 op_l = entry->low_word;
1235 op_h = entry->high_word;
1237 dbg = get_irn_dbg_info(node);
1238 block = get_nodes_block(node);
1239 irg = current_ir_graph;
1241 idx = get_irn_idx(node);
1242 assert(idx < env->n_entries);
1243 env->entries[idx]->low_word = new_rd_Not(dbg, current_ir_graph, block, op_l, env->params->low_unsigned);
1244 env->entries[idx]->high_word = new_rd_Not(dbg, current_ir_graph, block, op_h, mode);
1250 static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) {
1251 ir_node *cmp, *left, *right, *block;
1252 ir_node *sel = get_Cond_selector(node);
1253 ir_mode *m = get_irn_mode(sel);
1258 node_entry_t *lentry, *rentry;
1259 ir_node *proj, *projT = NULL, *projF = NULL;
1260 ir_node *new_bl, *cmpH, *cmpL, *irn;
1261 ir_node *projHF, *projHT;
1270 cmp = get_Proj_pred(sel);
1274 left = get_Cmp_left(cmp);
1275 idx = get_irn_idx(left);
1276 lentry = env->entries[idx];
1283 right = get_Cmp_right(cmp);
1284 idx = get_irn_idx(right);
1285 rentry = env->entries[idx];
1288 if (! lentry->low_word || !rentry->low_word) {
1290 pdeq_putr(env->waitq, node);
1294 /* all right, build the code */
1295 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1296 long proj_nr = get_Proj_proj(proj);
1298 if (proj_nr == pn_Cond_true) {
1299 assert(projT == NULL && "more than one Proj(true)");
1302 assert(proj_nr == pn_Cond_false);
1303 assert(projF == NULL && "more than one Proj(false)");
1306 mark_irn_visited(proj);
1308 assert(projT && projF);
1310 /* create a new high compare */
1311 block = get_nodes_block(node);
1312 dbg = get_irn_dbg_info(cmp);
1313 irg = current_ir_graph;
1314 pnc = get_Proj_proj(sel);
1316 if (is_Const(right) && is_Const_null(right)) {
1317 if (pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) {
1318 /* x ==/!= 0 ==> or(low,high) ==/!= 0 */
1319 ir_mode *mode = env->params->low_unsigned;
1320 ir_node *low = new_r_Conv(irg, block, lentry->low_word, mode);
1321 ir_node *high = new_r_Conv(irg, block, lentry->high_word, mode);
1322 ir_node *or = new_rd_Or(dbg, irg, block, low, high, mode);
1323 ir_node *cmp = new_rd_Cmp(dbg, irg, block, or, new_Const_long(mode, 0));
1325 ir_node *proj = new_r_Proj(irg, block, cmp, mode_b, pnc);
1326 set_Cond_selector(node, proj);
1331 cmpH = new_rd_Cmp(dbg, irg, block, lentry->high_word, rentry->high_word);
1333 if (pnc == pn_Cmp_Eq) {
1334 /* simple case:a == b <==> a_h == b_h && a_l == b_l */
1335 pmap_entry *entry = pmap_find(env->proj_2_block, projF);
1338 dst_blk = entry->value;
1340 irn = new_r_Proj(irg, block, cmpH, mode_b, pn_Cmp_Eq);
1341 dbg = get_irn_dbg_info(node);
1342 irn = new_rd_Cond(dbg, irg, block, irn);
1344 projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1345 mark_irn_visited(projHF);
1346 exchange(projF, projHF);
1348 projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1349 mark_irn_visited(projHT);
1351 new_bl = new_r_Block(irg, 1, &projHT);
1353 dbg = get_irn_dbg_info(cmp);
1354 cmpL = new_rd_Cmp(dbg, irg, new_bl, lentry->low_word, rentry->low_word);
1355 irn = new_r_Proj(irg, new_bl, cmpL, mode_b, pn_Cmp_Eq);
1356 dbg = get_irn_dbg_info(node);
1357 irn = new_rd_Cond(dbg, irg, new_bl, irn);
1359 proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false);
1360 mark_irn_visited(proj);
1361 add_block_cf_input(dst_blk, projHF, proj);
1363 proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true);
1364 mark_irn_visited(proj);
1365 exchange(projT, proj);
1366 } else if (pnc == pn_Cmp_Lg) {
1367 /* simple case:a != b <==> a_h != b_h || a_l != b_l */
1368 pmap_entry *entry = pmap_find(env->proj_2_block, projT);
1371 dst_blk = entry->value;
1373 irn = new_r_Proj(irg, block, cmpH, mode_b, pn_Cmp_Lg);
1374 dbg = get_irn_dbg_info(node);
1375 irn = new_rd_Cond(dbg, irg, block, irn);
1377 projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1378 mark_irn_visited(projHT);
1379 exchange(projT, projHT);
1381 projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1382 mark_irn_visited(projHF);
1384 new_bl = new_r_Block(irg, 1, &projHF);
1386 dbg = get_irn_dbg_info(cmp);
1387 cmpL = new_rd_Cmp(dbg, irg, new_bl, lentry->low_word, rentry->low_word);
1388 irn = new_r_Proj(irg, new_bl, cmpL, mode_b, pn_Cmp_Lg);
1389 dbg = get_irn_dbg_info(node);
1390 irn = new_rd_Cond(dbg, irg, new_bl, irn);
1392 proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true);
1393 mark_irn_visited(proj);
1394 add_block_cf_input(dst_blk, projHT, proj);
1396 proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false);
1397 mark_irn_visited(proj);
1398 exchange(projF, proj);
1400 /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
1401 ir_node *dstT, *dstF, *newbl_eq, *newbl_l;
1404 entry = pmap_find(env->proj_2_block, projT);
1406 dstT = entry->value;
1408 entry = pmap_find(env->proj_2_block, projF);
1410 dstF = entry->value;
1412 irn = new_r_Proj(irg, block, cmpH, mode_b, pnc & ~pn_Cmp_Eq);
1413 dbg = get_irn_dbg_info(node);
1414 irn = new_rd_Cond(dbg, irg, block, irn);
1416 projHT = new_r_Proj(irg, block, irn, mode_X, pn_Cond_true);
1417 mark_irn_visited(projHT);
1418 exchange(projT, projHT);
1421 projHF = new_r_Proj(irg, block, irn, mode_X, pn_Cond_false);
1422 mark_irn_visited(projHF);
1424 newbl_eq = new_r_Block(irg, 1, &projHF);
1426 irn = new_r_Proj(irg, newbl_eq, cmpH, mode_b, pn_Cmp_Eq);
1427 irn = new_rd_Cond(dbg, irg, newbl_eq, irn);
1429 proj = new_r_Proj(irg, newbl_eq, irn, mode_X, pn_Cond_false);
1430 mark_irn_visited(proj);
1431 exchange(projF, proj);
1434 proj = new_r_Proj(irg, newbl_eq, irn, mode_X, pn_Cond_true);
1435 mark_irn_visited(proj);
1437 newbl_l = new_r_Block(irg, 1, &proj);
1439 dbg = get_irn_dbg_info(cmp);
1440 cmpL = new_rd_Cmp(dbg, irg, newbl_l, lentry->low_word, rentry->low_word);
1441 irn = new_r_Proj(irg, newbl_l, cmpL, mode_b, pnc);
1442 dbg = get_irn_dbg_info(node);
1443 irn = new_rd_Cond(dbg, irg, newbl_l, irn);
1445 proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_true);
1446 mark_irn_visited(proj);
1447 add_block_cf_input(dstT, projT, proj);
1449 proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_false);
1450 mark_irn_visited(proj);
1451 add_block_cf_input(dstF, projF, proj);
1454 /* we have changed the control flow */
1455 env->flags |= CF_CHANGED;
1457 idx = get_irn_idx(sel);
1459 if (env->entries[idx]) {
1461 Bad, a jump-table with double-word index.
1462 This should not happen, but if it does we handle
1463 it like a Conv were between (in other words, ignore
1467 if (! env->entries[idx]->low_word) {
1468 /* not ready yet, wait */
1469 pdeq_putr(env->waitq, node);
1472 set_Cond_selector(node, env->entries[idx]->low_word);
1478 * Translate a Conv to higher_signed
1480 static void lower_Conv_to_Ls(ir_node *node, lower_env_t *env) {
1481 ir_node *op = get_Conv_op(node);
1482 ir_mode *imode = get_irn_mode(op);
1483 ir_mode *dst_mode_l = env->params->low_unsigned;
1484 ir_mode *dst_mode_h = env->params->low_signed;
1485 int idx = get_irn_idx(node);
1486 ir_graph *irg = current_ir_graph;
1487 ir_node *block = get_nodes_block(node);
1488 dbg_info *dbg = get_irn_dbg_info(node);
1490 assert(idx < env->n_entries);
1492 if (mode_is_int(imode) || mode_is_reference(imode)) {
1493 if (imode == env->params->high_unsigned) {
1494 /* a Conv from Lu to Ls */
1495 int op_idx = get_irn_idx(op);
1497 if (! env->entries[op_idx]->low_word) {
1498 /* not ready yet, wait */
1499 pdeq_putr(env->waitq, node);
1502 env->entries[idx]->low_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->low_word, dst_mode_l);
1503 env->entries[idx]->high_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->high_word, dst_mode_h);
1505 /* simple case: create a high word */
1506 if (imode != dst_mode_l)
1507 op = new_rd_Conv(dbg, irg, block, op, dst_mode_l);
1509 env->entries[idx]->low_word = op;
1511 if (mode_is_signed(imode)) {
1512 ir_node *op_conv = new_rd_Conv(dbg, irg, block, op, dst_mode_h);
1513 env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op_conv,
1514 new_Const_long(dst_mode_l, get_mode_size_bits(dst_mode_h) - 1), dst_mode_h);
1516 env->entries[idx]->high_word = new_Const(get_mode_null(dst_mode_h));
1520 ir_node *irn, *call;
1521 ir_mode *omode = env->params->high_signed;
1522 ir_type *mtp = get_conv_type(imode, omode, env);
1524 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1525 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp);
1526 set_irn_pinned(call, get_irn_pinned(node));
1527 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1529 env->entries[idx]->low_word = new_r_Proj(irg, block, irn, dst_mode_l, 0);
1530 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode_h, 1);
1532 } /* lower_Conv_to_Ls */
1535 * Translate a Conv to higher_unsigned
1537 static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) {
1538 ir_node *op = get_Conv_op(node);
1539 ir_mode *imode = get_irn_mode(op);
1540 ir_mode *dst_mode = env->params->low_unsigned;
1541 int idx = get_irn_idx(node);
1542 ir_graph *irg = current_ir_graph;
1543 ir_node *block = get_nodes_block(node);
1544 dbg_info *dbg = get_irn_dbg_info(node);
1546 assert(idx < env->n_entries);
1548 if (mode_is_int(imode) || mode_is_reference(imode)) {
1549 if (imode == env->params->high_signed) {
1550 /* a Conv from Ls to Lu */
1551 int op_idx = get_irn_idx(op);
1553 if (! env->entries[op_idx]->low_word) {
1554 /* not ready yet, wait */
1555 pdeq_putr(env->waitq, node);
1558 env->entries[idx]->low_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->low_word, dst_mode);
1559 env->entries[idx]->high_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->high_word, dst_mode);
1561 /* simple case: create a high word */
1562 if (imode != dst_mode)
1563 op = new_rd_Conv(dbg, irg, block, op, dst_mode);
1565 env->entries[idx]->low_word = op;
1567 if (mode_is_signed(imode)) {
1568 env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op,
1569 new_Const_long(dst_mode, get_mode_size_bits(dst_mode) - 1), dst_mode);
1571 env->entries[idx]->high_word = new_Const(get_mode_null(dst_mode));
1575 ir_node *irn, *call;
1576 ir_mode *omode = env->params->high_unsigned;
1577 ir_type *mtp = get_conv_type(imode, omode, env);
1579 /* do an intrinsic call */
1580 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1581 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp);
1582 set_irn_pinned(call, get_irn_pinned(node));
1583 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1585 env->entries[idx]->low_word = new_r_Proj(irg, block, irn, dst_mode, 0);
1586 env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode, 1);
1588 } /* lower_Conv_to_Lu */
1591 * Translate a Conv from higher_signed
1593 static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) {
1594 ir_node *op = get_Conv_op(node);
1595 ir_mode *omode = get_irn_mode(node);
1596 ir_node *block = get_nodes_block(node);
1597 dbg_info *dbg = get_irn_dbg_info(node);
1598 int idx = get_irn_idx(op);
1599 ir_graph *irg = current_ir_graph;
1601 assert(idx < env->n_entries);
1603 if (! env->entries[idx]->low_word) {
1604 /* not ready yet, wait */
1605 pdeq_putr(env->waitq, node);
1609 if (mode_is_int(omode) || mode_is_reference(omode)) {
1610 op = env->entries[idx]->low_word;
1612 /* simple case: create a high word */
1613 if (omode != env->params->low_signed)
1614 op = new_rd_Conv(dbg, irg, block, op, omode);
1616 set_Conv_op(node, op);
1618 ir_node *irn, *call, *in[2];
1619 ir_mode *imode = env->params->high_signed;
1620 ir_type *mtp = get_conv_type(imode, omode, env);
1622 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1623 in[0] = env->entries[idx]->low_word;
1624 in[1] = env->entries[idx]->high_word;
1626 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 2, in, mtp);
1627 set_irn_pinned(call, get_irn_pinned(node));
1628 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1630 exchange(node, new_r_Proj(irg, block, irn, omode, 0));
1632 } /* lower_Conv_from_Ls */
1635 * Translate a Conv from higher_unsigned
1637 static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) {
1638 ir_node *op = get_Conv_op(node);
1639 ir_mode *omode = get_irn_mode(node);
1640 ir_node *block = get_nodes_block(node);
1641 dbg_info *dbg = get_irn_dbg_info(node);
1642 int idx = get_irn_idx(op);
1643 ir_graph *irg = current_ir_graph;
1645 assert(idx < env->n_entries);
1647 if (! env->entries[idx]->low_word) {
1648 /* not ready yet, wait */
1649 pdeq_putr(env->waitq, node);
1653 if (mode_is_int(omode) || mode_is_reference(omode)) {
1654 op = env->entries[idx]->low_word;
1656 /* simple case: create a high word */
1657 if (omode != env->params->low_unsigned)
1658 op = new_rd_Conv(dbg, irg, block, op, omode);
1660 set_Conv_op(node, op);
1662 ir_node *irn, *call, *in[2];
1663 ir_mode *imode = env->params->high_unsigned;
1664 ir_type *mtp = get_conv_type(imode, omode, env);
1666 irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env);
1667 in[0] = env->entries[idx]->low_word;
1668 in[1] = env->entries[idx]->high_word;
1670 call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 2, in, mtp);
1671 set_irn_pinned(call, get_irn_pinned(node));
1672 irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
1674 exchange(node, new_r_Proj(irg, block, irn, omode, 0));
1676 } /* lower_Conv_from_Lu */
1681 static void lower_Conv(ir_node *node, ir_mode *mode, lower_env_t *env) {
1682 mode = get_irn_mode(node);
1684 if (mode == env->params->high_signed) {
1685 lower_Conv_to_Ls(node, env);
1686 } else if (mode == env->params->high_unsigned) {
1687 lower_Conv_to_Lu(node, env);
1689 ir_mode *mode = get_irn_mode(get_Conv_op(node));
1691 if (mode == env->params->high_signed) {
1692 lower_Conv_from_Ls(node, env);
1693 } else if (mode == env->params->high_unsigned) {
1694 lower_Conv_from_Lu(node, env);
1700 * Lower the method type.
1702 * @param mtp the method type to lower
1703 * @param ent the lower environment
1705 * @return the lowered type
1707 static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) {
1710 ir_type *res, *value_type;
1712 if (is_lowered_type(mtp))
1715 entry = pmap_find(lowered_type, mtp);
1717 int i, n, r, n_param, n_res;
1719 /* count new number of params */
1720 n_param = n = get_method_n_params(mtp);
1721 for (i = n_param - 1; i >= 0; --i) {
1722 ir_type *tp = get_method_param_type(mtp, i);
1724 if (is_Primitive_type(tp)) {
1725 ir_mode *mode = get_type_mode(tp);
1727 if (mode == env->params->high_signed ||
1728 mode == env->params->high_unsigned)
1733 /* count new number of results */
1734 n_res = r = get_method_n_ress(mtp);
1735 for (i = n_res - 1; i >= 0; --i) {
1736 ir_type *tp = get_method_res_type(mtp, i);
1738 if (is_Primitive_type(tp)) {
1739 ir_mode *mode = get_type_mode(tp);
1741 if (mode == env->params->high_signed ||
1742 mode == env->params->high_unsigned)
1747 id = id_mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp));
1748 res = new_type_method(id, n_param, n_res);
1750 /* set param types and result types */
1751 for (i = n_param = 0; i < n; ++i) {
1752 ir_type *tp = get_method_param_type(mtp, i);
1754 if (is_Primitive_type(tp)) {
1755 ir_mode *mode = get_type_mode(tp);
1757 if (mode == env->params->high_signed) {
1758 set_method_param_type(res, n_param++, tp_u);
1759 set_method_param_type(res, n_param++, tp_s);
1760 } else if (mode == env->params->high_unsigned) {
1761 set_method_param_type(res, n_param++, tp_u);
1762 set_method_param_type(res, n_param++, tp_u);
1764 set_method_param_type(res, n_param++, tp);
1767 set_method_param_type(res, n_param++, tp);
1770 for (i = n_res = 0; i < r; ++i) {
1771 ir_type *tp = get_method_res_type(mtp, i);
1773 if (is_Primitive_type(tp)) {
1774 ir_mode *mode = get_type_mode(tp);
1776 if (mode == env->params->high_signed) {
1777 set_method_res_type(res, n_res++, tp_u);
1778 set_method_res_type(res, n_res++, tp_s);
1779 } else if (mode == env->params->high_unsigned) {
1780 set_method_res_type(res, n_res++, tp_u);
1781 set_method_res_type(res, n_res++, tp_u);
1783 set_method_res_type(res, n_res++, tp);
1786 set_method_res_type(res, n_res++, tp);
1789 set_lowered_type(mtp, res);
1790 pmap_insert(lowered_type, mtp, res);
1792 value_type = get_method_value_param_type(mtp);
1793 if (value_type != NULL) {
1794 /* this creates a new value parameter type */
1795 (void)get_method_value_param_ent(res, 0);
1797 /* set new param positions */
1798 for (i = n_param = 0; i < n; ++i) {
1799 ir_type *tp = get_method_param_type(mtp, i);
1800 ident *id = get_method_param_ident(mtp, i);
1801 ir_entity *ent = get_method_value_param_ent(mtp, i);
1803 set_entity_link(ent, INT_TO_PTR(n_param));
1804 if (is_Primitive_type(tp)) {
1805 ir_mode *mode = get_type_mode(tp);
1807 if (mode == env->params->high_signed || mode == env->params->high_unsigned) {
1809 lid = id_mangle(id, env->first_id);
1810 set_method_param_ident(res, n_param, lid);
1811 set_entity_ident(get_method_value_param_ent(res, n_param), lid);
1812 lid = id_mangle(id, env->next_id);
1813 set_method_param_ident(res, n_param + 1, lid);
1814 set_entity_ident(get_method_value_param_ent(res, n_param + 1), lid);
1821 set_method_param_ident(res, n_param, id);
1822 set_entity_ident(get_method_value_param_ent(res, n_param), id);
1827 set_lowered_type(value_type, get_method_value_param_type(res));
1836 * Translate a Return.
1838 static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) {
1839 ir_graph *irg = current_ir_graph;
1840 ir_entity *ent = get_irg_entity(irg);
1841 ir_type *mtp = get_entity_type(ent);
1847 /* check if this return must be lowered */
1848 for (i = 0, n = get_Return_n_ress(node); i < n; ++i) {
1849 ir_node *pred = get_Return_res(node, i);
1850 ir_mode *mode = get_irn_op_mode(pred);
1852 if (mode == env->params->high_signed ||
1853 mode == env->params->high_unsigned) {
1854 idx = get_irn_idx(pred);
1855 if (! env->entries[idx]->low_word) {
1856 /* not ready yet, wait */
1857 pdeq_putr(env->waitq, node);
1866 ent = get_irg_entity(irg);
1867 mtp = get_entity_type(ent);
1869 mtp = lower_mtp(mtp, env);
1870 set_entity_type(ent, mtp);
1872 /* create a new in array */
1873 NEW_ARR_A(ir_node *, in, get_method_n_ress(mtp) + 1);
1874 in[0] = get_Return_mem(node);
1876 for (j = i = 0, n = get_Return_n_ress(node); i < n; ++i) {
1877 ir_node *pred = get_Return_res(node, i);
1879 idx = get_irn_idx(pred);
1880 assert(idx < env->n_entries);
1882 if (env->entries[idx]) {
1883 in[++j] = env->entries[idx]->low_word;
1884 in[++j] = env->entries[idx]->high_word;
1890 set_irn_in(node, j+1, in);
1891 } /* lower_Return */
1894 * Translate the parameters.
1896 static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) {
1897 ir_graph *irg = current_ir_graph;
1898 ir_entity *ent = get_irg_entity(irg);
1899 ir_type *tp = get_entity_type(ent);
1902 int i, j, n_params, rem;
1903 ir_node *proj, *args;
1906 if (is_lowered_type(tp)) {
1907 mtp = get_associated_type(tp);
1911 assert(! is_lowered_type(mtp));
1913 n_params = get_method_n_params(mtp);
1917 NEW_ARR_A(long, new_projs, n_params);
1919 /* first check if we have parameters that must be fixed */
1920 for (i = j = 0; i < n_params; ++i, ++j) {
1921 ir_type *tp = get_method_param_type(mtp, i);
1924 if (is_Primitive_type(tp)) {
1925 ir_mode *mode = get_type_mode(tp);
1927 if (mode == env->params->high_signed ||
1928 mode == env->params->high_unsigned)
1935 mtp = lower_mtp(mtp, env);
1936 set_entity_type(ent, mtp);
1938 /* switch off optimization for new Proj nodes or they might be CSE'ed
1939 with not patched one's */
1940 rem = get_optimize();
1943 /* ok, fix all Proj's and create new ones */
1944 args = get_irg_args(irg);
1945 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
1946 ir_node *pred = get_Proj_pred(proj);
1952 /* do not visit this node again */
1953 mark_irn_visited(proj);
1958 proj_nr = get_Proj_proj(proj);
1959 set_Proj_proj(proj, new_projs[proj_nr]);
1961 idx = get_irn_idx(proj);
1962 if (env->entries[idx]) {
1963 ir_mode *low_mode = env->params->low_unsigned;
1965 mode = get_irn_mode(proj);
1967 if (mode == env->params->high_signed) {
1968 mode = env->params->low_signed;
1970 mode = env->params->low_unsigned;
1973 dbg = get_irn_dbg_info(proj);
1974 env->entries[idx]->low_word =
1975 new_rd_Proj(dbg, irg, get_nodes_block(proj), args, low_mode, new_projs[proj_nr]);
1976 env->entries[idx]->high_word =
1977 new_rd_Proj(dbg, irg, get_nodes_block(proj), args, mode, new_projs[proj_nr] + 1);
1986 static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) {
1987 ir_graph *irg = current_ir_graph;
1988 ir_type *tp = get_Call_type(node);
1990 ir_node **in, *proj, *results;
1991 int n_params, n_res, need_lower = 0;
1993 long *res_numbers = NULL;
1996 if (is_lowered_type(tp)) {
1997 call_tp = get_associated_type(tp);
2002 assert(! is_lowered_type(call_tp));
2004 n_params = get_method_n_params(call_tp);
2005 for (i = 0; i < n_params; ++i) {
2006 ir_type *tp = get_method_param_type(call_tp, i);
2008 if (is_Primitive_type(tp)) {
2009 ir_mode *mode = get_type_mode(tp);
2011 if (mode == env->params->high_signed ||
2012 mode == env->params->high_unsigned) {
2018 n_res = get_method_n_ress(call_tp);
2020 NEW_ARR_A(long, res_numbers, n_res);
2022 for (i = j = 0; i < n_res; ++i, ++j) {
2023 ir_type *tp = get_method_res_type(call_tp, i);
2026 if (is_Primitive_type(tp)) {
2027 ir_mode *mode = get_type_mode(tp);
2029 if (mode == env->params->high_signed ||
2030 mode == env->params->high_unsigned) {
2041 /* let's lower it */
2042 call_tp = lower_mtp(call_tp, env);
2043 set_Call_type(node, call_tp);
2045 NEW_ARR_A(ir_node *, in, get_method_n_params(call_tp) + 2);
2047 in[0] = get_Call_mem(node);
2048 in[1] = get_Call_ptr(node);
2050 for (j = 2, i = 0; i < n_params; ++i) {
2051 ir_node *pred = get_Call_param(node, i);
2052 int idx = get_irn_idx(pred);
2054 if (env->entries[idx]) {
2055 if (! env->entries[idx]->low_word) {
2056 /* not ready yet, wait */
2057 pdeq_putr(env->waitq, node);
2060 in[j++] = env->entries[idx]->low_word;
2061 in[j++] = env->entries[idx]->high_word;
2067 set_irn_in(node, j, in);
2069 /* fix the results */
2071 for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
2072 long proj_nr = get_Proj_proj(proj);
2074 if (proj_nr == pn_Call_T_result && get_Proj_pred(proj) == node) {
2075 /* found the result proj */
2081 if (results) { /* there are results */
2082 int rem = get_optimize();
2084 /* switch off optimization for new Proj nodes or they might be CSE'ed
2085 with not patched one's */
2087 for (i = j = 0, proj = get_irn_link(results); proj; proj = get_irn_link(proj), ++i, ++j) {
2088 if (get_Proj_pred(proj) == results) {
2089 long proj_nr = get_Proj_proj(proj);
2092 /* found a result */
2093 set_Proj_proj(proj, res_numbers[proj_nr]);
2094 idx = get_irn_idx(proj);
2095 if (env->entries[idx]) {
2096 ir_mode *mode = get_irn_mode(proj);
2097 ir_mode *low_mode = env->params->low_unsigned;
2100 if (mode == env->params->high_signed) {
2101 mode = env->params->low_signed;
2103 mode = env->params->low_unsigned;
2106 dbg = get_irn_dbg_info(proj);
2107 env->entries[idx]->low_word =
2108 new_rd_Proj(dbg, irg, get_nodes_block(proj), results, low_mode, res_numbers[proj_nr]);
2109 env->entries[idx]->high_word =
2110 new_rd_Proj(dbg, irg, get_nodes_block(proj), results, mode, res_numbers[proj_nr] + 1);
2112 mark_irn_visited(proj);
2120 * Translate an Unknown into two.
2122 static void lower_Unknown(ir_node *node, ir_mode *mode, lower_env_t *env) {
2123 int idx = get_irn_idx(node);
2124 ir_graph *irg = current_ir_graph;
2125 ir_mode *low_mode = env->params->low_unsigned;
2127 env->entries[idx]->low_word = new_r_Unknown(irg, low_mode);
2128 env->entries[idx]->high_word = new_r_Unknown(irg, mode);
2129 } /* lower_Unknown */
2134 * First step: just create two templates
2136 static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) {
2137 ir_mode *mode_l = env->params->low_unsigned;
2138 ir_graph *irg = current_ir_graph;
2139 ir_node *block, *unk_l, *unk_h, *phi_l, *phi_h;
2140 ir_node **inl, **inh;
2142 int idx, i, arity = get_Phi_n_preds(phi);
2145 idx = get_irn_idx(phi);
2146 if (env->entries[idx]->low_word) {
2147 /* Phi nodes already build, check for inputs */
2148 ir_node *phil = env->entries[idx]->low_word;
2149 ir_node *phih = env->entries[idx]->high_word;
2151 for (i = 0; i < arity; ++i) {
2152 ir_node *pred = get_Phi_pred(phi, i);
2153 int idx = get_irn_idx(pred);
2155 if (env->entries[idx]->low_word) {
2156 set_Phi_pred(phil, i, env->entries[idx]->low_word);
2157 set_Phi_pred(phih, i, env->entries[idx]->high_word);
2159 /* still not ready */
2160 pdeq_putr(env->waitq, phi);
2166 /* first create a new in array */
2167 NEW_ARR_A(ir_node *, inl, arity);
2168 NEW_ARR_A(ir_node *, inh, arity);
2169 unk_l = new_r_Unknown(irg, mode_l);
2170 unk_h = new_r_Unknown(irg, mode);
2172 for (i = 0; i < arity; ++i) {
2173 ir_node *pred = get_Phi_pred(phi, i);
2174 int idx = get_irn_idx(pred);
2176 if (env->entries[idx]->low_word) {
2177 inl[i] = env->entries[idx]->low_word;
2178 inh[i] = env->entries[idx]->high_word;
2186 dbg = get_irn_dbg_info(phi);
2187 block = get_nodes_block(phi);
2189 idx = get_irn_idx(phi);
2190 assert(idx < env->n_entries);
2191 env->entries[idx]->low_word = phi_l = new_rd_Phi(dbg, irg, block, arity, inl, mode_l);
2192 env->entries[idx]->high_word = phi_h = new_rd_Phi(dbg, irg, block, arity, inh, mode);
2194 /* Don't forget to link the new Phi nodes into the block.
2195 * Beware that some Phis might be optimized away. */
2197 add_Block_phi(block, phi_l);
2199 add_Block_phi(block, phi_h);
2202 /* not yet finished */
2203 pdeq_putr(env->waitq, phi);
2210 static void lower_Mux(ir_node *mux, ir_mode *mode, lower_env_t *env) {
2211 ir_graph *irg = current_ir_graph;
2212 ir_node *block, *val;
2213 ir_node *true_l, *true_h, *false_l, *false_h, *sel;
2217 val = get_Mux_true(mux);
2218 idx = get_irn_idx(val);
2219 if (env->entries[idx]->low_word) {
2220 /* Values already build */
2221 true_l = env->entries[idx]->low_word;
2222 true_h = env->entries[idx]->high_word;
2224 /* still not ready */
2225 pdeq_putr(env->waitq, mux);
2229 val = get_Mux_false(mux);
2230 idx = get_irn_idx(val);
2231 if (env->entries[idx]->low_word) {
2232 /* Values already build */
2233 false_l = env->entries[idx]->low_word;
2234 false_h = env->entries[idx]->high_word;
2236 /* still not ready */
2237 pdeq_putr(env->waitq, mux);
2242 sel = get_Mux_sel(mux);
2244 dbg = get_irn_dbg_info(mux);
2245 block = get_nodes_block(mux);
2247 idx = get_irn_idx(mux);
2248 assert(idx < env->n_entries);
2249 env->entries[idx]->low_word = new_rd_Mux(dbg, irg, block, sel, false_l, true_l, mode);
2250 env->entries[idx]->high_word = new_rd_Mux(dbg, irg, block, sel, false_h, true_h, mode);
2254 * Translate an ASM node.
2256 static void lower_ASM(ir_node *asmn, ir_mode *mode, lower_env_t *env) {
2257 ir_mode *his = env->params->high_signed;
2258 ir_mode *hiu = env->params->high_unsigned;
2264 for (i = get_irn_arity(asmn) - 1; i >= 0; --i) {
2265 ir_mode *op_mode = get_irn_mode(get_irn_n(asmn, i));
2266 if (op_mode == his || op_mode == hiu) {
2267 panic("lowering ASM unimplemented");
2274 n = get_irn_link(n);
2278 proj_mode = get_irn_mode(n);
2279 if (proj_mode == his || proj_mode == hiu) {
2280 panic("lowering ASM unimplemented");
2286 * Translate a Sel node.
2288 static void lower_Sel(ir_node *sel, ir_mode *mode, lower_env_t *env) {
2289 ir_node *ptr = get_Sel_ptr(sel);
2291 /* we must only lower value parameter sels if we change the
2292 value parameter type. */
2293 if (env->value_param_tp != NULL &&
2294 ptr == get_irg_value_param_base(current_ir_graph)) {
2295 ir_entity *ent = get_Sel_entity(sel);
2296 int pos = PTR_TO_INT(get_entity_link(ent));
2298 assert(get_entity_owner(ent) == env->value_param_tp);
2300 ent = get_method_value_param_ent(env->l_mtp, pos);
2301 set_Sel_entity(sel, ent);
2306 * check for opcodes that must always be lowered.
2308 static int always_lower(ir_opcode code) {
2322 } /* always_lower */
2325 * lower boolean Proj(Cmp)
2327 static ir_node *lower_boolean_Proj_Cmp(ir_node *proj, ir_node *cmp, lower_env_t *env) {
2329 ir_node *l, *r, *low, *high, *t, *res;
2332 ir_graph *irg = current_ir_graph;
2335 l = get_Cmp_left(cmp);
2336 lidx = get_irn_idx(l);
2337 if (! env->entries[lidx]->low_word) {
2338 /* still not ready */
2342 r = get_Cmp_right(cmp);
2343 ridx = get_irn_idx(r);
2344 if (! env->entries[ridx]->low_word) {
2345 /* still not ready */
2349 pnc = get_Proj_proj(proj);
2350 blk = get_nodes_block(cmp);
2351 db = get_irn_dbg_info(cmp);
2352 low = new_rd_Cmp(db, irg, blk, env->entries[lidx]->low_word, env->entries[ridx]->low_word);
2353 high = new_rd_Cmp(db, irg, blk, env->entries[lidx]->high_word, env->entries[ridx]->high_word);
2355 if (pnc == pn_Cmp_Eq) {
2356 /* simple case:a == b <==> a_h == b_h && a_l == b_l */
2357 res = new_rd_And(db, irg, blk,
2358 new_r_Proj(irg, blk, low, mode_b, pnc),
2359 new_r_Proj(irg, blk, high, mode_b, pnc),
2361 } else if (pnc == pn_Cmp_Lg) {
2362 /* simple case:a != b <==> a_h != b_h || a_l != b_l */
2363 res = new_rd_Or(db, irg, blk,
2364 new_r_Proj(irg, blk, low, mode_b, pnc),
2365 new_r_Proj(irg, blk, high, mode_b, pnc),
2368 /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
2369 t = new_rd_And(db, irg, blk,
2370 new_r_Proj(irg, blk, low, mode_b, pnc),
2371 new_r_Proj(irg, blk, high, mode_b, pn_Cmp_Eq),
2373 res = new_rd_Or(db, irg, blk,
2374 new_r_Proj(irg, blk, high, mode_b, pnc & ~pn_Cmp_Eq),
2379 } /* lower_boolean_Proj_Cmp */
2382 * The type of a lower function.
2384 * @param node the node to be lowered
2385 * @param mode the low mode for the destination node
2386 * @param env the lower environment
2388 typedef void (*lower_func)(ir_node *node, ir_mode *mode, lower_env_t *env);
2393 static void lower_ops(ir_node *node, void *env)
2395 lower_env_t *lenv = env;
2396 node_entry_t *entry;
2397 int idx = get_irn_idx(node);
2398 ir_mode *mode = get_irn_mode(node);
2400 if (mode == mode_b || is_Mux(node) || is_Conv(node)) {
2403 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
2404 ir_node *proj = get_irn_n(node, i);
2406 if (is_Proj(proj)) {
2407 ir_node *cmp = get_Proj_pred(proj);
2410 ir_node *arg = get_Cmp_left(cmp);
2412 mode = get_irn_mode(arg);
2413 if (mode == lenv->params->high_signed ||
2414 mode == lenv->params->high_unsigned) {
2415 ir_node *res = lower_boolean_Proj_Cmp(proj, cmp, lenv);
2418 /* could not lower because predecessors not ready */
2419 waitq_put(lenv->waitq, node);
2422 set_irn_n(node, i, res);
2429 entry = idx < lenv->n_entries ? lenv->entries[idx] : NULL;
2430 if (entry || always_lower(get_irn_opcode(node))) {
2431 ir_op *op = get_irn_op(node);
2432 lower_func func = (lower_func)op->ops.generic;
2435 mode = get_irn_op_mode(node);
2437 if (mode == lenv->params->high_signed)
2438 mode = lenv->params->low_signed;
2440 mode = lenv->params->low_unsigned;
2442 DB((dbg, LEVEL_1, " %+F\n", node));
2443 func(node, mode, lenv);
2448 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
2451 * Compare two op_mode_entry_t's.
2453 static int cmp_op_mode(const void *elt, const void *key, size_t size) {
2454 const op_mode_entry_t *e1 = elt;
2455 const op_mode_entry_t *e2 = key;
2458 return (e1->op - e2->op) | (e1->imode - e2->imode) | (e1->omode - e2->omode);
2462 * Compare two conv_tp_entry_t's.
2464 static int cmp_conv_tp(const void *elt, const void *key, size_t size) {
2465 const conv_tp_entry_t *e1 = elt;
2466 const conv_tp_entry_t *e2 = key;
2469 return (e1->imode - e2->imode) | (e1->omode - e2->omode);
2473 * Enter a lowering function into an ir_op.
2475 static void enter_lower_func(ir_op *op, lower_func func) {
2476 op->ops.generic = (op_func)func;
2477 } /* enter_lower_func */
2480 * Returns non-zero if a method type must be lowered.
2482 * @param mtp the method type
2484 static int mtp_must_to_lowered(ir_type *mtp, lower_env_t *env) {
2487 n_params = get_method_n_params(mtp);
2491 /* first check if we have parameters that must be fixed */
2492 for (i = 0; i < n_params; ++i) {
2493 ir_type *tp = get_method_param_type(mtp, i);
2495 if (is_Primitive_type(tp)) {
2496 ir_mode *mode = get_type_mode(tp);
2498 if (mode == env->params->high_signed ||
2499 mode == env->params->high_unsigned)
2504 } /* mtp_must_to_lowered */
2509 void lower_dw_ops(const lwrdw_param_t *param)
2518 if (! param->enable)
2521 FIRM_DBG_REGISTER(dbg, "firm.lower.dw");
2523 assert(2 * get_mode_size_bits(param->low_signed) == get_mode_size_bits(param->high_signed));
2524 assert(2 * get_mode_size_bits(param->low_unsigned) == get_mode_size_bits(param->high_unsigned));
2525 assert(get_mode_size_bits(param->low_signed) == get_mode_size_bits(param->low_unsigned));
2527 /* create the necessary maps */
2529 prim_types = pmap_create();
2530 if (! intrinsic_fkt)
2531 intrinsic_fkt = new_set(cmp_op_mode, iro_Last + 1);
2533 conv_types = new_set(cmp_conv_tp, 16);
2535 lowered_type = pmap_create();
2537 /* create a primitive unsigned and signed type */
2539 tp_u = get_primitive_type(param->low_unsigned);
2541 tp_s = get_primitive_type(param->low_signed);
2543 /* create method types for the created binop calls */
2545 binop_tp_u = new_type_method(IDENT("binop_u_intrinsic"), 4, 2);
2546 set_method_param_type(binop_tp_u, 0, tp_u);
2547 set_method_param_type(binop_tp_u, 1, tp_u);
2548 set_method_param_type(binop_tp_u, 2, tp_u);
2549 set_method_param_type(binop_tp_u, 3, tp_u);
2550 set_method_res_type(binop_tp_u, 0, tp_u);
2551 set_method_res_type(binop_tp_u, 1, tp_u);
2554 binop_tp_s = new_type_method(IDENT("binop_s_intrinsic"), 4, 2);
2555 set_method_param_type(binop_tp_s, 0, tp_u);
2556 set_method_param_type(binop_tp_s, 1, tp_s);
2557 set_method_param_type(binop_tp_s, 2, tp_u);
2558 set_method_param_type(binop_tp_s, 3, tp_s);
2559 set_method_res_type(binop_tp_s, 0, tp_u);
2560 set_method_res_type(binop_tp_s, 1, tp_s);
2562 if (! shiftop_tp_u) {
2563 shiftop_tp_u = new_type_method(IDENT("shiftop_u_intrinsic"), 3, 2);
2564 set_method_param_type(shiftop_tp_u, 0, tp_u);
2565 set_method_param_type(shiftop_tp_u, 1, tp_u);
2566 set_method_param_type(shiftop_tp_u, 2, tp_u);
2567 set_method_res_type(shiftop_tp_u, 0, tp_u);
2568 set_method_res_type(shiftop_tp_u, 1, tp_u);
2570 if (! shiftop_tp_s) {
2571 shiftop_tp_s = new_type_method(IDENT("shiftop_s_intrinsic"), 3, 2);
2572 set_method_param_type(shiftop_tp_s, 0, tp_u);
2573 set_method_param_type(shiftop_tp_s, 1, tp_s);
2574 set_method_param_type(shiftop_tp_s, 2, tp_u);
2575 set_method_res_type(shiftop_tp_s, 0, tp_u);
2576 set_method_res_type(shiftop_tp_s, 1, tp_s);
2579 unop_tp_u = new_type_method(IDENT("unop_u_intrinsic"), 2, 2);
2580 set_method_param_type(unop_tp_u, 0, tp_u);
2581 set_method_param_type(unop_tp_u, 1, tp_u);
2582 set_method_res_type(unop_tp_u, 0, tp_u);
2583 set_method_res_type(unop_tp_u, 1, tp_u);
2586 unop_tp_s = new_type_method(IDENT("unop_s_intrinsic"), 2, 2);
2587 set_method_param_type(unop_tp_s, 0, tp_u);
2588 set_method_param_type(unop_tp_s, 1, tp_s);
2589 set_method_res_type(unop_tp_s, 0, tp_u);
2590 set_method_res_type(unop_tp_s, 1, tp_s);
2593 lenv.tv_mode_bytes = new_tarval_from_long(get_mode_size_bytes(param->low_unsigned), param->low_unsigned);
2594 lenv.tv_mode_bits = new_tarval_from_long(get_mode_size_bits(param->low_unsigned), param->low_unsigned);
2595 lenv.waitq = new_pdeq();
2596 lenv.params = param;
2597 lenv.first_id = new_id_from_chars(param->little_endian ? ".l" : ".h", 2);
2598 lenv.next_id = new_id_from_chars(param->little_endian ? ".h" : ".l", 2);
2600 /* first clear the generic function pointer for all ops */
2601 clear_irp_opcodes_generic_func();
2603 #define LOWER2(op, fkt) enter_lower_func(op_##op, fkt)
2604 #define LOWER(op) LOWER2(op, lower_##op)
2605 #define LOWER_BIN(op) LOWER2(op, lower_Binop)
2606 #define LOWER_UN(op) LOWER2(op, lower_Unop)
2608 /* the table of all operations that must be lowered follows */
2646 /* transform all graphs */
2647 rem = current_ir_graph;
2648 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2649 ir_graph *irg = get_irp_irg(i);
2654 obstack_init(&lenv.obst);
2656 n_idx = get_irg_last_idx(irg);
2657 n_idx = n_idx + (n_idx >> 2); /* add 25% */
2658 lenv.n_entries = n_idx;
2659 lenv.entries = NEW_ARR_F(node_entry_t *, n_idx);
2660 memset(lenv.entries, 0, n_idx * sizeof(lenv.entries[0]));
2664 lenv.proj_2_block = pmap_create();
2666 lenv.value_param_tp = NULL;
2668 ir_reserve_resources(irg, IR_RESOURCE_PHI_LIST | IR_RESOURCE_IRN_LINK);
2670 ent = get_irg_entity(irg);
2671 mtp = get_entity_type(ent);
2673 if (mtp_must_to_lowered(mtp, &lenv)) {
2674 ir_type *ltp = lower_mtp(mtp, &lenv);
2675 lenv.flags |= MUST_BE_LOWERED;
2676 set_entity_type(ent, ltp);
2679 lenv.value_param_tp = get_method_value_param_type(mtp);
2683 /* first step: link all nodes and allocate data */
2684 irg_walk_graph(irg, firm_clear_node_and_phi_links, prepare_links_and_handle_rotl, &lenv);
2686 if (lenv.flags & MUST_BE_LOWERED) {
2687 DB((dbg, LEVEL_1, "Lowering graph %+F\n", irg));
2689 /* must do some work */
2690 irg_walk_graph(irg, NULL, lower_ops, &lenv);
2692 /* last step: all waiting nodes */
2693 DB((dbg, LEVEL_1, "finishing waiting nodes:\n"));
2694 current_ir_graph = irg;
2695 while (! pdeq_empty(lenv.waitq)) {
2696 ir_node *node = pdeq_getl(lenv.waitq);
2698 lower_ops(node, &lenv);
2701 ir_free_resources(irg, IR_RESOURCE_PHI_LIST | IR_RESOURCE_IRN_LINK);
2703 /* outs are invalid, we changed the graph */
2704 set_irg_outs_inconsistent(irg);
2706 if (lenv.flags & CF_CHANGED) {
2707 /* control flow changed, dominance info is invalid */
2708 set_irg_doms_inconsistent(irg);
2709 set_irg_extblk_inconsistent(irg);
2710 set_irg_loopinfo_inconsistent(irg);
2713 ir_free_resources(irg, IR_RESOURCE_PHI_LIST | IR_RESOURCE_IRN_LINK);
2715 pmap_destroy(lenv.proj_2_block);
2716 DEL_ARR_F(lenv.entries);
2717 obstack_free(&lenv.obst, NULL);
2719 del_pdeq(lenv.waitq);
2720 current_ir_graph = rem;
2721 } /* lower_dw_ops */
2723 /* Default implementation. */
2724 ir_entity *def_create_intrinsic_fkt(ir_type *method, const ir_op *op,
2725 const ir_mode *imode, const ir_mode *omode,
2733 if (imode == omode) {
2734 snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));
2736 snprintf(buf, sizeof(buf), "__l%s%s%s", get_op_name(op),
2737 get_mode_name(imode), get_mode_name(omode));
2739 id = new_id_from_str(buf);
2741 ent = new_entity(get_glob_type(), id, method);
2742 set_entity_ld_ident(ent, get_entity_ident(ent));
2743 set_entity_visibility(ent, visibility_external_allocated);
2745 } /* def_create_intrinsic_fkt */