From c5b097020aab073264183bdcf76753907f682452 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 17 Oct 2011 15:39:28 +0200 Subject: [PATCH] be: factor out can_move_to function from sparc_emitter --- ir/be/bepeephole.c | 49 ++++++++++++++++ ir/be/bepeephole.h | 10 ++++ ir/be/sparc/sparc_emitter.c | 113 +++++++++++------------------------- 3 files changed, 94 insertions(+), 78 deletions(-) diff --git a/ir/be/bepeephole.c b/ir/be/bepeephole.c index 6f971df5d..a3fa31d14 100644 --- a/ir/be/bepeephole.c +++ b/ir/be/bepeephole.c @@ -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. diff --git a/ir/be/bepeephole.h b/ir/be/bepeephole.h index fca32e943..3731be44a 100644 --- a/ir/be/bepeephole.h +++ b/ir/be/bepeephole.h @@ -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) diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index c9116aeaf..cb37079bf 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -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; } } -- 2.20.1