X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_transform.c;h=c5572b51c044ec325d3a02b26d74850235856a31;hb=a45e4bda739bc9e6c78874b0bc518edbb8efec9c;hp=59514e8dd76bc9f0820d98c17978147acf95477b;hpb=c3f8810dcc28bba4e949a8be4da6506d884d49d3;p=libfirm diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 59514e8dd..c5572b51c 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -356,11 +356,22 @@ typedef enum { MATCH_SIZE_NEUTRAL = 1 << 1, } match_flags_t; -typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2); -typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot); +/** + * possible binop constructors. + */ +typedef struct arm_binop_factory_t { + /** normal reg op reg operation. */ + ir_node *(*new_binop_reg)(dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2); + /** normal reg op imm operation. */ + ir_node *(*new_binop_imm)(dbg_info *dbgi, ir_node *block, ir_node *op1, unsigned char imm8, unsigned char imm_rot); + /** barrel shifter reg op (reg shift reg operation. */ + ir_node *(*new_binop_reg_shift_reg)(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, ir_node *shift, arm_shift_modifier_t shift_modifier); + /** barrel shifter reg op (reg shift imm operation. */ + ir_node *(*new_binop_reg_shift_imm)(dbg_info *dbgi, ir_node *block, ir_node *left, ir_node *right, arm_shift_modifier_t shift_modifier, unsigned shift_immediate); +} arm_binop_factory_t; static ir_node *gen_int_binop(ir_node *node, match_flags_t flags, - new_binop_reg_func new_reg, new_binop_imm_func new_imm) + const arm_binop_factory_t *factory) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *op1 = get_binop_left(node); @@ -379,15 +390,78 @@ static ir_node *gen_int_binop(ir_node *node, match_flags_t flags, if (try_encode_as_immediate(op2, &imm)) { ir_node *new_op1 = be_transform_node(op1); - return new_imm(dbgi, block, new_op1, imm.imm_8, imm.rot); + return factory->new_binop_imm(dbgi, block, new_op1, imm.imm_8, imm.rot); } new_op2 = be_transform_node(op2); if ((flags & MATCH_COMMUTATIVE) && try_encode_as_immediate(op1, &imm)) { - return new_imm(dbgi, block, new_op2, imm.imm_8, imm.rot); + return factory->new_binop_imm(dbgi, block, new_op2, imm.imm_8, imm.rot); } new_op1 = be_transform_node(op1); - return new_reg(dbgi, block, new_op1, new_op2); + /* check if we can fold in a Mov */ + if (is_arm_Mov(new_op2)) { + const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op2); + + switch (attr->shift_modifier) { + ir_node *mov_op, *mov_sft; + + case ARM_SHF_IMM: + case ARM_SHF_ASR_IMM: + case ARM_SHF_LSL_IMM: + case ARM_SHF_LSR_IMM: + case ARM_SHF_ROR_IMM: + if (factory->new_binop_reg_shift_imm) { + mov_op = get_irn_n(new_op2, 0); + return factory->new_binop_reg_shift_imm(dbgi, block, new_op1, mov_op, + attr->shift_modifier, attr->shift_immediate); + } + break; + + case ARM_SHF_ASR_REG: + case ARM_SHF_LSL_REG: + case ARM_SHF_LSR_REG: + case ARM_SHF_ROR_REG: + if (factory->new_binop_reg_shift_reg) { + mov_op = get_irn_n(new_op2, 0); + mov_sft = get_irn_n(new_op2, 1); + return factory->new_binop_reg_shift_reg(dbgi, block, new_op1, mov_op, mov_sft, + attr->shift_modifier); + } + break; + } + } + if ((flags & MATCH_COMMUTATIVE) && is_arm_Mov(new_op1)) { + const arm_shifter_operand_t *attr = get_arm_shifter_operand_attr_const(new_op1); + + switch (attr->shift_modifier) { + ir_node *mov_op, *mov_sft; + + case ARM_SHF_IMM: + case ARM_SHF_ASR_IMM: + case ARM_SHF_LSL_IMM: + case ARM_SHF_LSR_IMM: + case ARM_SHF_ROR_IMM: + if (factory->new_binop_reg_shift_imm) { + mov_op = get_irn_n(new_op1, 0); + return factory->new_binop_reg_shift_imm(dbgi, block, new_op2, mov_op, + attr->shift_modifier, attr->shift_immediate); + } + break; + + case ARM_SHF_ASR_REG: + case ARM_SHF_LSL_REG: + case ARM_SHF_LSR_REG: + case ARM_SHF_ROR_REG: + if (factory->new_binop_reg_shift_reg) { + mov_op = get_irn_n(new_op1, 0); + mov_sft = get_irn_n(new_op1, 1); + return factory->new_binop_reg_shift_reg(dbgi, block, new_op2, mov_op, mov_sft, + attr->shift_modifier); + } + break; + } + } + return factory->new_binop_reg(dbgi, block, new_op1, new_op2); } /** @@ -397,7 +471,14 @@ static ir_node *gen_int_binop(ir_node *node, match_flags_t flags, */ static ir_node *gen_Add(ir_node *node) { - ir_mode *mode = get_irn_mode(node); + static const arm_binop_factory_t add_factory = { + new_bd_arm_Add_reg, + new_bd_arm_Add_imm, + new_bd_arm_Add_reg_shift_reg, + new_bd_arm_Add_reg_shift_imm + }; + + ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { ir_node *block = be_transform_node(get_nodes_block(node)); @@ -433,8 +514,7 @@ static ir_node *gen_Add(ir_node *node) } #endif - return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, - new_bd_arm_Add_reg, new_bd_arm_Add_imm); + return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &add_factory); } } @@ -491,24 +571,49 @@ static ir_node *gen_Quot(ir_node *node) static ir_node *gen_And(ir_node *node) { - return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, - new_bd_arm_And_reg, new_bd_arm_And_imm); + static const arm_binop_factory_t and_factory = { + new_bd_arm_And_reg, + new_bd_arm_And_imm, + new_bd_arm_And_reg_shift_reg, + new_bd_arm_And_reg_shift_imm + }; + + return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &and_factory); } static ir_node *gen_Or(ir_node *node) { - return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, - new_bd_arm_Or_reg, new_bd_arm_Or_imm); + static const arm_binop_factory_t or_factory = { + new_bd_arm_Or_reg, + new_bd_arm_Or_imm, + new_bd_arm_Or_reg_shift_reg, + new_bd_arm_Or_reg_shift_imm + }; + + return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &or_factory); } static ir_node *gen_Eor(ir_node *node) { - return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, - new_bd_arm_Eor_reg, new_bd_arm_Eor_imm); + static const arm_binop_factory_t eor_factory = { + new_bd_arm_Eor_reg, + new_bd_arm_Eor_imm, + new_bd_arm_Eor_reg_shift_reg, + new_bd_arm_Eor_reg_shift_imm + }; + + return gen_int_binop(node, MATCH_COMMUTATIVE | MATCH_SIZE_NEUTRAL, &eor_factory); } static ir_node *gen_Sub(ir_node *node) { + static const arm_binop_factory_t sub_factory = { + new_bd_arm_Sub_reg, + new_bd_arm_Sub_imm, + new_bd_arm_Sub_reg_shift_reg, + new_bd_arm_Sub_reg_shift_imm + }; + ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *op1 = get_Sub_left(node); ir_node *new_op1 = be_transform_node(op1); @@ -527,8 +632,7 @@ static ir_node *gen_Sub(ir_node *node) panic("Softfloat not supported yet"); } } else { - return gen_int_binop(node, MATCH_SIZE_NEUTRAL, - new_bd_arm_Sub_reg, new_bd_arm_Sub_imm); + return gen_int_binop(node, MATCH_SIZE_NEUTRAL, &sub_factory); } } @@ -1299,7 +1403,7 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node) ir_node *call = get_Proj_pred(get_Proj_pred(node)); ir_node *new_call = be_transform_node(call); ir_type *function_type = get_Call_type(call); - calling_convention_t *cconv = decide_calling_convention(function_type); + calling_convention_t *cconv = arm_decide_calling_convention(function_type); const reg_or_stackslot_t *res = &cconv->results[pn]; ir_mode *mode; int regn; @@ -1312,7 +1416,7 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node) } mode = res->reg0->reg_class->mode; - free_calling_convention(cconv); + arm_free_calling_convention(cconv); return new_r_Proj(new_call, mode, regn); } @@ -1616,7 +1720,7 @@ static ir_node *gen_Call(ir_node *node) ir_node *new_mem = be_transform_node(mem); dbg_info *dbgi = get_irn_dbg_info(node); ir_type *type = get_Call_type(node); - calling_convention_t *cconv = decide_calling_convention(type); + calling_convention_t *cconv = arm_decide_calling_convention(type); int n_params = get_Call_n_params(node); int n_param_regs = sizeof(param_regs)/sizeof(param_regs[0]); /* max inputs: memory, callee, register arguments */ @@ -1782,7 +1886,7 @@ static ir_node *gen_Call(ir_node *node) /* copy pinned attribute */ set_irn_pinned(res, get_irn_pinned(node)); - free_calling_convention(cconv); + arm_free_calling_convention(cconv); return res; } @@ -1941,7 +2045,7 @@ void arm_transform_graph(arm_code_gen_t *cg) abihelper = be_abihelper_prepare(irg); be_collect_stacknodes(abihelper); assert(cconv == NULL); - cconv = decide_calling_convention(get_entity_type(entity)); + cconv = arm_decide_calling_convention(get_entity_type(entity)); create_stacklayout(irg); be_transform_graph(cg->irg, NULL); @@ -1949,7 +2053,7 @@ void arm_transform_graph(arm_code_gen_t *cg) be_abihelper_finish(abihelper); abihelper = NULL; - free_calling_convention(cconv); + arm_free_calling_convention(cconv); cconv = NULL; frame_type = get_irg_frame_type(irg);