Commit d476ede5 authored by Matthias Braun's avatar Matthias Braun
Browse files

sparc: peephole - fold copy into restore

parent 1da86703
......@@ -53,7 +53,10 @@ typedef void (*peephole_opt_func) (ir_node *node);
/**
* Notify the peephole phase about a newly added node, so it can update its
* internal state. This is not needed for the new node, when
* be_peephole_exchange() is used. */
* be_peephole_exchange() is used.
* Note: Contrary to normal exchange you mustn't remove the node from the
* schedule either before exchange. Exchange will do that for you.
*/
void be_peephole_new_node(ir_node *nw);
/**
......
......@@ -860,6 +860,31 @@ static void emit_sparc_Return(const ir_node *node)
fill_delay_slot();
}
static const arch_register_t *map_i_to_o_reg(const arch_register_t *reg)
{
unsigned idx = reg->global_index;
if (idx < REG_I0 || idx > REG_I7)
return reg;
idx += REG_O0 - REG_I0;
assert(REG_O0 <= idx && idx <= REG_O7);
return &sparc_registers[idx];
}
static void emit_sparc_Restore(const ir_node *node)
{
const arch_register_t *destreg
= arch_get_irn_register_out(node, pn_sparc_Restore_res);
be_emit_cstring("\trestore ");
sparc_emit_source_register(node, 1);
be_emit_cstring(", ");
sparc_emit_reg_or_imm(node, 2);
be_emit_cstring(", ");
destreg = map_i_to_o_reg(destreg);
be_emit_char('%');
be_emit_string(arch_register_get_name(destreg));
be_emit_finish_line_gas(node);
}
static void emit_sparc_FrameAddr(const ir_node *node)
{
const sparc_attr_t *attr = get_sparc_attr_const(node);
......@@ -1134,6 +1159,7 @@ static void sparc_register_emitters(void)
set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr);
set_emitter(op_sparc_SMulh, emit_sparc_Mulh);
set_emitter(op_sparc_UMulh, emit_sparc_Mulh);
set_emitter(op_sparc_Restore, emit_sparc_Restore);
set_emitter(op_sparc_Return, emit_sparc_Return);
set_emitter(op_sparc_SDiv, emit_sparc_SDiv);
set_emitter(op_sparc_SwitchJmp, emit_sparc_SwitchJmp);
......
......@@ -417,6 +417,55 @@ static void peephole_sparc_FrameAddr(ir_node *node)
(void) node;
}
static bool is_restorezeroopt_reg(const arch_register_t *reg)
{
unsigned index = reg->global_index;
return (index >= REG_G0 && index <= REG_G7)
|| (index >= REG_I0 && index <= REG_I7);
}
static void peephole_sparc_RestoreZero(ir_node *node)
{
/* restore gives us a free "add" instruction, let's try to use that to fold
* an instruction in */
ir_node *try = sched_prev(node);
/* output must not be local, or out reg (it would be strange though if
* they were) */
if (be_is_Copy(try)) {
dbg_info *dbgi;
ir_node *block;
ir_node *new_restore;
ir_node *op;
ir_node *fp;
ir_node *res;
ir_node *stack;
ir_mode *mode;
const arch_register_t *reg = arch_get_irn_register(try);
if (!is_restorezeroopt_reg(reg))
return;
op = get_irn_n(try, n_be_Copy_op);
fp = get_irn_n(node, n_sparc_RestoreZero_frame_pointer);
dbgi = get_irn_dbg_info(node);
block = get_nodes_block(node);
new_restore = new_bd_sparc_Restore_imm(dbgi, block, fp, op, NULL, 0);
arch_set_irn_register_out(new_restore, pn_sparc_Restore_stack,
&sparc_registers[REG_SP]);
arch_set_irn_register_out(new_restore, pn_sparc_Restore_res,
reg);
mode = get_irn_mode(node);
stack = new_r_Proj(new_restore, mode, pn_sparc_Restore_stack);
res = new_r_Proj(new_restore, mode, pn_sparc_Restore_res);
sched_add_before(node, new_restore);
be_peephole_exchange(node, stack);
be_peephole_exchange(try, res);
}
}
static void finish_sparc_Return(ir_node *node)
{
ir_node *schedpoint = node;
......@@ -512,6 +561,8 @@ void sparc_finish(ir_graph *irg)
clear_irp_opcodes_generic_func();
register_peephole_optimisation(op_be_IncSP, peephole_be_IncSP);
register_peephole_optimisation(op_sparc_FrameAddr, peephole_sparc_FrameAddr);
register_peephole_optimisation(op_sparc_RestoreZero,
peephole_sparc_RestoreZero);
be_peephole_opt(irg);
/* perform legalizations (mostly fix nodes with too big immediates) */
......
......@@ -104,9 +104,11 @@ $mode_fp4 = "mode_E"; # not correct, we need to register a new mode
# emit source reg or imm dep. on node's arity
RI => "${arch}_emit_reg_or_imm(node, -1);",
R1I => "${arch}_emit_reg_or_imm(node, 1);",
R2I => "${arch}_emit_reg_or_imm(node, 2);",
S0 => "${arch}_emit_source_register(node, 0);",
S1 => "${arch}_emit_source_register(node, 1);",
D0 => "${arch}_emit_dest_register(node, 0);",
D1 => "${arch}_emit_dest_register(node, 1);",
HIM => "${arch}_emit_high_immediate(node);",
LM => "${arch}_emit_load_mode(node);",
SM => "${arch}_emit_store_mode(node);",
......@@ -407,22 +409,19 @@ Save => {
},
Restore => {
emit => '. restore %S0, %R1I, %D0',
outs => [ "stack" ],
ins => [ "stack" ],
outs => [ "stack", "res" ],
constructors => {
imm => {
attr => "ir_entity *immediate_entity, int32_t immediate_value",
custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
reg_req => { in => [ "sp" ], out => [ "sp:I|S" ] },
ins => [ "stack" ],
reg_req => { in => [ "frame_pointer", "gp" ], out => [ "sp:I|S", "gp" ] },
ins => [ "frame_pointer", "left" ],
},
reg => {
reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
ins => [ "stack", "increment" ],
reg_req => { in => [ "frame_pointer", "gp", "gp" ], out => [ "sp:I|S", "gp" ] },
ins => [ "frame_pointer", "left", "right" ],
}
},
mode => $mode_gp,
},
RestoreZero => {
......
Supports Markdown
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