- Add a peephole phase that fixes all stack offsets
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 29 May 2008 01:58:34 +0000 (01:58 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 29 May 2008 01:58:34 +0000 (01:58 +0000)
[r19823]

ir/be/arm/arm_new_nodes.c
ir/be/arm/arm_new_nodes.h
ir/be/arm/arm_optimize.c [new file with mode: 0644]
ir/be/arm/arm_optimize.h [new file with mode: 0644]
ir/be/arm/arm_transform.c
ir/be/arm/bearch_arm.c

index 544e133..3fbe4fd 100644 (file)
@@ -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"
index a2c4944..d2a2dcb 100644 (file)
@@ -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 (file)
index 0000000..06f909c
--- /dev/null
@@ -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 (file)
index 0000000..92f7243
--- /dev/null
@@ -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 */
index 2ef8019..d1bc9b3 100644 (file)
@@ -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);
index ca59770..77a1631 100644 (file)
@@ -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);
 }