Commit 2ba0d753 authored by Matthias Braun's avatar Matthias Braun
Browse files

adapt sparc backend to new prolog/epilog handling

parent df2b9574
......@@ -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;
......
......@@ -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
......@@ -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;
......
......@@ -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
......@@ -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));
......
......@@ -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);
......
......@@ -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)
......
......@@ -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
......@@ -44,11 +44,120 @@
#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);
......
......@@ -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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment