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 This file implements the IR transformation from firm into
24 * @author Christian Wuerdig, Matthias Braun
35 #include "irgraph_t.h"
40 #include "iredges_t.h"
52 #include "../benode_t.h"
53 #include "../besched.h"
55 #include "../beutil.h"
56 #include "../beirg_t.h"
57 #include "../betranshlp.h"
60 #include "bearch_ia32_t.h"
61 #include "ia32_nodes_attr.h"
62 #include "ia32_transform.h"
63 #include "ia32_new_nodes.h"
64 #include "ia32_map_regs.h"
65 #include "ia32_dbg_stat.h"
66 #include "ia32_optimize.h"
67 #include "ia32_util.h"
68 #include "ia32_address_mode.h"
69 #include "ia32_architecture.h"
71 #include "gen_ia32_regalloc_if.h"
73 #define SFP_SIGN "0x80000000"
74 #define DFP_SIGN "0x8000000000000000"
75 #define SFP_ABS "0x7FFFFFFF"
76 #define DFP_ABS "0x7FFFFFFFFFFFFFFF"
77 #define DFP_INTMAX "9223372036854775807"
79 #define TP_SFP_SIGN "ia32_sfp_sign"
80 #define TP_DFP_SIGN "ia32_dfp_sign"
81 #define TP_SFP_ABS "ia32_sfp_abs"
82 #define TP_DFP_ABS "ia32_dfp_abs"
83 #define TP_INT_MAX "ia32_int_max"
85 #define ENT_SFP_SIGN "IA32_SFP_SIGN"
86 #define ENT_DFP_SIGN "IA32_DFP_SIGN"
87 #define ENT_SFP_ABS "IA32_SFP_ABS"
88 #define ENT_DFP_ABS "IA32_DFP_ABS"
89 #define ENT_INT_MAX "IA32_INT_MAX"
91 #define mode_vfp (ia32_reg_classes[CLASS_ia32_vfp].mode)
92 #define mode_xmm (ia32_reg_classes[CLASS_ia32_xmm].mode)
94 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
96 /** hold the current code generator during transformation */
97 static ia32_code_gen_t *env_cg = NULL;
98 static ir_node *initial_fpcw = NULL;
99 static heights_t *heights = NULL;
101 extern ir_op *get_op_Mulh(void);
103 typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
104 ir_node *block, ir_node *base, ir_node *index, ir_node *mem,
105 ir_node *op1, ir_node *op2);
107 typedef ir_node *construct_binop_flags_func(dbg_info *db, ir_graph *irg,
108 ir_node *block, ir_node *base, ir_node *index, ir_node *mem,
109 ir_node *op1, ir_node *op2, ir_node *flags);
111 typedef ir_node *construct_shift_func(dbg_info *db, ir_graph *irg,
112 ir_node *block, ir_node *op1, ir_node *op2);
114 typedef ir_node *construct_binop_dest_func(dbg_info *db, ir_graph *irg,
115 ir_node *block, ir_node *base, ir_node *index, ir_node *mem,
118 typedef ir_node *construct_unop_dest_func(dbg_info *db, ir_graph *irg,
119 ir_node *block, ir_node *base, ir_node *index, ir_node *mem);
121 typedef ir_node *construct_binop_float_func(dbg_info *db, ir_graph *irg,
122 ir_node *block, ir_node *base, ir_node *index, ir_node *mem,
123 ir_node *op1, ir_node *op2, ir_node *fpcw);
125 typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
126 ir_node *block, ir_node *op);
128 static ir_node *try_create_Immediate(ir_node *node,
129 char immediate_constraint_type);
131 static ir_node *create_immediate_or_transform(ir_node *node,
132 char immediate_constraint_type);
134 static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
135 dbg_info *dbgi, ir_node *block,
136 ir_node *op, ir_node *orig_node);
139 * Return true if a mode can be stored in the GP register set
141 static INLINE int mode_needs_gp_reg(ir_mode *mode) {
142 if(mode == mode_fpcw)
144 if(get_mode_size_bits(mode) > 32)
146 return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
150 * creates a unique ident by adding a number to a tag
152 * @param tag the tag string, must contain a %d if a number
155 static ident *unique_id(const char *tag)
157 static unsigned id = 0;
160 snprintf(str, sizeof(str), tag, ++id);
161 return new_id_from_str(str);
165 * Get a primitive type for a mode.
167 static ir_type *get_prim_type(pmap *types, ir_mode *mode)
169 pmap_entry *e = pmap_find(types, mode);
174 snprintf(buf, sizeof(buf), "prim_type_%s", get_mode_name(mode));
175 res = new_type_primitive(new_id_from_str(buf), mode);
176 set_type_alignment_bytes(res, 16);
177 pmap_insert(types, mode, res);
185 * Creates an immediate.
187 * @param symconst if set, create a SymConst immediate
188 * @param symconst_sign sign for the symconst
189 * @param val integer value for the immediate
191 static ir_node *create_Immediate(ir_entity *symconst, int symconst_sign, long val)
193 ir_graph *irg = current_ir_graph;
194 ir_node *start_block = get_irg_start_block(irg);
195 ir_node *immediate = new_rd_ia32_Immediate(NULL, irg, start_block,
196 symconst, symconst_sign, val);
197 arch_set_irn_register(env_cg->arch_env, immediate, &ia32_gp_regs[REG_GP_NOREG]);
203 * Get an atomic entity that is initialized with a tarval forming
206 * @param cnst the node representing the constant
208 static ir_entity *create_float_const_entity(ir_node *cnst)
210 ia32_isa_t *isa = env_cg->isa;
211 tarval *key = get_Const_tarval(cnst);
212 pmap_entry *e = pmap_find(isa->tv_ent, key);
218 ir_mode *mode = get_tarval_mode(tv);
221 if (! ia32_cg_config.use_sse2) {
222 /* try to reduce the mode to produce smaller sized entities */
223 if (mode != mode_F) {
224 if (tarval_ieee754_can_conv_lossless(tv, mode_F)) {
226 tv = tarval_convert_to(tv, mode);
227 } else if (mode != mode_D) {
228 if (tarval_ieee754_can_conv_lossless(tv, mode_D)) {
230 tv = tarval_convert_to(tv, mode);
236 if (mode == get_irn_mode(cnst)) {
237 /* mode was not changed */
238 tp = get_Const_type(cnst);
239 if (tp == firm_unknown_type)
240 tp = get_prim_type(isa->types, mode);
242 tp = get_prim_type(isa->types, mode);
244 res = new_entity(get_glob_type(), unique_id(".LC%u"), tp);
246 set_entity_ld_ident(res, get_entity_ident(res));
247 set_entity_visibility(res, visibility_local);
248 set_entity_variability(res, variability_constant);
249 set_entity_allocation(res, allocation_static);
251 /* we create a new entity here: It's initialization must resist on the
253 rem = current_ir_graph;
254 current_ir_graph = get_const_code_irg();
255 set_atomic_ent_value(res, new_Const_type(tv, tp));
256 current_ir_graph = rem;
258 pmap_insert(isa->tv_ent, key, res);
266 /** Return non-zero is a node represents the 0 constant. */
267 static int is_Const_0(ir_node *node) {
268 return is_Const(node) && is_Const_null(node);
271 /** Return non-zero is a node represents the 1 constant. */
272 static int is_Const_1(ir_node *node) {
273 return is_Const(node) && is_Const_one(node);
276 /** Return non-zero is a node represents the -1 constant. */
277 static int is_Const_Minus_1(ir_node *node) {
278 return is_Const(node) && is_Const_all_one(node);
282 * returns true if constant can be created with a simple float command
284 static int is_simple_x87_Const(ir_node *node)
286 tarval *tv = get_Const_tarval(node);
287 if (tarval_is_null(tv) || tarval_is_one(tv))
290 /* TODO: match all the other float constants */
295 * returns true if constant can be created with a simple float command
297 static int is_simple_sse_Const(ir_node *node)
299 tarval *tv = get_Const_tarval(node);
300 ir_mode *mode = get_tarval_mode(tv);
305 if (tarval_is_null(tv) || tarval_is_one(tv))
308 if (mode == mode_D) {
309 unsigned val = get_tarval_sub_bits(tv, 0) |
310 (get_tarval_sub_bits(tv, 1) << 8) |
311 (get_tarval_sub_bits(tv, 2) << 16) |
312 (get_tarval_sub_bits(tv, 3) << 24);
314 /* lower 32bit are zero, really a 32bit constant */
318 /* TODO: match all the other float constants */
323 * Transforms a Const.
325 static ir_node *gen_Const(ir_node *node) {
326 ir_graph *irg = current_ir_graph;
327 ir_node *old_block = get_nodes_block(node);
328 ir_node *block = be_transform_node(old_block);
329 dbg_info *dbgi = get_irn_dbg_info(node);
330 ir_mode *mode = get_irn_mode(node);
332 assert(is_Const(node));
334 if (mode_is_float(mode)) {
336 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
337 ir_node *nomem = new_NoMem();
341 if (ia32_cg_config.use_sse2) {
342 tarval *tv = get_Const_tarval(node);
343 if (tarval_is_null(tv)) {
344 load = new_rd_ia32_xZero(dbgi, irg, block);
345 set_ia32_ls_mode(load, mode);
347 } else if (tarval_is_one(tv)) {
348 int cnst = mode == mode_F ? 26 : 55;
349 ir_node *imm1 = create_Immediate(NULL, 0, cnst);
350 ir_node *imm2 = create_Immediate(NULL, 0, 2);
351 ir_node *pslld, *psrld;
353 load = new_rd_ia32_xAllOnes(dbgi, irg, block);
354 set_ia32_ls_mode(load, mode);
355 pslld = new_rd_ia32_xPslld(dbgi, irg, block, load, imm1);
356 set_ia32_ls_mode(pslld, mode);
357 psrld = new_rd_ia32_xPsrld(dbgi, irg, block, pslld, imm2);
358 set_ia32_ls_mode(psrld, mode);
360 } else if (mode == mode_F) {
361 /* we can place any 32bit constant by using a movd gp, sse */
362 unsigned val = get_tarval_sub_bits(tv, 0) |
363 (get_tarval_sub_bits(tv, 1) << 8) |
364 (get_tarval_sub_bits(tv, 2) << 16) |
365 (get_tarval_sub_bits(tv, 3) << 24);
366 ir_node *cnst = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, val);
367 load = new_rd_ia32_xMovd(dbgi, irg, block, cnst);
368 set_ia32_ls_mode(load, mode);
371 if (mode == mode_D) {
372 unsigned val = get_tarval_sub_bits(tv, 0) |
373 (get_tarval_sub_bits(tv, 1) << 8) |
374 (get_tarval_sub_bits(tv, 2) << 16) |
375 (get_tarval_sub_bits(tv, 3) << 24);
377 ir_node *imm32 = create_Immediate(NULL, 0, 32);
378 ir_node *cnst, *psllq;
380 /* fine, lower 32bit are zero, produce 32bit value */
381 val = get_tarval_sub_bits(tv, 4) |
382 (get_tarval_sub_bits(tv, 5) << 8) |
383 (get_tarval_sub_bits(tv, 6) << 16) |
384 (get_tarval_sub_bits(tv, 7) << 24);
385 cnst = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, val);
386 load = new_rd_ia32_xMovd(dbgi, irg, block, cnst);
387 set_ia32_ls_mode(load, mode);
388 psllq = new_rd_ia32_xPsllq(dbgi, irg, block, load, imm32);
389 set_ia32_ls_mode(psllq, mode);
394 floatent = create_float_const_entity(node);
396 load = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem,
398 set_ia32_op_type(load, ia32_AddrModeS);
399 set_ia32_am_sc(load, floatent);
400 set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
401 res = new_r_Proj(irg, block, load, mode_xmm, pn_ia32_xLoad_res);
404 if (is_Const_null(node)) {
405 load = new_rd_ia32_vfldz(dbgi, irg, block);
407 set_ia32_ls_mode(load, mode);
408 } else if (is_Const_one(node)) {
409 load = new_rd_ia32_vfld1(dbgi, irg, block);
411 set_ia32_ls_mode(load, mode);
413 floatent = create_float_const_entity(node);
415 load = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
416 set_ia32_op_type(load, ia32_AddrModeS);
417 set_ia32_am_sc(load, floatent);
418 set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
419 res = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
420 /* take the mode from the entity */
421 set_ia32_ls_mode(load, get_type_mode(get_entity_type(floatent)));
425 /* Const Nodes before the initial IncSP are a bad idea, because
426 * they could be spilled and we have no SP ready at that point yet.
427 * So add a dependency to the initial frame pointer calculation to
428 * avoid that situation.
430 if (get_irg_start_block(irg) == block) {
431 add_irn_dep(load, get_irg_frame(irg));
434 SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
436 } else { /* non-float mode */
438 tarval *tv = get_Const_tarval(node);
441 tv = tarval_convert_to(tv, mode_Iu);
443 if (tv == get_tarval_bad() || tv == get_tarval_undefined() ||
445 panic("couldn't convert constant tarval (%+F)", node);
447 val = get_tarval_long(tv);
449 cnst = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, val);
450 SET_IA32_ORIG_NODE(cnst, ia32_get_old_node_name(env_cg, node));
453 if (get_irg_start_block(irg) == block) {
454 add_irn_dep(cnst, get_irg_frame(irg));
462 * Transforms a SymConst.
464 static ir_node *gen_SymConst(ir_node *node) {
465 ir_graph *irg = current_ir_graph;
466 ir_node *old_block = get_nodes_block(node);
467 ir_node *block = be_transform_node(old_block);
468 dbg_info *dbgi = get_irn_dbg_info(node);
469 ir_mode *mode = get_irn_mode(node);
472 if (mode_is_float(mode)) {
473 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
474 ir_node *nomem = new_NoMem();
476 if (ia32_cg_config.use_sse2)
477 cnst = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem, mode_E);
479 cnst = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode_E);
480 set_ia32_am_sc(cnst, get_SymConst_entity(node));
481 set_ia32_use_frame(cnst);
485 if(get_SymConst_kind(node) != symconst_addr_ent) {
486 panic("backend only support symconst_addr_ent (at %+F)", node);
488 entity = get_SymConst_entity(node);
489 cnst = new_rd_ia32_Const(dbgi, irg, block, entity, 0, 0);
492 /* Const Nodes before the initial IncSP are a bad idea, because
493 * they could be spilled and we have no SP ready at that point yet
495 if (get_irg_start_block(irg) == block) {
496 add_irn_dep(cnst, get_irg_frame(irg));
499 SET_IA32_ORIG_NODE(cnst, ia32_get_old_node_name(env_cg, node));
504 /* Generates an entity for a known FP const (used for FP Neg + Abs) */
505 ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
506 static const struct {
508 const char *ent_name;
509 const char *cnst_str;
512 } names [ia32_known_const_max] = {
513 { TP_SFP_SIGN, ENT_SFP_SIGN, SFP_SIGN, 0, 16 }, /* ia32_SSIGN */
514 { TP_DFP_SIGN, ENT_DFP_SIGN, DFP_SIGN, 1, 16 }, /* ia32_DSIGN */
515 { TP_SFP_ABS, ENT_SFP_ABS, SFP_ABS, 0, 16 }, /* ia32_SABS */
516 { TP_DFP_ABS, ENT_DFP_ABS, DFP_ABS, 1, 16 }, /* ia32_DABS */
517 { TP_INT_MAX, ENT_INT_MAX, DFP_INTMAX, 2, 4 } /* ia32_INTMAX */
519 static ir_entity *ent_cache[ia32_known_const_max];
521 const char *tp_name, *ent_name, *cnst_str;
529 ent_name = names[kct].ent_name;
530 if (! ent_cache[kct]) {
531 tp_name = names[kct].tp_name;
532 cnst_str = names[kct].cnst_str;
534 switch (names[kct].mode) {
535 case 0: mode = mode_Iu; break;
536 case 1: mode = mode_Lu; break;
537 default: mode = mode_F; break;
539 tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
540 tp = new_type_primitive(new_id_from_str(tp_name), mode);
541 /* set the specified alignment */
542 set_type_alignment_bytes(tp, names[kct].align);
544 ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
546 set_entity_ld_ident(ent, get_entity_ident(ent));
547 set_entity_visibility(ent, visibility_local);
548 set_entity_variability(ent, variability_constant);
549 set_entity_allocation(ent, allocation_static);
551 /* we create a new entity here: It's initialization must resist on the
553 rem = current_ir_graph;
554 current_ir_graph = get_const_code_irg();
555 cnst = new_Const(mode, tv);
556 current_ir_graph = rem;
558 set_atomic_ent_value(ent, cnst);
560 /* cache the entry */
561 ent_cache[kct] = ent;
564 return ent_cache[kct];
569 * Prints the old node name on cg obst and returns a pointer to it.
571 const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
572 ia32_isa_t *isa = (ia32_isa_t*) cg->arch_env;
574 lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", irn);
575 obstack_1grow(isa->name_obst, 0);
576 return obstack_finish(isa->name_obst);
581 * return true if the node is a Proj(Load) and could be used in source address
582 * mode for another node. Will return only true if the @p other node is not
583 * dependent on the memory of the Load (for binary operations use the other
584 * input here, for unary operations use NULL).
586 static int ia32_use_source_address_mode(ir_node *block, ir_node *node,
587 ir_node *other, ir_node *other2, match_flags_t flags)
592 /* float constants are always available */
593 if (is_Const(node)) {
594 ir_mode *mode = get_irn_mode(node);
595 if (mode_is_float(mode)) {
596 if (ia32_cg_config.use_sse2) {
597 if (is_simple_sse_Const(node))
600 if (is_simple_x87_Const(node))
603 if (get_irn_n_edges(node) > 1)
611 load = get_Proj_pred(node);
612 pn = get_Proj_proj(node);
613 if (!is_Load(load) || pn != pn_Load_res)
615 if (get_nodes_block(load) != block)
617 /* we only use address mode if we're the only user of the load */
618 if (get_irn_n_edges(node) != (flags & match_two_users ? 2 : 1))
620 /* in some edge cases with address mode we might reach the load normally
621 * and through some AM sequence, if it is already materialized then we
622 * can't create an AM node from it */
623 if (be_is_transformed(node))
626 /* don't do AM if other node inputs depend on the load (via mem-proj) */
627 if (other != NULL && get_nodes_block(other) == block &&
628 heights_reachable_in_block(heights, other, load))
630 if (other2 != NULL && get_nodes_block(other2) == block &&
631 heights_reachable_in_block(heights, other2, load))
637 typedef struct ia32_address_mode_t ia32_address_mode_t;
638 struct ia32_address_mode_t {
642 ia32_op_type_t op_type;
646 unsigned commutative : 1;
647 unsigned ins_permuted : 1;
650 static void build_address_ptr(ia32_address_t *addr, ir_node *ptr, ir_node *mem)
654 /* construct load address */
655 memset(addr, 0, sizeof(addr[0]));
656 ia32_create_address_mode(addr, ptr, /*force=*/0);
658 noreg_gp = ia32_new_NoReg_gp(env_cg);
659 addr->base = addr->base ? be_transform_node(addr->base) : noreg_gp;
660 addr->index = addr->index ? be_transform_node(addr->index) : noreg_gp;
661 addr->mem = be_transform_node(mem);
664 static void build_address(ia32_address_mode_t *am, ir_node *node)
666 ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
667 ia32_address_t *addr = &am->addr;
673 if (is_Const(node)) {
674 ir_entity *entity = create_float_const_entity(node);
675 addr->base = noreg_gp;
676 addr->index = noreg_gp;
677 addr->mem = new_NoMem();
678 addr->symconst_ent = entity;
680 am->ls_mode = get_type_mode(get_entity_type(entity));
681 am->pinned = op_pin_state_floats;
685 load = get_Proj_pred(node);
686 ptr = get_Load_ptr(load);
687 mem = get_Load_mem(load);
688 new_mem = be_transform_node(mem);
689 am->pinned = get_irn_pinned(load);
690 am->ls_mode = get_Load_mode(load);
691 am->mem_proj = be_get_Proj_for_pn(load, pn_Load_M);
693 /* construct load address */
694 ia32_create_address_mode(addr, ptr, /*force=*/0);
696 addr->base = addr->base ? be_transform_node(addr->base) : noreg_gp;
697 addr->index = addr->index ? be_transform_node(addr->index) : noreg_gp;
701 static void set_address(ir_node *node, const ia32_address_t *addr)
703 set_ia32_am_scale(node, addr->scale);
704 set_ia32_am_sc(node, addr->symconst_ent);
705 set_ia32_am_offs_int(node, addr->offset);
706 if(addr->symconst_sign)
707 set_ia32_am_sc_sign(node);
709 set_ia32_use_frame(node);
710 set_ia32_frame_ent(node, addr->frame_entity);
714 * Apply attributes of a given address mode to a node.
716 static void set_am_attributes(ir_node *node, const ia32_address_mode_t *am)
718 set_address(node, &am->addr);
720 set_ia32_op_type(node, am->op_type);
721 set_ia32_ls_mode(node, am->ls_mode);
722 if (am->pinned == op_pin_state_pinned) {
723 /* beware: some nodes are already pinned and did not allow to change the state */
724 if (get_irn_pinned(node) != op_pin_state_pinned)
725 set_irn_pinned(node, op_pin_state_pinned);
728 set_ia32_commutative(node);
732 * Check, if a given node is a Down-Conv, ie. a integer Conv
733 * from a mode with a mode with more bits to a mode with lesser bits.
734 * Moreover, we return only true if the node has not more than 1 user.
736 * @param node the node
737 * @return non-zero if node is a Down-Conv
739 static int is_downconv(const ir_node *node)
747 /* we only want to skip the conv when we're the only user
748 * (not optimal but for now...)
750 if(get_irn_n_edges(node) > 1)
753 src_mode = get_irn_mode(get_Conv_op(node));
754 dest_mode = get_irn_mode(node);
755 return mode_needs_gp_reg(src_mode)
756 && mode_needs_gp_reg(dest_mode)
757 && get_mode_size_bits(dest_mode) < get_mode_size_bits(src_mode);
760 /* Skip all Down-Conv's on a given node and return the resulting node. */
761 ir_node *ia32_skip_downconv(ir_node *node) {
762 while (is_downconv(node))
763 node = get_Conv_op(node);
768 static ir_node *create_upconv(ir_node *node, ir_node *orig_node)
770 ir_mode *mode = get_irn_mode(node);
775 if(mode_is_signed(mode)) {
780 block = get_nodes_block(node);
781 dbgi = get_irn_dbg_info(node);
783 return create_I2I_Conv(mode, tgt_mode, dbgi, block, node, orig_node);
787 * matches operands of a node into ia32 addressing/operand modes. This covers
788 * usage of source address mode, immediates, operations with non 32-bit modes,
790 * The resulting data is filled into the @p am struct. block is the block
791 * of the node whose arguments are matched. op1, op2 are the first and second
792 * input that are matched (op1 may be NULL). other_op is another unrelated
793 * input that is not matched! but which is needed sometimes to check if AM
794 * for op1/op2 is legal.
795 * @p flags describes the supported modes of the operation in detail.
797 static void match_arguments(ia32_address_mode_t *am, ir_node *block,
798 ir_node *op1, ir_node *op2, ir_node *other_op,
801 ia32_address_t *addr = &am->addr;
802 ir_mode *mode = get_irn_mode(op2);
803 int mode_bits = get_mode_size_bits(mode);
804 ir_node *noreg_gp, *new_op1, *new_op2;
806 unsigned commutative;
807 int use_am_and_immediates;
810 memset(am, 0, sizeof(am[0]));
812 commutative = (flags & match_commutative) != 0;
813 use_am_and_immediates = (flags & match_am_and_immediates) != 0;
814 use_am = (flags & match_am) != 0;
815 use_immediate = (flags & match_immediate) != 0;
816 assert(!use_am_and_immediates || use_immediate);
819 assert(!commutative || op1 != NULL);
820 assert(use_am || !(flags & match_8bit_am));
821 assert(use_am || !(flags & match_16bit_am));
823 if (mode_bits == 8) {
824 if (!(flags & match_8bit_am))
826 /* we don't automatically add upconvs yet */
827 assert((flags & match_mode_neutral) || (flags & match_8bit));
828 } else if (mode_bits == 16) {
829 if (!(flags & match_16bit_am))
831 /* we don't automatically add upconvs yet */
832 assert((flags & match_mode_neutral) || (flags & match_16bit));
835 /* we can simply skip downconvs for mode neutral nodes: the upper bits
836 * can be random for these operations */
837 if (flags & match_mode_neutral) {
838 op2 = ia32_skip_downconv(op2);
840 op1 = ia32_skip_downconv(op1);
844 /* match immediates. firm nodes are normalized: constants are always on the
847 if (!(flags & match_try_am) && use_immediate) {
848 new_op2 = try_create_Immediate(op2, 0);
851 noreg_gp = ia32_new_NoReg_gp(env_cg);
852 if (new_op2 == NULL &&
853 use_am && ia32_use_source_address_mode(block, op2, op1, other_op, flags)) {
854 build_address(am, op2);
855 new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
856 if (mode_is_float(mode)) {
857 new_op2 = ia32_new_NoReg_vfp(env_cg);
861 am->op_type = ia32_AddrModeS;
862 } else if (commutative && (new_op2 == NULL || use_am_and_immediates) &&
864 ia32_use_source_address_mode(block, op1, op2, other_op, flags)) {
866 build_address(am, op1);
868 if (mode_is_float(mode)) {
869 noreg = ia32_new_NoReg_vfp(env_cg);
874 if (new_op2 != NULL) {
877 new_op1 = be_transform_node(op2);
879 am->ins_permuted = 1;
881 am->op_type = ia32_AddrModeS;
883 if (flags & match_try_am) {
886 am->op_type = ia32_Normal;
890 new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
892 new_op2 = be_transform_node(op2);
893 am->op_type = ia32_Normal;
894 am->ls_mode = get_irn_mode(op2);
895 if (flags & match_mode_neutral)
896 am->ls_mode = mode_Iu;
898 if (addr->base == NULL)
899 addr->base = noreg_gp;
900 if (addr->index == NULL)
901 addr->index = noreg_gp;
902 if (addr->mem == NULL)
903 addr->mem = new_NoMem();
905 am->new_op1 = new_op1;
906 am->new_op2 = new_op2;
907 am->commutative = commutative;
910 static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am)
915 if (am->mem_proj == NULL)
918 /* we have to create a mode_T so the old MemProj can attach to us */
919 mode = get_irn_mode(node);
920 load = get_Proj_pred(am->mem_proj);
922 mark_irn_visited(load);
923 be_set_transformed_node(load, node);
925 if (mode != mode_T) {
926 set_irn_mode(node, mode_T);
927 return new_rd_Proj(NULL, current_ir_graph, get_nodes_block(node), node, mode, pn_ia32_res);
934 * Construct a standard binary operation, set AM and immediate if required.
936 * @param node The original node for which the binop is created
937 * @param op1 The first operand
938 * @param op2 The second operand
939 * @param func The node constructor function
940 * @return The constructed ia32 node.
942 static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
943 construct_binop_func *func, match_flags_t flags)
946 ir_node *block, *new_block, *new_node;
947 ia32_address_mode_t am;
948 ia32_address_t *addr = &am.addr;
950 block = get_nodes_block(node);
951 match_arguments(&am, block, op1, op2, NULL, flags);
953 dbgi = get_irn_dbg_info(node);
954 new_block = be_transform_node(block);
955 new_node = func(dbgi, current_ir_graph, new_block,
956 addr->base, addr->index, addr->mem,
957 am.new_op1, am.new_op2);
958 set_am_attributes(new_node, &am);
959 /* we can't use source address mode anymore when using immediates */
960 if (is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
961 set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
962 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
964 new_node = fix_mem_proj(new_node, &am);
971 n_ia32_l_binop_right,
972 n_ia32_l_binop_eflags
974 COMPILETIME_ASSERT(n_ia32_l_binop_left == n_ia32_l_Adc_left, n_Adc_left)
975 COMPILETIME_ASSERT(n_ia32_l_binop_right == n_ia32_l_Adc_right, n_Adc_right)
976 COMPILETIME_ASSERT(n_ia32_l_binop_eflags == n_ia32_l_Adc_eflags, n_Adc_eflags)
977 COMPILETIME_ASSERT(n_ia32_l_binop_left == n_ia32_l_Sbb_minuend, n_Sbb_minuend)
978 COMPILETIME_ASSERT(n_ia32_l_binop_right == n_ia32_l_Sbb_subtrahend, n_Sbb_subtrahend)
979 COMPILETIME_ASSERT(n_ia32_l_binop_eflags == n_ia32_l_Sbb_eflags, n_Sbb_eflags)
982 * Construct a binary operation which also consumes the eflags.
984 * @param node The node to transform
985 * @param func The node constructor function
986 * @param flags The match flags
987 * @return The constructor ia32 node
989 static ir_node *gen_binop_flags(ir_node *node, construct_binop_flags_func *func,
992 ir_node *src_block = get_nodes_block(node);
993 ir_node *op1 = get_irn_n(node, n_ia32_l_binop_left);
994 ir_node *op2 = get_irn_n(node, n_ia32_l_binop_right);
996 ir_node *block, *new_node, *eflags, *new_eflags;
997 ia32_address_mode_t am;
998 ia32_address_t *addr = &am.addr;
1000 match_arguments(&am, src_block, op1, op2, NULL, flags);
1002 dbgi = get_irn_dbg_info(node);
1003 block = be_transform_node(src_block);
1004 eflags = get_irn_n(node, n_ia32_l_binop_eflags);
1005 new_eflags = be_transform_node(eflags);
1006 new_node = func(dbgi, current_ir_graph, block, addr->base, addr->index,
1007 addr->mem, am.new_op1, am.new_op2, new_eflags);
1008 set_am_attributes(new_node, &am);
1009 /* we can't use source address mode anymore when using immediates */
1010 if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
1011 set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
1012 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1014 new_node = fix_mem_proj(new_node, &am);
1019 static ir_node *get_fpcw(void)
1022 if (initial_fpcw != NULL)
1023 return initial_fpcw;
1025 fpcw = be_abi_get_ignore_irn(env_cg->birg->abi,
1026 &ia32_fp_cw_regs[REG_FPCW]);
1027 initial_fpcw = be_transform_node(fpcw);
1029 return initial_fpcw;
1033 * Construct a standard binary operation, set AM and immediate if required.
1035 * @param op1 The first operand
1036 * @param op2 The second operand
1037 * @param func The node constructor function
1038 * @return The constructed ia32 node.
1040 static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
1041 construct_binop_float_func *func,
1042 match_flags_t flags)
1044 ir_mode *mode = get_irn_mode(node);
1046 ir_node *block, *new_block, *new_node;
1047 ia32_address_mode_t am;
1048 ia32_address_t *addr = &am.addr;
1050 /* cannot use address mode with long double on x87 */
1051 if (get_mode_size_bits(mode) > 64)
1054 block = get_nodes_block(node);
1055 match_arguments(&am, block, op1, op2, NULL, flags);
1057 dbgi = get_irn_dbg_info(node);
1058 new_block = be_transform_node(block);
1059 new_node = func(dbgi, current_ir_graph, new_block,
1060 addr->base, addr->index, addr->mem,
1061 am.new_op1, am.new_op2, get_fpcw());
1062 set_am_attributes(new_node, &am);
1064 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1066 new_node = fix_mem_proj(new_node, &am);
1072 * Construct a shift/rotate binary operation, sets AM and immediate if required.
1074 * @param op1 The first operand
1075 * @param op2 The second operand
1076 * @param func The node constructor function
1077 * @return The constructed ia32 node.
1079 static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
1080 construct_shift_func *func,
1081 match_flags_t flags)
1084 ir_node *block, *new_block, *new_op1, *new_op2, *new_node;
1086 assert(! mode_is_float(get_irn_mode(node)));
1087 assert(flags & match_immediate);
1088 assert((flags & ~(match_mode_neutral | match_immediate)) == 0);
1090 if (flags & match_mode_neutral) {
1091 op1 = ia32_skip_downconv(op1);
1092 new_op1 = be_transform_node(op1);
1093 } else if (get_mode_size_bits(get_irn_mode(node)) != 32) {
1094 new_op1 = create_upconv(op1, node);
1096 new_op1 = be_transform_node(op1);
1099 /* the shift amount can be any mode that is bigger than 5 bits, since all
1100 * other bits are ignored anyway */
1101 while (is_Conv(op2) && get_irn_n_edges(op2) == 1) {
1102 op2 = get_Conv_op(op2);
1103 assert(get_mode_size_bits(get_irn_mode(op2)) >= 5);
1105 new_op2 = create_immediate_or_transform(op2, 0);
1107 dbgi = get_irn_dbg_info(node);
1108 block = get_nodes_block(node);
1109 new_block = be_transform_node(block);
1110 new_node = func(dbgi, current_ir_graph, new_block, new_op1, new_op2);
1111 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1113 /* lowered shift instruction may have a dependency operand, handle it here */
1114 if (get_irn_arity(node) == 3) {
1115 /* we have a dependency */
1116 ir_node *new_dep = be_transform_node(get_irn_n(node, 2));
1117 add_irn_dep(new_node, new_dep);
1125 * Construct a standard unary operation, set AM and immediate if required.
1127 * @param op The operand
1128 * @param func The node constructor function
1129 * @return The constructed ia32 node.
1131 static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func,
1132 match_flags_t flags)
1135 ir_node *block, *new_block, *new_op, *new_node;
1137 assert(flags == 0 || flags == match_mode_neutral);
1138 if (flags & match_mode_neutral) {
1139 op = ia32_skip_downconv(op);
1142 new_op = be_transform_node(op);
1143 dbgi = get_irn_dbg_info(node);
1144 block = get_nodes_block(node);
1145 new_block = be_transform_node(block);
1146 new_node = func(dbgi, current_ir_graph, new_block, new_op);
1148 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1153 static ir_node *create_lea_from_address(dbg_info *dbgi, ir_node *block,
1154 ia32_address_t *addr)
1156 ir_node *base, *index, *res;
1160 base = ia32_new_NoReg_gp(env_cg);
1162 base = be_transform_node(base);
1165 index = addr->index;
1166 if (index == NULL) {
1167 index = ia32_new_NoReg_gp(env_cg);
1169 index = be_transform_node(index);
1172 res = new_rd_ia32_Lea(dbgi, current_ir_graph, block, base, index);
1173 set_address(res, addr);
1179 * Returns non-zero if a given address mode has a symbolic or
1180 * numerical offset != 0.
1182 static int am_has_immediates(const ia32_address_t *addr)
1184 return addr->offset != 0 || addr->symconst_ent != NULL
1185 || addr->frame_entity || addr->use_frame;
1189 * Creates an ia32 Add.
1191 * @return the created ia32 Add node
1193 static ir_node *gen_Add(ir_node *node) {
1194 ir_mode *mode = get_irn_mode(node);
1195 ir_node *op1 = get_Add_left(node);
1196 ir_node *op2 = get_Add_right(node);
1198 ir_node *block, *new_block, *new_node, *add_immediate_op;
1199 ia32_address_t addr;
1200 ia32_address_mode_t am;
1202 if (mode_is_float(mode)) {
1203 if (ia32_cg_config.use_sse2)
1204 return gen_binop(node, op1, op2, new_rd_ia32_xAdd,
1205 match_commutative | match_am);
1207 return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd,
1208 match_commutative | match_am);
1211 ia32_mark_non_am(node);
1213 op2 = ia32_skip_downconv(op2);
1214 op1 = ia32_skip_downconv(op1);
1218 * 0. Immediate Trees (example Add(Symconst, Const) -> Const)
1219 * 1. Add with immediate -> Lea
1220 * 2. Add with possible source address mode -> Add
1221 * 3. Otherwise -> Lea
1223 memset(&addr, 0, sizeof(addr));
1224 ia32_create_address_mode(&addr, node, /*force=*/1);
1225 add_immediate_op = NULL;
1227 dbgi = get_irn_dbg_info(node);
1228 block = get_nodes_block(node);
1229 new_block = be_transform_node(block);
1232 if(addr.base == NULL && addr.index == NULL) {
1233 ir_graph *irg = current_ir_graph;
1234 new_node = new_rd_ia32_Const(dbgi, irg, new_block, addr.symconst_ent,
1235 addr.symconst_sign, addr.offset);
1236 add_irn_dep(new_node, get_irg_frame(irg));
1237 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1240 /* add with immediate? */
1241 if(addr.index == NULL) {
1242 add_immediate_op = addr.base;
1243 } else if(addr.base == NULL && addr.scale == 0) {
1244 add_immediate_op = addr.index;
1247 if(add_immediate_op != NULL) {
1248 if(!am_has_immediates(&addr)) {
1249 #ifdef DEBUG_libfirm
1250 ir_fprintf(stderr, "Optimisation warning Add x,0 (%+F) found\n",
1253 return be_transform_node(add_immediate_op);
1256 new_node = create_lea_from_address(dbgi, new_block, &addr);
1257 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1261 /* test if we can use source address mode */
1262 match_arguments(&am, block, op1, op2, NULL, match_commutative
1263 | match_mode_neutral | match_am | match_immediate | match_try_am);
1265 /* construct an Add with source address mode */
1266 if (am.op_type == ia32_AddrModeS) {
1267 ir_graph *irg = current_ir_graph;
1268 ia32_address_t *am_addr = &am.addr;
1269 new_node = new_rd_ia32_Add(dbgi, irg, new_block, am_addr->base,
1270 am_addr->index, am_addr->mem, am.new_op1,
1272 set_am_attributes(new_node, &am);
1273 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1275 new_node = fix_mem_proj(new_node, &am);
1280 /* otherwise construct a lea */
1281 new_node = create_lea_from_address(dbgi, new_block, &addr);
1282 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1287 * Creates an ia32 Mul.
1289 * @return the created ia32 Mul node
1291 static ir_node *gen_Mul(ir_node *node) {
1292 ir_node *op1 = get_Mul_left(node);
1293 ir_node *op2 = get_Mul_right(node);
1294 ir_mode *mode = get_irn_mode(node);
1296 if (mode_is_float(mode)) {
1297 if (ia32_cg_config.use_sse2)
1298 return gen_binop(node, op1, op2, new_rd_ia32_xMul,
1299 match_commutative | match_am);
1301 return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul,
1302 match_commutative | match_am);
1304 return gen_binop(node, op1, op2, new_rd_ia32_IMul,
1305 match_commutative | match_am | match_mode_neutral |
1306 match_immediate | match_am_and_immediates);
1310 * Creates an ia32 Mulh.
1311 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
1312 * this result while Mul returns the lower 32 bit.
1314 * @return the created ia32 Mulh node
1316 static ir_node *gen_Mulh(ir_node *node)
1318 ir_node *block = get_nodes_block(node);
1319 ir_node *new_block = be_transform_node(block);
1320 ir_graph *irg = current_ir_graph;
1321 dbg_info *dbgi = get_irn_dbg_info(node);
1322 ir_mode *mode = get_irn_mode(node);
1323 ir_node *op1 = get_Mulh_left(node);
1324 ir_node *op2 = get_Mulh_right(node);
1325 ir_node *proj_res_high;
1327 ia32_address_mode_t am;
1328 ia32_address_t *addr = &am.addr;
1330 assert(!mode_is_float(mode) && "Mulh with float not supported");
1331 assert(get_mode_size_bits(mode) == 32);
1333 match_arguments(&am, block, op1, op2, NULL, match_commutative | match_am);
1335 if (mode_is_signed(mode)) {
1336 new_node = new_rd_ia32_IMul1OP(dbgi, irg, new_block, addr->base,
1337 addr->index, addr->mem, am.new_op1,
1340 new_node = new_rd_ia32_Mul(dbgi, irg, new_block, addr->base,
1341 addr->index, addr->mem, am.new_op1,
1345 set_am_attributes(new_node, &am);
1346 /* we can't use source address mode anymore when using immediates */
1347 if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
1348 set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
1349 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1351 assert(get_irn_mode(new_node) == mode_T);
1353 fix_mem_proj(new_node, &am);
1355 assert(pn_ia32_IMul1OP_res_high == pn_ia32_Mul_res_high);
1356 proj_res_high = new_rd_Proj(dbgi, irg, block, new_node,
1357 mode_Iu, pn_ia32_IMul1OP_res_high);
1359 return proj_res_high;
1365 * Creates an ia32 And.
1367 * @return The created ia32 And node
1369 static ir_node *gen_And(ir_node *node) {
1370 ir_node *op1 = get_And_left(node);
1371 ir_node *op2 = get_And_right(node);
1372 assert(! mode_is_float(get_irn_mode(node)));
1374 /* is it a zero extension? */
1375 if (is_Const(op2)) {
1376 tarval *tv = get_Const_tarval(op2);
1377 long v = get_tarval_long(tv);
1379 if (v == 0xFF || v == 0xFFFF) {
1380 dbg_info *dbgi = get_irn_dbg_info(node);
1381 ir_node *block = get_nodes_block(node);
1388 assert(v == 0xFFFF);
1391 res = create_I2I_Conv(src_mode, mode_Iu, dbgi, block, op1, node);
1396 return gen_binop(node, op1, op2, new_rd_ia32_And,
1397 match_commutative | match_mode_neutral | match_am
1404 * Creates an ia32 Or.
1406 * @return The created ia32 Or node
1408 static ir_node *gen_Or(ir_node *node) {
1409 ir_node *op1 = get_Or_left(node);
1410 ir_node *op2 = get_Or_right(node);
1412 assert (! mode_is_float(get_irn_mode(node)));
1413 return gen_binop(node, op1, op2, new_rd_ia32_Or, match_commutative
1414 | match_mode_neutral | match_am | match_immediate);
1420 * Creates an ia32 Eor.
1422 * @return The created ia32 Eor node
1424 static ir_node *gen_Eor(ir_node *node) {
1425 ir_node *op1 = get_Eor_left(node);
1426 ir_node *op2 = get_Eor_right(node);
1428 assert(! mode_is_float(get_irn_mode(node)));
1429 return gen_binop(node, op1, op2, new_rd_ia32_Xor, match_commutative
1430 | match_mode_neutral | match_am | match_immediate);
1435 * Creates an ia32 Sub.
1437 * @return The created ia32 Sub node
1439 static ir_node *gen_Sub(ir_node *node) {
1440 ir_node *op1 = get_Sub_left(node);
1441 ir_node *op2 = get_Sub_right(node);
1442 ir_mode *mode = get_irn_mode(node);
1444 if (mode_is_float(mode)) {
1445 if (ia32_cg_config.use_sse2)
1446 return gen_binop(node, op1, op2, new_rd_ia32_xSub, match_am);
1448 return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfsub,
1452 if (is_Const(op2)) {
1453 ir_fprintf(stderr, "Optimisation warning: found sub with const (%+F)\n",
1457 return gen_binop(node, op1, op2, new_rd_ia32_Sub, match_mode_neutral
1458 | match_am | match_immediate);
1462 * Generates an ia32 DivMod with additional infrastructure for the
1463 * register allocator if needed.
1465 static ir_node *create_Div(ir_node *node)
1467 ir_graph *irg = current_ir_graph;
1468 dbg_info *dbgi = get_irn_dbg_info(node);
1469 ir_node *block = get_nodes_block(node);
1470 ir_node *new_block = be_transform_node(block);
1477 ir_node *sign_extension;
1478 ia32_address_mode_t am;
1479 ia32_address_t *addr = &am.addr;
1481 /* the upper bits have random contents for smaller modes */
1482 switch (get_irn_opcode(node)) {
1484 op1 = get_Div_left(node);
1485 op2 = get_Div_right(node);
1486 mem = get_Div_mem(node);
1487 mode = get_Div_resmode(node);
1490 op1 = get_Mod_left(node);
1491 op2 = get_Mod_right(node);
1492 mem = get_Mod_mem(node);
1493 mode = get_Mod_resmode(node);
1496 op1 = get_DivMod_left(node);
1497 op2 = get_DivMod_right(node);
1498 mem = get_DivMod_mem(node);
1499 mode = get_DivMod_resmode(node);
1502 panic("invalid divmod node %+F", node);
1505 match_arguments(&am, block, op1, op2, NULL, match_am);
1507 /* Beware: We don't need a Sync, if the memory predecessor of the Div node
1508 is the memory of the consumed address. We can have only the second op as address
1509 in Div nodes, so check only op2. */
1510 if(!is_NoMem(mem) && skip_Proj(mem) != skip_Proj(op2)) {
1511 new_mem = be_transform_node(mem);
1512 if(!is_NoMem(addr->mem)) {
1516 new_mem = new_rd_Sync(dbgi, irg, new_block, 2, in);
1519 new_mem = addr->mem;
1522 if (mode_is_signed(mode)) {
1523 ir_node *produceval = new_rd_ia32_ProduceVal(dbgi, irg, new_block);
1524 add_irn_dep(produceval, get_irg_frame(irg));
1525 sign_extension = new_rd_ia32_Cltd(dbgi, irg, new_block, am.new_op1,
1528 new_node = new_rd_ia32_IDiv(dbgi, irg, new_block, addr->base,
1529 addr->index, new_mem, am.new_op2,
1530 am.new_op1, sign_extension);
1532 sign_extension = new_rd_ia32_Const(dbgi, irg, new_block, NULL, 0, 0);
1533 add_irn_dep(sign_extension, get_irg_frame(irg));
1535 new_node = new_rd_ia32_Div(dbgi, irg, new_block, addr->base,
1536 addr->index, new_mem, am.new_op2,
1537 am.new_op1, sign_extension);
1540 set_irn_pinned(new_node, get_irn_pinned(node));
1542 set_am_attributes(new_node, &am);
1543 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1545 new_node = fix_mem_proj(new_node, &am);
1551 static ir_node *gen_Mod(ir_node *node) {
1552 return create_Div(node);
1555 static ir_node *gen_Div(ir_node *node) {
1556 return create_Div(node);
1559 static ir_node *gen_DivMod(ir_node *node) {
1560 return create_Div(node);
1566 * Creates an ia32 floating Div.
1568 * @return The created ia32 xDiv node
1570 static ir_node *gen_Quot(ir_node *node)
1572 ir_node *op1 = get_Quot_left(node);
1573 ir_node *op2 = get_Quot_right(node);
1575 if (ia32_cg_config.use_sse2) {
1576 return gen_binop(node, op1, op2, new_rd_ia32_xDiv, match_am);
1578 return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfdiv, match_am);
1584 * Creates an ia32 Shl.
1586 * @return The created ia32 Shl node
1588 static ir_node *gen_Shl(ir_node *node) {
1589 ir_node *left = get_Shl_left(node);
1590 ir_node *right = get_Shl_right(node);
1592 return gen_shift_binop(node, left, right, new_rd_ia32_Shl,
1593 match_mode_neutral | match_immediate);
1597 * Creates an ia32 Shr.
1599 * @return The created ia32 Shr node
1601 static ir_node *gen_Shr(ir_node *node) {
1602 ir_node *left = get_Shr_left(node);
1603 ir_node *right = get_Shr_right(node);
1605 return gen_shift_binop(node, left, right, new_rd_ia32_Shr, match_immediate);
1611 * Creates an ia32 Sar.
1613 * @return The created ia32 Shrs node
1615 static ir_node *gen_Shrs(ir_node *node) {
1616 ir_node *left = get_Shrs_left(node);
1617 ir_node *right = get_Shrs_right(node);
1618 ir_mode *mode = get_irn_mode(node);
1620 if(is_Const(right) && mode == mode_Is) {
1621 tarval *tv = get_Const_tarval(right);
1622 long val = get_tarval_long(tv);
1624 /* this is a sign extension */
1625 ir_graph *irg = current_ir_graph;
1626 dbg_info *dbgi = get_irn_dbg_info(node);
1627 ir_node *block = be_transform_node(get_nodes_block(node));
1629 ir_node *new_op = be_transform_node(op);
1630 ir_node *pval = new_rd_ia32_ProduceVal(dbgi, irg, block);
1631 add_irn_dep(pval, get_irg_frame(irg));
1633 return new_rd_ia32_Cltd(dbgi, irg, block, new_op, pval);
1637 /* 8 or 16 bit sign extension? */
1638 if(is_Const(right) && is_Shl(left) && mode == mode_Is) {
1639 ir_node *shl_left = get_Shl_left(left);
1640 ir_node *shl_right = get_Shl_right(left);
1641 if(is_Const(shl_right)) {
1642 tarval *tv1 = get_Const_tarval(right);
1643 tarval *tv2 = get_Const_tarval(shl_right);
1644 if(tv1 == tv2 && tarval_is_long(tv1)) {
1645 long val = get_tarval_long(tv1);
1646 if(val == 16 || val == 24) {
1647 dbg_info *dbgi = get_irn_dbg_info(node);
1648 ir_node *block = get_nodes_block(node);
1658 res = create_I2I_Conv(src_mode, mode_Is, dbgi, block,
1667 return gen_shift_binop(node, left, right, new_rd_ia32_Sar, match_immediate);
1673 * Creates an ia32 Rol.
1675 * @param op1 The first operator
1676 * @param op2 The second operator
1677 * @return The created ia32 RotL node
1679 static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) {
1680 return gen_shift_binop(node, op1, op2, new_rd_ia32_Rol, match_immediate);
1686 * Creates an ia32 Ror.
1687 * NOTE: There is no RotR with immediate because this would always be a RotL
1688 * "imm-mode_size_bits" which can be pre-calculated.
1690 * @param op1 The first operator
1691 * @param op2 The second operator
1692 * @return The created ia32 RotR node
1694 static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) {
1695 return gen_shift_binop(node, op1, op2, new_rd_ia32_Ror, match_immediate);
1701 * Creates an ia32 RotR or RotL (depending on the found pattern).
1703 * @return The created ia32 RotL or RotR node
1705 static ir_node *gen_Rotl(ir_node *node) {
1706 ir_node *rotate = NULL;
1707 ir_node *op1 = get_Rotl_left(node);
1708 ir_node *op2 = get_Rotl_right(node);
1710 /* Firm has only RotL, so we are looking for a right (op2)
1711 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
1712 that means we can create a RotR instead of an Add and a RotL */
1716 ir_node *left = get_Add_left(add);
1717 ir_node *right = get_Add_right(add);
1718 if (is_Const(right)) {
1719 tarval *tv = get_Const_tarval(right);
1720 ir_mode *mode = get_irn_mode(node);
1721 long bits = get_mode_size_bits(mode);
1723 if (is_Minus(left) &&
1724 tarval_is_long(tv) &&
1725 get_tarval_long(tv) == bits &&
1728 DB((dbg, LEVEL_1, "RotL into RotR ... "));
1729 rotate = gen_Ror(node, op1, get_Minus_op(left));
1734 if (rotate == NULL) {
1735 rotate = gen_Rol(node, op1, op2);
1744 * Transforms a Minus node.
1746 * @return The created ia32 Minus node
1748 static ir_node *gen_Minus(ir_node *node)
1750 ir_node *op = get_Minus_op(node);
1751 ir_node *block = be_transform_node(get_nodes_block(node));
1752 ir_graph *irg = current_ir_graph;
1753 dbg_info *dbgi = get_irn_dbg_info(node);
1754 ir_mode *mode = get_irn_mode(node);
1759 if (mode_is_float(mode)) {
1760 ir_node *new_op = be_transform_node(op);
1761 if (ia32_cg_config.use_sse2) {
1762 /* TODO: non-optimal... if we have many xXors, then we should
1763 * rather create a load for the const and use that instead of
1764 * several AM nodes... */
1765 ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
1766 ir_node *noreg_xmm = ia32_new_NoReg_xmm(env_cg);
1767 ir_node *nomem = new_rd_NoMem(irg);
1769 new_node = new_rd_ia32_xXor(dbgi, irg, block, noreg_gp, noreg_gp,
1770 nomem, new_op, noreg_xmm);
1772 size = get_mode_size_bits(mode);
1773 ent = ia32_gen_fp_known_const(size == 32 ? ia32_SSIGN : ia32_DSIGN);
1775 set_ia32_am_sc(new_node, ent);
1776 set_ia32_op_type(new_node, ia32_AddrModeS);
1777 set_ia32_ls_mode(new_node, mode);
1779 new_node = new_rd_ia32_vfchs(dbgi, irg, block, new_op);
1782 new_node = gen_unop(node, op, new_rd_ia32_Neg, match_mode_neutral);
1785 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1791 * Transforms a Not node.
1793 * @return The created ia32 Not node
1795 static ir_node *gen_Not(ir_node *node) {
1796 ir_node *op = get_Not_op(node);
1798 assert(get_irn_mode(node) != mode_b); /* should be lowered already */
1799 assert (! mode_is_float(get_irn_mode(node)));
1801 return gen_unop(node, op, new_rd_ia32_Not, match_mode_neutral);
1807 * Transforms an Abs node.
1809 * @return The created ia32 Abs node
1811 static ir_node *gen_Abs(ir_node *node)
1813 ir_node *block = get_nodes_block(node);
1814 ir_node *new_block = be_transform_node(block);
1815 ir_node *op = get_Abs_op(node);
1816 ir_graph *irg = current_ir_graph;
1817 dbg_info *dbgi = get_irn_dbg_info(node);
1818 ir_mode *mode = get_irn_mode(node);
1819 ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
1820 ir_node *nomem = new_NoMem();
1826 if (mode_is_float(mode)) {
1827 new_op = be_transform_node(op);
1829 if (ia32_cg_config.use_sse2) {
1830 ir_node *noreg_fp = ia32_new_NoReg_xmm(env_cg);
1831 new_node = new_rd_ia32_xAnd(dbgi,irg, new_block, noreg_gp, noreg_gp,
1832 nomem, new_op, noreg_fp);
1834 size = get_mode_size_bits(mode);
1835 ent = ia32_gen_fp_known_const(size == 32 ? ia32_SABS : ia32_DABS);
1837 set_ia32_am_sc(new_node, ent);
1839 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1841 set_ia32_op_type(new_node, ia32_AddrModeS);
1842 set_ia32_ls_mode(new_node, mode);
1844 new_node = new_rd_ia32_vfabs(dbgi, irg, new_block, new_op);
1845 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1848 ir_node *xor, *pval, *sign_extension;
1850 if (get_mode_size_bits(mode) == 32) {
1851 new_op = be_transform_node(op);
1853 new_op = create_I2I_Conv(mode, mode_Is, dbgi, block, op, node);
1856 pval = new_rd_ia32_ProduceVal(dbgi, irg, new_block);
1857 sign_extension = new_rd_ia32_Cltd(dbgi, irg, new_block,
1860 add_irn_dep(pval, get_irg_frame(irg));
1861 SET_IA32_ORIG_NODE(sign_extension,ia32_get_old_node_name(env_cg, node));
1863 xor = new_rd_ia32_Xor(dbgi, irg, new_block, noreg_gp, noreg_gp,
1864 nomem, new_op, sign_extension);
1865 SET_IA32_ORIG_NODE(xor, ia32_get_old_node_name(env_cg, node));
1867 new_node = new_rd_ia32_Sub(dbgi, irg, new_block, noreg_gp, noreg_gp,
1868 nomem, xor, sign_extension);
1869 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
1876 * Create a bt instruction for x & (1 << n) and place it into the block of cmp.
1878 static ir_node *gen_bt(ir_node *cmp, ir_node *x, ir_node *n) {
1879 dbg_info *dbgi = get_irn_dbg_info(cmp);
1880 ir_node *block = get_nodes_block(cmp);
1881 ir_node *new_block = be_transform_node(block);
1882 ir_node *op1 = be_transform_node(x);
1883 ir_node *op2 = be_transform_node(n);
1885 return new_rd_ia32_Bt(dbgi, current_ir_graph, new_block, op1, op2);
1889 * Transform a node returning a "flag" result.
1891 * @param node the node to transform
1892 * @param pnc_out the compare mode to use
1894 static ir_node *get_flags_node(ir_node *node, pn_Cmp *pnc_out)
1903 /* we have a Cmp as input */
1904 if (is_Proj(node)) {
1905 ir_node *pred = get_Proj_pred(node);
1907 pn_Cmp pnc = get_Proj_proj(node);
1908 if (ia32_cg_config.use_bt && (pnc == pn_Cmp_Lg || pnc == pn_Cmp_Eq)) {
1909 ir_node *l = get_Cmp_left(pred);
1910 ir_node *r = get_Cmp_right(pred);
1912 ir_node *la = get_And_left(l);
1913 ir_node *ra = get_And_right(l);
1915 ir_node *c = get_Shl_left(la);
1916 if (is_Const_1(c) && (is_Const_0(r) || r == la)) {
1917 /* (1 << n) & ra) */
1918 ir_node *n = get_Shl_right(la);
1919 flags = gen_bt(pred, ra, n);
1920 /* we must generate a Jc/Jnc jump */
1921 pnc = pnc == pn_Cmp_Lg ? pn_Cmp_Lt : pn_Cmp_Ge;
1924 *pnc_out = ia32_pn_Cmp_unsigned | pnc;
1929 ir_node *c = get_Shl_left(ra);
1930 if (is_Const_1(c) && (is_Const_0(r) || r == ra)) {
1931 /* la & (1 << n)) */
1932 ir_node *n = get_Shl_right(ra);
1933 flags = gen_bt(pred, la, n);
1934 /* we must generate a Jc/Jnc jump */
1935 pnc = pnc == pn_Cmp_Lg ? pn_Cmp_Lt : pn_Cmp_Ge;
1938 *pnc_out = ia32_pn_Cmp_unsigned | pnc;
1944 flags = be_transform_node(pred);
1950 /* a mode_b value, we have to compare it against 0 */
1951 dbgi = get_irn_dbg_info(node);
1952 new_block = be_transform_node(get_nodes_block(node));
1953 new_op = be_transform_node(node);
1954 noreg = ia32_new_NoReg_gp(env_cg);
1955 nomem = new_NoMem();
1956 flags = new_rd_ia32_Test(dbgi, current_ir_graph, new_block, noreg, noreg, nomem,
1957 new_op, new_op, /*is_permuted=*/0, /*cmp_unsigned=*/0);
1958 *pnc_out = pn_Cmp_Lg;
1963 * Transforms a Load.
1965 * @return the created ia32 Load node
1967 static ir_node *gen_Load(ir_node *node) {
1968 ir_node *old_block = get_nodes_block(node);
1969 ir_node *block = be_transform_node(old_block);
1970 ir_node *ptr = get_Load_ptr(node);
1971 ir_node *mem = get_Load_mem(node);
1972 ir_node *new_mem = be_transform_node(mem);
1975 ir_graph *irg = current_ir_graph;
1976 dbg_info *dbgi = get_irn_dbg_info(node);
1977 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
1978 ir_mode *mode = get_Load_mode(node);
1981 ia32_address_t addr;
1983 /* construct load address */
1984 memset(&addr, 0, sizeof(addr));
1985 ia32_create_address_mode(&addr, ptr, /*force=*/0);
1992 base = be_transform_node(base);
1998 index = be_transform_node(index);
2001 if (mode_is_float(mode)) {
2002 if (ia32_cg_config.use_sse2) {
2003 new_node = new_rd_ia32_xLoad(dbgi, irg, block, base, index, new_mem,
2005 res_mode = mode_xmm;
2007 new_node = new_rd_ia32_vfld(dbgi, irg, block, base, index, new_mem,
2009 res_mode = mode_vfp;
2012 assert(mode != mode_b);
2014 /* create a conv node with address mode for smaller modes */
2015 if(get_mode_size_bits(mode) < 32) {
2016 new_node = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index,
2017 new_mem, noreg, mode);
2019 new_node = new_rd_ia32_Load(dbgi, irg, block, base, index, new_mem);
2024 set_irn_pinned(new_node, get_irn_pinned(node));
2025 set_ia32_op_type(new_node, ia32_AddrModeS);
2026 set_ia32_ls_mode(new_node, mode);
2027 set_address(new_node, &addr);
2029 if(get_irn_pinned(node) == op_pin_state_floats) {
2030 add_ia32_flags(new_node, arch_irn_flags_rematerializable);
2033 /* make sure we are scheduled behind the initial IncSP/Barrier
2034 * to avoid spills being placed before it
2036 if (block == get_irg_start_block(irg)) {
2037 add_irn_dep(new_node, get_irg_frame(irg));
2040 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2045 static int use_dest_am(ir_node *block, ir_node *node, ir_node *mem,
2046 ir_node *ptr, ir_node *other)
2053 /* we only use address mode if we're the only user of the load */
2054 if(get_irn_n_edges(node) > 1)
2057 load = get_Proj_pred(node);
2060 if(get_nodes_block(load) != block)
2063 /* Store should be attached to the load */
2064 if(!is_Proj(mem) || get_Proj_pred(mem) != load)
2066 /* store should have the same pointer as the load */
2067 if(get_Load_ptr(load) != ptr)
2070 /* don't do AM if other node inputs depend on the load (via mem-proj) */
2071 if(other != NULL && get_nodes_block(other) == block
2072 && heights_reachable_in_block(heights, other, load))
2078 static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2,
2079 ir_node *mem, ir_node *ptr, ir_mode *mode,
2080 construct_binop_dest_func *func,
2081 construct_binop_dest_func *func8bit,
2082 match_flags_t flags)
2084 ir_node *src_block = get_nodes_block(node);
2086 ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg);
2087 ir_graph *irg = current_ir_graph;
2092 ia32_address_mode_t am;
2093 ia32_address_t *addr = &am.addr;
2094 memset(&am, 0, sizeof(am));
2096 assert(flags & match_dest_am);
2097 assert(flags & match_immediate); /* there is no destam node without... */
2098 commutative = (flags & match_commutative) != 0;
2100 if(use_dest_am(src_block, op1, mem, ptr, op2)) {
2101 build_address(&am, op1);
2102 new_op = create_immediate_or_transform(op2, 0);
2103 } else if(commutative && use_dest_am(src_block, op2, mem, ptr, op1)) {
2104 build_address(&am, op2);
2105 new_op = create_immediate_or_transform(op1, 0);
2110 if(addr->base == NULL)
2111 addr->base = noreg_gp;
2112 if(addr->index == NULL)
2113 addr->index = noreg_gp;
2114 if(addr->mem == NULL)
2115 addr->mem = new_NoMem();
2117 dbgi = get_irn_dbg_info(node);
2118 block = be_transform_node(src_block);
2119 if(get_mode_size_bits(mode) == 8) {
2120 new_node = func8bit(dbgi, irg, block, addr->base, addr->index,
2123 new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem,
2126 set_address(new_node, addr);
2127 set_ia32_op_type(new_node, ia32_AddrModeD);
2128 set_ia32_ls_mode(new_node, mode);
2129 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2134 static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem,
2135 ir_node *ptr, ir_mode *mode,
2136 construct_unop_dest_func *func)
2138 ir_graph *irg = current_ir_graph;
2139 ir_node *src_block = get_nodes_block(node);
2143 ia32_address_mode_t am;
2144 ia32_address_t *addr = &am.addr;
2145 memset(&am, 0, sizeof(am));
2147 if(!use_dest_am(src_block, op, mem, ptr, NULL))
2150 build_address(&am, op);
2152 dbgi = get_irn_dbg_info(node);
2153 block = be_transform_node(src_block);
2154 new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem);
2155 set_address(new_node, addr);
2156 set_ia32_op_type(new_node, ia32_AddrModeD);
2157 set_ia32_ls_mode(new_node, mode);
2158 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2163 static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem) {
2164 ir_mode *mode = get_irn_mode(node);
2165 ir_node *psi_true = get_Psi_val(node, 0);
2166 ir_node *psi_default = get_Psi_default(node);
2177 ia32_address_t addr;
2179 if(get_mode_size_bits(mode) != 8)
2182 if(is_Const_1(psi_true) && is_Const_0(psi_default)) {
2184 } else if(is_Const_0(psi_true) && is_Const_1(psi_default)) {
2190 build_address_ptr(&addr, ptr, mem);
2192 irg = current_ir_graph;
2193 dbgi = get_irn_dbg_info(node);
2194 block = get_nodes_block(node);
2195 new_block = be_transform_node(block);
2196 cond = get_Psi_cond(node, 0);
2197 flags = get_flags_node(cond, &pnc);
2198 new_mem = be_transform_node(mem);
2199 new_node = new_rd_ia32_SetMem(dbgi, irg, new_block, addr.base,
2200 addr.index, addr.mem, flags, pnc, negated);
2201 set_address(new_node, &addr);
2202 set_ia32_op_type(new_node, ia32_AddrModeD);
2203 set_ia32_ls_mode(new_node, mode);
2204 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2209 static ir_node *try_create_dest_am(ir_node *node) {
2210 ir_node *val = get_Store_value(node);
2211 ir_node *mem = get_Store_mem(node);
2212 ir_node *ptr = get_Store_ptr(node);
2213 ir_mode *mode = get_irn_mode(val);
2214 unsigned bits = get_mode_size_bits(mode);
2219 /* handle only GP modes for now... */
2220 if(!mode_needs_gp_reg(mode))
2224 /* store must be the only user of the val node */
2225 if(get_irn_n_edges(val) > 1)
2227 /* skip pointless convs */
2229 ir_node *conv_op = get_Conv_op(val);
2230 ir_mode *pred_mode = get_irn_mode(conv_op);
2231 if(pred_mode == mode_b || bits <= get_mode_size_bits(pred_mode)) {
2239 /* value must be in the same block */
2240 if(get_nodes_block(node) != get_nodes_block(val))
2243 switch (get_irn_opcode(val)) {
2245 op1 = get_Add_left(val);
2246 op2 = get_Add_right(val);
2247 if(is_Const_1(op2)) {
2248 new_node = dest_am_unop(val, op1, mem, ptr, mode,
2249 new_rd_ia32_IncMem);
2251 } else if(is_Const_Minus_1(op2)) {
2252 new_node = dest_am_unop(val, op1, mem, ptr, mode,
2253 new_rd_ia32_DecMem);
2256 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2257 new_rd_ia32_AddMem, new_rd_ia32_AddMem8Bit,
2258 match_dest_am | match_commutative |
2262 op1 = get_Sub_left(val);
2263 op2 = get_Sub_right(val);
2265 ir_fprintf(stderr, "Optimisation warning: not-normalize sub ,C"
2268 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2269 new_rd_ia32_SubMem, new_rd_ia32_SubMem8Bit,
2270 match_dest_am | match_immediate |
2274 op1 = get_And_left(val);
2275 op2 = get_And_right(val);
2276 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2277 new_rd_ia32_AndMem, new_rd_ia32_AndMem8Bit,
2278 match_dest_am | match_commutative |
2282 op1 = get_Or_left(val);
2283 op2 = get_Or_right(val);
2284 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2285 new_rd_ia32_OrMem, new_rd_ia32_OrMem8Bit,
2286 match_dest_am | match_commutative |
2290 op1 = get_Eor_left(val);
2291 op2 = get_Eor_right(val);
2292 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2293 new_rd_ia32_XorMem, new_rd_ia32_XorMem8Bit,
2294 match_dest_am | match_commutative |
2298 op1 = get_Shl_left(val);
2299 op2 = get_Shl_right(val);
2300 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2301 new_rd_ia32_ShlMem, new_rd_ia32_ShlMem,
2302 match_dest_am | match_immediate);
2305 op1 = get_Shr_left(val);
2306 op2 = get_Shr_right(val);
2307 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2308 new_rd_ia32_ShrMem, new_rd_ia32_ShrMem,
2309 match_dest_am | match_immediate);
2312 op1 = get_Shrs_left(val);
2313 op2 = get_Shrs_right(val);
2314 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2315 new_rd_ia32_SarMem, new_rd_ia32_SarMem,
2316 match_dest_am | match_immediate);
2319 op1 = get_Rotl_left(val);
2320 op2 = get_Rotl_right(val);
2321 new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
2322 new_rd_ia32_RolMem, new_rd_ia32_RolMem,
2323 match_dest_am | match_immediate);
2325 /* TODO: match ROR patterns... */
2327 new_node = try_create_SetMem(val, ptr, mem);
2330 op1 = get_Minus_op(val);
2331 new_node = dest_am_unop(val, op1, mem, ptr, mode, new_rd_ia32_NegMem);
2334 /* should be lowered already */
2335 assert(mode != mode_b);
2336 op1 = get_Not_op(val);
2337 new_node = dest_am_unop(val, op1, mem, ptr, mode, new_rd_ia32_NotMem);
2343 if(new_node != NULL) {
2344 if(get_irn_pinned(new_node) != op_pin_state_pinned &&
2345 get_irn_pinned(node) == op_pin_state_pinned) {
2346 set_irn_pinned(new_node, op_pin_state_pinned);
2353 static int is_float_to_int32_conv(const ir_node *node)
2355 ir_mode *mode = get_irn_mode(node);
2359 if(get_mode_size_bits(mode) != 32 || !mode_needs_gp_reg(mode))
2364 conv_op = get_Conv_op(node);
2365 conv_mode = get_irn_mode(conv_op);
2367 if(!mode_is_float(conv_mode))
2374 * Transform a Store(floatConst).
2376 * @return the created ia32 Store node
2378 static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) {
2379 ir_mode *mode = get_irn_mode(cns);
2380 int size = get_mode_size_bits(mode);
2381 tarval *tv = get_Const_tarval(cns);
2382 ir_node *block = get_nodes_block(node);
2383 ir_node *new_block = be_transform_node(block);
2384 ir_node *ptr = get_Store_ptr(node);
2385 ir_node *mem = get_Store_mem(node);
2386 ir_graph *irg = current_ir_graph;
2387 dbg_info *dbgi = get_irn_dbg_info(node);
2388 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
2391 ia32_address_t addr;
2393 unsigned val = get_tarval_sub_bits(tv, 0) |
2394 (get_tarval_sub_bits(tv, 1) << 8) |
2395 (get_tarval_sub_bits(tv, 2) << 16) |
2396 (get_tarval_sub_bits(tv, 3) << 24);
2397 ir_node *imm = create_Immediate(NULL, 0, val);
2399 /* construct store address */
2400 memset(&addr, 0, sizeof(addr));
2401 ia32_create_address_mode(&addr, ptr, /*force=*/0);
2403 if (addr.base == NULL) {
2406 addr.base = be_transform_node(addr.base);
2409 if (addr.index == NULL) {
2412 addr.index = be_transform_node(addr.index);
2414 addr.mem = be_transform_node(mem);
2416 new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
2417 addr.index, addr.mem, imm);
2419 set_irn_pinned(new_node, get_irn_pinned(node));
2420 set_ia32_op_type(new_node, ia32_AddrModeD);
2421 set_ia32_ls_mode(new_node, mode_Iu);
2423 set_address(new_node, &addr);
2425 /** add more stores if needed */
2427 unsigned val = get_tarval_sub_bits(tv, ofs) |
2428 (get_tarval_sub_bits(tv, ofs + 1) << 8) |
2429 (get_tarval_sub_bits(tv, ofs + 2) << 16) |
2430 (get_tarval_sub_bits(tv, ofs + 3) << 24);
2431 ir_node *imm = create_Immediate(NULL, 0, val);
2434 addr.mem = new_node;
2436 new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
2437 addr.index, addr.mem, imm);
2439 set_irn_pinned(new_node, get_irn_pinned(node));
2440 set_ia32_op_type(new_node, ia32_AddrModeD);
2441 set_ia32_ls_mode(new_node, mode_Iu);
2443 set_address(new_node, &addr);
2448 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2453 * Generate a vfist or vfisttp instruction.
2455 static ir_node *gen_vfist(dbg_info *dbgi, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index,
2456 ir_node *mem, ir_node *val, ir_node **fist)
2460 if (ia32_cg_config.use_fisttp) {
2461 /* Note: fisttp ALWAYS pop the tos. We have to ensure here that the value is copied
2462 if other users exists */
2463 const arch_register_class_t *reg_class = &ia32_reg_classes[CLASS_ia32_vfp];
2464 ir_node *vfisttp = new_rd_ia32_vfisttp(dbgi, irg, block, base, index, mem, val);
2465 ir_node *value = new_r_Proj(irg, block, vfisttp, mode_E, pn_ia32_vfisttp_res);
2466 be_new_Keep(reg_class, irg, block, 1, &value);
2468 new_node = new_r_Proj(irg, block, vfisttp, mode_M, pn_ia32_vfisttp_M);
2471 ir_node *trunc_mode = ia32_new_Fpu_truncate(env_cg);
2474 new_node = new_rd_ia32_vfist(dbgi, irg, block, base, index, mem, val, trunc_mode);
2480 * Transforms a normal Store.
2482 * @return the created ia32 Store node
2484 static ir_node *gen_normal_Store(ir_node *node)
2486 ir_node *val = get_Store_value(node);
2487 ir_mode *mode = get_irn_mode(val);
2488 ir_node *block = get_nodes_block(node);
2489 ir_node *new_block = be_transform_node(block);
2490 ir_node *ptr = get_Store_ptr(node);
2491 ir_node *mem = get_Store_mem(node);
2492 ir_graph *irg = current_ir_graph;
2493 dbg_info *dbgi = get_irn_dbg_info(node);
2494 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
2495 ir_node *new_val, *new_node, *store;
2496 ia32_address_t addr;
2498 /* check for destination address mode */
2499 new_node = try_create_dest_am(node);
2500 if (new_node != NULL)
2503 /* construct store address */
2504 memset(&addr, 0, sizeof(addr));
2505 ia32_create_address_mode(&addr, ptr, /*force=*/0);
2507 if (addr.base == NULL) {
2510 addr.base = be_transform_node(addr.base);
2513 if (addr.index == NULL) {
2516 addr.index = be_transform_node(addr.index);
2518 addr.mem = be_transform_node(mem);
2520 if (mode_is_float(mode)) {
2521 /* Convs (and strict-Convs) before stores are unnecessary if the mode
2523 while (is_Conv(val) && mode == get_irn_mode(val)) {
2524 ir_node *op = get_Conv_op(val);
2525 if (!mode_is_float(get_irn_mode(op)))
2529 new_val = be_transform_node(val);
2530 if (ia32_cg_config.use_sse2) {
2531 new_node = new_rd_ia32_xStore(dbgi, irg, new_block, addr.base,
2532 addr.index, addr.mem, new_val);
2534 new_node = new_rd_ia32_vfst(dbgi, irg, new_block, addr.base,
2535 addr.index, addr.mem, new_val, mode);
2538 } else if (!ia32_cg_config.use_sse2 && is_float_to_int32_conv(val)) {
2539 val = get_Conv_op(val);
2541 /* We can skip ALL Convs (and strict-Convs) before stores. */
2542 while (is_Conv(val)) {
2543 val = get_Conv_op(val);
2545 new_val = be_transform_node(val);
2546 new_node = gen_vfist(dbgi, irg, new_block, addr.base, addr.index, addr.mem, new_val, &store);
2548 new_val = create_immediate_or_transform(val, 0);
2549 assert(mode != mode_b);
2551 if (get_mode_size_bits(mode) == 8) {
2552 new_node = new_rd_ia32_Store8Bit(dbgi, irg, new_block, addr.base,
2553 addr.index, addr.mem, new_val);
2555 new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base,
2556 addr.index, addr.mem, new_val);
2561 set_irn_pinned(store, get_irn_pinned(node));
2562 set_ia32_op_type(store, ia32_AddrModeD);
2563 set_ia32_ls_mode(store, mode);
2565 set_address(store, &addr);
2566 SET_IA32_ORIG_NODE(store, ia32_get_old_node_name(env_cg, node));
2572 * Transforms a Store.
2574 * @return the created ia32 Store node
2576 static ir_node *gen_Store(ir_node *node)
2578 ir_node *val = get_Store_value(node);
2579 ir_mode *mode = get_irn_mode(val);
2581 if (mode_is_float(mode) && is_Const(val)) {
2584 /* we are storing a floating point constant */
2585 if (ia32_cg_config.use_sse2) {
2586 transform = !is_simple_sse_Const(val);
2588 transform = !is_simple_x87_Const(val);
2591 return gen_float_const_Store(node, val);
2593 return gen_normal_Store(node);
2597 * Transforms a Switch.
2599 * @return the created ia32 SwitchJmp node
2601 static ir_node *create_Switch(ir_node *node)
2603 ir_graph *irg = current_ir_graph;
2604 dbg_info *dbgi = get_irn_dbg_info(node);
2605 ir_node *block = be_transform_node(get_nodes_block(node));
2606 ir_node *sel = get_Cond_selector(node);
2607 ir_node *new_sel = be_transform_node(sel);
2608 int switch_min = INT_MAX;
2609 int switch_max = INT_MIN;
2610 long default_pn = get_Cond_defaultProj(node);
2612 const ir_edge_t *edge;
2614 assert(get_mode_size_bits(get_irn_mode(sel)) == 32);
2616 /* determine the smallest switch case value */
2617 foreach_out_edge(node, edge) {
2618 ir_node *proj = get_edge_src_irn(edge);
2619 long pn = get_Proj_proj(proj);
2620 if(pn == default_pn)
2629 if((unsigned) (switch_max - switch_min) > 256000) {
2630 panic("Size of switch %+F bigger than 256000", node);
2633 if (switch_min != 0) {
2634 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
2636 /* if smallest switch case is not 0 we need an additional sub */
2637 new_sel = new_rd_ia32_Lea(dbgi, irg, block, new_sel, noreg);
2638 add_ia32_am_offs_int(new_sel, -switch_min);
2639 set_ia32_op_type(new_sel, ia32_AddrModeS);
2641 SET_IA32_ORIG_NODE(new_sel, ia32_get_old_node_name(env_cg, node));
2644 new_node = new_rd_ia32_SwitchJmp(dbgi, irg, block, new_sel, default_pn);
2645 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2651 * Transform a Cond node.
2653 static ir_node *gen_Cond(ir_node *node) {
2654 ir_node *block = get_nodes_block(node);
2655 ir_node *new_block = be_transform_node(block);
2656 ir_graph *irg = current_ir_graph;
2657 dbg_info *dbgi = get_irn_dbg_info(node);
2658 ir_node *sel = get_Cond_selector(node);
2659 ir_mode *sel_mode = get_irn_mode(sel);
2660 ir_node *flags = NULL;
2664 if (sel_mode != mode_b) {
2665 return create_Switch(node);
2668 /* we get flags from a Cmp */
2669 flags = get_flags_node(sel, &pnc);
2671 new_node = new_rd_ia32_Jcc(dbgi, irg, new_block, flags, pnc);
2672 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2678 * Transforms a CopyB node.
2680 * @return The transformed node.
2682 static ir_node *gen_CopyB(ir_node *node) {
2683 ir_node *block = be_transform_node(get_nodes_block(node));
2684 ir_node *src = get_CopyB_src(node);
2685 ir_node *new_src = be_transform_node(src);
2686 ir_node *dst = get_CopyB_dst(node);
2687 ir_node *new_dst = be_transform_node(dst);
2688 ir_node *mem = get_CopyB_mem(node);
2689 ir_node *new_mem = be_transform_node(mem);
2690 ir_node *res = NULL;
2691 ir_graph *irg = current_ir_graph;
2692 dbg_info *dbgi = get_irn_dbg_info(node);
2693 int size = get_type_size_bytes(get_CopyB_type(node));
2696 /* If we have to copy more than 32 bytes, we use REP MOVSx and */
2697 /* then we need the size explicitly in ECX. */
2698 if (size >= 32 * 4) {
2699 rem = size & 0x3; /* size % 4 */
2702 res = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, size);
2703 add_irn_dep(res, get_irg_frame(irg));
2705 res = new_rd_ia32_CopyB(dbgi, irg, block, new_dst, new_src, res, new_mem, rem);
2708 ir_fprintf(stderr, "Optimisation warning copyb %+F with size <4\n",
2711 res = new_rd_ia32_CopyB_i(dbgi, irg, block, new_dst, new_src, new_mem, size);
2714 SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
2719 static ir_node *gen_be_Copy(ir_node *node)
2721 ir_node *new_node = be_duplicate_node(node);
2722 ir_mode *mode = get_irn_mode(new_node);
2724 if (mode_needs_gp_reg(mode)) {
2725 set_irn_mode(new_node, mode_Iu);
2731 static ir_node *create_Fucom(ir_node *node)
2733 ir_graph *irg = current_ir_graph;
2734 dbg_info *dbgi = get_irn_dbg_info(node);
2735 ir_node *block = get_nodes_block(node);
2736 ir_node *new_block = be_transform_node(block);
2737 ir_node *left = get_Cmp_left(node);
2738 ir_node *new_left = be_transform_node(left);
2739 ir_node *right = get_Cmp_right(node);
2743 if(ia32_cg_config.use_fucomi) {
2744 new_right = be_transform_node(right);
2745 new_node = new_rd_ia32_vFucomi(dbgi, irg, new_block, new_left,
2747 set_ia32_commutative(new_node);
2748 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2750 if(ia32_cg_config.use_ftst && is_Const_0(right)) {
2751 new_node = new_rd_ia32_vFtstFnstsw(dbgi, irg, new_block, new_left,
2754 new_right = be_transform_node(right);
2755 new_node = new_rd_ia32_vFucomFnstsw(dbgi, irg, new_block, new_left,
2759 set_ia32_commutative(new_node);
2761 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2763 new_node = new_rd_ia32_Sahf(dbgi, irg, new_block, new_node);
2764 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2770 static ir_node *create_Ucomi(ir_node *node)
2772 ir_graph *irg = current_ir_graph;
2773 dbg_info *dbgi = get_irn_dbg_info(node);
2774 ir_node *src_block = get_nodes_block(node);
2775 ir_node *new_block = be_transform_node(src_block);
2776 ir_node *left = get_Cmp_left(node);
2777 ir_node *right = get_Cmp_right(node);
2779 ia32_address_mode_t am;
2780 ia32_address_t *addr = &am.addr;
2782 match_arguments(&am, src_block, left, right, NULL,
2783 match_commutative | match_am);
2785 new_node = new_rd_ia32_Ucomi(dbgi, irg, new_block, addr->base, addr->index,
2786 addr->mem, am.new_op1, am.new_op2,
2788 set_am_attributes(new_node, &am);
2790 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2792 new_node = fix_mem_proj(new_node, &am);
2798 * helper function: checks wether all Cmp projs are Lg or Eq which is needed
2799 * to fold an and into a test node
2801 static int can_fold_test_and(ir_node *node)
2803 const ir_edge_t *edge;
2805 /** we can only have eq and lg projs */
2806 foreach_out_edge(node, edge) {
2807 ir_node *proj = get_edge_src_irn(edge);
2808 pn_Cmp pnc = get_Proj_proj(proj);
2809 if(pnc != pn_Cmp_Eq && pnc != pn_Cmp_Lg)
2817 * Generate code for a Cmp.
2819 static ir_node *gen_Cmp(ir_node *node)
2821 ir_graph *irg = current_ir_graph;
2822 dbg_info *dbgi = get_irn_dbg_info(node);
2823 ir_node *block = get_nodes_block(node);
2824 ir_node *new_block = be_transform_node(block);
2825 ir_node *left = get_Cmp_left(node);
2826 ir_node *right = get_Cmp_right(node);
2827 ir_mode *cmp_mode = get_irn_mode(left);
2829 ia32_address_mode_t am;
2830 ia32_address_t *addr = &am.addr;
2833 if(mode_is_float(cmp_mode)) {
2834 if (ia32_cg_config.use_sse2) {
2835 return create_Ucomi(node);
2837 return create_Fucom(node);
2841 assert(mode_needs_gp_reg(cmp_mode));
2843 /* we prefer the Test instruction where possible except cases where
2844 * we can use SourceAM */
2845 cmp_unsigned = !mode_is_signed(cmp_mode);
2846 if (is_Const_0(right)) {
2848 get_irn_n_edges(left) == 1 &&
2849 can_fold_test_and(node)) {
2850 /* Test(and_left, and_right) */
2851 ir_node *and_left = get_And_left(left);
2852 ir_node *and_right = get_And_right(left);
2853 ir_mode *mode = get_irn_mode(and_left);
2855 match_arguments(&am, block, and_left, and_right, NULL,
2857 match_am | match_8bit_am | match_16bit_am |
2858 match_am_and_immediates | match_immediate |
2859 match_8bit | match_16bit);
2860 if (get_mode_size_bits(mode) == 8) {
2861 new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
2862 addr->index, addr->mem, am.new_op1,
2863 am.new_op2, am.ins_permuted,
2866 new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
2867 addr->index, addr->mem, am.new_op1,
2868 am.new_op2, am.ins_permuted, cmp_unsigned);
2871 match_arguments(&am, block, NULL, left, NULL,
2872 match_am | match_8bit_am | match_16bit_am |
2873 match_8bit | match_16bit);
2874 if (am.op_type == ia32_AddrModeS) {
2876 ir_node *imm_zero = try_create_Immediate(right, 0);
2877 if (get_mode_size_bits(cmp_mode) == 8) {
2878 new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
2879 addr->index, addr->mem, am.new_op2,
2880 imm_zero, am.ins_permuted,
2883 new_node = new_rd_ia32_Cmp(dbgi, irg, new_block, addr->base,
2884 addr->index, addr->mem, am.new_op2,
2885 imm_zero, am.ins_permuted, cmp_unsigned);
2888 /* Test(left, left) */
2889 if (get_mode_size_bits(cmp_mode) == 8) {
2890 new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base,
2891 addr->index, addr->mem, am.new_op2,
2892 am.new_op2, am.ins_permuted,
2895 new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base,
2896 addr->index, addr->mem, am.new_op2,
2897 am.new_op2, am.ins_permuted,
2903 /* Cmp(left, right) */
2904 match_arguments(&am, block, left, right, NULL,
2905 match_commutative | match_am | match_8bit_am |
2906 match_16bit_am | match_am_and_immediates |
2907 match_immediate | match_8bit | match_16bit);
2908 if (get_mode_size_bits(cmp_mode) == 8) {
2909 new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base,
2910 addr->index, addr->mem, am.new_op1,
2911 am.new_op2, am.ins_permuted,
2914 new_node = new_rd_ia32_Cmp(dbgi, irg, new_block, addr->base,
2915 addr->index, addr->mem, am.new_op1,
2916 am.new_op2, am.ins_permuted, cmp_unsigned);
2919 set_am_attributes(new_node, &am);
2920 assert(cmp_mode != NULL);
2921 set_ia32_ls_mode(new_node, cmp_mode);
2923 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2925 new_node = fix_mem_proj(new_node, &am);
2930 static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags,
2933 ir_graph *irg = current_ir_graph;
2934 dbg_info *dbgi = get_irn_dbg_info(node);
2935 ir_node *block = get_nodes_block(node);
2936 ir_node *new_block = be_transform_node(block);
2937 ir_node *val_true = get_Psi_val(node, 0);
2938 ir_node *val_false = get_Psi_default(node);
2940 match_flags_t match_flags;
2941 ia32_address_mode_t am;
2942 ia32_address_t *addr;
2944 assert(ia32_cg_config.use_cmov);
2945 assert(mode_needs_gp_reg(get_irn_mode(val_true)));
2949 match_flags = match_commutative | match_am | match_16bit_am |
2952 match_arguments(&am, block, val_false, val_true, flags, match_flags);
2954 new_node = new_rd_ia32_CMov(dbgi, irg, new_block, addr->base, addr->index,
2955 addr->mem, am.new_op1, am.new_op2, new_flags,
2956 am.ins_permuted, pnc);
2957 set_am_attributes(new_node, &am);
2959 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
2961 new_node = fix_mem_proj(new_node, &am);
2967 * Creates a ia32 Setcc instruction.
2969 static ir_node *create_set_32bit(dbg_info *dbgi, ir_node *new_block,
2970 ir_node *flags, pn_Cmp pnc, ir_node *orig_node,
2973 ir_graph *irg = current_ir_graph;
2974 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
2975 ir_node *nomem = new_NoMem();
2976 ir_mode *mode = get_irn_mode(orig_node);
2979 new_node = new_rd_ia32_Set(dbgi, irg, new_block, flags, pnc, ins_permuted);
2980 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, orig_node));
2982 /* we might need to conv the result up */
2983 if (get_mode_size_bits(mode) > 8) {
2984 new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, noreg, noreg,
2985 nomem, new_node, mode_Bu);
2986 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, orig_node));
2993 * Create instruction for an unsigned Difference or Zero.
2995 static ir_node *create_Doz(ir_node *psi, ir_node *a, ir_node *b) {
2996 ir_graph *irg = current_ir_graph;
2997 ir_mode *mode = get_irn_mode(psi);
2998 ir_node *new_node, *sub, *sbb, *eflags, *block, *noreg, *tmpreg, *nomem;
3001 new_node = gen_binop(psi, a, b, new_rd_ia32_Sub,
3002 match_mode_neutral | match_am | match_immediate | match_two_users);
3004 block = get_nodes_block(new_node);
3006 if (is_Proj(new_node)) {
3007 sub = get_Proj_pred(new_node);
3008 assert(is_ia32_Sub(sub));
3011 set_irn_mode(sub, mode_T);
3012 new_node = new_rd_Proj(NULL, irg, block, sub, mode, pn_ia32_res);
3014 eflags = new_rd_Proj(NULL, irg, block, sub, mode_Iu, pn_ia32_Sub_flags);
3016 dbgi = get_irn_dbg_info(psi);
3017 noreg = ia32_new_NoReg_gp(env_cg);
3018 tmpreg = new_rd_ia32_ProduceVal(dbgi, irg, block);
3019 nomem = new_NoMem();
3020 sbb = new_rd_ia32_Sbb(dbgi, irg, block, noreg, noreg, nomem, tmpreg, tmpreg, eflags);
3022 new_node = new_rd_ia32_And(dbgi, irg, block, noreg, noreg, nomem, new_node, sbb);
3023 set_ia32_commutative(new_node);
3028 * Transforms a Psi node into CMov.
3030 * @return The transformed node.
3032 static ir_node *gen_Psi(ir_node *node)
3034 dbg_info *dbgi = get_irn_dbg_info(node);
3035 ir_node *block = get_nodes_block(node);
3036 ir_node *new_block = be_transform_node(block);
3037 ir_node *psi_true = get_Psi_val(node, 0);
3038 ir_node *psi_default = get_Psi_default(node);
3039 ir_node *cond = get_Psi_cond(node, 0);
3040 ir_mode *mode = get_irn_mode(node);
3043 assert(get_Psi_n_conds(node) == 1);
3044 assert(get_irn_mode(cond) == mode_b);
3046 /* Note: a Psi node uses a Load two times IFF it's used in the compare AND in the result */
3047 if (mode_is_float(mode)) {
3048 ir_node *cmp = get_Proj_pred(cond);
3049 ir_node *cmp_left = get_Cmp_left(cmp);
3050 ir_node *cmp_right = get_Cmp_right(cmp);
3051 pn_Cmp pnc = get_Proj_proj(cond);
3053 if (ia32_cg_config.use_sse2) {
3054 if (pnc == pn_Cmp_Lt || pnc == pn_Cmp_Le) {
3055 if (cmp_left == psi_true && cmp_right == psi_default) {
3056 /* psi(a <= b, a, b) => MIN */
3057 return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMin,
3058 match_commutative | match_am | match_two_users);
3059 } else if (cmp_left == psi_default && cmp_right == psi_true) {
3060 /* psi(a <= b, b, a) => MAX */
3061 return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMax,
3062 match_commutative | match_am | match_two_users);
3064 } else if (pnc == pn_Cmp_Gt || pnc == pn_Cmp_Ge) {
3065 if (cmp_left == psi_true && cmp_right == psi_default) {
3066 /* psi(a >= b, a, b) => MAX */
3067 return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMax,
3068 match_commutative | match_am | match_two_users);
3069 } else if (cmp_left == psi_default && cmp_right == psi_true) {
3070 /* psi(a >= b, b, a) => MIN */
3071 return gen_binop(node, cmp_left, cmp_right, new_rd_ia32_xMin,
3072 match_commutative | match_am | match_two_users);
3076 panic("cannot transform floating point Psi");
3082 assert(mode_needs_gp_reg(mode));
3084 if (is_Proj(cond)) {
3085 ir_node *cmp = get_Proj_pred(cond);
3087 ir_node *cmp_left = get_Cmp_left(cmp);
3088 ir_node *cmp_right = get_Cmp_right(cmp);
3089 pn_Cmp pnc = get_Proj_proj(cond);
3091 /* check for unsigned Doz first */
3092 if ((pnc & pn_Cmp_Gt) && !mode_is_signed(mode) &&
3093 is_Const_0(psi_default) && is_Sub(psi_true) &&
3094 get_Sub_left(psi_true) == cmp_left && get_Sub_right(psi_true) == cmp_right) {
3095 /* Psi(a >=u b, a - b, 0) unsigned Doz */
3096 return create_Doz(node, cmp_left, cmp_right);
3097 } else if ((pnc & pn_Cmp_Lt) && !mode_is_signed(mode) &&
3098 is_Const_0(psi_true) && is_Sub(psi_default) &&
3099 get_Sub_left(psi_default) == cmp_left && get_Sub_right(psi_default) == cmp_right) {
3100 /* Psi(a <=u b, 0, a - b) unsigned Doz */
3101 return create_Doz(node, cmp_left, cmp_right);
3106 flags = get_flags_node(cond, &pnc);
3108 if (is_Const(psi_true) && is_Const(psi_default)) {
3109 /* both are const, good */
3110 if (is_Const_1(psi_true) && is_Const_0(psi_default)) {
3111 new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_premuted=*/0);
3112 } else if (is_Const_0(psi_true) && is_Const_1(psi_default)) {
3113 new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_premuted=*/1);
3115 /* Not that simple. */
3120 new_node = create_CMov(node, cond, flags, pnc);
3128 * Create a conversion from x87 state register to general purpose.
3130 static ir_node *gen_x87_fp_to_gp(ir_node *node) {
3131 ir_node *block = be_transform_node(get_nodes_block(node));
3132 ir_node *op = get_Conv_op(node);
3133 ir_node *new_op = be_transform_node(op);
3134 ia32_code_gen_t *cg = env_cg;
3135 ir_graph *irg = current_ir_graph;
3136 dbg_info *dbgi = get_irn_dbg_info(node);
3137 ir_node *noreg = ia32_new_NoReg_gp(cg);
3138 ir_mode *mode = get_irn_mode(node);
3139 ir_node *fist, *load, *mem;
3141 mem = gen_vfist(dbgi, irg, block, get_irg_frame(irg), noreg, new_NoMem(), new_op, &fist);
3142 set_irn_pinned(fist, op_pin_state_floats);
3143 set_ia32_use_frame(fist);
3144 set_ia32_op_type(fist, ia32_AddrModeD);
3146 assert(get_mode_size_bits(mode) <= 32);
3147 /* exception we can only store signed 32 bit integers, so for unsigned
3148 we store a 64bit (signed) integer and load the lower bits */
3149 if(get_mode_size_bits(mode) == 32 && !mode_is_signed(mode)) {
3150 set_ia32_ls_mode(fist, mode_Ls);
3152 set_ia32_ls_mode(fist, mode_Is);
3154 SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(cg, node));
3157 load = new_rd_ia32_Load(dbgi, irg, block, get_irg_frame(irg), noreg, mem);
3159 set_irn_pinned(load, op_pin_state_floats);
3160 set_ia32_use_frame(load);
3161 set_ia32_op_type(load, ia32_AddrModeS);
3162 set_ia32_ls_mode(load, mode_Is);
3163 if(get_ia32_ls_mode(fist) == mode_Ls) {
3164 ia32_attr_t *attr = get_ia32_attr(load);
3165 attr->data.need_64bit_stackent = 1;
3167 ia32_attr_t *attr = get_ia32_attr(load);
3168 attr->data.need_32bit_stackent = 1;
3170 SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(cg, node));
3172 return new_r_Proj(irg, block, load, mode_Iu, pn_ia32_Load_res);
3176 * Creates a x87 strict Conv by placing a Sore and a Load
3178 static ir_node *gen_x87_strict_conv(ir_mode *tgt_mode, ir_node *node)
3180 ir_node *block = get_nodes_block(node);
3181 ir_graph *irg = current_ir_graph;
3182 dbg_info *dbgi = get_irn_dbg_info(node);
3183 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
3184 ir_node *nomem = new_NoMem();
3185 ir_node *frame = get_irg_frame(irg);
3186 ir_node *store, *load;
3189 store = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, nomem, node,
3191 set_ia32_use_frame(store);
3192 set_ia32_op_type(store, ia32_AddrModeD);
3193 SET_IA32_ORIG_NODE(store, ia32_get_old_node_name(env_cg, node));
3195 load = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, store,
3197 set_ia32_use_frame(load);
3198 set_ia32_op_type(load, ia32_AddrModeS);
3199 SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
3201 new_node = new_r_Proj(irg, block, load, mode_E, pn_ia32_vfld_res);
3206 * Create a conversion from general purpose to x87 register
3208 static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) {
3209 ir_node *src_block = get_nodes_block(node);
3210 ir_node *block = be_transform_node(src_block);
3211 ir_graph *irg = current_ir_graph;
3212 dbg_info *dbgi = get_irn_dbg_info(node);
3213 ir_node *op = get_Conv_op(node);
3214 ir_node *new_op = NULL;
3218 ir_mode *store_mode;
3224 /* fild can use source AM if the operand is a signed 32bit integer */
3225 if (src_mode == mode_Is) {
3226 ia32_address_mode_t am;
3228 match_arguments(&am, src_block, NULL, op, NULL,
3229 match_am | match_try_am);
3230 if (am.op_type == ia32_AddrModeS) {
3231 ia32_address_t *addr = &am.addr;
3233 fild = new_rd_ia32_vfild(dbgi, irg, block, addr->base,
3234 addr->index, addr->mem);
3235 new_node = new_r_Proj(irg, block, fild, mode_vfp,
3238 set_am_attributes(fild, &am);
3239 SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
3241 fix_mem_proj(fild, &am);
3246 if(new_op == NULL) {
3247 new_op = be_transform_node(op);
3250 noreg = ia32_new_NoReg_gp(env_cg);
3251 nomem = new_NoMem();
3252 mode = get_irn_mode(op);
3254 /* first convert to 32 bit signed if necessary */
3255 src_bits = get_mode_size_bits(src_mode);
3256 if (src_bits == 8) {
3257 new_op = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, block, noreg, noreg, nomem,
3259 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
3261 } else if (src_bits < 32) {
3262 new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, noreg, noreg, nomem,
3264 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
3268 assert(get_mode_size_bits(mode) == 32);
3271 store = new_rd_ia32_Store(dbgi, irg, block, get_irg_frame(irg), noreg, nomem,
3274 set_ia32_use_frame(store);
3275 set_ia32_op_type(store, ia32_AddrModeD);
3276 set_ia32_ls_mode(store, mode_Iu);
3278 /* exception for 32bit unsigned, do a 64bit spill+load */
3279 if(!mode_is_signed(mode)) {
3282 ir_node *zero_const = create_Immediate(NULL, 0, 0);
3284 ir_node *zero_store = new_rd_ia32_Store(dbgi, irg, block,
3285 get_irg_frame(irg), noreg, nomem,
3288 set_ia32_use_frame(zero_store);
3289 set_ia32_op_type(zero_store, ia32_AddrModeD);
3290 add_ia32_am_offs_int(zero_store, 4);
3291 set_ia32_ls_mode(zero_store, mode_Iu);
3296 store = new_rd_Sync(dbgi, irg, block, 2, in);
3297 store_mode = mode_Ls;
3299 store_mode = mode_Is;
3303 fild = new_rd_ia32_vfild(dbgi, irg, block, get_irg_frame(irg), noreg, store);
3305 set_ia32_use_frame(fild);
3306 set_ia32_op_type(fild, ia32_AddrModeS);
3307 set_ia32_ls_mode(fild, store_mode);
3309 new_node = new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
3315 * Create a conversion from one integer mode into another one
3317 static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
3318 dbg_info *dbgi, ir_node *block, ir_node *op,
3321 ir_graph *irg = current_ir_graph;
3322 int src_bits = get_mode_size_bits(src_mode);
3323 int tgt_bits = get_mode_size_bits(tgt_mode);
3324 ir_node *new_block = be_transform_node(block);
3326 ir_mode *smaller_mode;
3328 ia32_address_mode_t am;
3329 ia32_address_t *addr = &am.addr;
3332 if (src_bits < tgt_bits) {
3333 smaller_mode = src_mode;
3334 smaller_bits = src_bits;
3336 smaller_mode = tgt_mode;
3337 smaller_bits = tgt_bits;
3340 #ifdef DEBUG_libfirm
3342 ir_fprintf(stderr, "Optimisation warning: conv after constant %+F\n",
3347 match_arguments(&am, block, NULL, op, NULL,
3348 match_8bit | match_16bit |
3349 match_am | match_8bit_am | match_16bit_am);
3350 if (smaller_bits == 8) {
3351 new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, addr->base,
3352 addr->index, addr->mem, am.new_op2,
3355 new_node = new_rd_ia32_Conv_I2I(dbgi, irg, new_block, addr->base,
3356 addr->index, addr->mem, am.new_op2,
3359 set_am_attributes(new_node, &am);
3360 /* match_arguments assume that out-mode = in-mode, this isn't true here
3362 set_ia32_ls_mode(new_node, smaller_mode);
3363 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
3364 new_node = fix_mem_proj(new_node, &am);
3369 * Transforms a Conv node.
3371 * @return The created ia32 Conv node
3373 static ir_node *gen_Conv(ir_node *node) {
3374 ir_node *block = get_nodes_block(node);
3375 ir_node *new_block = be_transform_node(block);
3376 ir_node *op = get_Conv_op(node);
3377 ir_node *new_op = NULL;
3378 ir_graph *irg = current_ir_graph;
3379 dbg_info *dbgi = get_irn_dbg_info(node);
3380 ir_mode *src_mode = get_irn_mode(op);
3381 ir_mode *tgt_mode = get_irn_mode(node);
3382 int src_bits = get_mode_size_bits(src_mode);
3383 int tgt_bits = get_mode_size_bits(tgt_mode);
3384 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
3385 ir_node *nomem = new_rd_NoMem(irg);
3386 ir_node *res = NULL;
3388 if (src_mode == mode_b) {
3389 assert(mode_is_int(tgt_mode) || mode_is_reference(tgt_mode));
3390 /* nothing to do, we already model bools as 0/1 ints */
3391 return be_transform_node(op);
3394 if (src_mode == tgt_mode) {
3395 if (get_Conv_strict(node)) {
3396 if (ia32_cg_config.use_sse2) {
3397 /* when we are in SSE mode, we can kill all strict no-op conversion */
3398 return be_transform_node(op);
3401 /* this should be optimized already, but who knows... */
3402 DEBUG_ONLY(ir_fprintf(stderr, "Debug warning: conv %+F is pointless\n", node));
3403 DB((dbg, LEVEL_1, "killed Conv(mode, mode) ..."));
3404 return be_transform_node(op);
3408 if (mode_is_float(src_mode)) {
3409 new_op = be_transform_node(op);
3410 /* we convert from float ... */
3411 if (mode_is_float(tgt_mode)) {
3412 if(src_mode == mode_E && tgt_mode == mode_D
3413 && !get_Conv_strict(node)) {
3414 DB((dbg, LEVEL_1, "killed Conv(mode, mode) ..."));
3419 if (ia32_cg_config.use_sse2) {
3420 DB((dbg, LEVEL_1, "create Conv(float, float) ..."));
3421 res = new_rd_ia32_Conv_FP2FP(dbgi, irg, new_block, noreg, noreg,
3423 set_ia32_ls_mode(res, tgt_mode);
3425 if(get_Conv_strict(node)) {
3426 res = gen_x87_strict_conv(tgt_mode, new_op);
3427 SET_IA32_ORIG_NODE(get_Proj_pred(res), ia32_get_old_node_name(env_cg, node));
3430 DB((dbg, LEVEL_1, "killed Conv(float, float) ..."));
3435 DB((dbg, LEVEL_1, "create Conv(float, int) ..."));
3436 if (ia32_cg_config.use_sse2) {
3437 res = new_rd_ia32_Conv_FP2I(dbgi, irg, new_block, noreg, noreg,
3439 set_ia32_ls_mode(res, src_mode);
3441 return gen_x87_fp_to_gp(node);
3445 /* we convert from int ... */
3446 if (mode_is_float(tgt_mode)) {
3448 DB((dbg, LEVEL_1, "create Conv(int, float) ..."));
3449 if (ia32_cg_config.use_sse2) {
3450 new_op = be_transform_node(op);
3451 res = new_rd_ia32_Conv_I2FP(dbgi, irg, new_block, noreg, noreg,
3453 set_ia32_ls_mode(res, tgt_mode);
3455 res = gen_x87_gp_to_fp(node, src_mode);
3456 if(get_Conv_strict(node)) {
3457 res = gen_x87_strict_conv(tgt_mode, res);
3458 SET_IA32_ORIG_NODE(get_Proj_pred(res),
3459 ia32_get_old_node_name(env_cg, node));
3463 } else if(tgt_mode == mode_b) {
3464 /* mode_b lowering already took care that we only have 0/1 values */
3465 DB((dbg, LEVEL_1, "omitting unnecessary Conv(%+F, %+F) ...",
3466 src_mode, tgt_mode));
3467 return be_transform_node(op);
3470 if (src_bits == tgt_bits) {
3471 DB((dbg, LEVEL_1, "omitting unnecessary Conv(%+F, %+F) ...",
3472 src_mode, tgt_mode));
3473 return be_transform_node(op);
3476 res = create_I2I_Conv(src_mode, tgt_mode, dbgi, block, op, node);
3484 static int check_immediate_constraint(long val, char immediate_constraint_type)
3486 switch (immediate_constraint_type) {
3490 return val >= 0 && val <= 32;
3492 return val >= 0 && val <= 63;
3494 return val >= -128 && val <= 127;
3496 return val == 0xff || val == 0xffff;
3498 return val >= 0 && val <= 3;
3500 return val >= 0 && val <= 255;
3502 return val >= 0 && val <= 127;
3506 panic("Invalid immediate constraint found");
3510 static ir_node *try_create_Immediate(ir_node *node,
3511 char immediate_constraint_type)
3514 tarval *offset = NULL;
3515 int offset_sign = 0;
3517 ir_entity *symconst_ent = NULL;
3518 int symconst_sign = 0;
3520 ir_node *cnst = NULL;
3521 ir_node *symconst = NULL;
3524 mode = get_irn_mode(node);
3525 if(!mode_is_int(mode) && !mode_is_reference(mode)) {
3529 if(is_Minus(node)) {
3531 node = get_Minus_op(node);
3534 if(is_Const(node)) {
3537 offset_sign = minus;
3538 } else if(is_SymConst(node)) {
3541 symconst_sign = minus;
3542 } else if(is_Add(node)) {
3543 ir_node *left = get_Add_left(node);
3544 ir_node *right = get_Add_right(node);
3545 if(is_Const(left) && is_SymConst(right)) {
3548 symconst_sign = minus;
3549 offset_sign = minus;
3550 } else if(is_SymConst(left) && is_Const(right)) {
3553 symconst_sign = minus;
3554 offset_sign = minus;
3556 } else if(is_Sub(node)) {
3557 ir_node *left = get_Sub_left(node);
3558 ir_node *right = get_Sub_right(node);
3559 if(is_Const(left) && is_SymConst(right)) {
3562 symconst_sign = !minus;
3563 offset_sign = minus;
3564 } else if(is_SymConst(left) && is_Const(right)) {
3567 symconst_sign = minus;
3568 offset_sign = !minus;
3575 offset = get_Const_tarval(cnst);
3576 if(tarval_is_long(offset)) {
3577 val = get_tarval_long(offset);
3579 ir_fprintf(stderr, "Optimisation Warning: tarval from %+F is not a "
3584 if(!check_immediate_constraint(val, immediate_constraint_type))
3587 if(symconst != NULL) {
3588 if(immediate_constraint_type != 0) {
3589 /* we need full 32bits for symconsts */
3593 /* unfortunately the assembler/linker doesn't support -symconst */
3597 if(get_SymConst_kind(symconst) != symconst_addr_ent)
3599 symconst_ent = get_SymConst_entity(symconst);
3601 if(cnst == NULL && symconst == NULL)
3604 if(offset_sign && offset != NULL) {
3605 offset = tarval_neg(offset);
3608 new_node = create_Immediate(symconst_ent, symconst_sign, val);
3613 static ir_node *create_immediate_or_transform(ir_node *node,
3614 char immediate_constraint_type)
3616 ir_node *new_node = try_create_Immediate(node, immediate_constraint_type);
3617 if (new_node == NULL) {
3618 new_node = be_transform_node(node);
3623 static const arch_register_req_t no_register_req = {
3624 arch_register_req_type_none,
3625 NULL, /* regclass */
3626 NULL, /* limit bitset */
3628 0 /* different pos */
3632 * An assembler constraint.
3634 typedef struct constraint_t constraint_t;
3635 struct constraint_t {
3638 const arch_register_req_t **out_reqs;
3640 const arch_register_req_t *req;
3641 unsigned immediate_possible;
3642 char immediate_type;
3645 static void parse_asm_constraint(int pos, constraint_t *constraint, const char *c)
3647 int immediate_possible = 0;
3648 char immediate_type = 0;
3649 unsigned limited = 0;
3650 const arch_register_class_t *cls = NULL;
3651 ir_graph *irg = current_ir_graph;
3652 struct obstack *obst = get_irg_obstack(irg);
3653 arch_register_req_t *req;
3654 unsigned *limited_ptr = NULL;
3658 /* TODO: replace all the asserts with nice error messages */
3661 /* a memory constraint: no need to do anything in backend about it
3662 * (the dependencies are already respected by the memory edge of
3664 constraint->req = &no_register_req;
3676 assert(cls == NULL ||
3677 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3678 cls = &ia32_reg_classes[CLASS_ia32_gp];
3679 limited |= 1 << REG_EAX;
3682 assert(cls == NULL ||
3683 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3684 cls = &ia32_reg_classes[CLASS_ia32_gp];
3685 limited |= 1 << REG_EBX;
3688 assert(cls == NULL ||
3689 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3690 cls = &ia32_reg_classes[CLASS_ia32_gp];
3691 limited |= 1 << REG_ECX;
3694 assert(cls == NULL ||
3695 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3696 cls = &ia32_reg_classes[CLASS_ia32_gp];
3697 limited |= 1 << REG_EDX;
3700 assert(cls == NULL ||
3701 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3702 cls = &ia32_reg_classes[CLASS_ia32_gp];
3703 limited |= 1 << REG_EDI;
3706 assert(cls == NULL ||
3707 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3708 cls = &ia32_reg_classes[CLASS_ia32_gp];
3709 limited |= 1 << REG_ESI;
3712 case 'q': /* q means lower part of the regs only, this makes no
3713 * difference to Q for us (we only assigne whole registers) */
3714 assert(cls == NULL ||
3715 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3716 cls = &ia32_reg_classes[CLASS_ia32_gp];
3717 limited |= 1 << REG_EAX | 1 << REG_EBX | 1 << REG_ECX |
3721 assert(cls == NULL ||
3722 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3723 cls = &ia32_reg_classes[CLASS_ia32_gp];
3724 limited |= 1 << REG_EAX | 1 << REG_EDX;
3727 assert(cls == NULL ||
3728 (cls == &ia32_reg_classes[CLASS_ia32_gp] && limited != 0));
3729 cls = &ia32_reg_classes[CLASS_ia32_gp];
3730 limited |= 1 << REG_EAX | 1 << REG_EBX | 1 << REG_ECX |
3731 1 << REG_EDX | 1 << REG_ESI | 1 << REG_EDI |
3738 assert(cls == NULL);
3739 cls = &ia32_reg_classes[CLASS_ia32_gp];
3745 /* TODO: mark values so the x87 simulator knows about t and u */
3746 assert(cls == NULL);
3747 cls = &ia32_reg_classes[CLASS_ia32_vfp];
3752 assert(cls == NULL);
3753 /* TODO: check that sse2 is supported */
3754 cls = &ia32_reg_classes[CLASS_ia32_xmm];
3764 assert(!immediate_possible);
3765 immediate_possible = 1;
3766 immediate_type = *c;
3770 assert(!immediate_possible);
3771 immediate_possible = 1;
3775 assert(!immediate_possible && cls == NULL);
3776 immediate_possible = 1;
3777 cls = &ia32_reg_classes[CLASS_ia32_gp];
3790 assert(constraint->is_in && "can only specify same constraint "
3793 sscanf(c, "%d%n", &same_as, &p);
3801 /* memory constraint no need to do anything in backend about it
3802 * (the dependencies are already respected by the memory edge of
3804 constraint->req = &no_register_req;
3807 case 'E': /* no float consts yet */
3808 case 'F': /* no float consts yet */
3809 case 's': /* makes no sense on x86 */
3810 case 'X': /* we can't support that in firm */
3813 case '<': /* no autodecrement on x86 */
3814 case '>': /* no autoincrement on x86 */
3815 case 'C': /* sse constant not supported yet */
3816 case 'G': /* 80387 constant not supported yet */
3817 case 'y': /* we don't support mmx registers yet */
3818 case 'Z': /* not available in 32 bit mode */
3819 case 'e': /* not available in 32 bit mode */
3820 panic("unsupported asm constraint '%c' found in (%+F)",
3821 *c, current_ir_graph);
3824 panic("unknown asm constraint '%c' found in (%+F)", *c,
3832 const arch_register_req_t *other_constr;
3834 assert(cls == NULL && "same as and register constraint not supported");
3835 assert(!immediate_possible && "same as and immediate constraint not "
3837 assert(same_as < constraint->n_outs && "wrong constraint number in "
3838 "same_as constraint");
3840 other_constr = constraint->out_reqs[same_as];
3842 req = obstack_alloc(obst, sizeof(req[0]));
3843 req->cls = other_constr->cls;
3844 req->type = arch_register_req_type_should_be_same;
3845 req->limited = NULL;
3846 req->other_same = 1U << pos;
3847 req->other_different = 0;
3849 /* switch constraints. This is because in firm we have same_as
3850 * constraints on the output constraints while in the gcc asm syntax
3851 * they are specified on the input constraints */
3852 constraint->req = other_constr;
3853 constraint->out_reqs[same_as] = req;
3854 constraint->immediate_possible = 0;
3858 if(immediate_possible && cls == NULL) {
3859 cls = &ia32_reg_classes[CLASS_ia32_gp];
3861 assert(!immediate_possible || cls == &ia32_reg_classes[CLASS_ia32_gp]);
3862 assert(cls != NULL);
3864 if(immediate_possible) {
3865 assert(constraint->is_in
3866 && "immediate make no sense for output constraints");
3868 /* todo: check types (no float input on 'r' constrained in and such... */
3871 req = obstack_alloc(obst, sizeof(req[0]) + sizeof(unsigned));
3872 limited_ptr = (unsigned*) (req+1);
3874 req = obstack_alloc(obst, sizeof(req[0]));
3876 memset(req, 0, sizeof(req[0]));
3879 req->type = arch_register_req_type_limited;
3880 *limited_ptr = limited;
3881 req->limited = limited_ptr;
3883 req->type = arch_register_req_type_normal;
3887 constraint->req = req;
3888 constraint->immediate_possible = immediate_possible;
3889 constraint->immediate_type = immediate_type;
3892 static void parse_clobber(ir_node *node, int pos, constraint_t *constraint,
3893 const char *clobber)
3895 ir_graph *irg = get_irn_irg(node);
3896 struct obstack *obst = get_irg_obstack(irg);
3897 const arch_register_t *reg = NULL;
3900 arch_register_req_t *req;
3901 const arch_register_class_t *cls;
3906 /* TODO: construct a hashmap instead of doing linear search for clobber
3908 for(c = 0; c < N_CLASSES; ++c) {
3909 cls = & ia32_reg_classes[c];
3910 for(r = 0; r < cls->n_regs; ++r) {
3911 const arch_register_t *temp_reg = arch_register_for_index(cls, r);
3912 if(strcmp(temp_reg->name, clobber) == 0
3913 || (c == CLASS_ia32_gp && strcmp(temp_reg->name+1, clobber) == 0)) {
3922 panic("Register '%s' mentioned in asm clobber is unknown\n", clobber);
3926 assert(reg->index < 32);
3928 limited = obstack_alloc(obst, sizeof(limited[0]));
3929 *limited = 1 << reg->index;
3931 req = obstack_alloc(obst, sizeof(req[0]));
3932 memset(req, 0, sizeof(req[0]));
3933 req->type = arch_register_req_type_limited;
3935 req->limited = limited;
3937 constraint->req = req;
3938 constraint->immediate_possible = 0;
3939 constraint->immediate_type = 0;
3942 static int is_memory_op(const ir_asm_constraint *constraint)
3944 ident *id = constraint->constraint;
3945 const char *str = get_id_str(id);
3948 for(c = str; *c != '\0'; ++c) {
3957 * generates code for a ASM node
3959 static ir_node *gen_ASM(ir_node *node)
3962 ir_graph *irg = current_ir_graph;
3963 ir_node *block = get_nodes_block(node);
3964 ir_node *new_block = be_transform_node(block);
3965 dbg_info *dbgi = get_irn_dbg_info(node);
3969 int n_out_constraints;
3971 const arch_register_req_t **out_reg_reqs;
3972 const arch_register_req_t **in_reg_reqs;
3973 ia32_asm_reg_t *register_map;
3974 unsigned reg_map_size = 0;
3975 struct obstack *obst;
3976 const ir_asm_constraint *in_constraints;
3977 const ir_asm_constraint *out_constraints;
3979 constraint_t parsed_constraint;
3981 arity = get_irn_arity(node);
3982 in = alloca(arity * sizeof(in[0]));
3983 memset(in, 0, arity * sizeof(in[0]));
3985 n_out_constraints = get_ASM_n_output_constraints(node);
3986 n_clobbers = get_ASM_n_clobbers(node);
3987 out_arity = n_out_constraints + n_clobbers;
3988 /* hack to keep space for mem proj */
3992 in_constraints = get_ASM_input_constraints(node);
3993 out_constraints = get_ASM_output_constraints(node);
3994 clobbers = get_ASM_clobbers(node);
3996 /* construct output constraints */
3997 obst = get_irg_obstack(irg);
3998 out_reg_reqs = obstack_alloc(obst, out_arity * sizeof(out_reg_reqs[0]));
3999 parsed_constraint.out_reqs = out_reg_reqs;
4000 parsed_constraint.n_outs = n_out_constraints;
4001 parsed_constraint.is_in = 0;
4003 for(i = 0; i < out_arity; ++i) {
4006 if(i < n_out_constraints) {
4007 const ir_asm_constraint *constraint = &out_constraints[i];
4008 c = get_id_str(constraint->constraint);
4009 parse_asm_constraint(i, &parsed_constraint, c);
4011 if(constraint->pos > reg_map_size)
4012 reg_map_size = constraint->pos;
4014 out_reg_reqs[i] = parsed_constraint.req;
4015 } else if(i < out_arity - 1) {
4016 ident *glob_id = clobbers [i - n_out_constraints];
4017 assert(glob_id != NULL);
4018 c = get_id_str(glob_id);
4019 parse_clobber(node, i, &parsed_constraint, c);
4021 out_reg_reqs[i+1] = parsed_constraint.req;
4025 out_reg_reqs[n_out_constraints] = &no_register_req;
4027 /* construct input constraints */
4028 in_reg_reqs = obstack_alloc(obst, arity * sizeof(in_reg_reqs[0]));
4029 parsed_constraint.is_in = 1;
4030 for(i = 0; i < arity; ++i) {
4031 const ir_asm_constraint *constraint = &in_constraints[i];
4032 ident *constr_id = constraint->constraint;
4033 const char *c = get_id_str(constr_id);
4035 parse_asm_constraint(i, &parsed_constraint, c);
4036 in_reg_reqs[i] = parsed_constraint.req;
4038 if(constraint->pos > reg_map_size)
4039 reg_map_size = constraint->pos;
4041 if(parsed_constraint.immediate_possible) {
4042 ir_node *pred = get_irn_n(node, i);
4043 char imm_type = parsed_constraint.immediate_type;
4044 ir_node *immediate = try_create_Immediate(pred, imm_type);
4046 if(immediate != NULL) {
4053 register_map = NEW_ARR_D(ia32_asm_reg_t, obst, reg_map_size);
4054 memset(register_map, 0, reg_map_size * sizeof(register_map[0]));
4056 for(i = 0; i < n_out_constraints; ++i) {
4057 const ir_asm_constraint *constraint = &out_constraints[i];
4058 unsigned pos = constraint->pos;
4060 assert(pos < reg_map_size);
4061 register_map[pos].use_input = 0;
4062 register_map[pos].valid = 1;
4063 register_map[pos].memory = is_memory_op(constraint);
4064 register_map[pos].inout_pos = i;
4065 register_map[pos].mode = constraint->mode;
4068 /* transform inputs */
4069 for(i = 0; i < arity; ++i) {
4070 const ir_asm_constraint *constraint = &in_constraints[i];
4071 unsigned pos = constraint->pos;
4072 ir_node *pred = get_irn_n(node, i);
4073 ir_node *transformed;
4075 assert(pos < reg_map_size);
4076 register_map[pos].use_input = 1;
4077 register_map[pos].valid = 1;
4078 register_map[pos].memory = is_memory_op(constraint);
4079 register_map[pos].inout_pos = i;
4080 register_map[pos].mode = constraint->mode;
4085 transformed = be_transform_node(pred);
4086 in[i] = transformed;
4089 new_node = new_rd_ia32_Asm(dbgi, irg, new_block, arity, in, out_arity,
4090 get_ASM_text(node), register_map);
4092 set_ia32_out_req_all(new_node, out_reg_reqs);
4093 set_ia32_in_req_all(new_node, in_reg_reqs);
4095 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
4101 * Transforms a FrameAddr into an ia32 Add.
4103 static ir_node *gen_be_FrameAddr(ir_node *node) {
4104 ir_node *block = be_transform_node(get_nodes_block(node));
4105 ir_node *op = be_get_FrameAddr_frame(node);
4106 ir_node *new_op = be_transform_node(op);
4107 ir_graph *irg = current_ir_graph;
4108 dbg_info *dbgi = get_irn_dbg_info(node);
4109 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4112 new_node = new_rd_ia32_Lea(dbgi, irg, block, new_op, noreg);
4113 set_ia32_frame_ent(new_node, arch_get_frame_entity(env_cg->arch_env, node));
4114 set_ia32_use_frame(new_node);
4116 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
4122 * In case SSE is used we need to copy the result from XMM0 to FPU TOS before return.
4124 static ir_node *gen_be_Return(ir_node *node) {
4125 ir_graph *irg = current_ir_graph;
4126 ir_node *ret_val = get_irn_n(node, be_pos_Return_val);
4127 ir_node *ret_mem = get_irn_n(node, be_pos_Return_mem);
4128 ir_entity *ent = get_irg_entity(irg);
4129 ir_type *tp = get_entity_type(ent);
4134 ir_node *frame, *sse_store, *fld, *mproj, *barrier;
4135 ir_node *new_barrier, *new_ret_val, *new_ret_mem;
4138 int pn_ret_val, pn_ret_mem, arity, i;
4140 assert(ret_val != NULL);
4141 if (be_Return_get_n_rets(node) < 1 || ! ia32_cg_config.use_sse2) {
4142 return be_duplicate_node(node);
4145 res_type = get_method_res_type(tp, 0);
4147 if (! is_Primitive_type(res_type)) {
4148 return be_duplicate_node(node);
4151 mode = get_type_mode(res_type);
4152 if (! mode_is_float(mode)) {
4153 return be_duplicate_node(node);
4156 assert(get_method_n_ress(tp) == 1);
4158 pn_ret_val = get_Proj_proj(ret_val);
4159 pn_ret_mem = get_Proj_proj(ret_mem);
4161 /* get the Barrier */
4162 barrier = get_Proj_pred(ret_val);
4164 /* get result input of the Barrier */
4165 ret_val = get_irn_n(barrier, pn_ret_val);
4166 new_ret_val = be_transform_node(ret_val);
4168 /* get memory input of the Barrier */
4169 ret_mem = get_irn_n(barrier, pn_ret_mem);
4170 new_ret_mem = be_transform_node(ret_mem);
4172 frame = get_irg_frame(irg);
4174 dbgi = get_irn_dbg_info(barrier);
4175 block = be_transform_node(get_nodes_block(barrier));
4177 noreg = ia32_new_NoReg_gp(env_cg);
4179 /* store xmm0 onto stack */
4180 sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg,
4181 new_ret_mem, new_ret_val);
4182 set_ia32_ls_mode(sse_store, mode);
4183 set_ia32_op_type(sse_store, ia32_AddrModeD);
4184 set_ia32_use_frame(sse_store);
4186 /* load into x87 register */
4187 fld = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, sse_store, mode);
4188 set_ia32_op_type(fld, ia32_AddrModeS);
4189 set_ia32_use_frame(fld);
4191 mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_vfld_M);
4192 fld = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_vfld_res);
4194 /* create a new barrier */
4195 arity = get_irn_arity(barrier);
4196 in = alloca(arity * sizeof(in[0]));
4197 for (i = 0; i < arity; ++i) {
4200 if (i == pn_ret_val) {
4202 } else if (i == pn_ret_mem) {
4205 ir_node *in = get_irn_n(barrier, i);
4206 new_in = be_transform_node(in);
4211 new_barrier = new_ir_node(dbgi, irg, block,
4212 get_irn_op(barrier), get_irn_mode(barrier),
4214 copy_node_attr(barrier, new_barrier);
4215 be_duplicate_deps(barrier, new_barrier);
4216 be_set_transformed_node(barrier, new_barrier);
4217 mark_irn_visited(barrier);
4219 /* transform normally */
4220 return be_duplicate_node(node);
4224 * Transform a be_AddSP into an ia32_SubSP.
4226 static ir_node *gen_be_AddSP(ir_node *node)
4228 ir_node *sz = get_irn_n(node, be_pos_AddSP_size);
4229 ir_node *sp = get_irn_n(node, be_pos_AddSP_old_sp);
4231 return gen_binop(node, sp, sz, new_rd_ia32_SubSP, match_am);
4235 * Transform a be_SubSP into an ia32_AddSP
4237 static ir_node *gen_be_SubSP(ir_node *node)
4239 ir_node *sz = get_irn_n(node, be_pos_SubSP_size);
4240 ir_node *sp = get_irn_n(node, be_pos_SubSP_old_sp);
4242 return gen_binop(node, sp, sz, new_rd_ia32_AddSP, match_am);
4246 * This function just sets the register for the Unknown node
4247 * as this is not done during register allocation because Unknown
4248 * is an "ignore" node.
4250 static ir_node *gen_Unknown(ir_node *node) {
4251 ir_mode *mode = get_irn_mode(node);
4253 if (mode_is_float(mode)) {
4254 if (ia32_cg_config.use_sse2) {
4255 return ia32_new_Unknown_xmm(env_cg);
4257 /* Unknown nodes are buggy in x87 simulator, use zero for now... */
4258 ir_graph *irg = current_ir_graph;
4259 dbg_info *dbgi = get_irn_dbg_info(node);
4260 ir_node *block = get_irg_start_block(irg);
4261 ir_node *ret = new_rd_ia32_vfldz(dbgi, irg, block);
4263 /* Const Nodes before the initial IncSP are a bad idea, because
4264 * they could be spilled and we have no SP ready at that point yet.
4265 * So add a dependency to the initial frame pointer calculation to
4266 * avoid that situation.
4268 add_irn_dep(ret, get_irg_frame(irg));
4271 } else if (mode_needs_gp_reg(mode)) {
4272 return ia32_new_Unknown_gp(env_cg);
4274 panic("unsupported Unknown-Mode");
4280 * Change some phi modes
4282 static ir_node *gen_Phi(ir_node *node) {
4283 ir_node *block = be_transform_node(get_nodes_block(node));
4284 ir_graph *irg = current_ir_graph;
4285 dbg_info *dbgi = get_irn_dbg_info(node);
4286 ir_mode *mode = get_irn_mode(node);
4289 if(mode_needs_gp_reg(mode)) {
4290 /* we shouldn't have any 64bit stuff around anymore */
4291 assert(get_mode_size_bits(mode) <= 32);
4292 /* all integer operations are on 32bit registers now */
4294 } else if(mode_is_float(mode)) {
4295 if (ia32_cg_config.use_sse2) {
4302 /* phi nodes allow loops, so we use the old arguments for now
4303 * and fix this later */
4304 phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
4305 get_irn_in(node) + 1);
4306 copy_node_attr(node, phi);
4307 be_duplicate_deps(node, phi);
4309 be_set_transformed_node(node, phi);
4310 be_enqueue_preds(node);
4318 static ir_node *gen_IJmp(ir_node *node)
4320 ir_node *block = get_nodes_block(node);
4321 ir_node *new_block = be_transform_node(block);
4322 dbg_info *dbgi = get_irn_dbg_info(node);
4323 ir_node *op = get_IJmp_target(node);
4325 ia32_address_mode_t am;
4326 ia32_address_t *addr = &am.addr;
4328 assert(get_irn_mode(op) == mode_P);
4330 match_arguments(&am, block, NULL, op, NULL,
4331 match_am | match_8bit_am | match_16bit_am |
4332 match_immediate | match_8bit | match_16bit);
4334 new_node = new_rd_ia32_IJmp(dbgi, current_ir_graph, new_block,
4335 addr->base, addr->index, addr->mem,
4337 set_am_attributes(new_node, &am);
4338 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
4340 new_node = fix_mem_proj(new_node, &am);
4346 * Transform a Bound node.
4348 static ir_node *gen_Bound(ir_node *node)
4351 ir_node *lower = get_Bound_lower(node);
4352 dbg_info *dbgi = get_irn_dbg_info(node);
4354 if (is_Const_0(lower)) {
4355 /* typical case for Java */
4356 ir_node *sub, *res, *flags, *block;
4357 ir_graph *irg = current_ir_graph;
4359 res = gen_binop(node, get_Bound_index(node), get_Bound_upper(node),
4360 new_rd_ia32_Sub, match_mode_neutral | match_am | match_immediate);
4362 block = get_nodes_block(res);
4363 if (! is_Proj(res)) {
4365 set_irn_mode(sub, mode_T);
4366 res = new_rd_Proj(NULL, irg, block, sub, mode_Iu, pn_ia32_res);
4368 sub = get_Proj_pred(res);
4370 flags = new_rd_Proj(NULL, irg, block, sub, mode_Iu, pn_ia32_Sub_flags);
4371 new_node = new_rd_ia32_Jcc(dbgi, irg, block, flags, pn_Cmp_Lt | ia32_pn_Cmp_unsigned);
4372 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
4374 panic("generic Bound not supported in ia32 Backend");
4380 typedef ir_node *construct_load_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
4383 typedef ir_node *construct_store_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \
4384 ir_node *val, ir_node *mem);
4387 * Transforms a lowered Load into a "real" one.
4389 static ir_node *gen_lowered_Load(ir_node *node, construct_load_func func)
4391 ir_node *block = be_transform_node(get_nodes_block(node));
4392 ir_node *ptr = get_irn_n(node, 0);
4393 ir_node *new_ptr = be_transform_node(ptr);
4394 ir_node *mem = get_irn_n(node, 1);
4395 ir_node *new_mem = be_transform_node(mem);
4396 ir_graph *irg = current_ir_graph;
4397 dbg_info *dbgi = get_irn_dbg_info(node);
4398 ir_mode *mode = get_ia32_ls_mode(node);
4399 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4402 new_op = func(dbgi, irg, block, new_ptr, noreg, new_mem);
4404 set_ia32_op_type(new_op, ia32_AddrModeS);
4405 set_ia32_am_offs_int(new_op, get_ia32_am_offs_int(node));
4406 set_ia32_am_scale(new_op, get_ia32_am_scale(node));
4407 set_ia32_am_sc(new_op, get_ia32_am_sc(node));
4408 if (is_ia32_am_sc_sign(node))
4409 set_ia32_am_sc_sign(new_op);
4410 set_ia32_ls_mode(new_op, mode);
4411 if (is_ia32_use_frame(node)) {
4412 set_ia32_frame_ent(new_op, get_ia32_frame_ent(node));
4413 set_ia32_use_frame(new_op);
4416 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
4422 * Transforms a lowered Store into a "real" one.
4424 static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func)
4426 ir_node *block = be_transform_node(get_nodes_block(node));
4427 ir_node *ptr = get_irn_n(node, 0);
4428 ir_node *new_ptr = be_transform_node(ptr);
4429 ir_node *val = get_irn_n(node, 1);
4430 ir_node *new_val = be_transform_node(val);
4431 ir_node *mem = get_irn_n(node, 2);
4432 ir_node *new_mem = be_transform_node(mem);
4433 ir_graph *irg = current_ir_graph;
4434 dbg_info *dbgi = get_irn_dbg_info(node);
4435 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4436 ir_mode *mode = get_ia32_ls_mode(node);
4440 new_op = func(dbgi, irg, block, new_ptr, noreg, new_val, new_mem);
4442 am_offs = get_ia32_am_offs_int(node);
4443 add_ia32_am_offs_int(new_op, am_offs);
4445 set_ia32_op_type(new_op, ia32_AddrModeD);
4446 set_ia32_ls_mode(new_op, mode);
4447 set_ia32_frame_ent(new_op, get_ia32_frame_ent(node));
4448 set_ia32_use_frame(new_op);
4450 SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
4455 static ir_node *gen_ia32_l_ShlDep(ir_node *node)
4457 ir_node *left = get_irn_n(node, n_ia32_l_ShlDep_val);
4458 ir_node *right = get_irn_n(node, n_ia32_l_ShlDep_count);
4460 return gen_shift_binop(node, left, right, new_rd_ia32_Shl,
4461 match_immediate | match_mode_neutral);
4464 static ir_node *gen_ia32_l_ShrDep(ir_node *node)
4466 ir_node *left = get_irn_n(node, n_ia32_l_ShrDep_val);
4467 ir_node *right = get_irn_n(node, n_ia32_l_ShrDep_count);
4468 return gen_shift_binop(node, left, right, new_rd_ia32_Shr,
4472 static ir_node *gen_ia32_l_SarDep(ir_node *node)
4474 ir_node *left = get_irn_n(node, n_ia32_l_SarDep_val);
4475 ir_node *right = get_irn_n(node, n_ia32_l_SarDep_count);
4476 return gen_shift_binop(node, left, right, new_rd_ia32_Sar,
4480 static ir_node *gen_ia32_l_Add(ir_node *node) {
4481 ir_node *left = get_irn_n(node, n_ia32_l_Add_left);
4482 ir_node *right = get_irn_n(node, n_ia32_l_Add_right);
4483 ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Add,
4484 match_commutative | match_am | match_immediate |
4485 match_mode_neutral);
4487 if(is_Proj(lowered)) {
4488 lowered = get_Proj_pred(lowered);
4490 assert(is_ia32_Add(lowered));
4491 set_irn_mode(lowered, mode_T);
4497 static ir_node *gen_ia32_l_Adc(ir_node *node)
4499 return gen_binop_flags(node, new_rd_ia32_Adc,
4500 match_commutative | match_am | match_immediate |
4501 match_mode_neutral);
4505 * Transforms an ia32_l_vfild into a "real" ia32_vfild node
4507 * @param node The node to transform
4508 * @return the created ia32 vfild node
4510 static ir_node *gen_ia32_l_vfild(ir_node *node) {
4511 return gen_lowered_Load(node, new_rd_ia32_vfild);
4515 * Transforms an ia32_l_Load into a "real" ia32_Load node
4517 * @param node The node to transform
4518 * @return the created ia32 Load node
4520 static ir_node *gen_ia32_l_Load(ir_node *node) {
4521 return gen_lowered_Load(node, new_rd_ia32_Load);
4525 * Transforms an ia32_l_Store into a "real" ia32_Store node
4527 * @param node The node to transform
4528 * @return the created ia32 Store node
4530 static ir_node *gen_ia32_l_Store(ir_node *node) {
4531 return gen_lowered_Store(node, new_rd_ia32_Store);
4535 * Transforms a l_vfist into a "real" vfist node.
4537 * @param node The node to transform
4538 * @return the created ia32 vfist node
4540 static ir_node *gen_ia32_l_vfist(ir_node *node) {
4541 ir_node *block = be_transform_node(get_nodes_block(node));
4542 ir_node *ptr = get_irn_n(node, 0);
4543 ir_node *new_ptr = be_transform_node(ptr);
4544 ir_node *val = get_irn_n(node, 1);
4545 ir_node *new_val = be_transform_node(val);
4546 ir_node *mem = get_irn_n(node, 2);
4547 ir_node *new_mem = be_transform_node(mem);
4548 ir_graph *irg = current_ir_graph;
4549 dbg_info *dbgi = get_irn_dbg_info(node);
4550 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4551 ir_mode *mode = get_ia32_ls_mode(node);
4552 ir_node *memres, *fist;
4555 memres = gen_vfist(dbgi, irg, block, new_ptr, noreg, new_mem, new_val, &fist);
4556 am_offs = get_ia32_am_offs_int(node);
4557 add_ia32_am_offs_int(fist, am_offs);
4559 set_ia32_op_type(fist, ia32_AddrModeD);
4560 set_ia32_ls_mode(fist, mode);
4561 set_ia32_frame_ent(fist, get_ia32_frame_ent(node));
4562 set_ia32_use_frame(fist);
4564 SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node));
4570 * Transforms a l_MulS into a "real" MulS node.
4572 * @return the created ia32 Mul node
4574 static ir_node *gen_ia32_l_Mul(ir_node *node) {
4575 ir_node *left = get_binop_left(node);
4576 ir_node *right = get_binop_right(node);
4578 return gen_binop(node, left, right, new_rd_ia32_Mul,
4579 match_commutative | match_am | match_mode_neutral);
4583 * Transforms a l_IMulS into a "real" IMul1OPS node.
4585 * @return the created ia32 IMul1OP node
4587 static ir_node *gen_ia32_l_IMul(ir_node *node) {
4588 ir_node *left = get_binop_left(node);
4589 ir_node *right = get_binop_right(node);
4591 return gen_binop(node, left, right, new_rd_ia32_IMul1OP,
4592 match_commutative | match_am | match_mode_neutral);
4595 static ir_node *gen_ia32_l_Sub(ir_node *node) {
4596 ir_node *left = get_irn_n(node, n_ia32_l_Sub_minuend);
4597 ir_node *right = get_irn_n(node, n_ia32_l_Sub_subtrahend);
4598 ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Sub,
4599 match_am | match_immediate | match_mode_neutral);
4601 if(is_Proj(lowered)) {
4602 lowered = get_Proj_pred(lowered);
4604 assert(is_ia32_Sub(lowered));
4605 set_irn_mode(lowered, mode_T);
4611 static ir_node *gen_ia32_l_Sbb(ir_node *node) {
4612 return gen_binop_flags(node, new_rd_ia32_Sbb,
4613 match_am | match_immediate | match_mode_neutral);
4617 * Transforms a l_ShlD/l_ShrD into a ShlD/ShrD. Those nodes have 3 data inputs:
4618 * op1 - target to be shifted
4619 * op2 - contains bits to be shifted into target
4621 * Only op3 can be an immediate.
4623 static ir_node *gen_lowered_64bit_shifts(ir_node *node, ir_node *high,
4624 ir_node *low, ir_node *count)
4626 ir_node *block = get_nodes_block(node);
4627 ir_node *new_block = be_transform_node(block);
4628 ir_graph *irg = current_ir_graph;
4629 dbg_info *dbgi = get_irn_dbg_info(node);
4630 ir_node *new_high = be_transform_node(high);
4631 ir_node *new_low = be_transform_node(low);
4635 /* the shift amount can be any mode that is bigger than 5 bits, since all
4636 * other bits are ignored anyway */
4637 while (is_Conv(count) && get_irn_n_edges(count) == 1) {
4638 assert(get_mode_size_bits(get_irn_mode(count)) >= 5);
4639 count = get_Conv_op(count);
4641 new_count = create_immediate_or_transform(count, 0);
4643 if (is_ia32_l_ShlD(node)) {
4644 new_node = new_rd_ia32_ShlD(dbgi, irg, new_block, new_high, new_low,
4647 new_node = new_rd_ia32_ShrD(dbgi, irg, new_block, new_high, new_low,
4650 SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
4655 static ir_node *gen_ia32_l_ShlD(ir_node *node)
4657 ir_node *high = get_irn_n(node, n_ia32_l_ShlD_val_high);
4658 ir_node *low = get_irn_n(node, n_ia32_l_ShlD_val_low);
4659 ir_node *count = get_irn_n(node, n_ia32_l_ShlD_count);
4660 return gen_lowered_64bit_shifts(node, high, low, count);
4663 static ir_node *gen_ia32_l_ShrD(ir_node *node)
4665 ir_node *high = get_irn_n(node, n_ia32_l_ShrD_val_high);
4666 ir_node *low = get_irn_n(node, n_ia32_l_ShrD_val_low);
4667 ir_node *count = get_irn_n(node, n_ia32_l_ShrD_count);
4668 return gen_lowered_64bit_shifts(node, high, low, count);
4671 static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) {
4672 ir_node *src_block = get_nodes_block(node);
4673 ir_node *block = be_transform_node(src_block);
4674 ir_graph *irg = current_ir_graph;
4675 dbg_info *dbgi = get_irn_dbg_info(node);
4676 ir_node *frame = get_irg_frame(irg);
4677 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4678 ir_node *nomem = new_NoMem();
4679 ir_node *val_low = get_irn_n(node, n_ia32_l_LLtoFloat_val_low);
4680 ir_node *val_high = get_irn_n(node, n_ia32_l_LLtoFloat_val_high);
4681 ir_node *new_val_low = be_transform_node(val_low);
4682 ir_node *new_val_high = be_transform_node(val_high);
4687 ir_node *store_high;
4689 if(!mode_is_signed(get_irn_mode(val_high))) {
4690 panic("unsigned long long -> float not supported yet (%+F)", node);
4694 store_low = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
4696 store_high = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem,
4698 SET_IA32_ORIG_NODE(store_low, ia32_get_old_node_name(env_cg, node));
4699 SET_IA32_ORIG_NODE(store_high, ia32_get_old_node_name(env_cg, node));
4701 set_ia32_use_frame(store_low);
4702 set_ia32_use_frame(store_high);
4703 set_ia32_op_type(store_low, ia32_AddrModeD);
4704 set_ia32_op_type(store_high, ia32_AddrModeD);
4705 set_ia32_ls_mode(store_low, mode_Iu);
4706 set_ia32_ls_mode(store_high, mode_Is);
4707 add_ia32_am_offs_int(store_high, 4);
4711 sync = new_rd_Sync(dbgi, irg, block, 2, in);
4714 fild = new_rd_ia32_vfild(dbgi, irg, block, frame, noreg, sync);
4716 set_ia32_use_frame(fild);
4717 set_ia32_op_type(fild, ia32_AddrModeS);
4718 set_ia32_ls_mode(fild, mode_Ls);
4720 SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node));
4722 return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
4725 static ir_node *gen_ia32_l_FloattoLL(ir_node *node) {
4726 ir_node *src_block = get_nodes_block(node);
4727 ir_node *block = be_transform_node(src_block);
4728 ir_graph *irg = current_ir_graph;
4729 dbg_info *dbgi = get_irn_dbg_info(node);
4730 ir_node *frame = get_irg_frame(irg);
4731 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4732 ir_node *nomem = new_NoMem();
4733 ir_node *val = get_irn_n(node, n_ia32_l_FloattoLL_val);
4734 ir_node *new_val = be_transform_node(val);
4735 ir_node *fist, *mem;
4737 mem = gen_vfist(dbgi, irg, block, frame, noreg, nomem, new_val, &fist);
4738 SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node));
4739 set_ia32_use_frame(fist);
4740 set_ia32_op_type(fist, ia32_AddrModeD);
4741 set_ia32_ls_mode(fist, mode_Ls);
4747 * the BAD transformer.
4749 static ir_node *bad_transform(ir_node *node) {
4750 panic("No transform function for %+F available.\n", node);
4754 static ir_node *gen_Proj_l_FloattoLL(ir_node *node) {
4755 ir_graph *irg = current_ir_graph;
4756 ir_node *block = be_transform_node(get_nodes_block(node));
4757 ir_node *pred = get_Proj_pred(node);
4758 ir_node *new_pred = be_transform_node(pred);
4759 ir_node *frame = get_irg_frame(irg);
4760 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
4761 dbg_info *dbgi = get_irn_dbg_info(node);
4762 long pn = get_Proj_proj(node);
4767 load = new_rd_ia32_Load(dbgi, irg, block, frame, noreg, new_pred);
4768 SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
4769 set_ia32_use_frame(load);
4770 set_ia32_op_type(load, ia32_AddrModeS);
4771 set_ia32_ls_mode(load, mode_Iu);
4772 /* we need a 64bit stackslot (fist stores 64bit) even though we only load
4773 * 32 bit from it with this particular load */
4774 attr = get_ia32_attr(load);
4775 attr->data.need_64bit_stackent = 1;
4777 if (pn == pn_ia32_l_FloattoLL_res_high) {
4778 add_ia32_am_offs_int(load, 4);
4780 assert(pn == pn_ia32_l_FloattoLL_res_low);
4783 proj = new_r_Proj(irg, block, load, mode_Iu, pn_ia32_Load_res);
4789 * Transform the Projs of an AddSP.
4791 static ir_node *gen_Proj_be_AddSP(ir_node *node) {
4792 ir_node *block = be_transform_node(get_nodes_block(node));
4793 ir_node *pred = get_Proj_pred(node);
4794 ir_node *new_pred = be_transform_node(pred);
4795 ir_graph *irg = current_ir_graph;
4796 dbg_info *dbgi = get_irn_dbg_info(node);
4797 long proj = get_Proj_proj(node);
4799 if (proj == pn_be_AddSP_sp) {
4800 ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
4801 pn_ia32_SubSP_stack);
4802 arch_set_irn_register(env_cg->arch_env, res, &ia32_gp_regs[REG_ESP]);
4804 } else if(proj == pn_be_AddSP_res) {
4805 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
4806 pn_ia32_SubSP_addr);
4807 } else if (proj == pn_be_AddSP_M) {
4808 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_SubSP_M);
4812 return new_rd_Unknown(irg, get_irn_mode(node));
4816 * Transform the Projs of a SubSP.
4818 static ir_node *gen_Proj_be_SubSP(ir_node *node) {
4819 ir_node *block = be_transform_node(get_nodes_block(node));
4820 ir_node *pred = get_Proj_pred(node);
4821 ir_node *new_pred = be_transform_node(pred);
4822 ir_graph *irg = current_ir_graph;
4823 dbg_info *dbgi = get_irn_dbg_info(node);
4824 long proj = get_Proj_proj(node);
4826 if (proj == pn_be_SubSP_sp) {
4827 ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu,
4828 pn_ia32_AddSP_stack);
4829 arch_set_irn_register(env_cg->arch_env, res, &ia32_gp_regs[REG_ESP]);
4831 } else if (proj == pn_be_SubSP_M) {
4832 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_AddSP_M);
4836 return new_rd_Unknown(irg, get_irn_mode(node));
4840 * Transform and renumber the Projs from a Load.
4842 static ir_node *gen_Proj_Load(ir_node *node) {
4844 ir_node *block = be_transform_node(get_nodes_block(node));
4845 ir_node *pred = get_Proj_pred(node);
4846 ir_graph *irg = current_ir_graph;
4847 dbg_info *dbgi = get_irn_dbg_info(node);
4848 long proj = get_Proj_proj(node);
4850 /* loads might be part of source address mode matches, so we don't
4851 * transform the ProjMs yet (with the exception of loads whose result is
4854 if (is_Load(pred) && proj == pn_Load_M && get_irn_n_edges(pred) > 1) {
4857 /* this is needed, because sometimes we have loops that are only
4858 reachable through the ProjM */
4859 be_enqueue_preds(node);
4860 /* do it in 2 steps, to silence firm verifier */
4861 res = new_rd_Proj(dbgi, irg, block, pred, mode_M, pn_Load_M);
4862 set_Proj_proj(res, pn_ia32_mem);
4866 /* renumber the proj */
4867 new_pred = be_transform_node(pred);
4868 if (is_ia32_Load(new_pred)) {
4871 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Load_res);
4873 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Load_M);
4874 case pn_Load_X_regular:
4875 return new_rd_Jmp(dbgi, irg, block);
4876 case pn_Load_X_except:
4877 /* This Load might raise an exception. Mark it. */
4878 set_ia32_exc_label(new_pred, 1);
4879 return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Load_X_exc);
4883 } else if (is_ia32_Conv_I2I(new_pred) ||
4884 is_ia32_Conv_I2I8Bit(new_pred)) {
4885 set_irn_mode(new_pred, mode_T);
4886 if (proj == pn_Load_res) {
4887 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_res);
4888 } else if (proj == pn_Load_M) {
4889 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_mem);
4891 } else if (is_ia32_xLoad(new_pred)) {
4894 return new_rd_Proj(dbgi, irg, block, new_pred, mode_xmm, pn_ia32_xLoad_res);
4896 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_xLoad_M);
4897 case pn_Load_X_regular:
4898 return new_rd_Jmp(dbgi, irg, block);
4899 case pn_Load_X_except:
4900 /* This Load might raise an exception. Mark it. */
4901 set_ia32_exc_label(new_pred, 1);
4902 return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_xLoad_X_exc);
4906 } else if (is_ia32_vfld(new_pred)) {
4909 return new_rd_Proj(dbgi, irg, block, new_pred, mode_vfp, pn_ia32_vfld_res);
4911 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_vfld_M);
4912 case pn_Load_X_regular:
4913 return new_rd_Jmp(dbgi, irg, block);
4914 case pn_Load_X_except:
4915 /* This Load might raise an exception. Mark it. */
4916 set_ia32_exc_label(new_pred, 1);
4917 return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_xLoad_X_exc);
4922 /* can happen for ProJMs when source address mode happened for the
4925 /* however it should not be the result proj, as that would mean the
4926 load had multiple users and should not have been used for
4928 if (proj != pn_Load_M) {
4929 panic("internal error: transformed node not a Load");
4931 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, 1);
4935 return new_rd_Unknown(irg, get_irn_mode(node));
4939 * Transform and renumber the Projs from a DivMod like instruction.
4941 static ir_node *gen_Proj_DivMod(ir_node *node) {
4942 ir_node *block = be_transform_node(get_nodes_block(node));
4943 ir_node *pred = get_Proj_pred(node);
4944 ir_node *new_pred = be_transform_node(pred);
4945 ir_graph *irg = current_ir_graph;
4946 dbg_info *dbgi = get_irn_dbg_info(node);
4947 ir_mode *mode = get_irn_mode(node);
4948 long proj = get_Proj_proj(node);
4950 assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred));
4952 switch (get_irn_opcode(pred)) {
4956 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Div_M);
4958 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_div_res);
4959 case pn_Div_X_regular:
4960 return new_rd_Jmp(dbgi, irg, block);
4961 case pn_Div_X_except:
4962 set_ia32_exc_label(new_pred, 1);
4963 return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Div_X_exc);
4971 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Div_M);
4973 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_mod_res);
4974 case pn_Mod_X_except:
4975 set_ia32_exc_label(new_pred, 1);
4976 return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Div_X_exc);
4984 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_Div_M);
4985 case pn_DivMod_res_div:
4986 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_div_res);
4987 case pn_DivMod_res_mod:
4988 return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, pn_ia32_Div_mod_res);
4989 case pn_DivMod_X_regular:
4990 return new_rd_Jmp(dbgi, irg, block);
4991 case pn_DivMod_X_except:
4992 set_ia32_exc_label(new_pred, 1);
4993 return new_rd_Proj(dbgi, irg, block, new_pred, mode_X, pn_ia32_Div_X_exc);
5003 return new_rd_Unknown(irg, mode);
5007 * Transform and renumber the Projs from a CopyB.
5009 static ir_node *gen_Proj_CopyB(ir_node *node) {
5010 ir_node *block = be_transform_node(get_nodes_block(node));
5011 ir_node *pred = get_Proj_pred(node);
5012 ir_node *new_pred = be_transform_node(pred);
5013 ir_graph *irg = current_ir_graph;
5014 dbg_info *dbgi = get_irn_dbg_info(node);
5015 ir_mode *mode = get_irn_mode(node);
5016 long proj = get_Proj_proj(node);
5019 case pn_CopyB_M_regular:
5020 if (is_ia32_CopyB_i(new_pred)) {
5021 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_CopyB_i_M);
5022 } else if (is_ia32_CopyB(new_pred)) {
5023 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_CopyB_M);
5031 return new_rd_Unknown(irg, mode);
5035 * Transform and renumber the Projs from a Quot.
5037 static ir_node *gen_Proj_Quot(ir_node *node) {
5038 ir_node *block = be_transform_node(get_nodes_block(node));
5039 ir_node *pred = get_Proj_pred(node);
5040 ir_node *new_pred = be_transform_node(pred);
5041 ir_graph *irg = current_ir_graph;
5042 dbg_info *dbgi = get_irn_dbg_info(node);
5043 ir_mode *mode = get_irn_mode(node);
5044 long proj = get_Proj_proj(node);
5048 if (is_ia32_xDiv(new_pred)) {
5049 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_xDiv_M);
5050 } else if (is_ia32_vfdiv(new_pred)) {
5051 return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_vfdiv_M);
5055 if (is_ia32_xDiv(new_pred)) {
5056 return new_rd_Proj(dbgi, irg, block, new_pred, mode_xmm, pn_ia32_xDiv_res);
5057 } else if (is_ia32_vfdiv(new_pred)) {
5058 return new_rd_Proj(dbgi, irg, block, new_pred, mode_vfp, pn_ia32_vfdiv_res);
5061 case pn_Quot_X_regular:
5062 case pn_Quot_X_except:
5068 return new_rd_Unknown(irg, mode);
5072 * Transform the Thread Local Storage Proj.
5074 static ir_node *gen_Proj_tls(ir_node *node) {
5075 ir_node *block = be_transform_node(get_nodes_block(node));
5076 ir_graph *irg = current_ir_graph;
5077 dbg_info *dbgi = NULL;
5078 ir_node *res = new_rd_ia32_LdTls(dbgi, irg, block, mode_Iu);
5083 static ir_node *gen_be_Call(ir_node *node) {
5084 ir_node *res = be_duplicate_node(node);
5085 be_node_add_flags(res, -1, arch_irn_flags_modify_flags);
5090 static ir_node *gen_be_IncSP(ir_node *node) {
5091 ir_node *res = be_duplicate_node(node);
5092 be_node_add_flags(res, -1, arch_irn_flags_modify_flags);
5098 * Transform the Projs from a be_Call.
5100 static ir_node *gen_Proj_be_Call(ir_node *node) {
5101 ir_node *block = be_transform_node(get_nodes_block(node));
5102 ir_node *call = get_Proj_pred(node);
5103 ir_node *new_call = be_transform_node(call);
5104 ir_graph *irg = current_ir_graph;
5105 dbg_info *dbgi = get_irn_dbg_info(node);
5106 ir_type *method_type = be_Call_get_type(call);
5107 int n_res = get_method_n_ress(method_type);
5108 long proj = get_Proj_proj(node);
5109 ir_mode *mode = get_irn_mode(node);
5111 const arch_register_class_t *cls;
5113 /* The following is kinda tricky: If we're using SSE, then we have to
5114 * move the result value of the call in floating point registers to an
5115 * xmm register, we therefore construct a GetST0 -> xLoad sequence
5116 * after the call, we have to make sure to correctly make the
5117 * MemProj and the result Proj use these 2 nodes
5119 if (proj == pn_be_Call_M_regular) {
5120 // get new node for result, are we doing the sse load/store hack?
5121 ir_node *call_res = be_get_Proj_for_pn(call, pn_be_Call_first_res);
5122 ir_node *call_res_new;
5123 ir_node *call_res_pred = NULL;
5125 if (call_res != NULL) {
5126 call_res_new = be_transform_node(call_res);
5127 call_res_pred = get_Proj_pred(call_res_new);
5130 if (call_res_pred == NULL || be_is_Call(call_res_pred)) {
5131 return new_rd_Proj(dbgi, irg, block, new_call, mode_M,
5132 pn_be_Call_M_regular);
5134 assert(is_ia32_xLoad(call_res_pred));
5135 return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M,
5139 if (ia32_cg_config.use_sse2 && proj >= pn_be_Call_first_res
5140 && proj < (pn_be_Call_first_res + n_res) && mode_is_float(mode)) {
5142 ir_node *frame = get_irg_frame(irg);
5143 ir_node *noreg = ia32_new_NoReg_gp(env_cg);
5145 ir_node *call_mem = be_get_Proj_for_pn(call, pn_be_Call_M_regular);
5148 /* in case there is no memory output: create one to serialize the copy
5150 call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M,
5151 pn_be_Call_M_regular);
5152 call_res = new_rd_Proj(dbgi, irg, block, new_call, mode,
5153 pn_be_Call_first_res);
5155 /* store st(0) onto stack */
5156 fstp = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, call_mem,
5158 set_ia32_op_type(fstp, ia32_AddrModeD);
5159 set_ia32_use_frame(fstp);
5161 /* load into SSE register */
5162 sse_load = new_rd_ia32_xLoad(dbgi, irg, block, frame, noreg, fstp,
5164 set_ia32_op_type(sse_load, ia32_AddrModeS);
5165 set_ia32_use_frame(sse_load);
5167 sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm,
5173 /* transform call modes */
5174 if (mode_is_data(mode)) {
5175 cls = arch_get_irn_reg_class(env_cg->arch_env, node, -1);
5179 return new_rd_Proj(dbgi, irg, block, new_call, mode, proj);
5183 * Transform the Projs from a Cmp.
5185 static ir_node *gen_Proj_Cmp(ir_node *node)
5187 /* this probably means not all mode_b nodes were lowered... */
5188 panic("trying to directly transform Proj_Cmp %+F (mode_b not lowered?)",
5193 * Transform the Projs from a Bound.
5195 static ir_node *gen_Proj_Bound(ir_node *node)
5197 ir_node *new_node, *block;
5198 ir_node *pred = get_Proj_pred(node);
5200 switch (get_Proj_proj(node)) {
5202 return be_transform_node(get_Bound_mem(pred));
5203 case pn_Bound_X_regular:
5204 new_node = be_transform_node(pred);
5205 block = get_nodes_block(new_node);
5206 return new_r_Proj(current_ir_graph, block, new_node, mode_X, pn_ia32_Jcc_true);
5207 case pn_Bound_X_except:
5208 new_node = be_transform_node(pred);
5209 block = get_nodes_block(new_node);
5210 return new_r_Proj(current_ir_graph, block, new_node, mode_X, pn_ia32_Jcc_false);
5212 return be_transform_node(get_Bound_index(pred));
5214 panic("unsupported Proj from Bound");
5219 * Transform and potentially renumber Proj nodes.
5221 static ir_node *gen_Proj(ir_node *node) {
5222 ir_node *pred = get_Proj_pred(node);
5225 switch (get_irn_opcode(pred)) {
5227 proj = get_Proj_proj(node);
5228 if (proj == pn_Store_M) {
5229 return be_transform_node(pred);
5232 return new_r_Bad(current_ir_graph);
5235 return gen_Proj_Load(node);
5239 return gen_Proj_DivMod(node);
5241 return gen_Proj_CopyB(node);
5243 return gen_Proj_Quot(node);
5245 return gen_Proj_be_SubSP(node);
5247 return gen_Proj_be_AddSP(node);
5249 return gen_Proj_be_Call(node);
5251 return gen_Proj_Cmp(node);
5253 return gen_Proj_Bound(node);
5255 proj = get_Proj_proj(node);
5256 if (proj == pn_Start_X_initial_exec) {
5257 ir_node *block = get_nodes_block(pred);
5258 dbg_info *dbgi = get_irn_dbg_info(node);
5261 /* we exchange the ProjX with a jump */
5262 block = be_transform_node(block);
5263 jump = new_rd_Jmp(dbgi, current_ir_graph, block);
5266 if (node == be_get_old_anchor(anchor_tls)) {
5267 return gen_Proj_tls(node);
5272 if (is_ia32_l_FloattoLL(pred)) {
5273 return gen_Proj_l_FloattoLL(node);
5275 } else if (!is_ia32_irn(pred)) { // Quick hack for SIMD optimization
5279 ir_mode *mode = get_irn_mode(node);
5280 if (mode_needs_gp_reg(mode)) {
5281 ir_node *new_pred = be_transform_node(pred);
5282 ir_node *block = be_transform_node(get_nodes_block(node));
5283 ir_node *new_proj = new_r_Proj(current_ir_graph, block, new_pred,
5284 mode_Iu, get_Proj_proj(node));
5285 #ifdef DEBUG_libfirm
5286 new_proj->node_nr = node->node_nr;
5292 return be_duplicate_node(node);
5296 * Enters all transform functions into the generic pointer
5298 static void register_transformers(void)
5302 /* first clear the generic function pointer for all ops */
5303 clear_irp_opcodes_generic_func();
5305 #define GEN(a) { be_transform_func *func = gen_##a; op_##a->ops.generic = (op_func) func; }
5306 #define BAD(a) op_##a->ops.generic = (op_func)bad_transform
5345 /* transform ops from intrinsic lowering */
5361 GEN(ia32_l_LLtoFloat);
5362 GEN(ia32_l_FloattoLL);
5368 /* we should never see these nodes */
5383 /* handle generic backend nodes */
5392 op_Mulh = get_op_Mulh();
5401 * Pre-transform all unknown and noreg nodes.
5403 static void ia32_pretransform_node(void *arch_cg) {
5404 ia32_code_gen_t *cg = arch_cg;
5406 cg->unknown_gp = be_pre_transform_node(cg->unknown_gp);
5407 cg->unknown_vfp = be_pre_transform_node(cg->unknown_vfp);
5408 cg->unknown_xmm = be_pre_transform_node(cg->unknown_xmm);
5409 cg->noreg_gp = be_pre_transform_node(cg->noreg_gp);
5410 cg->noreg_vfp = be_pre_transform_node(cg->noreg_vfp);
5411 cg->noreg_xmm = be_pre_transform_node(cg->noreg_xmm);
5416 * Walker, checks if all ia32 nodes producing more than one result have
5417 * its Projs, otherwise creates new Projs and keep them using a be_Keep node.
5419 static void add_missing_keep_walker(ir_node *node, void *data)
5422 unsigned found_projs = 0;
5423 const ir_edge_t *edge;
5424 ir_mode *mode = get_irn_mode(node);
5429 if(!is_ia32_irn(node))
5432 n_outs = get_ia32_n_res(node);
5435 if(is_ia32_SwitchJmp(node))
5438 assert(n_outs < (int) sizeof(unsigned) * 8);
5439 foreach_out_edge(node, edge) {
5440 ir_node *proj = get_edge_src_irn(edge);
5441 int pn = get_Proj_proj(proj);
5443 assert(get_irn_mode(proj) == mode_M || pn < n_outs);
5444 found_projs |= 1 << pn;
5448 /* are keeps missing? */
5450 for(i = 0; i < n_outs; ++i) {
5453 const arch_register_req_t *req;
5454 const arch_register_class_t *cls;
5456 if(found_projs & (1 << i)) {
5460 req = get_ia32_out_req(node, i);
5465 if(cls == &ia32_reg_classes[CLASS_ia32_flags]) {
5469 block = get_nodes_block(node);
5470 in[0] = new_r_Proj(current_ir_graph, block, node,
5471 arch_register_class_mode(cls), i);
5472 if(last_keep != NULL) {
5473 be_Keep_add_node(last_keep, cls, in[0]);
5475 last_keep = be_new_Keep(cls, current_ir_graph, block, 1, in);
5476 if(sched_is_scheduled(node)) {
5477 sched_add_after(node, last_keep);
5484 * Adds missing keeps to nodes. Adds missing Proj nodes for unused outputs
5487 void ia32_add_missing_keeps(ia32_code_gen_t *cg)
5489 ir_graph *irg = be_get_birg_irg(cg->birg);
5490 irg_walk_graph(irg, add_missing_keep_walker, NULL, NULL);
5493 /* do the transformation */
5494 void ia32_transform_graph(ia32_code_gen_t *cg) {
5496 ir_graph *irg = cg->irg;
5498 register_transformers();
5500 initial_fpcw = NULL;
5502 BE_TIMER_PUSH(t_heights);
5503 heights = heights_new(irg);
5504 BE_TIMER_POP(t_heights);
5505 ia32_calculate_non_address_mode_nodes(cg->birg);
5507 /* the transform phase is not safe for CSE (yet) because several nodes get
5508 * attributes set after their creation */
5509 cse_last = get_opt_cse();
5512 be_transform_graph(cg->birg, ia32_pretransform_node, cg);
5514 set_opt_cse(cse_last);
5516 ia32_free_non_address_mode_nodes();
5517 heights_free(heights);
5521 void ia32_init_transform(void)
5523 FIRM_DBG_REGISTER(dbg, "firm.be.ia32.transform");