X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_transform.c;h=42a8f1ccb8bd9796e9dd9c7633caef70cfa09d33;hb=c8ab4da3eb7f8cd6f63235b2fb532ae6eb60fa8f;hp=6989766c71f4d140a8d79dda5df9f929c43272c9;hpb=eeb0e901a64b96dca670ed0df5a8b63caa7df249;p=libfirm diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 6989766c7..42a8f1ccb 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -76,18 +76,19 @@ #define SFP_ABS "0x7FFFFFFF" #define DFP_ABS "0x7FFFFFFFFFFFFFFF" #define DFP_INTMAX "9223372036854775807" +#define ULL_BIAS "18446744073709551616" #define TP_SFP_SIGN "ia32_sfp_sign" #define TP_DFP_SIGN "ia32_dfp_sign" #define TP_SFP_ABS "ia32_sfp_abs" #define TP_DFP_ABS "ia32_dfp_abs" -#define TP_INT_MAX "ia32_int_max" +#define TP_ULL_BIAS "ia32_ull_bias" -#define ENT_SFP_SIGN "IA32_SFP_SIGN" -#define ENT_DFP_SIGN "IA32_DFP_SIGN" -#define ENT_SFP_ABS "IA32_SFP_ABS" -#define ENT_DFP_ABS "IA32_DFP_ABS" -#define ENT_INT_MAX "IA32_INT_MAX" +#define ENT_SFP_SIGN ".LC_ia32_sfp_sign" +#define ENT_DFP_SIGN ".LC_ia32_dfp_sign" +#define ENT_SFP_ABS ".LC_ia32_sfp_abs" +#define ENT_DFP_ABS ".LC_ia32_dfp_abs" +#define ENT_ULL_BIAS ".LC_ia32_ull_bias" #define mode_vfp (ia32_reg_classes[CLASS_ia32_vfp].mode) #define mode_xmm (ia32_reg_classes[CLASS_ia32_xmm].mode) @@ -366,14 +367,12 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) { TP_DFP_SIGN, ENT_DFP_SIGN, DFP_SIGN, 1, 16 }, /* ia32_DSIGN */ { TP_SFP_ABS, ENT_SFP_ABS, SFP_ABS, 0, 16 }, /* ia32_SABS */ { TP_DFP_ABS, ENT_DFP_ABS, DFP_ABS, 1, 16 }, /* ia32_DABS */ - { TP_INT_MAX, ENT_INT_MAX, DFP_INTMAX, 2, 4 } /* ia32_INTMAX */ + { TP_ULL_BIAS, ENT_ULL_BIAS, ULL_BIAS, 2, 4 } /* ia32_ULLBIAS */ }; static ir_entity *ent_cache[ia32_known_const_max]; const char *tp_name, *ent_name, *cnst_str; ir_type *tp; - ir_node *cnst; - ir_graph *rem; ir_entity *ent; tarval *tv; ir_mode *mode; @@ -393,6 +392,14 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) /* set the specified alignment */ set_type_alignment_bytes(tp, names[kct].align); + if (kct == ia32_ULLBIAS) { + /* we are in the backend, construct a fixed type here */ + unsigned size = get_type_size_bytes(tp); + tp = new_type_array(new_id_from_str(tp_name), 1, tp); + set_type_alignment_bytes(tp, names[kct].align); + set_type_size_bytes(tp, 2 * size); + set_type_state(tp, layout_fixed); + } ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp); set_entity_ld_ident(ent, get_entity_ident(ent)); @@ -400,14 +407,18 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) set_entity_variability(ent, variability_constant); set_entity_allocation(ent, allocation_static); - /* we create a new entity here: It's initialization must resist on the - const code irg */ - rem = current_ir_graph; - current_ir_graph = get_const_code_irg(); - cnst = new_Const(mode, tv); - current_ir_graph = rem; + if (kct == ia32_ULLBIAS) { + ir_initializer_t *initializer = create_initializer_compound(2); - set_atomic_ent_value(ent, cnst); + set_initializer_compound_value(initializer, 0, + create_initializer_tarval(get_tarval_null(mode))); + set_initializer_compound_value(initializer, 1, + create_initializer_tarval(tv)); + + set_entity_initializer(ent, initializer); + } else { + set_entity_initializer(ent, create_initializer_tarval(tv)); + } /* cache the entry */ ent_cache[kct] = ent; @@ -593,9 +604,10 @@ static int is_downconv(const ir_node *node) src_mode = get_irn_mode(get_Conv_op(node)); dest_mode = get_irn_mode(node); - return ia32_mode_needs_gp_reg(src_mode) - && ia32_mode_needs_gp_reg(dest_mode) - && get_mode_size_bits(dest_mode) < get_mode_size_bits(src_mode); + return + ia32_mode_needs_gp_reg(src_mode) && + ia32_mode_needs_gp_reg(dest_mode) && + get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode); } /* Skip all Down-Conv's on a given node and return the resulting node. */ @@ -662,16 +674,9 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, assert(use_am || !(flags & match_8bit_am)); assert(use_am || !(flags & match_16bit_am)); - if (mode_bits == 8) { - if (!(flags & match_8bit_am)) - use_am = 0; - /* we don't automatically add upconvs yet */ - assert((flags & match_mode_neutral) || (flags & match_8bit)); - } else if (mode_bits == 16) { - if (!(flags & match_16bit_am)) - use_am = 0; - /* we don't automatically add upconvs yet */ - assert((flags & match_mode_neutral) || (flags & match_16bit)); + if ((mode_bits == 8 && !(flags & match_8bit_am)) || + (mode_bits == 16 && !(flags & match_16bit_am))) { + use_am = 0; } /* we can simply skip downconvs for mode neutral nodes: the upper bits @@ -2229,13 +2234,25 @@ static ir_node *try_create_dest_am(ir_node *node) return new_node; } +static bool possible_int_mode_for_fp(ir_mode *mode) +{ + unsigned size; + + if (!mode_is_signed(mode)) + return false; + size = get_mode_size_bits(mode); + if (size != 16 && size != 32) + return false; + return true; +} + static int is_float_to_int_conv(const ir_node *node) { ir_mode *mode = get_irn_mode(node); ir_node *conv_op; ir_mode *conv_mode; - if (mode != mode_Is && mode != mode_Hs) + if (!possible_int_mode_for_fp(mode)) return 0; if (!is_Conv(node)) @@ -2750,8 +2767,7 @@ static ir_node *gen_Cmp(ir_node *node) 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); + match_am_and_immediates | match_immediate); /* use 32bit compare mode if possible since the opcode is smaller */ if (upper_bits_clean(am.new_op1, cmp_mode) && @@ -2772,7 +2788,7 @@ static ir_node *gen_Cmp(ir_node *node) match_arguments(&am, block, left, right, NULL, match_commutative | match_am | match_8bit_am | match_16bit_am | match_am_and_immediates | - match_immediate | match_8bit | match_16bit); + match_immediate); /* 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)) { @@ -2808,7 +2824,6 @@ static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags, ir_node *val_true = get_Mux_true(node); ir_node *val_false = get_Mux_false(node); ir_node *new_node; - match_flags_t match_flags; ia32_address_mode_t am; ia32_address_t *addr; @@ -2817,10 +2832,8 @@ static ir_node *create_CMov(ir_node *node, ir_node *flags, ir_node *new_flags, addr = &am.addr; - match_flags = match_commutative | match_am | match_16bit_am | - match_mode_neutral; - - match_arguments(&am, block, val_false, val_true, flags, match_flags); + match_arguments(&am, block, val_false, val_true, flags, + match_commutative | match_am | match_16bit_am | match_mode_neutral); new_node = new_bd_ia32_CMov(dbgi, new_block, addr->base, addr->index, addr->mem, am.new_op1, am.new_op2, new_flags, @@ -3101,11 +3114,10 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) ir_node *new_node; /* fild can use source AM if the operand is a signed 16bit or 32bit integer */ - if (src_mode == mode_Is || src_mode == mode_Hs) { + if (possible_int_mode_for_fp(src_mode)) { ia32_address_mode_t am; - match_arguments(&am, src_block, NULL, op, NULL, - match_am | match_try_am | match_16bit | match_16bit_am); + match_arguments(&am, src_block, NULL, op, NULL, match_am | match_try_am | match_16bit_am); if (am.op_type == ia32_AddrModeS) { ia32_address_t *addr = &am.addr; @@ -3132,8 +3144,10 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) /* first convert to 32 bit signed if necessary */ if (get_mode_size_bits(src_mode) < 32) { - new_op = create_Conv_I2I(dbgi, block, noreg, noreg, nomem, new_op, src_mode); - SET_IA32_ORIG_NODE(new_op, node); + if (!upper_bits_clean(new_op, src_mode)) { + new_op = create_Conv_I2I(dbgi, block, noreg, noreg, nomem, new_op, src_mode); + SET_IA32_ORIG_NODE(new_op, node); + } mode = mode_Is; } @@ -3210,7 +3224,6 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode, #endif 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)) { @@ -3254,6 +3267,9 @@ static ir_node *gen_Conv(ir_node *node) ir_node *nomem = new_NoMem(); ir_node *res = NULL; + assert(!mode_is_int(src_mode) || src_bits <= 32); + assert(!mode_is_int(tgt_mode) || tgt_bits <= 32); + if (src_mode == mode_b) { assert(mode_is_int(tgt_mode) || mode_is_reference(tgt_mode)); /* nothing to do, we already model bools as 0/1 ints */ @@ -3789,13 +3805,11 @@ static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) ir_node *new_val_low = be_transform_node(val_low); ir_node *new_val_high = be_transform_node(val_high); ir_node *in[2]; - ir_node *sync; - ir_node *fild; - ir_node *store_low; - ir_node *store_high; + ir_node *sync, *fild, *res; + ir_node *store_low, *store_high; - if (!mode_is_signed(get_irn_mode(val_high))) { - panic("unsigned long long -> float not supported yet (%+F)", node); + if (ia32_cg_config.use_sse2) { + panic("ia32_l_LLtoFloat not implemented for SSE2"); } /* do a store */ @@ -3827,7 +3841,40 @@ static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) SET_IA32_ORIG_NODE(fild, node); - return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res); + res = new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res); + + if (! mode_is_signed(get_irn_mode(val_high))) { + ia32_address_mode_t am; + + ir_node *count = create_Immediate(NULL, 0, 31); + ir_node *fadd; + + am.addr.base = ia32_new_NoReg_gp(env_cg); + am.addr.index = new_bd_ia32_Shr(dbgi, block, new_val_high, count); + am.addr.mem = nomem; + am.addr.offset = 0; + am.addr.scale = 2; + am.addr.symconst_ent = ia32_gen_fp_known_const(ia32_ULLBIAS); + am.addr.use_frame = 0; + am.addr.frame_entity = NULL; + am.addr.symconst_sign = 0; + am.ls_mode = mode_F; + am.mem_proj = nomem; + am.op_type = ia32_AddrModeS; + am.new_op1 = res; + am.new_op2 = ia32_new_NoReg_vfp(env_cg); + am.pinned = op_pin_state_floats; + am.commutative = 1; + am.ins_permuted = 0; + + fadd = new_bd_ia32_vfadd(dbgi, block, am.addr.base, am.addr.index, am.addr.mem, + am.new_op1, am.new_op2, get_fpcw()); + set_am_attributes(fadd, &am); + + set_irn_mode(fadd, mode_T); + res = new_rd_Proj(NULL, irg, block, fadd, mode_vfp, pn_ia32_res); + } + return res; } static ir_node *gen_ia32_l_FloattoLL(ir_node *node)