adapt sparc backend to new prolog/epilog handling
authorMatthias Braun <matze@braunis.de>
Wed, 13 Apr 2011 12:18:35 +0000 (14:18 +0200)
committerMatthias Braun <matze@braunis.de>
Wed, 13 Apr 2011 13:11:52 +0000 (15:11 +0200)
ir/be/benode.c
ir/be/benode.h
ir/be/ia32/bearch_ia32.c
ir/be/ia32/bearch_ia32_t.h
ir/be/ia32/ia32_fpu.c
ir/be/ia32/ia32_transform.c
ir/be/sparc/bearch_sparc.c
ir/be/sparc/bearch_sparc_t.h
ir/be/sparc/sparc_finish.c
ir/be/sparc/sparc_transform.c

index 4d6b9da..1813101 100644 (file)
@@ -1050,6 +1050,63 @@ static const arch_irn_ops_t be_node_irn_ops = {
        NULL,    /* perform_memory_operand  */
 };
 
+static int get_start_reg_index(ir_graph *irg, const arch_register_t *reg)
+{
+       ir_node *start  = get_irg_start(irg);
+       unsigned n_outs = arch_irn_get_n_outs(start);
+       int      i;
+
+       /* do a naive linear search... */
+       for (i = 0; i < (int)n_outs; ++i) {
+               const arch_register_req_t *out_req
+                       = arch_get_out_register_req(start, i);
+               if (! (out_req->type & arch_register_req_type_limited))
+                       continue;
+               if (out_req->cls != arch_register_get_class(reg))
+                       continue;
+               if (!rbitset_is_set(out_req->limited, reg->index))
+                       continue;
+               return i;
+       }
+       panic("Tried querying undefined register '%s' at Start", reg->name);
+}
+
+ir_node *be_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg)
+{
+       int      i     = get_start_reg_index(irg, reg);
+       ir_node *start = get_irg_start(irg);
+       ir_mode *mode  = arch_register_class_mode(arch_register_get_class(reg));
+       const ir_edge_t *edge;
+
+       foreach_out_edge(start, edge) {
+               ir_node *proj = get_edge_src_irn(edge);
+               if (!is_Proj(proj)) // maybe End/Anchor
+                       continue;
+               if (get_Proj_proj(proj) == i) {
+                       return proj;
+               }
+       }
+       return new_r_Proj(start, mode, i);
+}
+
+int be_find_return_reg_input(ir_node *ret, const arch_register_t *reg)
+{
+       int arity = get_irn_arity(ret);
+       int i;
+       /* do a naive linear search... */
+       for (i = 0; i < arity; ++i) {
+               const arch_register_req_t *req = arch_get_in_register_req(ret, i);
+               if (! (req->type & arch_register_req_type_limited))
+                       continue;
+               if (req->cls != arch_register_get_class(reg))
+                       continue;
+               if (!rbitset_is_set(req->limited, reg->index))
+                       continue;
+               return i;
+       }
+       panic("Tried querying undefined register '%s' at Return", reg->name);
+}
+
 static arch_irn_class_t dummy_classify(const ir_node *node)
 {
        (void) node;
index 38cecd0..b809078 100644 (file)
@@ -479,6 +479,17 @@ void be_dump_phi_reg_reqs(FILE *out, ir_node *node, dump_reason_t reason);
 ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
                     const arch_register_class_t *cls);
 
+/**
+ * Search for output of start node with a specific register
+ */
+ir_node *be_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg);
+
+/**
+ * Search for input of a return node with a specific register and return
+ * its number.
+ */
+int be_find_return_reg_input(ir_node *ret, const arch_register_t *reg);
+
 static inline int be_is_Spill    (const ir_node *irn) { return get_irn_opcode(irn) == beo_Spill    ; }
 static inline int be_is_Reload   (const ir_node *irn) { return get_irn_opcode(irn) == beo_Reload   ; }
 static inline int be_is_Copy     (const ir_node *irn) { return get_irn_opcode(irn) == beo_Copy     ; }
@@ -491,7 +502,7 @@ static inline int be_is_Return   (const ir_node *irn) { return get_irn_opcode(ir
 static inline int be_is_IncSP    (const ir_node *irn) { return get_irn_opcode(irn) == beo_IncSP    ; }
 static inline int be_is_AddSP    (const ir_node *irn) { return get_irn_opcode(irn) == beo_AddSP    ; }
 static inline int be_is_SubSP    (const ir_node *irn) { return get_irn_opcode(irn) == beo_SubSP    ; }
-static inline int be_is_Start    (const ir_node *irn) { return get_irn_opcode(irn) == beo_Start; }
+static inline int be_is_Start    (const ir_node *irn) { return get_irn_opcode(irn) == beo_Start    ; }
 static inline int be_is_FrameAddr(const ir_node *irn) { return get_irn_opcode(irn) == beo_FrameAddr; }
 
 #endif
index b246f68..1fc7910 100644 (file)
@@ -263,45 +263,6 @@ static int ia32_get_sp_bias(const ir_node *node)
        return 0;
 }
 
-static int get_start_reg_index(ir_graph *irg, const arch_register_t *reg)
-{
-       ir_node *start  = get_irg_start(irg);
-       unsigned n_outs = arch_irn_get_n_outs(start);
-       int      i;
-
-       /* do a naive linear search... */
-       for (i = 0; i < (int)n_outs; ++i) {
-               const arch_register_req_t *out_req
-                       = arch_get_out_register_req(start, i);
-               if (! (out_req->type & arch_register_req_type_limited))
-                       continue;
-               if (out_req->cls != arch_register_get_class(reg))
-                       continue;
-               if (!rbitset_is_set(out_req->limited, reg->index))
-                       continue;
-               return i;
-       }
-       panic("Tried querying undefined register '%s' at Start", reg->name);
-}
-
-ir_node *ia32_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg)
-{
-       int      i     = get_start_reg_index(irg, reg);
-       ir_node *start = get_irg_start(irg);
-       ir_mode *mode  = arch_register_class_mode(arch_register_get_class(reg));
-       const ir_edge_t *edge;
-
-       foreach_out_edge(start, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               if (!is_Proj(proj)) // maybe End/Anchor
-                       continue;
-               if (get_Proj_proj(proj) == i) {
-                       return proj;
-               }
-       }
-       return new_r_Proj(start, mode, i);
-}
-
 /**
  * Build the between type and entities if not already build.
  */
@@ -1028,7 +989,7 @@ static void transform_MemPerm(ir_node *node)
 {
        ir_node         *block = get_nodes_block(node);
        ir_graph        *irg   = get_irn_irg(node);
-       ir_node         *sp    = ia32_get_initial_reg_value(irg, &ia32_registers[REG_ESP]);
+       ir_node         *sp    = be_get_initial_reg_value(irg, &ia32_registers[REG_ESP]);
        int              arity = be_get_MemPerm_entity_arity(node);
        ir_node        **pops  = ALLOCAN(ir_node*, arity);
        ir_node         *in[1];
@@ -1292,7 +1253,7 @@ static void introduce_prolog_epilog(ir_graph *irg)
        ir_type               *frame_type = get_irg_frame_type(irg);
        unsigned               frame_size = get_type_size_bytes(frame_type);
        be_stack_layout_t     *layout     = be_get_irg_stack_layout(irg);
-       ir_node               *initial_sp = ia32_get_initial_reg_value(irg, sp);
+       ir_node               *initial_sp = be_get_initial_reg_value(irg, sp);
        ir_node               *curr_sp    = initial_sp;
        ir_mode               *mode_gp    = mode_Iu;
 
@@ -1300,7 +1261,7 @@ static void introduce_prolog_epilog(ir_graph *irg)
                /* push ebp */
                ir_node *mem        = get_irg_initial_mem(irg);
                ir_node *noreg      = ia32_new_NoReg_gp(irg);
-               ir_node *initial_bp = ia32_get_initial_reg_value(irg, bp);
+               ir_node *initial_bp = be_get_initial_reg_value(irg, bp);
                ir_node *curr_bp    = initial_bp;
                ir_node *push       = new_bd_ia32_Push(NULL, block, noreg, noreg, mem, curr_bp, curr_sp);
                ir_node *incsp;
index dae6feb..91514bb 100644 (file)
@@ -154,9 +154,4 @@ ir_entity *ia32_get_return_address_entity(ir_graph *irg);
  */
 ir_entity *ia32_get_frame_address_entity(ir_graph *irg);
 
-/**
- * Get node representing the initial value of a register
- */
-ir_node *ia32_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg);
-
 #endif
index 35d2faf..bb3ab79 100644 (file)
@@ -260,7 +260,7 @@ static void rewire_fpu_mode_nodes(ir_graph *irg)
                return;
        }
 
-       initial_value = ia32_get_initial_reg_value(irg, reg);
+       initial_value = be_get_initial_reg_value(irg, reg);
        be_ssa_construction_init(&senv, irg);
        be_ssa_construction_add_copies(&senv, env.state_nodes,
                                       ARR_LEN(env.state_nodes));
index 9fca9eb..a9acd89 100644 (file)
@@ -5822,8 +5822,7 @@ void ia32_transform_graph(ir_graph *irg)
        initial_fpcw       = NULL;
        ia32_no_pic_adjust = 0;
 
-       old_initial_fpcw
-               = ia32_get_initial_reg_value(irg, &ia32_registers[REG_FPCW]);
+       old_initial_fpcw = be_get_initial_reg_value(irg, &ia32_registers[REG_FPCW]);
 
        be_timer_push(T_HEIGHTS);
        ia32_heights = heights_new(irg);
index 499c71f..f53f983 100644 (file)
@@ -292,6 +292,8 @@ static void sparc_after_ra(ir_graph *irg)
        be_free_frame_entity_coalescer(fec_env);
 
        irg_block_walk_graph(irg, NULL, sparc_after_ra_walker, NULL);
+
+       sparc_introduce_prolog_epilog(irg);
 }
 
 static void sparc_init_graph(ir_graph *irg)
index 5648fc7..650ec68 100644 (file)
@@ -74,4 +74,6 @@ static inline bool sparc_is_value_imm_encodeable(int32_t value)
 
 void sparc_finish(ir_graph *irg);
 
+void sparc_introduce_prolog_epilog(ir_graph *irg);
+
 #endif
index 9f1806c..9d060f4 100644 (file)
 #include "sparc_new_nodes.h"
 #include "irprog.h"
 #include "irgmod.h"
+#include "ircons.h"
 
 #include "../bepeephole.h"
 #include "../benode.h"
 #include "../besched.h"
 
+static void kill_unused_stacknodes(ir_node *node)
+{
+       if (get_irn_n_edges(node) > 0)
+               return;
+
+       if (be_is_IncSP(node)) {
+               sched_remove(node);
+               kill_node(node);
+       } else if (is_Phi(node)) {
+               int       arity = get_irn_arity(node);
+               ir_node **ins   = ALLOCAN(ir_node*, arity);
+               int       i;
+               sched_remove(node);
+               memcpy(ins, get_irn_in(node), arity*sizeof(ins[0]));
+               kill_node(node);
+
+               for (i = 0; i < arity; ++i)
+                       kill_unused_stacknodes(ins[i]);
+       }
+}
+
+static void introduce_epilog(ir_node *ret)
+{
+       const arch_register_t *sp_reg     = &sparc_registers[REG_SP];
+       ir_graph              *irg        = get_irn_irg(ret);
+       be_stack_layout_t     *layout     = be_get_irg_stack_layout(irg);
+       ir_node               *block      = get_nodes_block(ret);
+       ir_type               *frame_type = get_irg_frame_type(irg);
+       unsigned               frame_size = get_type_size_bytes(frame_type);
+       int                    sp_idx     = be_find_return_reg_input(ret, sp_reg);
+       ir_node               *sp         = get_irn_n(ret, sp_idx);
+
+       if (!layout->sp_relative) {
+               const arch_register_t *fp_reg = &sparc_registers[REG_FRAME_POINTER];
+               ir_node *fp      = be_get_initial_reg_value(irg, fp_reg);
+               ir_node *restore = new_bd_sparc_RestoreZero(NULL, block, fp);
+               sched_add_before(ret, restore);
+               arch_set_irn_register(restore, sp_reg);
+               set_irn_n(ret, sp_idx, restore);
+
+               kill_unused_stacknodes(sp);
+       } else {
+               ir_node *incsp  = be_new_IncSP(sp_reg, block, sp, frame_size, 0);
+               set_irn_n(ret, sp_idx, incsp);
+               sched_add_before(ret, incsp);
+       }
+}
+
+void sparc_introduce_prolog_epilog(ir_graph *irg)
+{
+       const arch_register_t *sp_reg     = &sparc_registers[REG_SP];
+       ir_node               *start      = get_irg_start(irg);
+       be_stack_layout_t     *layout     = be_get_irg_stack_layout(irg);
+       ir_node               *block      = get_nodes_block(start);
+       ir_node               *initial_sp = be_get_initial_reg_value(irg, sp_reg);
+       ir_node               *sp         = initial_sp;
+       ir_node               *schedpoint = start;
+       ir_type               *frame_type = get_irg_frame_type(irg);
+       unsigned               frame_size = get_type_size_bytes(frame_type);
+
+       /* introduce epilog for every return node */
+       {
+               ir_node *end_block = get_irg_end_block(irg);
+               int      arity     = get_irn_arity(end_block);
+               int      i;
+
+               for (i = 0; i < arity; ++i) {
+                       ir_node *ret = get_irn_n(end_block, i);
+                       assert(be_is_Return(ret));
+                       introduce_epilog(ret);
+               }
+       }
+
+       while (be_is_Keep(sched_next(schedpoint)))
+               schedpoint = sched_next(schedpoint);
+
+       if (!layout->sp_relative) {
+               ir_node *incsp;
+               ir_node *save = new_bd_sparc_Save_imm(NULL, block, sp, NULL,
+                                                     -SPARC_MIN_STACKSIZE);
+               arch_set_irn_register(save, sp_reg);
+               sched_add_after(schedpoint, save);
+               schedpoint = save;
+
+               incsp = be_new_IncSP(sp_reg, block, save, frame_size, 0);
+               edges_reroute(initial_sp, incsp);
+               set_irn_n(save, n_sparc_Save_stack, initial_sp);
+               sched_add_after(schedpoint, incsp);
+               schedpoint = incsp;
+
+               /* we still need the IncSP even if noone is explicitely using the
+                * value. (TODO: this isn't 100% correct yet, something at the end of
+                * the function should hold the IncSP, even if we use a restore
+                * which just overrides it instead of using the value)
+                */
+               if (get_irn_n_edges(incsp) == 0) {
+                       ir_node *in[] = { incsp };
+                       ir_node *keep = be_new_Keep(block, 1, in);
+                       sched_add_after(schedpoint, keep);
+               }
+       } else {
+               ir_node *incsp = be_new_IncSP(sp_reg, block, sp, frame_size, 0);
+               edges_reroute(initial_sp, incsp);
+               be_set_IncSP_pred(incsp, sp);
+               sched_add_after(schedpoint, incsp);
+       }
+}
+
 static void finish_sparc_Save(ir_node *node)
 {
        sparc_attr_t *attr = get_sparc_attr(node);
@@ -265,11 +374,13 @@ static void register_peephole_optimisation(ir_op *op, peephole_opt_func func)
 
 void sparc_finish(ir_graph *irg)
 {
+       /* perform peephole optimizations */
        clear_irp_opcodes_generic_func();
        register_peephole_optimisation(op_be_IncSP,        peephole_be_IncSP);
        register_peephole_optimisation(op_sparc_FrameAddr, peephole_sparc_FrameAddr);
        be_peephole_opt(irg);
 
+       /* perform legalizations (mostly fix nodes with too big immediates) */
        clear_irp_opcodes_generic_func();
        register_peephole_optimisation(op_be_IncSP,        finish_be_IncSP);
        register_peephole_optimisation(op_be_Return,       finish_be_Return);
index 06c8913..e7b3dc5 100644 (file)
@@ -1301,9 +1301,7 @@ static ir_node *gen_Start(ir_node *node)
        ir_node   *block         = get_nodes_block(node);
        ir_node   *new_block     = be_transform_node(block);
        dbg_info  *dbgi          = get_irn_dbg_info(node);
-       ir_node   *mem;
        ir_node   *start;
-ir_node   *sp;
        size_t     i;
 
        /* stackpointer is important at function prolog */
@@ -1337,25 +1335,6 @@ ir_node   *sp;
        }
 
        start = be_prolog_create_start(abihelper, dbgi, new_block);
-#if 0
-       mem   = be_prolog_get_memory(abihelper);
-       sp    = be_prolog_get_reg_value(abihelper, sp_reg);
-
-       if (!cconv->omit_fp) {
-               ir_node *save = new_bd_sparc_Save_imm(NULL, block, sp, NULL,
-                                                     -SPARC_MIN_STACKSIZE);
-               arch_irn_add_flags(save, arch_irn_flags_prolog);
-               arch_set_irn_register(save, sp_reg);
-               sp = save;
-               keep_alive(save);
-       }
-
-       sp = be_new_IncSP(sp_reg, new_block, sp, BE_STACK_FRAME_SIZE_EXPAND, 0);
-       arch_irn_add_flags(sp, arch_irn_flags_prolog);
-       be_prolog_set_reg_value(abihelper, sp_reg, sp);
-       be_prolog_set_memory(abihelper, mem);
-#endif
-
        return start;
 }
 
@@ -1428,24 +1407,6 @@ static ir_node *gen_Return(ir_node *node)
                }
        }
 
-#if 0
-       /* we need a restore instruction */
-       if (!cconv->omit_fp) {
-               ir_node *fp      = be_prolog_get_reg_value(abihelper, fp_reg);
-               ir_node *restore = new_bd_sparc_RestoreZero(NULL, block, fp);
-               arch_irn_add_flags(restore, arch_irn_flags_epilog);
-               arch_set_irn_register(restore, sp_reg);
-               be_epilog_set_reg_value(abihelper, sp_reg, restore);
-       } else {
-               /* epilog code: an incsp */
-               sp = be_epilog_get_reg_value(abihelper, sp_reg);
-               sp = be_new_IncSP(sp_reg, new_block, sp,
-                                                 BE_STACK_FRAME_SIZE_SHRINK, 0);
-               arch_irn_add_flags(sp, arch_irn_flags_epilog);
-               be_epilog_set_reg_value(abihelper, sp_reg, sp);
-       }
-#endif
-
        bereturn = be_epilog_create_return(abihelper, dbgi, new_block);
        return bereturn;
 }