X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_transform.c;h=48f40127868e42b424d20695aab24f5a1ac7e914;hb=65f6cc39305e6880fe45709a8a2e1c24445395e3;hp=8144253bd360d296f646bfa8abc612fe88e99741;hpb=99ba6c297269d17b31574fedc5618dd0a7ae8b0c;p=libfirm diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 8144253bd..48f401278 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -447,8 +447,7 @@ const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) { } #endif /* NDEBUG */ -static int use_source_address_mode(ir_node *block, ir_node *node, - ir_node *other) +int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other) { ir_mode *mode; ir_node *load; @@ -553,7 +552,8 @@ typedef enum { match_commutative = 1 << 0, match_am_and_immediates = 1 << 1, match_no_am = 1 << 2, - match_8_16_bit_am = 1 << 3 + match_8_16_bit_am = 1 << 3, + match_no_immediate = 1 << 4 } match_flags_t; static void match_arguments(ia32_address_mode_t *am, ir_node *block, @@ -566,20 +566,27 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, int use_am; int commutative; int use_am_and_immediates; + int use_immediate; memset(am, 0, sizeof(am[0])); commutative = (flags & match_commutative) != 0; use_am_and_immediates = (flags & match_am_and_immediates) != 0; use_am = ! (flags & match_no_am); + use_immediate = !(flags & match_no_immediate); + + assert(op2 != NULL); + assert(!commutative || op1 != NULL); + if(!(flags & match_8_16_bit_am) + && op1 != NULL && get_mode_size_bits(get_irn_mode(op1)) < 32) use_am = 0; - new_op2 = try_create_Immediate(op2, 0); + new_op2 = (use_immediate ? try_create_Immediate(op2, 0) : NULL); if(new_op2 == NULL && use_am && use_source_address_mode(block, op2, op1)) { build_address(am, op2); - new_op1 = be_transform_node(op1); + new_op1 = (op1 == NULL ? NULL : be_transform_node(op1)); new_op2 = noreg_gp; am->op_type = ia32_AddrModeS; } else if(commutative && (new_op2 == NULL || use_am_and_immediates) && @@ -594,7 +601,7 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block, } am->op_type = ia32_AddrModeS; } else { - new_op1 = be_transform_node(op1); + new_op1 = (op1 == NULL ? NULL : be_transform_node(op1)); if(new_op2 == NULL) new_op2 = be_transform_node(op2); am->op_type = ia32_Normal; @@ -1620,8 +1627,8 @@ static ir_node *gen_Load(ir_node *node) { /* create a conv node with address mode for smaller modes */ if(get_mode_size_bits(mode) < 32) { - new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index, new_mem, - noreg, mode); + new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index, + new_mem, noreg, mode); } else { new_op = new_rd_ia32_Load(dbgi, irg, block, base, index, new_mem); } @@ -2145,7 +2152,8 @@ static ir_node *try_create_Test(ir_node *node) if(!is_Const_0(cmp_right)) return NULL; - if(is_And(cmp_left) && can_fold_test_and(node)) { + if(is_And(cmp_left) && get_irn_n_edges(cmp_left) == 1 && + can_fold_test_and(node)) { ir_node *and_left = get_And_left(cmp_left); ir_node *and_right = get_And_right(cmp_left); @@ -2455,18 +2463,47 @@ static ir_node *gen_x87_strict_conv(ir_mode *tgt_mode, ir_node *node) * Create a conversion from general purpose to x87 register */ static ir_node *gen_x87_gp_to_fp(ir_node *node, ir_mode *src_mode) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *op = get_Conv_op(node); - ir_node *new_op = be_transform_node(op); - ir_graph *irg = current_ir_graph; - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *noreg = ia32_new_NoReg_gp(env_cg); - ir_node *nomem = new_NoMem(); - ir_mode *mode = get_irn_mode(op); - ir_mode *store_mode; - ir_node *fild, *store; - ir_node *res; - int src_bits; + ir_node *src_block = get_nodes_block(node); + ir_node *block = be_transform_node(src_block); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *op = get_Conv_op(node); + ir_node *new_op; + ir_node *noreg; + ir_node *nomem; + ir_mode *mode; + ir_mode *store_mode; + ir_node *fild; + ir_node *store; + ir_node *res; + int src_bits; + + /* fild can use source AM if the operand is a signed 32bit integer */ + if (src_mode == mode_Is) { + ia32_address_mode_t am; + + match_arguments(&am, src_block, NULL, op, match_no_immediate); + if (am.op_type == ia32_AddrModeS) { + ia32_address_t *addr = &am.addr; + + fild = new_rd_ia32_vfild(dbgi, irg, block, addr->base, addr->index, addr->mem); + res = new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res); + + set_am_attributes(fild, &am); + SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node)); + + fix_mem_proj(fild, &am); + + return res; + } + new_op = am.new_op2; + } else { + new_op = be_transform_node(op); + } + + noreg = ia32_new_NoReg_gp(env_cg); + nomem = new_NoMem(); + mode = get_irn_mode(op); /* first convert to 32 bit signed if necessary */ src_bits = get_mode_size_bits(src_mode); @@ -2561,7 +2598,7 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode, new_op = noreg; am.op_type = ia32_AddrModeS; } else { - new_op = be_transform_node(op); + new_op = be_transform_node(op); am.op_type = ia32_Normal; } if(addr->base == NULL) @@ -3027,10 +3064,12 @@ void parse_asm_constraint(int pos, constraint_t *constraint, const char *c) case 'y': /* we don't support mmx registers yet */ case 'Z': /* not available in 32 bit mode */ case 'e': /* not available in 32 bit mode */ - assert(0 && "asm constraint not supported"); + panic("unsupported asm constraint '%c' found in (%+F)", + *c, current_ir_graph); break; default: - assert(0 && "unknown asm constraint found"); + panic("unknown asm constraint '%c' found in (%+F)", *c, + current_ir_graph); break; } ++c; @@ -3051,7 +3090,8 @@ void parse_asm_constraint(int pos, constraint_t *constraint, const char *c) req->cls = other_constr->cls; req->type = arch_register_req_type_should_be_same; req->limited = NULL; - req->other_same = pos; + req->other_same[0] = pos; + req->other_same[1] = -1; req->other_different = -1; /* switch constraints. This is because in firm we have same_as @@ -3788,32 +3828,47 @@ static ir_node *gen_ia32_l_IMul(ir_node *node) { return muls; } -static ir_node *gen_ia32_Add64Bit(ir_node *node) -{ - ir_node *a_l = be_transform_node(get_irn_n(node, 0)); - ir_node *a_h = be_transform_node(get_irn_n(node, 1)); - ir_node *b_l = create_immediate_or_transform(get_irn_n(node, 2), 0); - ir_node *b_h = create_immediate_or_transform(get_irn_n(node, 3), 0); - ir_node *block = be_transform_node(get_nodes_block(node)); - dbg_info *dbgi = get_irn_dbg_info(node); - ir_graph *irg = current_ir_graph; - ir_node *new_op = new_rd_ia32_Add64Bit(dbgi, irg, block, a_l, a_h, b_l, b_h); - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); - return new_op; +static ir_node *gen_ia32_l_Sub(ir_node *node) { + ir_node *left = get_irn_n(node, n_ia32_l_Sub_left); + ir_node *right = get_irn_n(node, n_ia32_l_Sub_right); + ir_node *lowered = gen_binop(node, left, right, new_rd_ia32_Sub, 0); + + if(is_Proj(lowered)) { + lowered = get_Proj_pred(lowered); + } else { + assert(is_ia32_Sub(lowered)); + set_irn_mode(lowered, mode_T); + } + + return lowered; } -static ir_node *gen_ia32_Sub64Bit(ir_node *node) -{ - ir_node *a_l = be_transform_node(get_irn_n(node, 0)); - ir_node *a_h = be_transform_node(get_irn_n(node, 1)); - ir_node *b_l = create_immediate_or_transform(get_irn_n(node, 2), 0); - ir_node *b_h = create_immediate_or_transform(get_irn_n(node, 3), 0); - ir_node *block = be_transform_node(get_nodes_block(node)); - dbg_info *dbgi = get_irn_dbg_info(node); - ir_graph *irg = current_ir_graph; - ir_node *new_op = new_rd_ia32_Sub64Bit(dbgi, irg, block, a_l, a_h, b_l, b_h); - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); - return new_op; +static ir_node *gen_ia32_l_Sbb(ir_node *node) { + ir_node *src_block = get_nodes_block(node); + ir_node *block = be_transform_node(src_block); + ir_node *op1 = get_irn_n(node, n_ia32_l_Sbb_left); + ir_node *op2 = get_irn_n(node, n_ia32_l_Sbb_right); + ir_node *flags = get_irn_n(node, n_ia32_l_Sbb_eflags); + ir_node *new_flags = be_transform_node(flags); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *new_node; + ia32_address_mode_t am; + ia32_address_t *addr = &am.addr; + + match_arguments(&am, src_block, op1, op2, match_commutative); + + new_node = new_rd_ia32_Sbb(dbgi, irg, block, addr->base, addr->index, + addr->mem, am.new_op1, am.new_op2, new_flags); + set_am_attributes(new_node, &am); + /* we can't use source address mode anymore when using immediates */ + if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2)) + set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none); + SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node)); + + new_node = fix_mem_proj(new_node, &am); + + return new_node; } /** @@ -4499,8 +4554,6 @@ static void register_transformers(void) GEN(IJmp); /* transform ops from intrinsic lowering */ - GEN(ia32_Add64Bit); - GEN(ia32_Sub64Bit); GEN(ia32_l_Add); GEN(ia32_l_Adc); GEN(ia32_l_Neg); @@ -4512,6 +4565,8 @@ static void register_transformers(void) GEN(ia32_l_SarDep); GEN(ia32_l_ShlD); GEN(ia32_l_ShrD); + GEN(ia32_l_Sub); + GEN(ia32_l_Sbb); GEN(ia32_l_vfdiv); GEN(ia32_l_vfprem); GEN(ia32_l_vfmul); @@ -4654,14 +4709,18 @@ void ia32_add_missing_keeps(ia32_code_gen_t *cg) /* do the transformation */ void ia32_transform_graph(ia32_code_gen_t *cg) { + ir_graph *irg = cg->irg; + register_transformers(); env_cg = cg; initial_fpcw = NULL; - heights = heights_new(cg->irg); + heights = heights_new(irg); + calculate_non_address_mode_nodes(irg); be_transform_graph(cg->birg, ia32_pretransform_node, cg); + free_non_address_mode_nodes(); heights_free(heights); heights = NULL; }