X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fia32%2Fia32_transform.c;h=8319bbeb1384b4bb9c008ed22274f47f64d18b72;hb=e3b765fcef0e337f4fe2e17d57d2fbaf1912ec79;hp=d7eaaa1e7dca1db77bcb485eafdffb75666a327f;hpb=85f517eca982e6a4e1d1848eb67634ae33b70de9;p=libfirm diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index d7eaaa1e7..8319bbeb1 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -48,13 +48,13 @@ #include "array_t.h" #include "heights.h" -#include "../benode.h" -#include "../besched.h" -#include "../beabi.h" -#include "../beutil.h" -#include "../beirg.h" -#include "../betranshlp.h" -#include "../be_t.h" +#include "benode.h" +#include "besched.h" +#include "beabi.h" +#include "beutil.h" +#include "beirg.h" +#include "betranshlp.h" +#include "be_t.h" #include "bearch_ia32_t.h" #include "ia32_common_transform.h" @@ -71,20 +71,6 @@ /* define this to construct SSE constants instead of load them */ #undef CONSTRUCT_SSE_CONST - -#define SFP_SIGN "0x80000000" -#define DFP_SIGN "0x8000000000000000" -#define SFP_ABS "0x7FFFFFFF" -#define DFP_ABS "0x7FFFFFFFFFFFFFFF" -#define DFP_INTMAX "9223372036854775807" -#define ULL_BIAS "18446744073709551616" - -#define ENT_SFP_SIGN "C_ia32_sfp_sign" -#define ENT_DFP_SIGN "C_ia32_dfp_sign" -#define ENT_SFP_ABS "C_ia32_sfp_abs" -#define ENT_DFP_ABS "C_ia32_dfp_abs" -#define ENT_ULL_BIAS "C_ia32_ull_bias" - #define mode_vfp (ia32_reg_classes[CLASS_ia32_vfp].mode) #define mode_xmm (ia32_reg_classes[CLASS_ia32_xmm].mode) @@ -215,20 +201,23 @@ static ir_node *get_symconst_base(void) */ static ir_node *gen_Const(ir_node *node) { - ir_node *old_block = get_nodes_block(node); - ir_node *block = be_transform_node(old_block); - dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); + ir_node *old_block = get_nodes_block(node); + ir_node *block = be_transform_node(old_block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); + ir_tarval *tv = get_Const_tarval(node); assert(is_Const(node)); if (mode_is_float(mode)) { - ir_node *res = NULL; - ir_node *load; - ir_entity *floatent; + ir_graph *irg = get_irn_irg(node); + const arch_env_t *arch_env = be_get_irg_arch_env(irg); + ia32_isa_t *isa = (ia32_isa_t*) arch_env; + ir_node *res = NULL; + ir_node *load; + ir_entity *floatent; if (ia32_cg_config.use_sse2) { - ir_tarval *tv = get_Const_tarval(node); if (tarval_is_null(tv)) { load = new_bd_ia32_xZero(dbgi, block); set_ia32_ls_mode(load, mode); @@ -285,22 +274,22 @@ static ir_node *gen_Const(ir_node *node) } } #endif /* CONSTRUCT_SSE_CONST */ - floatent = ia32_create_float_const_entity(node); + floatent = ia32_create_float_const_entity(isa, tv, NULL); base = get_symconst_base(); load = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP, nomem, mode); set_ia32_op_type(load, ia32_AddrModeS); set_ia32_am_sc(load, floatent); - arch_irn_add_flags(load, arch_irn_flags_rematerializable); + arch_add_irn_flags(load, arch_irn_flags_rematerializable); res = new_r_Proj(load, mode_xmm, pn_ia32_xLoad_res); } } else { - if (is_Const_null(node)) { + if (tarval_is_null(tv)) { load = new_bd_ia32_vfldz(dbgi, block); res = load; set_ia32_ls_mode(load, mode); - } else if (is_Const_one(node)) { + } else if (tarval_is_one(tv)) { load = new_bd_ia32_vfld1(dbgi, block); res = load; set_ia32_ls_mode(load, mode); @@ -308,7 +297,7 @@ static ir_node *gen_Const(ir_node *node) ir_mode *ls_mode; ir_node *base; - floatent = ia32_create_float_const_entity(node); + floatent = ia32_create_float_const_entity(isa, tv, NULL); /* create_float_const_ent is smart and sometimes creates smaller entities */ ls_mode = get_type_mode(get_entity_type(floatent)); @@ -317,7 +306,7 @@ static ir_node *gen_Const(ir_node *node) ls_mode); set_ia32_op_type(load, ia32_AddrModeS); set_ia32_am_sc(load, floatent); - arch_irn_add_flags(load, arch_irn_flags_rematerializable); + arch_add_irn_flags(load, arch_irn_flags_rematerializable); res = new_r_Proj(load, mode_vfp, pn_ia32_vfld_res); } } @@ -327,9 +316,8 @@ end: SET_IA32_ORIG_NODE(load, node); return res; } else { /* non-float mode */ - ir_node *cnst; - ir_tarval *tv = get_Const_tarval(node); - long val; + ir_node *cnst; + long val; tv = tarval_convert_to(tv, mode_Iu); @@ -359,9 +347,9 @@ static ir_node *gen_SymConst(ir_node *node) if (mode_is_float(mode)) { if (ia32_cg_config.use_sse2) - cnst = new_bd_ia32_xLoad(dbgi, block, noreg_GP, noreg_GP, nomem, mode_E); + cnst = new_bd_ia32_xLoad(dbgi, block, noreg_GP, noreg_GP, nomem, mode_D); else - cnst = new_bd_ia32_vfld(dbgi, block, noreg_GP, noreg_GP, nomem, mode_E); + cnst = new_bd_ia32_vfld(dbgi, block, noreg_GP, noreg_GP, nomem, ia32_mode_E); set_ia32_am_sc(cnst, get_SymConst_entity(node)); set_ia32_use_frame(cnst); } else { @@ -386,64 +374,18 @@ static ir_node *gen_SymConst(ir_node *node) return cnst; } -/** - * Create a float type for the given mode and cache it. - * - * @param mode the mode for the float type (might be integer mode for SSE2 types) - * @param align alignment - */ -static ir_type *ia32_create_float_type(ir_mode *mode, unsigned align) +static ir_type *make_array_type(ir_type *tp) { - ir_type *tp; - - assert(align <= 16); - - if (mode == mode_Iu) { - static ir_type *int_Iu[16] = {NULL, }; - - if (int_Iu[align] == NULL) { - int_Iu[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return int_Iu[align]; - } else if (mode == mode_Lu) { - static ir_type *int_Lu[16] = {NULL, }; - - if (int_Lu[align] == NULL) { - int_Lu[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return int_Lu[align]; - } else if (mode == mode_F) { - static ir_type *float_F[16] = {NULL, }; - - if (float_F[align] == NULL) { - float_F[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return float_F[align]; - } else if (mode == mode_D) { - static ir_type *float_D[16] = {NULL, }; - - if (float_D[align] == NULL) { - float_D[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return float_D[align]; - } else { - static ir_type *float_E[16] = {NULL, }; - - if (float_E[align] == NULL) { - float_E[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return float_E[align]; - } + unsigned alignment = get_type_alignment_bytes(tp); + unsigned size = get_type_size_bytes(tp); + ir_type *res = new_type_array(1, tp); + set_type_alignment_bytes(res, alignment); + set_array_bounds_int(res, 0, 0, 2); + if (alignment > size) + size = alignment; + set_type_size_bytes(res, 2 * size); + set_type_state(res, layout_fixed); + return res; } /** @@ -454,33 +396,27 @@ static ir_type *ia32_create_float_type(ir_mode *mode, unsigned align) static ir_type *ia32_create_float_array(ir_type *tp) { ir_mode *mode = get_type_mode(tp); - unsigned align = get_type_alignment_bytes(tp); ir_type *arr; - assert(align <= 16); - if (mode == mode_F) { - static ir_type *float_F[16] = {NULL, }; + static ir_type *float_F; - if (float_F[align] != NULL) - return float_F[align]; - arr = float_F[align] = new_type_array(1, tp); + arr = float_F; + if (arr == NULL) + arr = float_F = make_array_type(tp); } else if (mode == mode_D) { - static ir_type *float_D[16] = {NULL, }; + static ir_type *float_D; - if (float_D[align] != NULL) - return float_D[align]; - arr = float_D[align] = new_type_array(1, tp); + arr = float_D; + if (arr == NULL) + arr = float_D = make_array_type(tp); } else { - static ir_type *float_E[16] = {NULL, }; + static ir_type *float_E; - if (float_E[align] != NULL) - return float_E[align]; - arr = float_E[align] = new_type_array(1, tp); + arr = float_E; + if (arr == NULL) + arr = float_E = make_array_type(tp); } - set_type_alignment_bytes(arr, align); - set_type_size_bytes(arr, 2 * get_type_size_bytes(tp)); - set_type_state(arr, layout_fixed); return arr; } @@ -488,58 +424,56 @@ static ir_type *ia32_create_float_array(ir_type *tp) ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) { static const struct { - const char *ent_name; + const char *name; const char *cnst_str; - char mode; - unsigned char align; + char mode; } names [ia32_known_const_max] = { - { ENT_SFP_SIGN, SFP_SIGN, 0, 16 }, /* ia32_SSIGN */ - { ENT_DFP_SIGN, DFP_SIGN, 1, 16 }, /* ia32_DSIGN */ - { ENT_SFP_ABS, SFP_ABS, 0, 16 }, /* ia32_SABS */ - { ENT_DFP_ABS, DFP_ABS, 1, 16 }, /* ia32_DABS */ - { ENT_ULL_BIAS, ULL_BIAS, 2, 4 } /* ia32_ULLBIAS */ + { "C_sfp_sign", "0x80000000", 0 }, + { "C_dfp_sign", "0x8000000000000000", 1 }, + { "C_sfp_abs", "0x7FFFFFFF", 0 }, + { "C_dfp_abs", "0x7FFFFFFFFFFFFFFF", 1 }, + { "C_ull_bias", "0x10000000000000000", 2 } }; static ir_entity *ent_cache[ia32_known_const_max]; - const char *ent_name, *cnst_str; - ir_type *tp; - ir_entity *ent; - ir_tarval *tv; - ir_mode *mode; - - ent_name = names[kct].ent_name; - if (! ent_cache[kct]) { - cnst_str = names[kct].cnst_str; + ir_entity *ent = ent_cache[kct]; + if (ent == NULL) { + ir_graph *irg = current_ir_graph; + const arch_env_t *arch_env = be_get_irg_arch_env(irg); + ia32_isa_t *isa = (ia32_isa_t*) arch_env; + const char *cnst_str = names[kct].cnst_str; + ident *name = new_id_from_str(names[kct].name); + ir_mode *mode; + ir_tarval *tv; switch (names[kct].mode) { case 0: mode = mode_Iu; break; case 1: mode = mode_Lu; break; - default: mode = mode_F; break; + case 2: mode = mode_F; break; + default: panic("internal compiler error (ia32_gen_fp_known_const)"); } - tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode); - tp = ia32_create_float_type(mode, names[kct].align); + tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode); - if (kct == ia32_ULLBIAS) - tp = ia32_create_float_array(tp); - ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp); + if (kct == ia32_ULLBIAS) { + ir_type *type = ia32_get_prim_type(mode_F); + ir_type *atype = ia32_create_float_array(type); + ir_initializer_t *initializer; - set_entity_ld_ident(ent, get_entity_ident(ent)); - add_entity_linkage(ent, IR_LINKAGE_CONSTANT); - set_entity_visibility(ent, ir_visibility_private); + ent = new_entity(get_glob_type(), name, atype); - if (kct == ia32_ULLBIAS) { - ir_initializer_t *initializer = create_initializer_compound(2); + set_entity_ld_ident(ent, name); + set_entity_visibility(ent, ir_visibility_private); + add_entity_linkage(ent, IR_LINKAGE_CONSTANT); + initializer = create_initializer_compound(2); set_initializer_compound_value(initializer, 0, create_initializer_tarval(get_mode_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)); + ent = ia32_create_float_const_entity(isa, tv, name); } - /* cache the entry */ ent_cache[kct] = ent; } @@ -639,7 +573,11 @@ static void build_address(ia32_address_mode_t *am, ir_node *node, /* floating point immediates */ if (is_Const(node)) { - ir_entity *entity = ia32_create_float_const_entity(node); + ir_graph *irg = get_irn_irg(node); + const arch_env_t *arch_env = be_get_irg_arch_env(irg); + ia32_isa_t *isa = (ia32_isa_t*) arch_env; + ir_tarval *tv = get_Const_tarval(node); + ir_entity *entity = ia32_create_float_const_entity(isa, tv, NULL); addr->base = get_symconst_base(); addr->index = noreg_GP; addr->mem = nomem; @@ -1111,15 +1049,19 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2, { dbg_info *dbgi; ir_node *block, *new_block, *new_op1, *new_op2, *new_node; + ir_mode *mode = get_irn_mode(node); - assert(! mode_is_float(get_irn_mode(node))); + assert(! mode_is_float(mode)); assert(flags & match_immediate); assert((flags & ~(match_mode_neutral | match_immediate)) == 0); + if (get_mode_modulo_shift(mode) != 32) + panic("modulo shift!=32 not supported by ia32 backend"); + if (flags & match_mode_neutral) { op1 = ia32_skip_downconv(op1); new_op1 = be_transform_node(op1); - } else if (get_mode_size_bits(get_irn_mode(node)) != 32) { + } else if (get_mode_size_bits(mode) != 32) { new_op1 = create_upconv(op1, node); } else { new_op1 = be_transform_node(op1); @@ -1235,6 +1177,118 @@ static int am_has_immediates(const ia32_address_t *addr) || addr->frame_entity || addr->use_frame; } +typedef ir_node* (*new_shiftd_func)(dbg_info *dbgi, ir_node *block, + ir_node *high, ir_node *low, + ir_node *count); + +/** + * Transforms a l_ShlD/l_ShrD into a ShlD/ShrD. Those nodes have 3 data inputs: + * op1 - target to be shifted + * op2 - contains bits to be shifted into target + * op3 - shift count + * Only op3 can be an immediate. + */ +static ir_node *gen_64bit_shifts(dbg_info *dbgi, ir_node *block, + ir_node *high, ir_node *low, ir_node *count, + new_shiftd_func func) +{ + ir_node *new_block = be_transform_node(block); + ir_node *new_high = be_transform_node(high); + ir_node *new_low = be_transform_node(low); + ir_node *new_count; + ir_node *new_node; + + /* 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 && + mode_is_int(get_irn_mode(count))) { + assert(get_mode_size_bits(get_irn_mode(count)) >= 5); + count = get_Conv_op(count); + } + new_count = create_immediate_or_transform(count, 0); + + new_node = func(dbgi, new_block, new_high, new_low, new_count); + return new_node; +} + +/** + * test wether 2 values result in 'x' and '32-x' when interpreted as a shift + * value. + */ +static bool is_complementary_shifts(ir_node *value1, ir_node *value2) +{ + if (is_Const(value1) && is_Const(value2)) { + ir_tarval *tv1 = get_Const_tarval(value1); + ir_tarval *tv2 = get_Const_tarval(value2); + if (tarval_is_long(tv1) && tarval_is_long(tv2)) { + long v1 = get_tarval_long(tv1); + long v2 = get_tarval_long(tv2); + return v1 <= v2 && v2 == 32-v1; + } + } + return false; +} + +static ir_node *match_64bit_shift(ir_node *node) +{ + ir_node *op1 = get_binop_left(node); + ir_node *op2 = get_binop_right(node); + assert(is_Or(node) || is_Add(node)); + + if (is_Shr(op1)) { + ir_node *tmp = op1; + op1 = op2; + op2 = tmp; + } + + /* match ShlD operation */ + if (is_Shl(op1) && is_Shr(op2)) { + ir_node *shl_right = get_Shl_right(op1); + ir_node *shl_left = get_Shl_left(op1); + ir_node *shr_right = get_Shr_right(op2); + ir_node *shr_left = get_Shr_left(op2); + /* constant ShlD operation */ + if (is_complementary_shifts(shl_right, shr_right)) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + return gen_64bit_shifts(dbgi, block, shl_left, shr_left, shl_right, + new_bd_ia32_ShlD); + } + /* constant ShrD operation */ + if (is_complementary_shifts(shr_right, shl_right)) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + return gen_64bit_shifts(dbgi, block, shr_left, shl_left, shr_right, + new_bd_ia32_ShrD); + } + /* lower_dw produces the following for ShlD: + * Or(Shr(Shr(high,1),Not(c)),Shl(low,c)) */ + if (is_Shr(shr_left) && is_Not(shr_right) + && is_Const_1(get_Shr_right(shr_left)) + && get_Not_op(shr_right) == shl_right) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *val_h = get_Shr_left(shr_left); + return gen_64bit_shifts(dbgi, block, shl_left, val_h, shl_right, + new_bd_ia32_ShlD); + } + /* lower_dw produces the following for ShrD: + * Or(Shl(Shl(high,1),Not(c)), Shr(low,c)) */ + if (is_Shl(shl_left) && is_Not(shl_right) + && is_Const_1(get_Shl_right(shl_left)) + && get_Not_op(shl_right) == shr_right) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *val_h = get_Shl_left(shl_left); + return gen_64bit_shifts(dbgi, block, shr_left, val_h, shr_right, + new_bd_ia32_ShrD); + } + } + + return NULL; +} + /** * Creates an ia32 Add. * @@ -1250,6 +1304,10 @@ static ir_node *gen_Add(ir_node *node) ia32_address_t addr; ia32_address_mode_t am; + new_node = match_64bit_shift(node); + if (new_node != NULL) + return new_node; + if (mode_is_float(mode)) { if (ia32_cg_config.use_sse2) return gen_binop(node, op1, op2, new_bd_ia32_xAdd, @@ -1420,117 +1478,6 @@ static ir_node *gen_And(ir_node *node) match_commutative | match_mode_neutral | match_am | match_immediate); } -/** - * test wether 2 values result in 'x' and '32-x' when interpreted as a shift - * value. - */ -static bool is_complementary_shifts(ir_node *value1, ir_node *value2) -{ - if (is_Const(value1) && is_Const(value2)) { - ir_tarval *tv1 = get_Const_tarval(value1); - ir_tarval *tv2 = get_Const_tarval(value2); - if (tarval_is_long(tv1) && tarval_is_long(tv2)) { - long v1 = get_tarval_long(tv1); - long v2 = get_tarval_long(tv2); - return v1 <= v2 && v2 == 32-v1; - } - } - return false; -} - -typedef ir_node* (*new_shiftd_func)(dbg_info *dbgi, ir_node *block, - ir_node *high, ir_node *low, - ir_node *count); - -/** - * Transforms a l_ShlD/l_ShrD into a ShlD/ShrD. Those nodes have 3 data inputs: - * op1 - target to be shifted - * op2 - contains bits to be shifted into target - * op3 - shift count - * Only op3 can be an immediate. - */ -static ir_node *gen_64bit_shifts(dbg_info *dbgi, ir_node *block, - ir_node *high, ir_node *low, ir_node *count, - new_shiftd_func func) -{ - ir_node *new_block = be_transform_node(block); - ir_node *new_high = be_transform_node(high); - ir_node *new_low = be_transform_node(low); - ir_node *new_count; - ir_node *new_node; - - /* 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 && - mode_is_int(get_irn_mode(count))) { - assert(get_mode_size_bits(get_irn_mode(count)) >= 5); - count = get_Conv_op(count); - } - new_count = create_immediate_or_transform(count, 0); - - new_node = func(dbgi, new_block, new_high, new_low, new_count); - return new_node; -} - -static ir_node *match_64bit_shift(ir_node *node) -{ - ir_node *op1 = get_Or_left(node); - ir_node *op2 = get_Or_right(node); - - if (is_Shr(op1)) { - ir_node *tmp = op1; - op1 = op2; - op2 = tmp; - } - - /* match ShlD operation */ - if (is_Shl(op1) && is_Shr(op2)) { - ir_node *shl_right = get_Shl_right(op1); - ir_node *shl_left = get_Shl_left(op1); - ir_node *shr_right = get_Shr_right(op2); - ir_node *shr_left = get_Shr_left(op2); - /* constant ShlD operation */ - if (is_complementary_shifts(shl_right, shr_right)) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - return gen_64bit_shifts(dbgi, block, shl_left, shr_left, shl_right, - new_bd_ia32_ShlD); - } - /* constant ShrD operation */ - if (is_complementary_shifts(shr_right, shl_right)) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - return gen_64bit_shifts(dbgi, block, shr_left, shl_left, shr_right, - new_bd_ia32_ShrD); - } - /* lower_dw produces the following for ShlD: - * Or(Shr(Shr(high,1),Not(c)),Shl(low,c)) */ - if (is_Shr(shr_left) && is_Not(shr_right) - && is_Const_1(get_Shr_right(shr_left)) - && get_Not_op(shr_right) == shl_right) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *val_h = get_Shr_left(shr_left); - return gen_64bit_shifts(dbgi, block, shl_left, val_h, shl_right, - new_bd_ia32_ShlD); - } - /* lower_dw produces the following for ShrD: - * Or(Shl(Shl(high,1),Not(c)), Shr(low,c)) */ - if (is_Shl(shl_left) && is_Not(shl_right) - && is_Const_1(get_Shl_right(shl_left)) - && get_Not_op(shl_right) == shr_right) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *val_h = get_Shl_left(shl_left); - return gen_64bit_shifts(dbgi, block, shr_left, val_h, shr_right, - new_bd_ia32_ShrD); - } - } - - return NULL; -} - /** * Creates an ia32 Or. * @@ -2094,17 +2041,6 @@ static ia32_condition_code_t relation_to_condition_code(ir_relation relation, } } -static ir_node *get_flags_mode_b(ir_node *node, ia32_condition_code_t *cc_out) -{ - /* a mode_b value, we have to compare it against 0 */ - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *new_block = be_transform_node(get_nodes_block(node)); - ir_node *new_op = be_transform_node(node); - ir_node *flags = new_bd_ia32_Test(dbgi, new_block, noreg_GP, noreg_GP, nomem, new_op, new_op, false); - *cc_out = ia32_cc_not_equal; - return flags; -} - static ir_node *get_flags_node_cmp(ir_node *cmp, ia32_condition_code_t *cc_out) { /* must have a Cmp as input */ @@ -2166,10 +2102,8 @@ static ir_node *get_flags_node_cmp(ir_node *cmp, ia32_condition_code_t *cc_out) */ static ir_node *get_flags_node(ir_node *node, ia32_condition_code_t *cc_out) { - if (is_Cmp(node)) - return get_flags_node_cmp(node, cc_out); - assert(get_irn_mode(node) == mode_b); - return get_flags_mode_b(node, cc_out); + assert(is_Cmp(node)); + return get_flags_node_cmp(node, cc_out); } /** @@ -2240,7 +2174,7 @@ static ir_node *gen_Load(ir_node *node) assert((int)pn_ia32_xLoad_res == (int)pn_ia32_vfld_res && (int)pn_ia32_vfld_res == (int)pn_ia32_Load_res && (int)pn_ia32_Load_res == (int)pn_ia32_res); - arch_irn_add_flags(new_node, arch_irn_flags_rematerializable); + arch_add_irn_flags(new_node, arch_irn_flags_rematerializable); } SET_IA32_ORIG_NODE(new_node, node); @@ -2626,17 +2560,27 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) ir_node *ins[4]; ia32_address_t addr; - assert(size % 4 == 0); - assert(size <= 16); - build_address_ptr(&addr, ptr, mem); 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); + unsigned val; + unsigned delta; + ir_mode *mode; + if (size >= 4) { + 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); + delta = 4; + mode = mode_Iu; + } else if (size >= 2) { + val= get_tarval_sub_bits(tv, ofs) | + (get_tarval_sub_bits(tv, ofs + 1) << 8); + delta = 2; + mode = mode_Hu; + } else { + panic("invalid size of Store float to mem (%+F)", node); + } ir_node *imm = ia32_create_Immediate(NULL, 0, val); ir_node *new_node = new_bd_ia32_Store(dbgi, new_block, addr.base, @@ -2646,16 +2590,16 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) ir_set_throws_exception(new_node, throws_exception); 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_ia32_ls_mode(new_node, mode); set_address(new_node, &addr); SET_IA32_ORIG_NODE(new_node, node); assert(i < 4); ins[i++] = new_mem; - size -= 4; - ofs += 4; - addr.offset += 4; + size -= delta; + ofs += delta; + addr.offset += delta; } while (size != 0); if (i > 1) { @@ -2675,7 +2619,7 @@ static ir_node *gen_vfist(dbg_info *dbgi, ir_node *block, ir_node *base, /* Note: fisttp ALWAYS pop the tos. We have to ensure here that the value is copied if other users exists */ ir_node *vfisttp = new_bd_ia32_vfisttp(dbgi, block, base, index, mem, val); - ir_node *value = new_r_Proj(vfisttp, mode_E, pn_ia32_vfisttp_res); + ir_node *value = new_r_Proj(vfisttp, ia32_mode_E, pn_ia32_vfisttp_res); be_new_Keep(block, 1, &value); return vfisttp; @@ -2793,8 +2737,8 @@ static ir_node *gen_general_Store(ir_node *node) */ static ir_node *gen_Store(ir_node *node) { - ir_node *val = get_Store_value(node); - ir_mode *mode = get_irn_mode(val); + ir_node *val = get_Store_value(node); + ir_mode *mode = get_irn_mode(val); if (mode_is_float(mode) && is_Const(val)) { /* We can transform every floating const store @@ -3017,7 +2961,8 @@ static bool upper_bits_clean(ir_node *transformed_node, ir_mode *mode) return shifted == 0 || shifted == -1; } else { unsigned long shifted = (unsigned long)attr->offset; - shifted >>= get_mode_size_bits(mode); + shifted >>= get_mode_size_bits(mode)-1; + shifted >>= 1; return shifted == 0; } } @@ -3251,7 +3196,7 @@ static ir_entity *ia32_create_const_array(ir_node *c0, ir_node *c1, ir_mode **ne } - tp = ia32_create_float_type(mode, 4); + tp = ia32_get_prim_type(mode); tp = ia32_create_float_array(tp); ent = new_entity(get_glob_type(), id_unique("C%u"), tp); @@ -3441,13 +3386,13 @@ static ir_node *gen_Mux(ir_node *node) assert(get_irn_mode(sel) == mode_b); - is_abs = ir_mux_is_abs(sel, mux_true, mux_false); + is_abs = ir_mux_is_abs(sel, mux_false, mux_true); if (is_abs != 0) { if (ia32_mode_needs_gp_reg(mode)) { ir_fprintf(stderr, "Optimisation warning: Integer abs %+F not transformed\n", node); } else { - ir_node *op = ir_get_abs_op(sel, mux_true, mux_false); + ir_node *op = ir_get_abs_op(sel, mux_false, mux_true); return create_float_abs(dbgi, block, op, is_abs < 0, node); } } @@ -3501,31 +3446,15 @@ static ir_node *gen_Mux(ir_node *node) am.addr.symconst_ent = ia32_create_const_array(mux_false, mux_true, &new_mode); - switch (get_mode_size_bytes(new_mode)) { - case 4: + if (new_mode == mode_F) { scale = 2; - break; - case 8: + } else if (new_mode == mode_D) { scale = 3; - break; - case 10: - /* use 2 * 5 */ - scale = 1; - new_node = new_bd_ia32_Lea(dbgi, new_block, new_node, new_node); - set_ia32_am_scale(new_node, 2); - break; - case 12: - /* use 4 * 3 */ - scale = 2; - new_node = new_bd_ia32_Lea(dbgi, new_block, new_node, new_node); - set_ia32_am_scale(new_node, 1); - break; - case 16: + } else if (new_mode == ia32_mode_E) { /* arg, shift 16 NOT supported */ scale = 3; new_node = new_bd_ia32_Lea(dbgi, new_block, new_node, new_node); - break; - default: + } else { panic("Unsupported constant size"); } @@ -3650,7 +3579,6 @@ static ir_node *gen_Mux(ir_node *node) } } - /** * Create a conversion from x87 state register to general purpose. */ @@ -3727,7 +3655,7 @@ static ir_node *gen_x87_strict_conv(ir_mode *tgt_mode, ir_node *node) set_ia32_op_type(load, ia32_AddrModeS); SET_IA32_ORIG_NODE(load, node); - new_node = new_r_Proj(load, mode_E, pn_ia32_vfld_res); + new_node = new_r_Proj(load, ia32_mode_E, pn_ia32_vfld_res); return new_node; } @@ -3925,7 +3853,7 @@ static ir_node *gen_Conv(ir_node *node) } } else { /* this should be optimized already, but who knows... */ - DEBUG_ONLY(ir_fprintf(stderr, "Debug warning: conv %+F is pointless\n", node)); + DEBUG_ONLY(ir_fprintf(stderr, "Debug warning: conv %+F is pointless\n", node);) DB((dbg, LEVEL_1, "killed Conv(mode, mode) ...")); return be_transform_node(op); } @@ -3981,7 +3909,7 @@ static ir_node *gen_Conv(ir_node *node) set_ia32_ls_mode(res, tgt_mode); } else { unsigned int_mantissa = get_mode_size_bits(src_mode) - (mode_is_signed(src_mode) ? 1 : 0); - unsigned float_mantissa = tarval_ieee754_get_mantissa_size(tgt_mode); + unsigned float_mantissa = get_mode_mantissa_size(tgt_mode); res = gen_x87_gp_to_fp(node, src_mode); /* we need a strict-Conv, if the int mode has more bits than the @@ -4137,8 +4065,8 @@ static ir_node *gen_be_AddSP(ir_node *node) ir_node *new_node = gen_binop(node, sp, sz, new_bd_ia32_SubSP, match_am | match_immediate); assert(is_ia32_SubSP(new_node)); - arch_irn_set_register(new_node, pn_ia32_SubSP_stack, - &ia32_registers[REG_ESP]); + arch_set_irn_register_out(new_node, pn_ia32_SubSP_stack, + &ia32_registers[REG_ESP]); return new_node; } @@ -4153,8 +4081,8 @@ static ir_node *gen_be_SubSP(ir_node *node) ir_node *new_node = gen_binop(node, sp, sz, new_bd_ia32_AddSP, match_am | match_immediate); assert(is_ia32_AddSP(new_node)); - arch_irn_set_register(new_node, pn_ia32_AddSP_stack, - &ia32_registers[REG_ESP]); + arch_set_irn_register_out(new_node, pn_ia32_AddSP_stack, + &ia32_registers[REG_ESP]); return new_node; } @@ -4195,7 +4123,7 @@ static ir_node *gen_Phi(ir_node *node) copy_node_attr(irg, node, phi); be_duplicate_deps(node, phi); - arch_set_out_register_req(phi, 0, req); + arch_set_irn_register_req_out(phi, 0, req); be_enqueue_preds(node); @@ -4837,7 +4765,8 @@ static ir_node *gen_be_Call(ir_node *node) i = get_irn_arity(node) - 1; fpcw = be_transform_node(get_irn_n(node, i--)); for (; i >= n_be_Call_first_arg; --i) { - arch_register_req_t const *const req = arch_get_register_req(node, i); + arch_register_req_t const *const req + = arch_get_irn_register_req_in(node, i); ir_node *const reg_parm = be_transform_node(get_irn_n(node, i)); assert(req->type == arch_register_req_type_limited); @@ -4933,7 +4862,7 @@ static ir_node *gen_return_address(ir_node *node) assert((int)pn_ia32_xLoad_res == (int)pn_ia32_vfld_res && (int)pn_ia32_vfld_res == (int)pn_ia32_Load_res && (int)pn_ia32_Load_res == (int)pn_ia32_res); - arch_irn_add_flags(load, arch_irn_flags_rematerializable); + arch_add_irn_flags(load, arch_irn_flags_rematerializable); } SET_IA32_ORIG_NODE(load, node); @@ -4984,7 +4913,7 @@ static ir_node *gen_frame_address(ir_node *node) assert((int)pn_ia32_xLoad_res == (int)pn_ia32_vfld_res && (int)pn_ia32_vfld_res == (int)pn_ia32_Load_res && (int)pn_ia32_Load_res == (int)pn_ia32_res); - arch_irn_add_flags(load, arch_irn_flags_rematerializable); + arch_add_irn_flags(load, arch_irn_flags_rematerializable); } SET_IA32_ORIG_NODE(load, node); @@ -5187,6 +5116,8 @@ static ir_node *gen_parity(ir_node *node) ir_node *xor2 = new_bd_ia32_XorHighLow(dbgi, new_block, xor); ir_node *flags; + set_ia32_commutative(xor); + set_irn_mode(xor2, mode_T); flags = new_r_Proj(xor2, mode_Iu, pn_ia32_XorHighLow_flags); @@ -5569,7 +5500,7 @@ static ir_node *gen_Proj_Builtin(ir_node *proj) static ir_node *gen_be_IncSP(ir_node *node) { ir_node *res = be_duplicate_node(node); - arch_irn_add_flags(res, arch_irn_flags_modify_flags); + arch_add_irn_flags(res, arch_irn_flags_modify_flags); return res; } @@ -5591,7 +5522,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node) } /* transform call modes */ if (mode_is_data(mode)) { - const arch_register_class_t *cls = arch_get_irn_reg_class_out(node); + const arch_register_class_t *cls = arch_get_irn_reg_class(node); mode = cls->mode; } @@ -5605,8 +5536,8 @@ static ir_node *gen_Proj_be_Call(ir_node *node) } else if (proj == pn_be_Call_X_regular) { proj = pn_ia32_Call_X_regular; } else { - arch_register_req_t const *const req = arch_get_register_req_out(node); - int const n_outs = arch_irn_get_n_outs(new_call); + arch_register_req_t const *const req = arch_get_irn_register_req(node); + int const n_outs = arch_get_irn_n_outs(new_call); int i; assert(proj >= pn_be_Call_first_res); @@ -5614,7 +5545,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node) for (i = 0; i < n_outs; ++i) { arch_register_req_t const *const new_req - = arch_get_out_register_req(new_call, i); + = arch_get_irn_register_req_out(new_call, i); if (!(new_req->type & arch_register_req_type_limited) || new_req->cls != req->cls || @@ -5661,11 +5592,11 @@ static ir_node *gen_Proj_ASM(ir_node *node) long pos = get_Proj_proj(node); if (mode == mode_M) { - pos = arch_irn_get_n_outs(new_pred)-1; + pos = arch_get_irn_n_outs(new_pred)-1; } else if (mode_is_int(mode) || mode_is_reference(mode)) { mode = mode_Iu; } else if (mode_is_float(mode)) { - mode = mode_E; + mode = ia32_mode_E; } else { panic("unexpected proj mode at ASM"); } @@ -5887,7 +5818,11 @@ static void postprocess_fp_call_results(void) assert((long)pn_ia32_xStore_X_except == (long)pn_ia32_vfst_X_except); exchange(succ, st); - } else if (new_res == NULL) { + + continue; + } + + if (new_res == NULL) { dbg_info *db = get_irn_dbg_info(call); ir_node *block = get_nodes_block(call); ir_node *frame = get_irg_frame(current_ir_graph);