X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbespill.c;h=2495cc7f3cd174c2696a2387cdf4e079f7fe9aa8;hb=d5975c9df2dee13abedf388f1d70397a2163b69f;hp=ac5120ba8df42ea05d9a6e564fd75a9e1974b38e;hpb=3ae5692990249ceae26a1c7517f2c658c493bb0d;p=libfirm diff --git a/ir/be/bespill.c b/ir/be/bespill.c index ac5120ba8..2495cc7f3 100644 --- a/ir/be/bespill.c +++ b/ir/be/bespill.c @@ -1,10 +1,28 @@ +/* + * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + /** * @file + * @brief Main spill driver. * @author Daniel Grund, Sebastian Hack, Matthias Braun * @date 29.09.2005 * @version $Id$ - * Copyright: (c) Universitaet Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -38,10 +56,12 @@ #include "benodesets.h" #include "bespilloptions.h" #include "bestatevent.h" -#include "beirgmod.h" +#include "bessaconstr.h" +#include "beirg_t.h" +#include "beintlive_t.h" -// only rematerialise when costs are less than REMAT_COST_LIMIT -// TODO determine a good value here... +/* only rematerialise when costs are less than REMAT_COST_LIMIT */ +/* TODO determine a good value here... */ #define REMAT_COST_LIMIT 10 typedef struct _reloader_t reloader_t; @@ -230,12 +250,16 @@ void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before, to_spill, before, allow_remat ? "" : " not")); } -static ir_node *get_reload_insertion_point(ir_node *block, int pos) { +/** + * Returns the point at which you can insert a node that should be executed + * before block @p block when coming from pred @p pos. + */ +static ir_node *get_block_insertion_point(ir_node *block, int pos) { ir_node *predblock, *last; - /* simply add the reload to the beginning of the block if we only have 1 predecessor - * (we don't need to check for phis as there can't be any in a block with only 1 pred) - */ + /* simply add the reload to the beginning of the block if we only have 1 + * predecessor. We don't need to check for phis as there can't be any in a + * block with only 1 pred. */ if(get_Block_n_cfgpreds(block) == 1) { assert(!is_Phi(sched_first(block))); return sched_first(block); @@ -264,7 +288,7 @@ static ir_node *get_reload_insertion_point(ir_node *block, int pos) { void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block, int pos, const arch_register_class_t *reload_cls, int allow_remat) { - ir_node *before = get_reload_insertion_point(block, pos); + ir_node *before = get_block_insertion_point(block, pos); be_add_reload(env, to_spill, before, reload_cls, allow_remat); } @@ -302,9 +326,9 @@ void be_spill_phi(spill_env_t *env, ir_node *node) { */ /** - * Schedules a node after an instruction. (That is the place after all projs and phis - * that are scheduled after the instruction) - * This function also skips phi nodes at the beginning of a block + * Schedules a node after an instruction. That is the place after all projs and + * phis that are scheduled after the instruction. This function also skips phi + * nodes at the beginning of a block */ static void sched_add_after_insn(ir_node *sched_after, ir_node *node) { ir_node *next = sched_next(sched_after); @@ -338,8 +362,8 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) { /* Trying to spill an already spilled value, no need for a new spill * node then, we can simply connect to the same one for this reload * - * (although rematerialization code should handle most of these cases - * this can still happen when spilling Phis) + * Normally reloads get simply rematerialized instead of spilled again; this + * can happen annyway when the reload is the pred of a phi to spill) */ if (be_is_Reload(to_spill)) { spillinfo->spill = get_irn_n(to_spill, be_pos_Reload_mem); @@ -347,14 +371,20 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) { return; } - if (arch_irn_is(env->arch_env, to_spill, dont_spill)) { - assert(0 && "Attempt to spill a node marked 'dont_spill'"); + assert(!(arch_irn_is(env->arch_env, to_spill, dont_spill) + && "Attempt to spill a node marked 'dont_spill'")); + + /* some backends have virtual noreg/unknown nodes that are not scheduled */ + if(!sched_is_scheduled(to_spill)) { + spillinfo->spill = new_NoMem(); + return; } + /* - We switch on optimizations here to get CSE. This is needed as some backends - have some extra spill phases and we want to make use of those spills instead - of creating new ones. + We switch on optimizations here to get CSE. This is needed as some + backends have some extra spill phases and we want to make use of those + spills instead of creating new ones. */ save_optimization_state(&opt); set_optimize(1); @@ -363,8 +393,7 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) { if (! sched_is_scheduled(spillinfo->spill)) { DB((env->dbg, LEVEL_1, "add spill %+F after %+F\n", spillinfo->spill, to_spill)); sched_add_after_insn(to_spill, spillinfo->spill); - } - else { + } else { DB((env->dbg, LEVEL_1, "re-using spill %+F after %+F\n", spillinfo->spill, to_spill)); } } @@ -445,7 +474,7 @@ static void spill_node(spill_env_t *env, spill_info_t *spillinfo) { return; to_spill = spillinfo->spilled_node; - assert(sched_is_scheduled(to_spill) && "Node to be spilled must be scheduled!"); + if (is_Phi(to_spill) && ir_nodeset_contains(&env->mem_phis, to_spill)) { spill_phi(env, spillinfo); } else { @@ -657,7 +686,7 @@ int be_get_reload_costs(spill_env_t *env, ir_node *to_spill, ir_node *before) { } int be_get_reload_costs_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block, int pos) { - ir_node *before = get_reload_insertion_point(block, pos); + ir_node *before = get_block_insertion_point(block, pos); return be_get_reload_costs(env, to_spill, before); } @@ -697,7 +726,7 @@ void be_insert_spills_reloads(spill_env_t *env) { /* go through all reloads for this spill */ for (rld = si->reloaders; rld; rld = rld->next) { - ir_node *copy; /* a reaload is a "copy" of the original value */ + ir_node *copy; /* a reload is a "copy" of the original value */ if (rld->rematted_node != NULL) { copy = rld->rematted_node; @@ -727,14 +756,25 @@ void be_insert_spills_reloads(spill_env_t *env) { /* if we had any reloads or remats, then we need to reconstruct the * SSA form for the spilled value */ if (ARR_LEN(copies) > 0) { - /* Matze: used mem_phis as ignore uses in the past, I don't see how - one of the mem_phis can be a use of the spilled value... - so I changed this to NULL now */ - be_ssa_construction( - be_get_birg_dom_front(env->birg), - be_get_birg_liveness(env->birg), - spilled_node, ARR_LEN(copies), copies, - NULL, 0); + be_ssa_construction_env_t senv; + /* be_lv_t *lv = be_get_birg_liveness(env->birg); */ + + be_ssa_construction_init(&senv, env->birg); + be_ssa_construction_add_copy(&senv, spilled_node); + be_ssa_construction_add_copies(&senv, copies, ARR_LEN(copies)); + be_ssa_construction_fix_users(&senv, spilled_node); + +#if 0 + /* no need to enable this as long as we invalidate liveness + after this function... */ + be_ssa_construction_update_liveness_phis(&senv); + be_liveness_update(spilled_node); + len = ARR_LEN(copies); + for(i = 0; i < len; ++i) { + be_liveness_update(lv, copies[i]); + } +#endif + be_ssa_construction_destroy(&senv); } DEL_ARR_F(copies); @@ -750,7 +790,7 @@ void be_insert_spills_reloads(spill_env_t *env) { #endif /* FIRM_STATISTICS */ be_remove_dead_nodes_from_schedule(env->irg); - /* Matze: In theory be_ssa_construction should take care of the livenes... + /* Matze: In theory be_ssa_construction should take care of the liveness... * try to disable this again in the future */ be_invalidate_liveness(env->birg); }