X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_transform.c;h=9d014768873eb865ec24ceb41d38514510c58607;hb=eb593ca265a302849042866b57a3cf7a6e9495ab;hp=bf8b48d476a9d3074e693b2d9549083855aae01d;hpb=474b310a6b3b42af6e7ced8851187a2081f07860;p=libfirm diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index bf8b48d47..9d0147688 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -29,6 +29,7 @@ #endif #include +#include #include "irargs_t.h" #include "irnode_t.h" @@ -47,6 +48,7 @@ #include "irdom.h" #include "archop.h" #include "error.h" +#include "array_t.h" #include "height.h" #include "../benode_t.h" @@ -131,46 +133,46 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode, ir_node *op, ir_node *orig_node); /** Return non-zero is a node represents the 0 constant. */ -static int is_Const_0(ir_node *node) { +static bool is_Const_0(ir_node *node) { return is_Const(node) && is_Const_null(node); } /** Return non-zero is a node represents the 1 constant. */ -static int is_Const_1(ir_node *node) { +static bool is_Const_1(ir_node *node) { return is_Const(node) && is_Const_one(node); } /** Return non-zero is a node represents the -1 constant. */ -static int is_Const_Minus_1(ir_node *node) { +static bool is_Const_Minus_1(ir_node *node) { return is_Const(node) && is_Const_all_one(node); } /** * returns true if constant can be created with a simple float command */ -static int is_simple_x87_Const(ir_node *node) +static bool is_simple_x87_Const(ir_node *node) { tarval *tv = get_Const_tarval(node); if (tarval_is_null(tv) || tarval_is_one(tv)) - return 1; + return true; /* TODO: match all the other float constants */ - return 0; + return false; } /** * returns true if constant can be created with a simple float command */ -static int is_simple_sse_Const(ir_node *node) +static bool is_simple_sse_Const(ir_node *node) { tarval *tv = get_Const_tarval(node); ir_mode *mode = get_tarval_mode(tv); if (mode == mode_F) - return 1; + return true; if (tarval_is_null(tv) || tarval_is_one(tv)) - return 1; + return true; if (mode == mode_D) { unsigned val = get_tarval_sub_bits(tv, 0) | @@ -179,11 +181,11 @@ static int is_simple_sse_Const(ir_node *node) (get_tarval_sub_bits(tv, 3) << 24); if (val == 0) /* lower 32bit are zero, really a 32bit constant */ - return 1; + return true; } /* TODO: match all the other float constants */ - return 0; + return false; } /** @@ -431,44 +433,6 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) { return ent_cache[kct]; } -static int prevents_AM(ir_node *const block, ir_node *const am_candidate, - ir_node *const other) -{ - if (get_nodes_block(other) != block) - return 0; - - if (is_Sync(other)) { - int i; - - for (i = get_Sync_n_preds(other) - 1; i >= 0; --i) { - ir_node *const pred = get_Sync_pred(other, i); - - if (get_nodes_block(pred) != block) - continue; - - /* Do not block ourselves from getting eaten */ - if (is_Proj(pred) && get_Proj_pred(pred) == am_candidate) - continue; - - if (!heights_reachable_in_block(heights, pred, am_candidate)) - continue; - - return 1; - } - - return 0; - } else { - /* Do not block ourselves from getting eaten */ - if (is_Proj(other) && get_Proj_pred(other) == am_candidate) - return 0; - - if (!heights_reachable_in_block(heights, other, am_candidate)) - return 0; - - return 1; - } -} - /** * return true if the node is a Proj(Load) and could be used in source address * mode for another node. Will return only true if the @p other node is not @@ -530,6 +494,7 @@ struct ia32_address_mode_t { ia32_address_t addr; ir_mode *ls_mode; ir_node *mem_proj; + ir_node *am_node; ia32_op_type_t op_type; ir_node *new_op1; ir_node *new_op2; @@ -580,6 +545,7 @@ static void build_address(ia32_address_mode_t *am, ir_node *node) am->pinned = get_irn_pinned(load); am->ls_mode = get_Load_mode(load); am->mem_proj = be_get_Proj_for_pn(load, pn_Load_M); + am->am_node = node; /* construct load address */ ia32_create_address_mode(addr, ptr, /*force=*/0); @@ -771,20 +737,19 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, } am->op_type = ia32_AddrModeS; } else { + am->op_type = ia32_Normal; + if (flags & match_try_am) { am->new_op1 = NULL; am->new_op2 = NULL; - am->op_type = ia32_Normal; return; } new_op1 = (op1 == NULL ? NULL : be_transform_node(op1)); if (new_op2 == NULL) new_op2 = be_transform_node(op2); - am->op_type = ia32_Normal; - am->ls_mode = get_irn_mode(op2); - if (flags & match_mode_neutral) - am->ls_mode = mode_Iu; + am->ls_mode = + (flags & match_mode_neutral ? mode_Iu : get_irn_mode(op2)); } if (addr->base == NULL) addr->base = noreg_gp; @@ -798,6 +763,12 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, am->commutative = commutative; } +static void set_transformed_and_mark(ir_node *const old_node, ir_node *const new_node) +{ + mark_irn_visited(old_node); + be_set_transformed_node(old_node, new_node); +} + static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am) { ir_mode *mode; @@ -810,8 +781,7 @@ static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am) mode = get_irn_mode(node); load = get_Proj_pred(am->mem_proj); - mark_irn_visited(load); - be_set_transformed_node(load, node); + set_transformed_and_mark(load, node); if (mode != mode_T) { set_irn_mode(node, mode_T); @@ -883,16 +853,16 @@ static ir_node *gen_binop_flags(ir_node *node, construct_binop_flags_func *func, ir_node *src_block = get_nodes_block(node); ir_node *op1 = get_irn_n(node, n_ia32_l_binop_left); ir_node *op2 = get_irn_n(node, n_ia32_l_binop_right); + ir_node *eflags = get_irn_n(node, n_ia32_l_binop_eflags); dbg_info *dbgi; - ir_node *block, *new_node, *eflags, *new_eflags; + ir_node *block, *new_node, *new_eflags; ia32_address_mode_t am; ia32_address_t *addr = &am.addr; - match_arguments(&am, src_block, op1, op2, NULL, flags); + match_arguments(&am, src_block, op1, op2, eflags, flags); dbgi = get_irn_dbg_info(node); block = be_transform_node(src_block); - eflags = get_irn_n(node, n_ia32_l_binop_eflags); new_eflags = be_transform_node(eflags); new_node = func(dbgi, current_ir_graph, block, addr->base, addr->index, addr->mem, am.new_op1, am.new_op2, new_eflags); @@ -1974,38 +1944,51 @@ static int use_dest_am(ir_node *block, ir_node *node, ir_node *mem, { ir_node *load; - if(!is_Proj(node)) + if (!is_Proj(node)) return 0; /* we only use address mode if we're the only user of the load */ - if(get_irn_n_edges(node) > 1) + if (get_irn_n_edges(node) > 1) return 0; load = get_Proj_pred(node); - if(!is_Load(load)) + if (!is_Load(load)) return 0; - if(get_nodes_block(load) != block) + if (get_nodes_block(load) != block) return 0; - /* Store should be attached to the load */ - if(!is_Proj(mem) || get_Proj_pred(mem) != load) - return 0; /* store should have the same pointer as the load */ - if(get_Load_ptr(load) != ptr) + if (get_Load_ptr(load) != ptr) return 0; /* don't do AM if other node inputs depend on the load (via mem-proj) */ - if(other != NULL && get_nodes_block(other) == block - && heights_reachable_in_block(heights, other, load)) + if (other != NULL && + get_nodes_block(other) == block && + heights_reachable_in_block(heights, other, load)) { return 0; + } - return 1; -} + if (is_Sync(mem)) { + int i; -static void set_transformed_and_mark(ir_node *const old_node, ir_node *const new_node) -{ - mark_irn_visited(old_node); - be_set_transformed_node(old_node, new_node); + for (i = get_Sync_n_preds(mem) - 1; i >= 0; --i) { + ir_node *const pred = get_Sync_pred(mem, i); + + if (is_Proj(pred) && get_Proj_pred(pred) == load) + continue; + + if (get_nodes_block(pred) == block && + heights_reachable_in_block(heights, pred, load)) { + return 0; + } + } + } else { + /* Store should be attached to the load */ + if (!is_Proj(mem) || get_Proj_pred(mem) != load) + return 0; + } + + return 1; } static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2, @@ -2019,6 +2002,7 @@ static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2, ir_node *noreg_gp = ia32_new_NoReg_gp(env_cg); ir_graph *irg = current_ir_graph; dbg_info *dbgi; + ir_node *new_mem; ir_node *new_node; ir_node *new_op; ir_node *mem_proj; @@ -2048,13 +2032,15 @@ static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2, if(addr->mem == NULL) addr->mem = new_NoMem(); - dbgi = get_irn_dbg_info(node); - block = be_transform_node(src_block); + dbgi = get_irn_dbg_info(node); + block = be_transform_node(src_block); + new_mem = transform_AM_mem(irg, block, am.am_node, mem, addr->mem); + if(get_mode_size_bits(mode) == 8) { new_node = func8bit(dbgi, irg, block, addr->base, addr->index, - addr->mem, new_op); + new_mem, new_op); } else { - new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem, + new_node = func(dbgi, irg, block, addr->base, addr->index, new_mem, new_op); } set_address(new_node, addr); @@ -2073,12 +2059,13 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem, ir_node *ptr, ir_mode *mode, construct_unop_dest_func *func) { - ir_graph *irg = current_ir_graph; - ir_node *src_block = get_nodes_block(node); - ir_node *block; + ir_graph *irg = current_ir_graph; + ir_node *src_block = get_nodes_block(node); + ir_node *block; dbg_info *dbgi; - ir_node *new_node; - ir_node *mem_proj; + ir_node *new_mem; + ir_node *new_node; + ir_node *mem_proj; ia32_address_mode_t am; ia32_address_t *addr = &am.addr; memset(&am, 0, sizeof(am)); @@ -2090,7 +2077,8 @@ static ir_node *dest_am_unop(ir_node *node, ir_node *op, ir_node *mem, dbgi = get_irn_dbg_info(node); block = be_transform_node(src_block); - new_node = func(dbgi, irg, block, addr->base, addr->index, addr->mem); + new_mem = transform_AM_mem(irg, block, am.am_node, mem, addr->mem); + new_node = func(dbgi, irg, block, addr->base, addr->index, new_mem); set_address(new_node, addr); set_ia32_op_type(new_node, ia32_AddrModeD); set_ia32_ls_mode(new_node, mode); @@ -2171,6 +2159,8 @@ static ir_node *try_create_dest_am(ir_node *node) { if(is_Conv(val)) { ir_node *conv_op = get_Conv_op(val); ir_mode *pred_mode = get_irn_mode(conv_op); + if (!ia32_mode_needs_gp_reg(pred_mode)) + break; if(pred_mode == mode_b || bits <= get_mode_size_bits(pred_mode)) { val = conv_op; continue; @@ -2204,9 +2194,8 @@ static ir_node *try_create_dest_am(ir_node *node) { case iro_Sub: op1 = get_Sub_left(val); op2 = get_Sub_right(val); - if(is_Const(op2)) { - ir_fprintf(stderr, "Optimisation warning: not-normalize sub ,C" - "found\n"); + if (is_Const(op2)) { + ir_fprintf(stderr, "Optimisation warning: not-normalized sub ,C found\n"); } new_node = dest_am_binop(val, op1, op2, mem, ptr, mode, new_rd_ia32_SubMem, new_rd_ia32_SubMem8Bit, @@ -2322,78 +2311,52 @@ static int is_float_to_int32_conv(const ir_node *node) * * @return the created ia32 Store node */ -static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) { - ir_mode *mode = get_irn_mode(cns); - int size = get_mode_size_bits(mode); - tarval *tv = get_Const_tarval(cns); - ir_node *block = get_nodes_block(node); - ir_node *new_block = be_transform_node(block); - ir_node *ptr = get_Store_ptr(node); - ir_node *mem = get_Store_mem(node); - ir_graph *irg = current_ir_graph; - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *noreg = ia32_new_NoReg_gp(env_cg); - int ofs = 4; - ir_node *new_node; - ia32_address_t addr; - - unsigned val = get_tarval_sub_bits(tv, 0) | - (get_tarval_sub_bits(tv, 1) << 8) | - (get_tarval_sub_bits(tv, 2) << 16) | - (get_tarval_sub_bits(tv, 3) << 24); - ir_node *imm = create_Immediate(NULL, 0, val); - - /* construct store address */ - memset(&addr, 0, sizeof(addr)); - ia32_create_address_mode(&addr, ptr, /*force=*/0); - - if (addr.base == NULL) { - addr.base = noreg; - } else { - addr.base = be_transform_node(addr.base); - } - - if (addr.index == NULL) { - addr.index = noreg; - } else { - addr.index = be_transform_node(addr.index); - } - addr.mem = be_transform_node(mem); +static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) +{ + ir_mode *mode = get_irn_mode(cns); + unsigned size = get_mode_size_bytes(mode); + tarval *tv = get_Const_tarval(cns); + ir_node *block = get_nodes_block(node); + ir_node *new_block = be_transform_node(block); + ir_node *ptr = get_Store_ptr(node); + ir_node *mem = get_Store_mem(node); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + int ofs = 0; + size_t i = 0; + ir_node *ins[4]; + ia32_address_t addr; - new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base, - addr.index, addr.mem, imm); + assert(size % 4 == 0); + assert(size <= 16); - set_irn_pinned(new_node, get_irn_pinned(node)); - set_ia32_op_type(new_node, ia32_AddrModeD); - set_ia32_ls_mode(new_node, mode_Iu); - - set_address(new_node, &addr); + build_address_ptr(&addr, ptr, mem); - /** add more stores if needed */ - while (size > 32) { - unsigned val = get_tarval_sub_bits(tv, ofs) | - (get_tarval_sub_bits(tv, ofs + 1) << 8) | + do { + unsigned val = + get_tarval_sub_bits(tv, ofs) | + (get_tarval_sub_bits(tv, ofs + 1) << 8) | (get_tarval_sub_bits(tv, ofs + 2) << 16) | (get_tarval_sub_bits(tv, ofs + 3) << 24); ir_node *imm = create_Immediate(NULL, 0, val); - addr.offset += 4; - addr.mem = new_node; - - new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base, + ir_node *new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base, addr.index, addr.mem, imm); set_irn_pinned(new_node, get_irn_pinned(node)); set_ia32_op_type(new_node, ia32_AddrModeD); set_ia32_ls_mode(new_node, mode_Iu); - set_address(new_node, &addr); - size -= 32; - ofs += 4; - } + SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node)); - SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node)); - return new_node; + ins[i++] = new_node; + + size -= 4; + ofs += 4; + addr.offset += 4; + } while (size != 0); + + return i == 1 ? ins[0] : new_rd_Sync(dbgi, irg, new_block, i, ins); } /** @@ -2532,7 +2495,7 @@ static ir_node *gen_Store(ir_node *node) ir_mode *mode = get_irn_mode(val); if (mode_is_float(mode) && is_Const(val)) { - int transform = 1; + int transform; /* we are storing a floating point constant */ if (ia32_cg_config.use_sse2) { @@ -2706,10 +2669,10 @@ static ir_node *create_Ucomi(ir_node *node) } /** - * helper function: checks wether all Cmp projs are Lg or Eq which is needed + * helper function: checks whether all Cmp projs are Lg or Eq which is needed * to fold an and into a test node */ -static int can_fold_test_and(ir_node *node) +static bool can_fold_test_and(ir_node *node) { const ir_edge_t *edge; @@ -2718,10 +2681,84 @@ static int can_fold_test_and(ir_node *node) ir_node *proj = get_edge_src_irn(edge); pn_Cmp pnc = get_Proj_proj(proj); if(pnc != pn_Cmp_Eq && pnc != pn_Cmp_Lg) - return 0; + return false; } - return 1; + return true; +} + +/** + * returns true if it is assured, that the upper bits of a node are "clean" + * which means for a 16 or 8 bit value, that the upper bits in the register + * are 0 for unsigned and a copy of the last significant bit for unsigned + * numbers. + */ +static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode) +{ + assert(ia32_mode_needs_gp_reg(mode)); + if (get_mode_size_bits(mode) >= 32) + return true; + + if (is_Proj(transformed_node)) + return upper_bits_clean(get_Proj_pred(transformed_node), mode); + + if (is_ia32_Conv_I2I(transformed_node) + || is_ia32_Conv_I2I8Bit(transformed_node)) { + ir_mode *smaller_mode = get_ia32_ls_mode(transformed_node); + if (mode_is_signed(smaller_mode) != mode_is_signed(mode)) + return false; + if (get_mode_size_bits(smaller_mode) > get_mode_size_bits(mode)) + return false; + + return true; + } + + if (is_ia32_Shr(transformed_node) && !mode_is_signed(mode)) { + ir_node *right = get_irn_n(transformed_node, n_ia32_Shr_count); + if (is_ia32_Immediate(right) || is_ia32_Const(right)) { + const ia32_immediate_attr_t *attr + = get_ia32_immediate_attr_const(right); + if (attr->symconst == 0 + && (unsigned) attr->offset >= (32 - get_mode_size_bits(mode))) { + return true; + } + } + return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Shr_val), mode); + } + + if (is_ia32_And(transformed_node) && !mode_is_signed(mode)) { + ir_node *right = get_irn_n(transformed_node, n_ia32_And_right); + if (is_ia32_Immediate(right) || is_ia32_Const(right)) { + const ia32_immediate_attr_t *attr + = get_ia32_immediate_attr_const(right); + if (attr->symconst == 0 + && (unsigned) attr->offset + <= (0xffffffff >> (32 - get_mode_size_bits(mode)))) { + return true; + } + } + /* TODO recurse? */ + } + + /* TODO recurse on Or, Xor, ... if appropriate? */ + + if (is_ia32_Immediate(transformed_node) + || is_ia32_Const(transformed_node)) { + const ia32_immediate_attr_t *attr + = get_ia32_immediate_attr_const(transformed_node); + if (mode_is_signed(mode)) { + long shifted = attr->offset >> (get_mode_size_bits(mode) - 1); + if (shifted == 0 || shifted == -1) + return true; + } else { + unsigned long shifted = (unsigned long) attr->offset; + shifted >>= get_mode_size_bits(mode); + if (shifted == 0) + return true; + } + } + + return false; } /** @@ -2760,22 +2797,35 @@ static ir_node *gen_Cmp(ir_node *node) /* Test(and_left, and_right) */ ir_node *and_left = get_And_left(left); ir_node *and_right = get_And_right(left); - ir_mode *mode = get_irn_mode(and_left); + + /* matze: code here used mode instead of cmd_mode, I think it is always + * the same as cmp_mode, but I leave this here to see if this is really + * true... + */ + assert(get_irn_mode(and_left) == cmp_mode); match_arguments(&am, block, and_left, and_right, NULL, match_commutative | match_am | match_8bit_am | match_16bit_am | match_am_and_immediates | match_immediate | match_8bit | match_16bit); - if (get_mode_size_bits(mode) == 8) { + + /* use 32bit compare mode if possible since the opcode is smaller */ + if (upper_bits_clean(am.new_op1, cmp_mode) && + upper_bits_clean(am.new_op2, cmp_mode)) { + cmp_mode = mode_is_signed(cmp_mode) ? mode_Is : mode_Iu; + } + + if (get_mode_size_bits(cmp_mode) == 8) { new_node = new_rd_ia32_Test8Bit(dbgi, irg, new_block, addr->base, - addr->index, addr->mem, am.new_op1, - am.new_op2, am.ins_permuted, - cmp_unsigned); + addr->index, addr->mem, am.new_op1, + am.new_op2, am.ins_permuted, + cmp_unsigned); } else { new_node = new_rd_ia32_Test(dbgi, irg, new_block, addr->base, - addr->index, addr->mem, am.new_op1, - am.new_op2, am.ins_permuted, cmp_unsigned); + addr->index, addr->mem, am.new_op1, + am.new_op2, am.ins_permuted, + cmp_unsigned); } } else { /* Cmp(left, right) */ @@ -2783,6 +2833,12 @@ static ir_node *gen_Cmp(ir_node *node) match_commutative | match_am | match_8bit_am | match_16bit_am | match_am_and_immediates | match_immediate | match_8bit | match_16bit); + /* use 32bit compare mode if possible since the opcode is smaller */ + if (upper_bits_clean(am.new_op1, cmp_mode) && + upper_bits_clean(am.new_op2, cmp_mode)) { + cmp_mode = mode_is_signed(cmp_mode) ? mode_Is : mode_Iu; + } + if (get_mode_size_bits(cmp_mode) == 8) { new_node = new_rd_ia32_Cmp8Bit(dbgi, irg, new_block, addr->base, addr->index, addr->mem, am.new_op1, @@ -3223,6 +3279,17 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode, match_arguments(&am, block, NULL, op, NULL, match_8bit | match_16bit | match_am | match_8bit_am | match_16bit_am); + + if (upper_bits_clean(am.new_op2, smaller_mode)) { + /* unnecessary conv. in theory it shouldn't have been AM */ + assert(is_ia32_NoReg_GP(addr->base)); + assert(is_ia32_NoReg_GP(addr->index)); + assert(is_NoMem(addr->mem)); + assert(am.addr.offset == 0); + assert(am.addr.symconst_ent == NULL); + return am.new_op2; + } + if (smaller_bits == 8) { new_node = new_rd_ia32_Conv_I2I8Bit(dbgi, irg, new_block, addr->base, addr->index, addr->mem, am.new_op2, @@ -3338,7 +3405,8 @@ static ir_node *gen_Conv(ir_node *node) { switch (get_mode_size_bits(tgt_mode)) { case 32: float_mantissa = 23 + 1; break; // + 1 for implicit 1 case 64: float_mantissa = 52 + 1; break; - case 80: float_mantissa = 64 + 1; break; + case 80: + case 96: float_mantissa = 64; break; default: float_mantissa = 0; break; } if (float_mantissa < int_mantissa) { @@ -3495,8 +3563,7 @@ static ir_node *gen_be_Return(ir_node *node) { arity, in); copy_node_attr(barrier, new_barrier); be_duplicate_deps(barrier, new_barrier); - be_set_transformed_node(barrier, new_barrier); - mark_irn_visited(barrier); + set_transformed_and_mark(barrier, new_barrier); /* transform normally */ return be_duplicate_node(node); @@ -3510,7 +3577,8 @@ static ir_node *gen_be_AddSP(ir_node *node) ir_node *sz = get_irn_n(node, be_pos_AddSP_size); ir_node *sp = get_irn_n(node, be_pos_AddSP_old_sp); - return gen_binop(node, sp, sz, new_rd_ia32_SubSP, match_am); + return gen_binop(node, sp, sz, new_rd_ia32_SubSP, + match_am | match_immediate); } /** @@ -3521,7 +3589,8 @@ static ir_node *gen_be_SubSP(ir_node *node) ir_node *sz = get_irn_n(node, be_pos_SubSP_size); ir_node *sp = get_irn_n(node, be_pos_SubSP_old_sp); - return gen_binop(node, sp, sz, new_rd_ia32_AddSP, match_am); + return gen_binop(node, sp, sz, new_rd_ia32_AddSP, + match_am | match_immediate); } /** @@ -3625,81 +3694,6 @@ static ir_node *gen_Bound(ir_node *node) } -typedef ir_node *construct_load_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \ - ir_node *mem); - -typedef ir_node *construct_store_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \ - ir_node *val, ir_node *mem); - -/** - * Transforms a lowered Load into a "real" one. - */ -static ir_node *gen_lowered_Load(ir_node *node, construct_load_func func) -{ - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *ptr = get_irn_n(node, 0); - ir_node *new_ptr = be_transform_node(ptr); - ir_node *mem = get_irn_n(node, 1); - ir_node *new_mem = be_transform_node(mem); - ir_graph *irg = current_ir_graph; - dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_ia32_ls_mode(node); - ir_node *noreg = ia32_new_NoReg_gp(env_cg); - ir_node *new_op; - - new_op = func(dbgi, irg, block, new_ptr, noreg, new_mem); - - set_ia32_op_type(new_op, ia32_AddrModeS); - set_ia32_am_offs_int(new_op, get_ia32_am_offs_int(node)); - set_ia32_am_scale(new_op, get_ia32_am_scale(node)); - set_ia32_am_sc(new_op, get_ia32_am_sc(node)); - if (is_ia32_am_sc_sign(node)) - set_ia32_am_sc_sign(new_op); - set_ia32_ls_mode(new_op, mode); - if (is_ia32_use_frame(node)) { - set_ia32_frame_ent(new_op, get_ia32_frame_ent(node)); - set_ia32_use_frame(new_op); - } - - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); - - return new_op; -} - -/** - * Transforms a lowered Store into a "real" one. - */ -static ir_node *gen_lowered_Store(ir_node *node, construct_store_func func) -{ - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *ptr = get_irn_n(node, 0); - ir_node *new_ptr = be_transform_node(ptr); - ir_node *val = get_irn_n(node, 1); - ir_node *new_val = be_transform_node(val); - ir_node *mem = get_irn_n(node, 2); - ir_node *new_mem = be_transform_node(mem); - ir_graph *irg = current_ir_graph; - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *noreg = ia32_new_NoReg_gp(env_cg); - ir_mode *mode = get_ia32_ls_mode(node); - ir_node *new_op; - long am_offs; - - new_op = func(dbgi, irg, block, new_ptr, noreg, new_val, new_mem); - - am_offs = get_ia32_am_offs_int(node); - add_ia32_am_offs_int(new_op, am_offs); - - set_ia32_op_type(new_op, ia32_AddrModeD); - set_ia32_ls_mode(new_op, mode); - set_ia32_frame_ent(new_op, get_ia32_frame_ent(node)); - set_ia32_use_frame(new_op); - - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); - - return new_op; -} - static ir_node *gen_ia32_l_ShlDep(ir_node *node) { ir_node *left = get_irn_n(node, n_ia32_l_ShlDep_val); @@ -3749,71 +3743,6 @@ static ir_node *gen_ia32_l_Adc(ir_node *node) match_mode_neutral); } -/** - * Transforms an ia32_l_vfild into a "real" ia32_vfild node - * - * @param node The node to transform - * @return the created ia32 vfild node - */ -static ir_node *gen_ia32_l_vfild(ir_node *node) { - return gen_lowered_Load(node, new_rd_ia32_vfild); -} - -/** - * Transforms an ia32_l_Load into a "real" ia32_Load node - * - * @param node The node to transform - * @return the created ia32 Load node - */ -static ir_node *gen_ia32_l_Load(ir_node *node) { - return gen_lowered_Load(node, new_rd_ia32_Load); -} - -/** - * Transforms an ia32_l_Store into a "real" ia32_Store node - * - * @param node The node to transform - * @return the created ia32 Store node - */ -static ir_node *gen_ia32_l_Store(ir_node *node) { - return gen_lowered_Store(node, new_rd_ia32_Store); -} - -/** - * Transforms a l_vfist into a "real" vfist node. - * - * @param node The node to transform - * @return the created ia32 vfist node - */ -static ir_node *gen_ia32_l_vfist(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *ptr = get_irn_n(node, 0); - ir_node *new_ptr = be_transform_node(ptr); - ir_node *val = get_irn_n(node, 1); - ir_node *new_val = be_transform_node(val); - ir_node *mem = get_irn_n(node, 2); - ir_node *new_mem = be_transform_node(mem); - ir_graph *irg = current_ir_graph; - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *noreg = ia32_new_NoReg_gp(env_cg); - ir_mode *mode = get_ia32_ls_mode(node); - ir_node *memres, *fist; - long am_offs; - - memres = gen_vfist(dbgi, irg, block, new_ptr, noreg, new_mem, new_val, &fist); - am_offs = get_ia32_am_offs_int(node); - add_ia32_am_offs_int(fist, am_offs); - - set_ia32_op_type(fist, ia32_AddrModeD); - set_ia32_ls_mode(fist, mode); - set_ia32_frame_ent(fist, get_ia32_frame_ent(node)); - set_ia32_use_frame(fist); - - SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node)); - - return memres; -} - /** * Transforms a l_MulS into a "real" MulS node. * @@ -3882,7 +3811,9 @@ static ir_node *gen_lowered_64bit_shifts(ir_node *node, ir_node *high, /* the shift amount can be any mode that is bigger than 5 bits, since all * other bits are ignored anyway */ - while (is_Conv(count) && get_irn_n_edges(count) == 1) { + while (is_Conv(count) && + get_irn_n_edges(count) == 1 && + mode_is_int(get_irn_mode(count))) { assert(get_mode_size_bits(get_irn_mode(count)) >= 5); count = get_Conv_op(count); } @@ -3995,7 +3926,7 @@ static ir_node *gen_ia32_l_FloattoLL(ir_node *node) { * the BAD transformer. */ static ir_node *bad_transform(ir_node *node) { - panic("No transform function for %+F available.\n", node); + panic("No transform function for %+F available.", node); return NULL; } @@ -4056,8 +3987,7 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) { return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_SubSP_M); } - assert(0); - return new_rd_Unknown(irg, get_irn_mode(node)); + panic("No idea how to transform proj->AddSP"); } /** @@ -4080,8 +4010,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) { return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_ia32_AddSP_M); } - assert(0); - return new_rd_Unknown(irg, get_irn_mode(node)); + panic("No idea how to transform proj->SubSP"); } /** @@ -4179,8 +4108,7 @@ static ir_node *gen_Proj_Load(ir_node *node) { return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, 1); } - assert(0); - return new_rd_Unknown(irg, get_irn_mode(node)); + panic("No idea how to transform proj"); } /** @@ -4192,7 +4120,6 @@ static ir_node *gen_Proj_DivMod(ir_node *node) { ir_node *new_pred = be_transform_node(pred); ir_graph *irg = current_ir_graph; dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); long proj = get_Proj_proj(node); assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred)); @@ -4247,8 +4174,7 @@ static ir_node *gen_Proj_DivMod(ir_node *node) { break; } - assert(0); - return new_rd_Unknown(irg, mode); + panic("No idea how to transform proj->DivMod"); } /** @@ -4260,7 +4186,6 @@ static ir_node *gen_Proj_CopyB(ir_node *node) { ir_node *new_pred = be_transform_node(pred); ir_graph *irg = current_ir_graph; dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); long proj = get_Proj_proj(node); switch(proj) { @@ -4275,8 +4200,7 @@ static ir_node *gen_Proj_CopyB(ir_node *node) { break; } - assert(0); - return new_rd_Unknown(irg, mode); + panic("No idea how to transform proj->CopyB"); } /** @@ -4288,7 +4212,6 @@ static ir_node *gen_Proj_Quot(ir_node *node) { ir_node *new_pred = be_transform_node(pred); ir_graph *irg = current_ir_graph; dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); long proj = get_Proj_proj(node); switch(proj) { @@ -4312,14 +4235,26 @@ static ir_node *gen_Proj_Quot(ir_node *node) { break; } - assert(0); - return new_rd_Unknown(irg, mode); + panic("No idea how to transform proj->Quot"); } static ir_node *gen_be_Call(ir_node *node) { ir_node *res = be_duplicate_node(node); + ir_type *call_tp; + be_node_add_flags(res, -1, arch_irn_flags_modify_flags); + /* Run the x87 simulator if the call returns a float value */ + call_tp = be_Call_get_type(node); + if (get_method_n_ress(call_tp) > 0) { + ir_type *const res_type = get_method_res_type(call_tp, 0); + ir_mode *const res_mode = get_type_mode(res_type); + + if (res_mode != NULL && mode_is_float(res_mode)) { + env_cg->do_x87_sim = 1; + } + } + return res; } @@ -4480,8 +4415,7 @@ static ir_node *gen_Proj(ir_node *node) { if (proj == pn_Store_M) { return be_transform_node(pred); } else { - assert(0); - return new_r_Bad(current_ir_graph); + panic("No idea how to transform proj->Store"); } case iro_Load: return gen_Proj_Load(node); @@ -4607,10 +4541,6 @@ static void register_transformers(void) GEN(ia32_l_ShrD); GEN(ia32_l_Sub); GEN(ia32_l_Sbb); - GEN(ia32_l_vfild); - GEN(ia32_l_Load); - GEN(ia32_l_vfist); - GEN(ia32_l_Store); GEN(ia32_l_LLtoFloat); GEN(ia32_l_FloattoLL);