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

be: factor out can_move_to function from sparc_emitter

parent 6da9f4a5
......@@ -248,6 +248,55 @@ bool be_has_only_one_user(ir_node *node)
return n_users == 1;
}
bool be_can_move_before(const ir_node *node, const ir_node *before)
{
int node_arity = get_irn_arity(node);
ir_node *schedpoint = sched_next(node);
while (schedpoint != before) {
int i;
int arity = get_irn_arity(schedpoint);
unsigned n_outs = arch_get_irn_n_outs(schedpoint);
/* the node must not use our computed values */
for (i = 0; i < arity; ++i) {
ir_node *in = get_irn_n(schedpoint, i);
if (skip_Proj(in) == node)
return false;
}
/* the node must not overwrite registers of our inputs */
for (i = 0; i < node_arity; ++i) {
ir_node *in = get_irn_n(node, i);
const arch_register_t *reg = arch_get_irn_register(in);
const arch_register_req_t *in_req
= arch_get_irn_register_req_in(node, i);
unsigned o;
if (reg == NULL)
continue;
for (o = 0; o < n_outs; ++o) {
const arch_register_t *outreg
= arch_get_irn_register_out(schedpoint, o);
const arch_register_req_t *outreq
= arch_get_irn_register_req_out(schedpoint, o);
if (outreg == NULL)
continue;
if (outreg->global_index >= reg->global_index
&& outreg->global_index
< (unsigned)reg->global_index + in_req->width)
return false;
if (reg->global_index >= outreg->global_index
&& reg->global_index
< (unsigned)outreg->global_index + outreq->width)
return false;
}
}
schedpoint = sched_next(schedpoint);
}
return true;
}
/*
* Tries to optimize a beIncSP node with its previous IncSP node.
* Must be run from a be_peephole_opt() context.
......
......@@ -73,6 +73,16 @@ ir_node *be_peephole_IncSP_IncSP(ir_node *node);
bool be_has_only_one_user(ir_node *node);
/**
* In a scheduled program with registers assigned,
* checks wether @p node can be moved before @p before without changing program
* semantics.
*
* Note: It is allowed to use this function without being in a peephole
* optimization phase.
*/
bool be_can_move_before(const ir_node *node, const ir_node *before);
/**
* Do peephole optimisations. It traverses the schedule of all blocks in
* backward direction. The register_values variable indicates which (live)
......
......@@ -50,6 +50,7 @@
#include "be_dbgout.h"
#include "benode.h"
#include "bestack.h"
#include "bepeephole.h"
#include "sparc_emitter.h"
#include "gen_sparc_emitter.h"
......@@ -392,85 +393,41 @@ static bool writes_reg(const ir_node *node, const arch_register_t *reg)
static bool can_move_into_delayslot(const ir_node *node, const ir_node *to)
{
int node_arity = get_irn_arity(node);
ir_node *schedpoint = sched_next(node);
while (true) {
if (schedpoint != to) {
int i;
int arity = get_irn_arity(schedpoint);
unsigned n_outs = arch_get_irn_n_outs(schedpoint);
/* the node must not use our computed values */
for (i = 0; i < arity; ++i) {
ir_node *in = get_irn_n(schedpoint, i);
if (skip_Proj(in) == node)
return false;
}
/* the node must not overwrite registers of our inputs */
for (i = 0; i < node_arity; ++i) {
ir_node *in = get_irn_n(node, i);
const arch_register_t *reg = arch_get_irn_register(in);
const arch_register_req_t *in_req
= arch_get_irn_register_req_in(node, i);
unsigned o;
if (reg == NULL)
continue;
for (o = 0; o < n_outs; ++o) {
const arch_register_t *outreg
= arch_get_irn_register_out(schedpoint, o);
const arch_register_req_t *outreq
= arch_get_irn_register_req_out(schedpoint, o);
if (outreg == NULL)
continue;
if (outreg->global_index >= reg->global_index
&& outreg->global_index
< (unsigned)reg->global_index + in_req->width)
return false;
if (reg->global_index >= outreg->global_index
&& reg->global_index
< (unsigned)outreg->global_index + outreq->width)
return false;
}
}
} else {
if (is_sparc_Call(to)) {
ir_node *check;
/** all deps are used after the delay slot so, we're fine */
if (!is_sparc_reg_call(to))
return true;
check = get_irn_n(to, get_sparc_Call_dest_addr_pos(to));
if (skip_Proj(check) == node)
return false;
/* the Call also destroys the value of %o7, but since this is
* currently marked as ignore register in the backend, it
* should never be used by the instruction in the delay slot. */
if (uses_reg(node, &sparc_registers[REG_O7]))
return false;
return true;
} else if (is_sparc_Return(to)) {
/* return uses the value of %o7, all other values are not
* immediately used */
if (writes_reg(node, &sparc_registers[REG_O7]))
return false;
return true;
} else {
/* the node must not use our computed values */
int arity = get_irn_arity(to);
int i;
for (i = 0; i < arity; ++i) {
ir_node *in = get_irn_n(to, i);
if (skip_Proj(in) == node)
return false;
}
return true;
}
}
if (!be_can_move_before(node, to))
return false;
schedpoint = sched_next(schedpoint);
if (is_sparc_Call(to)) {
ir_node *check;
/** all deps are used after the delay slot so, we're fine */
if (!is_sparc_reg_call(to))
return true;
check = get_irn_n(to, get_sparc_Call_dest_addr_pos(to));
if (skip_Proj(check) == node)
return false;
/* the Call also destroys the value of %o7, but since this is
* currently marked as ignore register in the backend, it
* should never be used by the instruction in the delay slot. */
if (uses_reg(node, &sparc_registers[REG_O7]))
return false;
return true;
} else if (is_sparc_Return(to)) {
/* return uses the value of %o7, all other values are not
* immediately used */
if (writes_reg(node, &sparc_registers[REG_O7]))
return false;
return true;
} else {
/* the node must not use our computed values */
int arity = get_irn_arity(to);
int i;
for (i = 0; i < arity; ++i) {
ir_node *in = get_irn_n(to, i);
if (skip_Proj(in) == node)
return false;
}
return true;
}
}
......
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