X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_transform.c;h=aa376a9112343da59e6d3ff4d96884620b420be7;hb=1872920c09708b361d06c0dc9f4c1fd0a03544f5;hp=2ef801958e7d1f878639a674796a6ddd899e92de;hpb=ede86ffb1270f07437edcc8ea3dd5d46530f93eb;p=libfirm diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 2ef801958..aa376a911 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -49,6 +49,7 @@ #include "arm_nodes_attr.h" #include "archop.h" #include "arm_transform.h" +#include "arm_optimize.h" #include "arm_new_nodes.h" #include "arm_map_regs.h" @@ -77,62 +78,10 @@ static INLINE int mode_needs_gp_reg(ir_mode *mode) { return mode_is_int(mode) || mode_is_reference(mode); } -typedef struct vals_ { - int ops; - unsigned char values[4]; - unsigned char shifts[4]; -} vals; - -/** Execute ROL. */ -static unsigned do_rol(unsigned v, unsigned rol) { - return (v << rol) | (v >> (32 - rol)); -} - -/** - * construct 8bit values and rot amounts for a value - */ -static void gen_vals_from_word(unsigned int value, vals *result) -{ - int initial = 0; - - memset(result, 0, sizeof(*result)); - - /* special case: we prefer shift amount 0 */ - if (value < 0x100) { - result->values[0] = value; - result->ops = 1; - return; - } - - while (value != 0) { - if (value & 0xFF) { - unsigned v = do_rol(value, 8) & 0xFFFFFF; - int shf = 0; - for (;;) { - if ((v & 3) != 0) - break; - shf += 2; - v >>= 2; - } - v &= 0xFF; - shf = (initial + shf - 8) & 0x1F; - result->values[result->ops] = v; - result->shifts[result->ops] = shf; - ++result->ops; - - value ^= do_rol(v, shf) >> initial; - } - else { - value >>= 8; - initial += 8; - } - } -} - /** * Creates a arm_Const node. */ -static ir_node *create_const_node(dbg_info *dbg, ir_node *block, long value) { +static ir_node *create_mov_node(dbg_info *dbg, ir_node *block, long value) { ir_mode *mode = mode_Iu; ir_graph *irg = current_ir_graph; ir_node *res; @@ -148,7 +97,7 @@ static ir_node *create_const_node(dbg_info *dbg, ir_node *block, long value) { /** * Creates a arm_Const_Neg node. */ -static ir_node *create_const_neg_node(dbg_info *dbg, ir_node *block, long value) { +static ir_node *create_mvn_node(dbg_info *dbg, ir_node *block, long value) { ir_mode *mode = mode_Iu; ir_graph *irg = current_ir_graph; ir_node *res; @@ -163,38 +112,21 @@ static ir_node *create_const_neg_node(dbg_info *dbg, ir_node *block, long value) #define NEW_BINOP_NODE(opname, env, op1, op2) new_rd_arm_##opname(env->dbg, current_ir_graph, env->block, op1, op2, env->mode) -/** - * Encodes an immediate with shifter operand - */ -static unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate) { - return immediate | ((shift>>1)<<8); -} - -/** - * Decode an immediate with shifter operand - */ -unsigned int arm_decode_imm_w_shift(long imm_value) { - unsigned l = (unsigned)imm_value; - unsigned rol = (l & ~0xFF) >> 7; - - return do_rol(l & 0xFF, rol); -} - /** * Creates a possible DAG for an constant. */ static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned int value) { ir_node *result; - vals v, vn; + arm_vals v, vn; int cnt; ir_mode *mode = mode_Iu; - gen_vals_from_word(value, &v); - gen_vals_from_word(~value, &vn); + arm_gen_vals_from_word(value, &v); + arm_gen_vals_from_word(~value, &vn); if (vn.ops < v.ops) { /* remove bits */ - result = create_const_neg_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); + result = create_mvn_node(dbg, block, arm_encode_imm_w_shift(vn.shifts[0], vn.values[0])); for (cnt = 1; cnt < vn.ops; ++cnt) { long value = arm_encode_imm_w_shift(vn.shifts[cnt], vn.values[cnt]); @@ -204,7 +136,7 @@ static ir_node *create_const_graph_value(dbg_info *dbg, ir_node *block, unsigned } else { /* add bits */ - result = create_const_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0])); + result = create_mov_node(dbg, block, arm_encode_imm_w_shift(v.shifts[0], v.values[0])); for (cnt = 1; cnt < v.ops; ++cnt) { long value = arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]); @@ -292,11 +224,11 @@ static ir_node *gen_Conv(ir_node *node) { } } else if (USE_VFP(env_cg->isa)) { - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } @@ -332,7 +264,7 @@ static ir_node *gen_Conv(ir_node *node) { return gen_zero_extension(dbg, block, new_op, min_bits); } } else { - panic("Cannot handle Conv %+F->%+F with %d->%d bits\n", src_mode, dst_mode, + panic("Cannot handle Conv %+F->%+F with %d->%d bits", src_mode, dst_mode, src_bits, dst_bits); return NULL; } @@ -385,11 +317,11 @@ static ir_node *gen_Add(ir_node *node) { return new_rd_arm_fpaAdf(dbg, irg, block, new_op1, new_op2, mode); } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } else { @@ -461,11 +393,11 @@ 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"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } @@ -500,10 +432,10 @@ static ir_node *gen_Quot(ir_node *node) { return new_rd_arm_fpaDvf(dbg, current_ir_graph, block, new_op1, new_op2, mode); } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } @@ -594,11 +526,11 @@ static ir_node *gen_Sub(ir_node *node) { return new_rd_arm_fpaSuf(dbg, irg, block, new_op1, new_op2, mode); } else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); return NULL; } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); return NULL; } } @@ -688,6 +620,106 @@ static ir_node *gen_Shrs(ir_node *node) { return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode); } +/** + * Creates an ARM Ror. + * + * @return the created ARM Ror node + */ +static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_node *new_op2 = be_transform_node(op2); + 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_ROR, get_arm_imm_value(new_op2)); + } + return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode); +} + +/** + * Creates an ARM Rol. + * + * @return the created ARM Rol node + * + * Note: there is no Rol on arm, we have to use Ror + */ +static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *new_op2 = be_transform_node(op2); + + new_op2 = new_rd_arm_Rsb_i(dbg, current_ir_graph, block, new_op2, mode, 32); + return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode); +} + +/** + * Creates an ARM ROR from a Firm Rotl. + * + * @return the created ARM Ror node + */ +static ir_node *gen_Rotl(ir_node *node) { + ir_node *rotate = NULL; + ir_node *op1 = get_Rotl_left(node); + ir_node *op2 = get_Rotl_right(node); + + /* Firm has only RotL, so we are looking for a right (op2) + operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e", + that means we can create a RotR. */ + + if (is_Add(op2)) { + ir_node *right = get_Add_right(op2); + if (is_Const(right)) { + tarval *tv = get_Const_tarval(right); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + ir_node *left = get_Add_left(op2); + + if (is_Minus(left) && + tarval_is_long(tv) && + get_tarval_long(tv) == bits && + bits == 32) + rotate = gen_Ror(node, op1, get_Minus_op(left)); + } + } else if (is_Sub(op2)) { + ir_node *left = get_Sub_left(op2); + if (is_Const(left)) { + tarval *tv = get_Const_tarval(left); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + ir_node *right = get_Sub_right(op2); + + if (tarval_is_long(tv) && + get_tarval_long(tv) == bits && + bits == 32) + rotate = gen_Ror(node, op1, right); + } + } else if (is_Const(op2)) { + tarval *tv = get_Const_tarval(op2); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + + if (tarval_is_long(tv) && bits == 32) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + + bits = (bits - get_tarval_long(tv)) & 31; + rotate = new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, bits); + } + } + + if (rotate == NULL) { + rotate = gen_Rol(node, op1, op2); + } + + return rotate; +} + /** * Transforms a Not node. * @@ -727,10 +759,10 @@ static ir_node *gen_Abs(ir_node *node) { return new_rd_arm_fpaAbs(dbg, current_ir_graph, block, new_op, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } assert(mode_is_data(mode)); @@ -756,10 +788,10 @@ static ir_node *gen_Minus(ir_node *node) { return new_rd_arm_fpaMvf(dbg, current_ir_graph, block, op, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } assert(mode_is_data(mode)); @@ -789,10 +821,10 @@ static ir_node *gen_Load(ir_node *node) { new_load = new_rd_arm_fpaLdf(dbg, irg, block, new_ptr, new_mem, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } else { @@ -811,7 +843,7 @@ static ir_node *gen_Load(ir_node *node) { new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); break; default: - panic("mode size not supported\n"); + panic("mode size not supported"); } } else { /* zero extended loads */ @@ -826,7 +858,7 @@ static ir_node *gen_Load(ir_node *node) { new_load = new_rd_arm_Load(dbg, irg, block, new_ptr, new_mem); break; default: - panic("mode size not supported\n"); + panic("mode size not supported"); } } } @@ -866,9 +898,9 @@ static ir_node *gen_Store(ir_node *node) { new_store = new_rd_arm_fpaStf(dbg, irg, block, new_ptr, new_val, new_mem, mode); else if (USE_VFP(env_cg->isa)) { assert(mode != mode_E && "IEEE Extended FP not supported"); - panic("VFP not supported yet\n"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } else { assert(mode_is_data(mode) && "unsupported mode for Store"); @@ -903,9 +935,9 @@ static ir_node *gen_Cond(ir_node *node) { ir_node *op1 = get_Cmp_left(cmp_node); ir_node *new_op1 = be_transform_node(op1); ir_node *op2 = get_Cmp_right(cmp_node); - ir_node *new_op2 = be_transform_node(op2); if (mode_is_float(get_irn_mode(op1))) { + ir_node *new_op2 = be_transform_node(op2); /* floating point compare */ pn_Cmp pnc = get_Proj_proj(selector); @@ -915,8 +947,12 @@ static ir_node *gen_Cond(ir_node *node) { } /* Hmm: use need cmfe */ return new_rd_arm_fpaCmfeBra(dbg, irg, block, new_op1, new_op2, pnc); + } else if (is_Const(op2) && tarval_is_null(get_Const_tarval(op2))) { + /* compare with 0 */ + return new_rd_arm_TstBra(dbg, irg, block, new_op1, new_op1, get_Proj_proj(selector)); } else { /* integer compare */ + ir_node *new_op2 = be_transform_node(op2); return new_rd_arm_CmpBra(dbg, irg, block, new_op1, new_op2, get_Proj_proj(selector)); } } else { @@ -1047,10 +1083,10 @@ static ir_node *gen_Const(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"); + panic("VFP not supported yet"); } else { - panic("Softfloat not supported yet\n"); + panic("Softfloat not supported yet"); } } return create_const_graph(node, block); @@ -1197,44 +1233,6 @@ static ir_node *gen_be_FrameAddr(ir_node *node) { return new_rd_arm_Add(dbg, current_ir_graph, block, new_op, cnst, mode, ARM_SHF_NONE, 0); } -#if 0 -/** - * Transforms a FrameLoad into an ARM Load. - */ -static ir_node *gen_FrameLoad(ir_node *irn) { - ir_node *new_op = NULL; - ir_node *noreg = ia32_new_NoReg_gp(env->cg); - ir_node *mem = get_irn_n(irn, 0); - ir_node *ptr = get_irn_n(irn, 1); - ir_entity *ent = be_get_frame_entity(irn); - ir_mode *mode = get_type_mode(get_entity_type(ent)); - - if (mode_is_float(mode)) { - if (USE_SSE2(env->cg)) - new_op = new_rd_ia32_fLoad(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T); - else { - env->cg->used_x87 = 1; - new_op = new_rd_ia32_vfld(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T); - } - } - else { - new_op = new_rd_ia32_Load(env->dbg, current_ir_graph, env->block, ptr, noreg, mem, mode_T); - } - - set_ia32_frame_ent(new_op, ent); - set_ia32_use_frame(new_op); - - set_ia32_am_support(new_op, ia32_am_Source); - set_ia32_op_type(new_op, ia32_AddrModeS); - set_ia32_am_flavour(new_op, ia32_B); - set_ia32_ls_mode(new_op, mode); - - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - - return new_op; -} -#endif - /** * Transform a be_AddSP into an arm_AddSP. Eat up const sizes. */ @@ -1249,8 +1247,8 @@ static ir_node *gen_be_AddSP(ir_node *node) { ir_node *nomem = new_NoMem(); ir_node *new_op; - /* ARM stack grows in reverse direction, make a SubSP */ - new_op = new_rd_arm_SubSP(dbgi, irg, block, new_sp, new_sz, nomem); + /* ARM stack grows in reverse direction, make a SubSPandCopy */ + new_op = new_rd_arm_SubSPandCopy(dbgi, irg, block, new_sp, new_sz, nomem); return new_op; } @@ -1409,14 +1407,14 @@ static ir_node *gen_Proj_be_AddSP(ir_node *node) { if (proj == pn_be_AddSP_sp) { ir_node *res = new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, - pn_arm_SubSP_stack); + pn_arm_SubSPandCopy_stack); arch_set_irn_register(env_cg->arch_env, res, &arm_gp_regs[REG_SP]); return res; } else if(proj == pn_be_AddSP_res) { return new_rd_Proj(dbgi, irg, block, new_pred, mode_Iu, - pn_arm_SubSP_addr); + pn_arm_SubSPandCopy_addr); } else if (proj == pn_be_AddSP_M) { - return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSP_M); + return new_rd_Proj(dbgi, irg, block, new_pred, mode_M, pn_arm_SubSPandCopy_M); } assert(0); @@ -1452,7 +1450,7 @@ static ir_node *gen_Proj_be_SubSP(ir_node *node) { */ static ir_node *gen_Proj_Cmp(ir_node *node) { (void) node; - panic("Psi NYI\n"); + panic("Mux NYI"); } @@ -1503,7 +1501,6 @@ static ir_node *gen_Proj(ir_node *node) { /* we exchange the ProjX with a jump */ block = be_transform_node(block); jump = new_rd_Jmp(dbgi, irg, block); - ir_fprintf(stderr, "created jump: %+F\n", jump); return jump; } if (node == get_irg_anchor(irg, anchor_tls)) { @@ -1622,7 +1619,7 @@ static ir_node *gen_Phi(ir_node *node) { * the BAD transformer. */ static ir_node *bad_transform(ir_node *irn) { - panic("ARM backend: Not implemented: %+F\n", irn); + panic("ARM backend: Not implemented: %+F", irn); return irn; } @@ -1655,7 +1652,7 @@ static void arm_register_transformers(void) { GEN(Shl); GEN(Shr); GEN(Shrs); - BAD(Rot); /* unsupported yet */ + GEN(Rotl); GEN(Quot); @@ -1675,8 +1672,7 @@ static void arm_register_transformers(void) { BAD(ASM); /* unsupported yet */ GEN(CopyB); - BAD(Mux); - BAD(Psi); /* unsupported yet */ + BAD(Mux); /* unsupported yet */ GEN(Proj); GEN(Phi);