From fdce0699d5d6ad23b9ce405e1a4fb9707fb9d51f Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Thu, 29 May 2008 01:58:34 +0000 Subject: [PATCH] - Add a peephole phase that fixes all stack offsets [r19823] --- ir/be/arm/arm_new_nodes.c | 1 + ir/be/arm/arm_new_nodes.h | 5 - ir/be/arm/arm_optimize.c | 406 ++++++++++++++++++++++++++++++++++++++ ir/be/arm/arm_optimize.h | 61 ++++++ ir/be/arm/arm_transform.c | 132 ++----------- ir/be/arm/bearch_arm.c | 24 ++- 6 files changed, 492 insertions(+), 137 deletions(-) create mode 100644 ir/be/arm/arm_optimize.c create mode 100644 ir/be/arm/arm_optimize.h diff --git a/ir/be/arm/arm_new_nodes.c b/ir/be/arm/arm_new_nodes.c index 544e1331e..3fbe4fd09 100644 --- a/ir/be/arm/arm_new_nodes.c +++ b/ir/be/arm/arm_new_nodes.c @@ -47,6 +47,7 @@ #include "arm_nodes_attr.h" #include "arm_new_nodes.h" +#include "arm_optimize.h" #include "../beabi.h" #include "bearch_arm_t.h" diff --git a/ir/be/arm/arm_new_nodes.h b/ir/be/arm/arm_new_nodes.h index a2c494441..d2a2dcb07 100644 --- a/ir/be/arm/arm_new_nodes.h +++ b/ir/be/arm/arm_new_nodes.h @@ -205,11 +205,6 @@ void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num); */ arm_shift_modifier get_arm_shift_modifier(const ir_node *node); -/** - * Decode an immediate with shifter operand - */ -unsigned int arm_decode_imm_w_shift(long imm_value); - /* Include the generated headers */ #include "gen_arm_new_nodes.h" diff --git a/ir/be/arm/arm_optimize.c b/ir/be/arm/arm_optimize.c new file mode 100644 index 000000000..06f909cc4 --- /dev/null +++ b/ir/be/arm/arm_optimize.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/** + * @file + * @brief Implements several optimizations for ARM. + * @author Michael Beck + * @version $Id: $ + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "irgmod.h" +#include "ircons.h" +#include "error.h" + +#include "benode_t.h" +#include "bepeephole.h" +#include "besched.h" + +#include "arm_optimize.h" +#include "gen_arm_regalloc_if.h" +#include "gen_arm_new_nodes.h" + +static const arch_env_t *arch_env; +static arm_code_gen_t *cg; + +/** Execute ARM ROL. */ +static unsigned arm_rol(unsigned v, unsigned rol) { + return (v << rol) | (v >> (32 - rol)); +} + +/* + * construct 8bit values and rot amounts for a value. + */ +void arm_gen_vals_from_word(unsigned int value, arm_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 = arm_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 ^= arm_rol(v, shf) >> initial; + } + else { + value >>= 8; + initial += 8; + } + } +} + +/** + * Encodes an immediate with shifter operand + */ +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 arm_rol(l & 0xFF, rol); +} + +/** + * Creates a Mov node. + */ +static ir_node *create_mov_node(ir_node *sched_point, dbg_info *dbg, ir_node *block, long value) { + ir_graph *irg = current_ir_graph; + ir_node *mov; + + mov = new_rd_arm_Mov_i(dbg, irg, block, mode_Iu, value); + arch_set_irn_register(arch_env, mov, &arm_gp_regs[REG_R12]); + sched_add_before(sched_point, mov); + return mov; +} + +/** + * Creates a Mvn node. + */ +static ir_node *create_mvn_node(ir_node *sched_point, dbg_info *dbg, ir_node *block, long value) { + ir_graph *irg = current_ir_graph; + ir_node *mvn; + + mvn = new_rd_arm_Mvn_i(dbg, irg, block, mode_Iu, value); + arch_set_irn_register(arch_env, mvn, &arm_gp_regs[REG_R12]); + sched_add_before(sched_point, mvn); + return mvn; +} + +/** + * Creates a possible DAG for an constant and schedule it before + * the node sched_point. + * The Dag deliveres it's result in register R12. + */ +static ir_node *create_const_graph_value(ir_node *sched_point, unsigned int value) { + dbg_info *dbg; + ir_node *block, *result; + arm_vals v, vn; + int cnt; + + arm_gen_vals_from_word(value, &v); + arm_gen_vals_from_word(~value, &vn); + + dbg = get_irn_dbg_info(sched_point); + block = get_nodes_block(sched_point); + + if (vn.ops < v.ops) { + /* remove bits */ + result = create_mvn_node(sched_point, 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]); + ir_node *bic_i_node = new_rd_arm_Bic_i(dbg, current_ir_graph, block, result, mode_Iu, value); + arch_set_irn_register(arch_env, bic_i_node, &arm_gp_regs[REG_R12]); + sched_add_before(sched_point, bic_i_node); + result = bic_i_node; + } + } + else { + /* add bits */ + result = create_mov_node(sched_point, 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]); + ir_node *orr_i_node = new_rd_arm_Or_i(dbg, current_ir_graph, block, result, mode_Iu, value); + arch_set_irn_register(arch_env, orr_i_node, &arm_gp_regs[REG_R12]); + sched_add_before(sched_point, orr_i_node); + result = orr_i_node; + } + } + return result; +} + + +/** + * Returns non.zero if the given offset can be directly encoded into an ARM instruction. + */ +static int allowed_arm_immediate(int offset, arm_vals *result) { + arm_gen_vals_from_word(offset, result); + return result->ops <= 1; +} + +/** + * Fix an IncSP node if the offset gets too big + */ +static void peephole_be_IncSP(ir_node *node) { + ir_graph *irg; + ir_node *block; + int offset, cnt, align, sign = 1; + arm_vals v; + + /* first optimize incsp->incsp combinations */ + be_peephole_IncSP_IncSP(node); + + offset = be_get_IncSP_offset(node); + /* can be transformed into Add OR Sub */ + if (offset < 0) { + sign = -1; + offset = -offset; + } + if (allowed_arm_immediate(offset, &v)) + return; + + be_set_IncSP_offset(node, (int)arm_encode_imm_w_shift(v.shifts[0], v.values[0]) * sign); + + irg = current_ir_graph; + block = get_nodes_block(node); + align = be_get_IncSP_align(node); + for (cnt = 1; cnt < v.ops; ++cnt) { + int value = (int)arm_encode_imm_w_shift(v.shifts[cnt], v.values[cnt]); + ir_node *next = be_new_IncSP(&arm_gp_regs[REG_SP], irg, block, node, value * sign, align); + sched_add_after(node, next); + node = next; + } +} + +/** + * creates the address by Adds + */ +static ir_node *gen_ptr_add(ir_node *node, ir_node *frame, arm_vals *v) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + int cnt; + ir_node *ptr; + + ptr = new_rd_arm_Add_i(dbg, irg, block, frame, mode_Iu, arm_encode_imm_w_shift(v->shifts[0], v->values[0])); + arch_set_irn_register(arch_env, ptr, &arm_gp_regs[REG_R12]); + sched_add_before(node, ptr); + + for (cnt = 1; cnt < v->ops; ++cnt) { + long value = arm_encode_imm_w_shift(v->shifts[cnt], v->values[cnt]); + ir_node *next = new_rd_arm_Add_i(dbg, irg, block, ptr, mode_Iu, value); + arch_set_irn_register(arch_env, next, &arm_gp_regs[REG_R12]); + sched_add_before(node, next); + ptr = next; + } + return ptr; +} + +/** +* creates the address by Subs +*/ +static ir_node *gen_ptr_sub(ir_node *node, ir_node *frame, arm_vals *v) +{ + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + int cnt; + ir_node *ptr; + + ptr = new_rd_arm_Sub_i(dbg, irg, block, frame, mode_Iu, arm_encode_imm_w_shift(v->shifts[0], v->values[0])); + arch_set_irn_register(arch_env, ptr, &arm_gp_regs[REG_R12]); + sched_add_before(node, ptr); + + for (cnt = 1; cnt < v->ops; ++cnt) { + long value = arm_encode_imm_w_shift(v->shifts[cnt], v->values[cnt]); + ir_node *next = new_rd_arm_Sub_i(dbg, irg, block, ptr, mode_Iu, value); + arch_set_irn_register(arch_env, next, &arm_gp_regs[REG_R12]); + sched_add_before(node, next); + ptr = next; + } + return ptr; +} + +/** + * Fix an be_Spill node if the offset gets too big + */ +static void peephole_be_Spill(ir_node *node) { + ir_entity *ent = be_get_frame_entity(node); + int use_add = 1, offset = get_entity_offset(ent); + ir_node *block, *ptr, *frame, *value, *store; + ir_mode *mode; + dbg_info *dbg; + ir_graph *irg; + arm_vals v; + + if (allowed_arm_immediate(offset, &v)) + return; + if (offset < 0) { + use_add = 0; + offset = -offset; + } + + frame = be_get_Spill_frame(node); + if (use_add) { + ptr = gen_ptr_add(node, frame, &v); + } else { + ptr = gen_ptr_sub(node, frame, &v); + } + + value = be_get_Spill_val(node); + mode = get_irn_mode(value); + irg = current_ir_graph; + dbg = get_irn_dbg_info(node); + block = get_nodes_block(node); + + if (mode_is_float(mode)) { + if (USE_FPA(cg->isa)) { + /* transform into fpaStf */ + store = new_rd_arm_fpaStf(dbg, irg, block, ptr, value, get_irg_no_mem(irg), mode); + sched_add_before(node, store); + } else { + panic("peephole_be_Spill: spill not supported for this mode"); + } + } else if (mode_is_dataM(mode)) { + /* transform into Store */; + store = new_rd_arm_Store(dbg, irg, block, ptr, value, get_irg_no_mem(irg)); + sched_add_before(node, store); + } else { + panic("peephole_be_Spill: spill not supported for this mode"); + } + + be_peephole_before_exchange(node, store); + sched_remove(node); + exchange(node, store); + be_peephole_after_exchange(store); +} + +/** + * Fix an be_Reload node if the offset gets too big + */ +static void peephole_be_Reload(ir_node *node) { + ir_entity *ent = be_get_frame_entity(node); + int use_add = 1, offset = get_entity_offset(ent); + ir_node *block, *ptr, *frame, *load, *mem, *proj; + ir_mode *mode; + dbg_info *dbg; + ir_graph *irg; + arm_vals v; + const arch_register_t *reg; + + if (allowed_arm_immediate(offset, &v)) + return; + if (offset < 0) { + use_add = 0; + offset = -offset; + } + + frame = be_get_Reload_frame(node); + if (use_add) { + ptr = gen_ptr_add(node, frame, &v); + } else { + ptr = gen_ptr_sub(node, frame, &v); + } + + reg = arch_get_irn_register(arch_env, node); + mem = be_get_Reload_mem(node); + mode = get_irn_mode(node); + irg = current_ir_graph; + dbg = get_irn_dbg_info(node); + block = get_nodes_block(node); + + if (mode_is_float(mode)) { + if (USE_FPA(cg->isa)) { + /* transform into fpaLdf */ + load = new_rd_arm_fpaLdf(dbg, irg, block, ptr, mem, mode); + sched_add_before(node, load); + proj = new_rd_Proj(dbg, irg, block, load, mode, pn_arm_fpaLdf_res); + arch_set_irn_register(arch_env, proj, reg); + } else { + panic("peephole_be_Spill: spill not supported for this mode"); + } + } else if (mode_is_dataM(mode)) { + /* transform into Store */; + load = new_rd_arm_Load(dbg, irg, block, ptr, mem); + sched_add_before(node, load); + proj = new_rd_Proj(dbg, irg, block, load, mode_Iu, pn_arm_Load_res); + arch_set_irn_register(arch_env, proj, reg); + } else { + panic("peephole_be_Spill: spill not supported for this mode"); + } + + be_peephole_before_exchange(node, proj); + sched_remove(node); + exchange(node, proj); + be_peephole_after_exchange(proj); +} + +/** + * Register a peephole optimization function. + */ +static void register_peephole_optimisation(ir_op *op, peephole_opt_func func) { + assert(op->ops.generic == NULL); + op->ops.generic = (op_func)func; +} + +/* Perform peephole-optimizations. */ +void arm_peephole_optimization(arm_code_gen_t *new_cg) +{ + cg = new_cg; + arch_env = cg->arch_env; + + /* register peephole optimizations */ + clear_irp_opcodes_generic_func(); + register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP); + register_peephole_optimisation(op_be_Spill, peephole_be_Spill); + register_peephole_optimisation(op_be_Reload, peephole_be_Reload); + + be_peephole_opt(cg->birg); +} diff --git a/ir/be/arm/arm_optimize.h b/ir/be/arm/arm_optimize.h new file mode 100644 index 000000000..92f724364 --- /dev/null +++ b/ir/be/arm/arm_optimize.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/** + * @file + * @brief Implements several optimizations for ARM. + * @author Michael Beck + * @version $Id: $ + */ +#ifndef FIRM_BE_ARM_ARM_OPTIMIZE_H +#define FIRM_BE_ARM_ARM_OPTIMIZE_H + +#include "irgraph.h" +#include "bearch_arm_t.h" + +typedef struct arm_vals { + int ops; + unsigned char values[4]; + unsigned char shifts[4]; +} arm_vals; + +/** + * Encodes an immediate with shifter operand + */ +unsigned int arm_encode_imm_w_shift(unsigned int shift, unsigned int immediate); + +/** + * Decode an immediate with shifter operand + */ +unsigned int arm_decode_imm_w_shift(long imm_value); + +/** + * construct 8bit values and rot amounts for a 32bit value. + */ +void arm_gen_vals_from_word(unsigned int value, arm_vals *result); + +/** + * Performs Peephole Optimizations an a graph. + * + * @param irg the graph + * @param cg the code generator object + */ +void arm_peephole_optimization(arm_code_gen_t *cg); + +#endif /* FIRM_BE_ARM_ARM_OPTIMIZE_H */ diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 2ef801958..d1bc9b35d 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]); @@ -1197,44 +1129,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 +1143,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 +1303,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); diff --git a/ir/be/arm/bearch_arm.c b/ir/be/arm/bearch_arm.c index ca5977093..77a1631a8 100644 --- a/ir/be/arm/bearch_arm.c +++ b/ir/be/arm/bearch_arm.c @@ -39,6 +39,7 @@ #include "irgopt.h" #include "iroptimize.h" #include "lowering.h" +#include "error.h" #include "bitset.h" #include "debug.h" @@ -62,6 +63,7 @@ #include "arm_new_nodes.h" /* arm nodes interface */ #include "gen_arm_regalloc_if.h" /* the generated interface (register type and class defenitions) */ #include "arm_transform.h" +#include "arm_optimize.h" #include "arm_emitter.h" #include "arm_map_regs.h" @@ -218,18 +220,14 @@ static arch_irn_flags_t arm_get_flags(const ir_node *irn) return flags; } -static ir_entity *arm_get_frame_entity(const ir_node *irn) -{ - (void) irn; - /* TODO: return the entity assigned to the frame */ +static ir_entity *arm_get_frame_entity(const ir_node *irn) { + /* we do NOT transform be_Spill or be_Reload nodes, so we never + have frame access using ARM nodes. */ return NULL; } -static void arm_set_frame_entity(ir_node *irn, ir_entity *ent) -{ - (void) irn; - (void) ent; - /* TODO: set the entity assigned to the frame */ +static void arm_set_frame_entity(ir_node *irn, ir_entity *ent) { + panic("arm_set_frame_entity() called. This should not happen."); } /** @@ -306,10 +304,10 @@ static void arm_prepare_graph(void *self) { */ static void arm_finish_irg(void *self) { - (void) self; - /* TODO: - fix offsets for nodes accessing stack - - ... - */ + arm_code_gen_t *cg = self; + + /* do peephole optimizations and fix stack offsets */ + arm_peephole_optimization(cg); } -- 2.20.1