- removed unused ia32_INTMAX constant
[libfirm] / ir / be / ia32 / ia32_transform.c
index 6989766..42a8f1c 100644 (file)
 #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)