- removed unused ia32_INTMAX constant
[libfirm] / ir / be / ia32 / ia32_transform.c
index 6f5a3f3..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_initializer_compound_value(initializer, 0,
+                               create_initializer_tarval(get_tarval_null(mode)));
+                       set_initializer_compound_value(initializer, 1,
+                               create_initializer_tarval(tv));
 
-               set_atomic_ent_value(ent, cnst);
+                       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
@@ -1967,7 +1972,6 @@ static ir_node *dest_am_binop(ir_node *node, ir_node *op1, ir_node *op2,
        ia32_address_t      *addr = &am.addr;
        memset(&am, 0, sizeof(am));
 
-       assert(flags & match_dest_am);
        assert(flags & match_immediate); /* there is no destam node without... */
        commutative = (flags & match_commutative) != 0;
 
@@ -2141,8 +2145,7 @@ static ir_node *try_create_dest_am(ir_node *node)
                }
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_AddMem, new_bd_ia32_AddMem8Bit,
-                                        match_dest_am | match_commutative |
-                                        match_immediate);
+                                        match_commutative | match_immediate);
                break;
        case iro_Sub:
                op1      = get_Sub_left(val);
@@ -2152,59 +2155,56 @@ static ir_node *try_create_dest_am(ir_node *node)
                }
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_SubMem, new_bd_ia32_SubMem8Bit,
-                                        match_dest_am | match_immediate);
+                                        match_immediate);
                break;
        case iro_And:
                op1      = get_And_left(val);
                op2      = get_And_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_AndMem, new_bd_ia32_AndMem8Bit,
-                                        match_dest_am | match_commutative |
-                                        match_immediate);
+                                        match_commutative | match_immediate);
                break;
        case iro_Or:
                op1      = get_Or_left(val);
                op2      = get_Or_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_OrMem, new_bd_ia32_OrMem8Bit,
-                                        match_dest_am | match_commutative |
-                                        match_immediate);
+                                        match_commutative | match_immediate);
                break;
        case iro_Eor:
                op1      = get_Eor_left(val);
                op2      = get_Eor_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_XorMem, new_bd_ia32_XorMem8Bit,
-                                        match_dest_am | match_commutative |
-                                        match_immediate);
+                                        match_commutative | match_immediate);
                break;
        case iro_Shl:
                op1      = get_Shl_left(val);
                op2      = get_Shl_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_ShlMem, new_bd_ia32_ShlMem,
-                                        match_dest_am | match_immediate);
+                                        match_immediate);
                break;
        case iro_Shr:
                op1      = get_Shr_left(val);
                op2      = get_Shr_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_ShrMem, new_bd_ia32_ShrMem,
-                                        match_dest_am | match_immediate);
+                                        match_immediate);
                break;
        case iro_Shrs:
                op1      = get_Shrs_left(val);
                op2      = get_Shrs_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_SarMem, new_bd_ia32_SarMem,
-                                        match_dest_am | match_immediate);
+                                        match_immediate);
                break;
        case iro_Rotl:
                op1      = get_Rotl_left(val);
                op2      = get_Rotl_right(val);
                new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
                                         new_bd_ia32_RolMem, new_bd_ia32_RolMem,
-                                        match_dest_am | match_immediate);
+                                        match_immediate);
                break;
        /* TODO: match ROR patterns... */
        case iro_Mux:
@@ -2234,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))
@@ -2673,13 +2685,18 @@ static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode)
                                return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Shr_val), mode);
                        }
 
-               case iro_ia32_And:
-                       if (mode_is_signed(mode))
-                               return false; /* TODO handle signed modes */
-                       return
-                               upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_right), mode) ||
-                               upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_left),  mode);
+               case iro_ia32_Sar:
+                       /* TODO too conservative if shift amount is constant */
+                       return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Sar_val), mode);
 
+               case iro_ia32_And:
+                       if (!mode_is_signed(mode)) {
+                               return
+                                       upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_right), mode) ||
+                                       upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_left),  mode);
+                       }
+                       /* TODO if one is known to be zero extended, then || is sufficient */
+                       /* FALLTHROUGH */
                case iro_ia32_Or:
                case iro_ia32_Xor:
                        return
@@ -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,
@@ -3071,6 +3084,16 @@ static ir_node *gen_x87_strict_conv(ir_mode *tgt_mode, ir_node *node)
        return new_node;
 }
 
+static ir_node *create_Conv_I2I(dbg_info *dbgi, ir_node *block, ir_node *base,
+               ir_node *index, ir_node *mem, ir_node *val, ir_mode *mode)
+{
+       ir_node *(*func)(dbg_info*, ir_node*, ir_node*, ir_node*, ir_node*, ir_node*, ir_mode*);
+
+       func = get_mode_size_bits(mode) == 8 ?
+               new_bd_ia32_Conv_I2I8Bit : new_bd_ia32_Conv_I2I;
+       return func(dbgi, block, base, index, mem, val, mode);
+}
+
 /**
  * Create a conversion from general purpose to x87 register
  */
@@ -3089,14 +3112,12 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode)
        ir_node  *fild;
        ir_node  *store;
        ir_node  *new_node;
-       int       src_bits;
 
        /* 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;
 
@@ -3122,16 +3143,11 @@ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode)
        mode   = get_irn_mode(op);
 
        /* first convert to 32 bit signed if necessary */
-       src_bits = get_mode_size_bits(src_mode);
-       if (src_bits == 8) {
-               new_op = new_bd_ia32_Conv_I2I8Bit(dbgi, block, noreg, noreg, nomem,
-                                                 new_op, src_mode);
-               SET_IA32_ORIG_NODE(new_op, node);
-               mode = mode_Is;
-       } else if (src_bits < 32) {
-               new_op = new_bd_ia32_Conv_I2I(dbgi, block, noreg, noreg, nomem,
-                                             new_op, src_mode);
-               SET_IA32_ORIG_NODE(new_op, node);
+       if (get_mode_size_bits(src_mode) < 32) {
+               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;
        }
 
@@ -3187,22 +3203,17 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
                                 dbg_info *dbgi, ir_node *block, ir_node *op,
                                 ir_node *node)
 {
-       int       src_bits  = get_mode_size_bits(src_mode);
-       int       tgt_bits  = get_mode_size_bits(tgt_mode);
-       ir_node  *new_block = be_transform_node(block);
-       ir_node  *new_node;
-       ir_mode  *smaller_mode;
-       int       smaller_bits;
+       ir_node             *new_block = be_transform_node(block);
+       ir_node             *new_node;
+       ir_mode             *smaller_mode;
        ia32_address_mode_t  am;
        ia32_address_t      *addr = &am.addr;
 
        (void) node;
-       if (src_bits < tgt_bits) {
+       if (get_mode_size_bits(src_mode) < get_mode_size_bits(tgt_mode)) {
                smaller_mode = src_mode;
-               smaller_bits = src_bits;
        } else {
                smaller_mode = tgt_mode;
-               smaller_bits = tgt_bits;
        }
 
 #ifdef DEBUG_libfirm
@@ -3213,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)) {
@@ -3226,15 +3236,8 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
                return am.new_op2;
        }
 
-       if (smaller_bits == 8) {
-               new_node = new_bd_ia32_Conv_I2I8Bit(dbgi, new_block, addr->base,
-                                                   addr->index, addr->mem, am.new_op2,
-                                                   smaller_mode);
-       } else {
-               new_node = new_bd_ia32_Conv_I2I(dbgi, new_block, addr->base,
-                                               addr->index, addr->mem, am.new_op2,
-                                               smaller_mode);
-       }
+       new_node = create_Conv_I2I(dbgi, new_block, addr->base, addr->index,
+                       addr->mem, am.new_op2, smaller_mode);
        set_am_attributes(new_node, &am);
        /* match_arguments assume that out-mode = in-mode, this isn't true here
         * so fix it */
@@ -3264,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 */
@@ -3581,9 +3587,7 @@ static ir_node *gen_IJmp(ir_node *node)
 
        assert(get_irn_mode(op) == mode_P);
 
-       match_arguments(&am, block, NULL, op, NULL,
-                       match_am | match_8bit_am | match_16bit_am |
-                       match_immediate | match_8bit | match_16bit);
+       match_arguments(&am, block, NULL, op, NULL, match_am | match_immediate);
 
        new_node = new_bd_ia32_IJmp(dbgi, new_block, addr->base, addr->index,
                        addr->mem, am.new_op2);
@@ -3801,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 */
@@ -3839,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)