X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_transform.c;h=ec1bcfde3a47bc042367d7d8c07a04b275302069;hb=ad7bf85c4c61ebcd417ce5ce81cbb314bac4b697;hp=17f65beb9df96518118bdedafc4eb2b45eb5d823;hpb=4e93e1cb7409412d405d9c4d06a54f5098021092;p=libfirm diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 17f65beb9..ec1bcfde3 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -42,6 +42,7 @@ #include "../benode_t.h" #include "../beirg_t.h" +#include "../beutil.h" #include "../betranshlp.h" #include "bearch_arm_t.h" @@ -131,10 +132,9 @@ static void gen_vals_from_word(unsigned int value, vals *result) /** * Creates a arm_Const node. */ -static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) { - tarval *tv = new_tarval_from_long(value, mode_Iu); - dbg_info *dbg = get_irn_dbg_info(irn); - ir_mode *mode = get_irn_mode(irn); +static ir_node *create_const_node(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, long value) { + ir_mode *mode = mode_Iu; + tarval *tv = new_tarval_from_long(value, mode); ir_node *res; if (mode_needs_gp_reg(mode)) @@ -148,10 +148,9 @@ static ir_node *create_const_node(be_abi_irg_t *abi, ir_node *irn, ir_node *bloc /** * Creates a arm_Const_Neg node. */ -static ir_node *create_const_neg_node(be_abi_irg_t *abi, ir_node *irn, ir_node *block, long value) { - tarval *tv = new_tarval_from_long(value, mode_Iu); - dbg_info *dbg = get_irn_dbg_info(irn); - ir_mode *mode = get_irn_mode(irn); +static ir_node *create_const_neg_node(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, long value) { + ir_mode *mode = mode_Iu; + tarval *tv = new_tarval_from_long(value, mode); ir_node *res; if (mode_needs_gp_reg(mode)) @@ -184,35 +183,31 @@ unsigned int arm_decode_imm_w_shift(tarval *tv) { /** * Creates a possible DAG for an constant. */ -static ir_node *create_const_graph_value(be_abi_irg_t *abi, ir_node *irn, ir_node *block, unsigned int value) { +static ir_node *create_const_graph_value(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, unsigned int value) { ir_node *result; vals v, vn; int cnt; - ir_mode *mode = get_irn_mode(irn); - dbg_info *dbg = get_irn_dbg_info(irn); + ir_mode *mode = mode_Iu; gen_vals_from_word(value, &v); gen_vals_from_word(~value, &vn); - if (mode_needs_gp_reg(mode)) - mode = mode_Iu; - if (vn.ops < v.ops) { /* remove bits */ - result = create_const_neg_node(abi, irn, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); + result = create_const_neg_node(abi, dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); for (cnt = 1; cnt < vn.ops; ++cnt) { - tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode_Iu); + tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]), mode); ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode, tv); result = bic_i_node; } } else { /* add bits */ - result = create_const_node(abi, irn, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0])); + result = create_const_node(abi, dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0])); for (cnt = 1; cnt < v.ops; ++cnt) { - tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode_Iu); + tarval *tv = new_tarval_from_long(arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]), mode); ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode, tv); result = orr_i_node; } @@ -236,25 +231,27 @@ static ir_node *create_const_graph(be_abi_irg_t *abi, ir_node *irn, ir_node *blo tv = tarval_convert_to(tv, mode_Iu); } value = get_tarval_long(tv); - return create_const_graph_value(abi, irn, block, value); + return create_const_graph_value(abi, get_irn_dbg_info(irn), block, value); } -static ir_node *gen_mask(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) { - ir_node *block = get_nodes_block(irn); +/** + * Create an And that will mask all upper bits + */ +static ir_node *gen_zero_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) { unsigned mask_bits = (1 << result_bits) - 1; - ir_node *mask_node = create_const_graph_value(abi, irn, block, mask_bits); - dbg_info *dbg = get_irn_dbg_info(irn); - return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, get_irn_mode(irn), ARM_SHF_NONE, NULL); + ir_node *mask_node = create_const_graph_value(abi, dbg, block, mask_bits); + return new_rd_arm_And(dbg, current_ir_graph, block, op, mask_node, mode_Iu, ARM_SHF_NONE, NULL); } -static ir_node *gen_sign_extension(be_abi_irg_t *abi, ir_node *irn, ir_node *op, int result_bits) { - ir_node *block = get_nodes_block(irn); +/** + * Generate code for a sign extension. + */ +static ir_node *gen_sign_extension(be_abi_irg_t *abi, dbg_info *dbg, ir_node *block, ir_node *op, int result_bits) { + ir_graph *irg = current_ir_graph; int shift_width = 32 - result_bits; - ir_graph *irg = current_ir_graph; - ir_node *shift_const_node = create_const_graph_value(abi, irn, block, shift_width); - dbg_info *dbg = get_irn_dbg_info(irn); - ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, get_irn_mode(op)); - ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, get_irn_mode(irn)); + ir_node *shift_const_node = create_const_graph_value(abi, dbg, block, shift_width); + ir_node *lshift_node = new_rd_arm_Shl(dbg, irg, block, op, shift_const_node, mode_Iu); + ir_node *rshift_node = new_rd_arm_Shrs(dbg, irg, block, lshift_node, shift_const_node, mode_Iu); return rshift_node; } @@ -272,9 +269,6 @@ static ir_node *gen_Conv(ir_node *node) { ir_mode *dst_mode = get_irn_mode(node); dbg_info *dbg = get_irn_dbg_info(node); - if (mode_needs_gp_reg(dst_mode)) - dst_mode = mode_Iu; - if (src_mode == dst_mode) return new_op; @@ -309,64 +303,38 @@ static ir_node *gen_Conv(ir_node *node) { else { /* complete in gp registers */ int src_bits = get_mode_size_bits(src_mode); int dst_bits = get_mode_size_bits(dst_mode); - int src_sign = get_mode_sign(src_mode); - int dst_sign = get_mode_sign(dst_mode); + int min_bits; + ir_mode *min_mode; - if (src_bits == dst_bits) { - /* kill 32 -> 32 convs */ - if (src_bits == 32) { + if (is_Load(skip_Proj(op))) { + if (src_bits == dst_bits) { + /* kill unneccessary conv */ return new_op; - } else if (dst_bits < 32) { - // 16 -> 16 - // unsigned -> unsigned - // NOP - // unsigned -> signed - // sign extension (31:16)=(15) - // signed -> unsigned - // zero extension (31:16)=0 - // signed -> signed - // NOP - if (src_sign && !dst_sign) { - return gen_mask(env_cg->birg->abi, node, new_op, dst_bits); - } else { - return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits); - } - } else { - panic("Cannot handle mode %+F with %d bits\n", dst_mode, dst_bits); - return NULL; } + /* after a load, the bit size is already converted */ + src_bits = 32; } - else if (src_bits < dst_bits) { - // 16 -> 32 - // unsigned -> unsigned - // NOP - // unsigned -> signed - // NOP - // signed -> unsigned - // sign extension (31:16)=(15) - // signed -> signed - // sign extension (31:16)=(15) - if (src_sign) { - return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits); + + if (src_bits == dst_bits) { + /* kill unneccessary conv */ + return new_op; + } else if (dst_bits <= 32 && src_bits <= 32) { + if (src_bits < dst_bits) { + min_bits = src_bits; + min_mode = src_mode; } else { - return new_op; + min_bits = dst_bits; + min_mode = dst_mode; } - } - else { - // 32 -> 16 - // unsigned -> unsigned - // maskieren (31:16)=0 - // unsigned -> signed - // maskieren (31:16)=0 - // signed -> unsigned - // maskieren (31:16)=0 - // signed -> signed - // sign extension (erledigt auch maskieren) (31:16)=(15) - if (src_sign && dst_sign) { - return gen_sign_extension(env_cg->birg->abi, node, new_op, dst_bits); + if (mode_is_signed(min_mode)) { + return gen_sign_extension(env_cg->birg->abi, dbg, block, new_op, min_bits); } else { - return gen_mask(env_cg->birg->abi, node, new_op, dst_bits); + return gen_zero_extension(env_cg->birg->abi, dbg, block, new_op, min_bits); } + } else { + panic("Cannot handle Conv %+F->%+F with %d->%d bits\n", src_mode, dst_mode, + src_bits, dst_bits); + return NULL; } } } @@ -422,6 +390,7 @@ static ir_node *gen_Add(ir_node *node) { } } else { assert(mode_is_numP(mode)); + mode = mode_Iu; if (is_arm_Mov_i(new_op1)) return new_rd_arm_Add_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); @@ -484,12 +453,15 @@ static ir_node *gen_Mul(ir_node *node) { else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet\n"); + return NULL; } else { panic("Softfloat not supported yet\n"); return NULL; } } + assert(mode_is_numP(mode)); + mode = mode_Iu; return new_rd_arm_Mul(dbg, irg, block, new_op1, new_op2, mode); } @@ -530,7 +502,7 @@ static ir_node *gen_Quot(ir_node *node) { ir_node *op2 = get_ ## op ## _right(node); \ ir_node *new_op2 = be_transform_node(op2); \ ir_graph *irg = current_ir_graph; \ - ir_mode *mode = get_irn_mode(node); \ + ir_mode *mode = mode_Iu; \ dbg_info *dbg = get_irn_dbg_info(node); \ int v; \ arm_shift_modifier mod; \ @@ -615,6 +587,7 @@ static ir_node *gen_Sub(ir_node *node) { } else { assert(mode_is_numP(mode) && "unknown mode for Sub"); + mode = mode_Iu; if (is_arm_Mov_i(new_op1)) return new_rd_arm_Rsb_i(dbg, irg, block, new_op2, mode, get_arm_value(new_op1)); @@ -649,7 +622,7 @@ static ir_node *gen_Shl(ir_node *node) { ir_node *new_op1 = be_transform_node(op1); ir_node *op2 = get_Shl_right(node); ir_node *new_op2 = be_transform_node(op2); - ir_mode *mode = get_irn_mode(node); + ir_mode *mode = mode_Iu; dbg_info *dbg = get_irn_dbg_info(node); if (is_arm_Mov_i(new_op2)) { @@ -669,7 +642,7 @@ static ir_node *gen_Shr(ir_node *node) { ir_node *new_op1 = be_transform_node(op1); ir_node *op2 = get_Shr_right(node); ir_node *new_op2 = be_transform_node(op2); - ir_mode *mode = get_irn_mode(node); + ir_mode *mode = mode_Iu; dbg_info *dbg = get_irn_dbg_info(node); if (is_arm_Mov_i(new_op2)) { @@ -689,11 +662,11 @@ static ir_node *gen_Shrs(ir_node *node) { ir_node *new_op1 = be_transform_node(op1); ir_node *op2 = get_Shrs_right(node); ir_node *new_op2 = be_transform_node(op2); - ir_mode *mode = get_irn_mode(node); + ir_mode *mode = mode_Iu; dbg_info *dbg = get_irn_dbg_info(node); if (is_arm_Mov_i(new_op2)) { - return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(op2)); + return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ASR, get_arm_value(new_op2)); } return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode); } @@ -709,6 +682,7 @@ static ir_node *gen_Not(ir_node *node) { ir_node *new_op = be_transform_node(op); dbg_info *dbg = get_irn_dbg_info(node); tarval *tv = NULL; + ir_mode *mode = mode_Iu; arm_shift_modifier mod = ARM_SHF_NONE; int v = is_shifter_operand(new_op, &mod); @@ -716,7 +690,7 @@ static ir_node *gen_Not(ir_node *node) { new_op = get_irn_n(new_op, 0); tv = new_tarval_from_long(v, mode_Iu); } - return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, get_irn_mode(node), mod, tv); + return new_rd_arm_Mvn(dbg, current_ir_graph, block, new_op, mode, mod, tv); } /** @@ -727,7 +701,7 @@ static ir_node *gen_Not(ir_node *node) { */ static ir_node *gen_Abs(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *op = get_Not_op(node); + ir_node *op = get_Abs_op(node); ir_node *new_op = be_transform_node(op); dbg_info *dbg = get_irn_dbg_info(node); ir_mode *mode = get_irn_mode(node); @@ -744,6 +718,8 @@ static ir_node *gen_Abs(ir_node *node) { panic("Softfloat not supported yet\n"); } } + assert(mode_is_numP(mode)); + mode = mode_Iu; return new_rd_arm_Abs(dbg, current_ir_graph, block, new_op, mode); } @@ -771,6 +747,8 @@ static ir_node *gen_Minus(ir_node *node) { panic("Softfloat not supported yet\n"); } } + assert(mode_is_numP(mode)); + mode = mode_Iu; return new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op, mode, get_mode_null(mode)); } @@ -810,9 +788,12 @@ static ir_node *gen_Load(ir_node *node) { switch (get_mode_size_bits(mode)) { case 8: new_load = new_rd_arm_Loadbs(dbg, irg, block, new_ptr, new_mem); + break; case 16: new_load = new_rd_arm_Loadhs(dbg, irg, block, new_ptr, new_mem); + break; case 32: + new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); break; default: panic("mode size not supported\n"); @@ -822,17 +803,27 @@ static ir_node *gen_Load(ir_node *node) { switch (get_mode_size_bits(mode)) { case 8: new_load = new_rd_arm_Loadb(dbg, irg, block, new_ptr, new_mem); + break; case 16: new_load = new_rd_arm_Loadh(dbg, irg, block, new_ptr, new_mem); + break; case 32: + new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); break; default: panic("mode size not supported\n"); } } - new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); } set_irn_pinned(new_load, get_irn_pinned(node)); + + /* check for special case: the loaded value might not be used */ + if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) { + /* add a result proj and a Keep to produce a pseudo use */ + ir_node *proj = new_r_Proj(irg, block, new_load, mode_Iu, pn_arm_Load_res); + be_new_Keep(arch_get_irn_reg_class(env_cg->arch_env, proj, -1), irg, block, 1, &proj); + } + return new_load; } @@ -935,7 +926,7 @@ static ir_node *gen_Cond(ir_node *node) { } - const_graph = create_const_graph_value(env_cg->birg->abi, node, block, translation); + const_graph = create_const_graph_value(env_cg->birg->abi, dbg, block, translation); sub = new_rd_arm_Sub(dbg, irg, block, new_op, const_graph, mode, ARM_SHF_NONE, NULL); return new_rd_arm_SwitchJmp(dbg, irg, block, sub, n_projs, get_Cond_defaultProj(node) - translation); } @@ -1002,7 +993,7 @@ static ir_node *gen_Const(ir_node *node) { */ static ir_node *gen_SymConst(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); - ir_mode *mode = get_irn_mode(node); + ir_mode *mode = mode_Iu; dbg_info *dbg = get_irn_dbg_info(node); ir_node *res; @@ -1120,8 +1111,8 @@ static ir_node *gen_be_FrameAddr(ir_node *node) { int offset = get_entity_offset(ent); ir_node *op = be_get_FrameAddr_frame(node); ir_node *new_op = be_transform_node(op); - ir_mode *mode = get_irn_mode(node); dbg_info *dbg = get_irn_dbg_info(node); + ir_mode *mode = mode_Iu; ir_node *cnst; if (be_is_IncSP(op)) { @@ -1129,7 +1120,7 @@ static ir_node *gen_be_FrameAddr(ir_node *node) { is relative. Both must be merged */ offset += get_sp_expand_offset(op); } - cnst = create_const_graph_value(env_cg->birg->abi, node, block, (unsigned)offset); + cnst = create_const_graph_value(env_cg->birg->abi, dbg, block, (unsigned)offset); if (is_arm_Mov_i(cnst)) return new_rd_arm_Add_i(dbg, current_ir_graph, block, new_op, mode, get_arm_value(cnst)); return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, NULL); @@ -1384,6 +1375,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) { * Transform the Projs from a Cmp. */ static ir_node *gen_Proj_Cmp(ir_node *node) { + (void) node; panic("Psi NYI\n"); } @@ -1464,8 +1456,9 @@ static ir_node *gen_Proj(ir_node *node) { * is an "ignore" node. */ static ir_node *gen_Unknown(ir_node *node) { + (void) node; + /* ir_mode *mode = get_irn_mode(node); -/* if (mode_is_float(mode)) { if (USE_FPA(env_cg->isa)) return arm_new_Unknown_fpa(env_cg); @@ -1548,7 +1541,6 @@ static void arm_register_transformers(void) { #define GEN(a) set_transformer(op_##a, gen_##a) #define BAD(a) set_transformer(op_##a, bad_transform) -#define IGN(a) GEN(Add); GEN(Sub); @@ -1585,9 +1577,6 @@ static void arm_register_transformers(void) { GEN(Proj); GEN(Phi); - IGN(Block); - IGN(End); - GEN(Const); GEN(SymConst); @@ -1630,7 +1619,6 @@ static void arm_register_transformers(void) { if (op_Mulh) BAD(Mulh); /* unsupported yet */ -#undef IGN #undef GEN #undef BAD } @@ -1640,6 +1628,7 @@ static void arm_register_transformers(void) { */ static void arm_pretransform_node(void *arch_cg) { arm_code_gen_t *cg = arch_cg; + (void) cg; } /**