/* TEMPLATE emitter */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef _WIN32
/* The codegenrator (transform FIRM into TEMPLATE FIRM */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "irnode_t.h"
/* The main TEMPLATE backend driver file. */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "pseudo_irg.h"
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_MALLOC_H
* @cvsid $Id$
*/
#ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
#endif
#include "obst.h"
DEBUG_ONLY(firm_dbg_module_t *dbg;) /**< The debugging module. */
};
-#if 0
-#define get_abi_from_handler(ptr) firm_container_of(ptr, be_abi_irg_t, irn_handler)
-#define get_abi_from_ops(ptr) firm_container_of(ptr, be_abi_irg_t, irn_ops)
-
-/* Forward, since be need it in be_abi_introduce(). */
-static const arch_irn_ops_if_t abi_irn_ops;
-static const arch_irn_handler_t abi_irn_handler;
-#endif
static heights_t *ir_heights;
/* Flag: if set, try to omit the frame pointer if called by the backend */
static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, ir_node *alloca_copy)
{
ir_graph *irg = env->birg->irg;
- const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
+ const arch_env_t *arch_env = env->birg->main_env->arch_env;
+ const arch_isa_t *isa = arch_env->isa;
ir_type *mt = get_Call_type(irn);
ir_node *call_ptr = get_Call_ptr(irn);
int n_params = get_method_n_params(mt);
assert(arg->in_reg);
be_set_constr_single_reg(low_call, BE_OUT_POS(pn), arg->reg);
+ arch_set_irn_register(arch_env, res_projs[i], arg->reg);
}
obstack_free(obst, in);
exchange(irn, low_call);
restore_optimization_state(&state);
FIRM_DBG_REGISTER(env->dbg, "firm.be.abi");
-#if 0
- memcpy(&env->irn_handler, &abi_irn_handler, sizeof(abi_irn_handler));
- env->irn_ops.impl = &abi_irn_ops;
-#endif
-
env->calls = NEW_ARR_F(ir_node*, 0);
/* Lower all call nodes in the IRG. */
survive_dce_register_irn(env->dce_survivor, (ir_node **) &ent->value);
}
-#if 0
- arch_env_push_irn_handler(env->birg->main_env->arch_env, &env->irn_handler);
-#endif
-
env->call->cb->done(env->cb);
env->cb = NULL;
return env;
del_pset(env->ignore_regs);
pmap_destroy(env->regs);
obstack_free(&env->obst, NULL);
-#if 0
- arch_env_pop_irn_handler(env->birg->main_env->arch_env);
-#endif
free(env);
}
*/
+typedef ir_node **node_array;
+
typedef struct fix_stack_walker_env_t {
- ir_node **nodes;
+ node_array sp_nodes;
+ node_array *state_nodes;
+ const arch_register_t **state_regs;
const arch_env_t *arch_env;
} fix_stack_walker_env_t;
if (arch_irn_is(env->arch_env, node, modify_sp)) {
assert(get_irn_mode(node) != mode_M && get_irn_mode(node) != mode_T);
- ARR_APP1(ir_node*, env->nodes, node);
+ ARR_APP1(ir_node*, env->sp_nodes, node);
+ }
+
+ if(ARR_LEN(env->state_nodes) > 0) {
+ int i, n;
+ const arch_register_t *reg = arch_get_irn_register(env->arch_env, node);
+
+ n = ARR_LEN(env->state_nodes);
+ for(i = 0; i < n; ++i) {
+ if(reg == env->state_regs[i]) {
+ ARR_APP1(ir_node*, env->state_nodes[i], node);
+ }
+ }
}
}
-void be_abi_fix_stack_nodes(be_abi_irg_t *env, be_lv_t *lv)
+void be_abi_fix_stack_nodes(be_abi_irg_t *env)
{
- int i;
+ int i, n;
ir_node **phis;
be_irg_t *birg = env->birg;
fix_stack_walker_env_t walker_env;
+ arch_isa_t *isa;
- walker_env.nodes = NEW_ARR_F(ir_node*, 0);
+ walker_env.sp_nodes = NEW_ARR_F(ir_node*, 0);
walker_env.arch_env = birg->main_env->arch_env;
+ walker_env.state_nodes = NEW_ARR_F(node_array, 0);
+ walker_env.state_regs = NEW_ARR_F(const arch_register_t*, 0);
+ isa = walker_env.arch_env->isa;
- be_assure_dom_front(birg);
+ /* collect all state registers */
+ for(i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
+ const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
+ int j, n_regs = cls->n_regs;
+
+ for(j = 0; j < n_regs; ++j) {
+ const arch_register_t *reg = arch_register_for_index(cls, j);
+ if(arch_register_type_is(reg, state)) {
+ node_array arr = NEW_ARR_F(ir_node*, 0);
+ ARR_APP1(node_array, walker_env.state_nodes, arr);
+ ARR_APP1(const arch_register_t*, walker_env.state_regs, reg);
+ }
+ }
+ }
irg_walk_graph(birg->irg, collect_stack_nodes_walker, NULL, &walker_env);
+ be_assure_dom_front(birg);
phis = be_ssa_construction(
be_get_birg_dom_front(birg),
be_get_birg_liveness(birg),
env->init_sp,
- ARR_LEN(walker_env.nodes), walker_env.nodes,
+ ARR_LEN(walker_env.sp_nodes), walker_env.sp_nodes,
NULL, 1);
/* set register requirements for stack phis */
}
DEL_ARR_F(phis);
- DEL_ARR_F(walker_env.nodes);
+ DEL_ARR_F(walker_env.sp_nodes);
+
+ n = ARR_LEN(walker_env.state_nodes);
+ for(i = 0; i < n; ++i) {
+ const arch_register_t *reg = walker_env.state_regs[i];
+ node_array nodes = walker_env.state_nodes[i];
+ ir_node *initial_value = be_abi_reg_map_get(env->regs, reg);
+
+ phis = be_ssa_construction(
+ be_get_birg_dom_front(birg),
+ be_get_birg_liveness(birg),
+ initial_value,
+ ARR_LEN(nodes), nodes,
+ NULL, 1);
+
+ /* set registers for the phis */
+ for(i = 0; i < ARR_LEN(phis); ++i) {
+ ir_node *phi = phis[i];
+ be_set_phi_flags(walker_env.arch_env, phi, arch_irn_flags_ignore);
+ arch_set_irn_register(walker_env.arch_env, phi, reg);
+ }
+ DEL_ARR_F(phis);
+ DEL_ARR_F(nodes);
+ }
}
static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias)
return abi->start_barrier;
}
-#if 0
-/*
- _____ _____ _ _ _ _ _ _
- |_ _| __ \| \ | | | | | | | | |
- | | | |__) | \| | | |__| | __ _ _ __ __| | | ___ _ __
- | | | _ /| . ` | | __ |/ _` | '_ \ / _` | |/ _ \ '__|
- _| |_| | \ \| |\ | | | | | (_| | | | | (_| | | __/ |
- |_____|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_|
-
- for Phi nodes which are created due to stack modifying nodes
- such as IncSP, AddSP and SetSP.
-
- These Phis are always to be ignored by the reg alloc and are
- fixed on the SP register of the ISA.
-*/
-
-static const void *abi_get_irn_ops(const arch_irn_handler_t *handler, const ir_node *irn)
-{
- const be_abi_irg_t *abi = get_abi_from_handler(handler);
- const void *res = NULL;
-
- if(is_Phi(irn) && pset_find_ptr(abi->stack_phis, (void *) irn))
- res = &abi->irn_ops;
-
- return res;
-}
-
-static
-const arch_register_req_t *abi_get_irn_reg_req(const void *self,
- const ir_node *irn, int pos)
-{
- be_abi_irg_t *abi = get_abi_from_ops(self);
-
- if(pos == BE_OUT_POS(0)) {
- return &abi->sp_req;
- } else if(pos >= 0 && pos < get_irn_arity(irn)) {
- return &abi->sp_cls_req;
- }
-
- return arch_no_register_req;
-}
-
-static void abi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg)
-{
-}
-
-static const arch_register_t *abi_get_irn_reg(const void *self, const ir_node *irn)
-{
- const be_abi_irg_t *abi = get_abi_from_ops(self);
- return abi->isa->sp;
-}
-
-static arch_irn_class_t abi_classify(const void *_self, const ir_node *irn)
-{
- return arch_irn_class_normal;
-}
-
-static arch_irn_flags_t abi_get_flags(const void *_self, const ir_node *irn)
-{
- return arch_irn_flags_ignore | arch_irn_flags_modify_sp;
-}
-
-static ir_entity *abi_get_frame_entity(const void *_self, const ir_node *irn)
-{
- return NULL;
-}
-
-static void abi_set_frame_entity(const void *_self, ir_node *irn, ir_entity *ent)
-{
-}
-
-static void abi_set_frame_offset(const void *_self, ir_node *irn, int bias)
-{
-}
-
-static int abi_get_sp_bias(const void *self, const ir_node *irn)
-{
- return 0;
-}
-
-static const arch_irn_ops_if_t abi_irn_ops = {
- abi_get_irn_reg_req,
- abi_set_irn_reg,
- abi_get_irn_reg,
- abi_classify,
- abi_get_flags,
- abi_get_frame_entity,
- abi_set_frame_entity,
- abi_set_frame_offset,
- abi_get_sp_bias,
- NULL, /* get_inverse */
- NULL, /* get_op_estimated_cost */
- NULL, /* possible_memory_operand */
- NULL, /* perform_memory_operand */
-};
-
-static const arch_irn_handler_t abi_irn_handler = {
- abi_get_irn_ops
-};
-#endif
-
/**
* Returns non-zero if the ABI has omitted the frame pointer in
* the current graph.
/**
* Rewire all stack modifying nodes and their users to assure SSA property.
* @param env The abi
- * @param lv Liveness object, so the liveness of changed and newly introduces nodes
- * can be recomputed. Maybe NULL (no liveness information update then)
*/
-void be_abi_fix_stack_nodes(be_abi_irg_t *env, be_lv_t *lv);
+void be_abi_fix_stack_nodes(be_abi_irg_t *env);
/**
* Put the registers which are forbidden specifically for this IRG in a bitset.
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_ALLOCA_H
* CVS-Id: $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "beblocksched.h"
* Released under the GPL
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_MALLOC_H
* Driver for the chordal register allocator.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <time.h>
*/
if (iteration == 0) {
check_for_memory_operands(chordal_env);
- be_abi_fix_stack_nodes(birg->abi, birg->lv);
+ be_abi_fix_stack_nodes(birg->abi);
}
BE_TIMER_PUSH(ra_timer.t_verify);
* conflicts is the best one.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_ALLOCA_H
* @date 14.04.2006
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <libcore/lc_opts.h>
* @date 25.07.2006
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <libcore/lc_opts.h>
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_ALLOCA_H
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "bedomfront.h"
* License: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "beemitter.h"
* @version $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "begnuas.h"
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "irgraph_t.h"
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
* @cvs-id $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdio.h>
* @date 6.12.2004
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "impl.h"
* Compute register pressure in loops
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "set.h"
* Performs lowering of perm nodes and spill/reload optimization.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
/* connect all stack modifying nodes together (see beabi.c) */
BE_TIMER_PUSH(t_abi);
- be_abi_fix_stack_nodes(birg->abi, NULL);
+ be_abi_fix_stack_nodes(birg->abi);
BE_TIMER_POP(t_abi);
dump(DUMP_SCHED, irg, "-fix_stack", dump_ir_block_graph_sched);
/* fix stack offsets */
BE_TIMER_PUSH(t_abi);
- be_abi_fix_stack_nodes(birg->abi, NULL);
+ be_abi_fix_stack_nodes(birg->abi);
be_remove_dead_nodes_from_schedule(irg);
be_abi_fix_stack_bias(birg->abi);
BE_TIMER_POP(t_abi);
* CVS-Id: $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
void be_init_loopana(void);
void be_init_spillslots(void);
void be_init_live(void);
+void be_init_state(void);
void be_quit_copystat(void);
be_init_ra();
be_init_spillbelady();
be_init_spillmorgan();
+ be_init_state();
be_init_ifg();
be_init_arch_ia32();
* Released under the GPL
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
dump_to_file(&raenv, out);
execute(callee, out, in);
done = read_and_apply_results(&raenv, in);
- be_abi_fix_stack_nodes(birg->abi, birg->lv);
+ be_abi_fix_stack_nodes(birg->abi);
ir_snprintf(in, sizeof(in), "-extern-%s-round-%d", raenv.cls->name, round);
be_dump(irg, in, dump_ir_block_graph_sched);
* @cvs-id $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
* @cvs-id $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
* @cvs-id $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
* @cvs-id $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
*
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_ALLOCA_H
*
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "bespillmorgan.h"
del_pset(use_end);
}
+#ifndef NDEBUG
/**
* Find a remat of value @p value in the epilog of @p pos
*/
return NULL;
}
+#endif
static spill_t *
add_to_spill_bb(spill_ilp_t * si, ir_node * bb, ir_node * irn)
assert(has_reg_class(si, tmp));
}
+#ifndef NDEBUG
for (n=get_irn_arity(irn)-1; n>=0; --n) {
ir_node *arg = get_irn_n(irn, n);
assert(!find_post_remat(arg, irn) && "there should be no post remat for an argument of an op");
}
+#endif
del_pset(remat_defs);
del_pset(used);
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
* @cvsid $Id$
*/
#ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
#endif
#include <stdio.h>
--- /dev/null
+/**
+ * @file
+ * @brief Handles state switching. This is basically the belady spill
+ * algorithm optimized for the 1-register case.
+ * @author Matthias Braun
+ * @date 26.03.2007
+ * @version $Id$
+ * Copyright: (c) Universitaet Karlsruhe
+ * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "bestate.h"
+
+#include "obst.h"
+#include "irgraph_t.h"
+#include "irnode_t.h"
+#include "irgwalk.h"
+#include "irloop.h"
+#include "iredges_t.h"
+#include "ircons_t.h"
+#include "irgmod.h"
+
+#include "bearch.h"
+#include "beuses_t.h"
+#include "besched_t.h"
+#include "belive_t.h"
+#include "bemodule.h"
+#include "benode_t.h"
+#include "beirgmod.h"
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
+
+typedef struct spill_info_t {
+ struct spill_info_t *next;
+ ir_node *value;
+ ir_node *spill;
+ ir_node **reloads;
+} spill_info_t;
+
+typedef struct minibelady_env_t {
+ struct obstack obst;
+ const arch_env_t *arch_env;
+ const arch_register_t *reg;
+ const be_lv_t *lv;
+ void *func_env;
+ create_reload_func create_reload;
+ create_spill_func create_spill;
+ spill_info_t *spills;
+
+ be_uses_t *uses; /**< env for the next-use magic */
+} minibelady_env_t;
+
+typedef struct block_info_t {
+ ir_node *start_state;
+ ir_node *end_state;
+} block_info_t;
+
+static INLINE
+block_info_t *new_block_info(struct obstack *obst, ir_node *block)
+{
+ block_info_t *res = obstack_alloc(obst, sizeof(*res));
+ memset(res, 0, sizeof(res[0]));
+
+ set_irn_link(block, res);
+ mark_irn_visited(block);
+
+ return res;
+}
+
+static INLINE
+block_info_t *get_block_info(ir_node *block)
+{
+ assert(irn_visited(block));
+ return (block_info_t*) get_irn_link(block);
+}
+
+static INLINE
+spill_info_t *create_spill_info(minibelady_env_t *env, ir_node *value)
+{
+ spill_info_t *spill_info = obstack_alloc(&env->obst, sizeof(spill_info[0]));
+ memset(spill_info, 0, sizeof(spill_info[0]));
+ spill_info->value = value;
+ spill_info->reloads = NEW_ARR_F(ir_node*, 0);
+
+ set_irn_link(value, spill_info);
+ mark_irn_visited(value);
+
+ spill_info->next = env->spills;
+ env->spills = spill_info;
+
+ return spill_info;
+}
+
+static
+spill_info_t *create_spill(minibelady_env_t *env, ir_node *value, int force)
+{
+ spill_info_t *spill_info;
+
+ if(irn_visited(value)) {
+ spill_info = (spill_info_t*) get_irn_link(value);
+ if(spill_info->spill != NULL || !force)
+ return spill_info;
+ } else {
+ spill_info = create_spill_info(env, value);
+ }
+
+ spill_info->spill = env->create_spill(env->func_env, value, force);
+
+ return spill_info;
+}
+
+static
+void create_reload(minibelady_env_t *env, ir_node *value, ir_node *before)
+{
+ spill_info_t *spill_info = create_spill(env, value, 0);
+ ir_node *spill = spill_info->spill;
+ ir_node *reload;
+
+ reload = env->create_reload(env->func_env, value, spill, before);
+ ARR_APP1(ir_node*, spill_info->reloads, reload);
+}
+
+static
+void spill_phi(minibelady_env_t *env, ir_node *phi)
+{
+ ir_graph *irg = get_irn_irg(phi);
+ ir_node *block = get_nodes_block(phi);
+ int i, arity = get_irn_arity(phi);
+ ir_node **in = alloca(arity * sizeof(in[0]));
+ ir_node *spill_to_kill = NULL;
+ spill_info_t *spill_info;
+
+ /* does a spill exist for the phis value? */
+ if(irn_visited(phi)) {
+ spill_info = (spill_info_t*) get_irn_link(phi);
+ spill_to_kill = spill_info->spill;
+ } else {
+ spill_info = create_spill_info(env, phi);
+ }
+
+ /* create a new phi-M with bad preds */
+ for(i = 0; i < arity; ++i) {
+ in[i] = new_r_Bad(irg);
+ }
+
+ DBG((dbg, LEVEL_2, "\tcreate Phi-M for %+F\n", phi));
+
+ /* create a Phi-M */
+ spill_info->spill = new_r_Phi(irg, block, arity, in, mode_M);
+
+ if(spill_to_kill != NULL) {
+ exchange(spill_to_kill, spill_info->spill);
+ sched_remove(spill_to_kill);
+ }
+
+ /* create spills for the phi values */
+ for(i = 0; i < arity; ++i) {
+ ir_node *in = get_irn_n(phi, i);
+ spill_info_t *pred_spill = create_spill(env, in, 1);
+ set_irn_n(spill_info->spill, i, pred_spill->spill);
+ }
+}
+
+static
+void belady(minibelady_env_t *env, ir_node *block);
+
+/**
+ * Collects all values live-in at block @p block and all phi results in this
+ * block.
+ * Then it adds the best values (at most n_regs) to the blocks start_workset.
+ * The phis among the remaining values get spilled: Introduce psudo-copies of
+ * their args to break interference and make it possible to spill them to the
+ * same spill slot.
+ */
+static
+block_info_t *compute_block_start_state(minibelady_env_t *env, ir_node *block)
+{
+ block_info_t *block_info;
+ be_next_use_t next_use;
+ ir_loop *loop;
+ ir_node *best_starter, *first;
+ ir_node *node;
+ int n_cfgpreds;
+ unsigned best_time;
+ int outer_loop_allowed;
+ int i;
+
+ /* Create the block info for this block. */
+ block_info = new_block_info(&env->obst, block);
+ n_cfgpreds = get_Block_n_cfgpreds(block);
+
+ /* no cfgpred -> no value active */
+ if(n_cfgpreds == 0) {
+ block_info->start_state = NULL;
+ return block_info;
+ }
+
+ /* for 1 pred only: simply take the the end-state of the pred */
+ if(n_cfgpreds == 1) {
+ ir_node *pred_block = get_Block_cfgpred_block(block, 0);
+ block_info_t *pred_info;
+
+ /* process pred block */
+ belady(env, pred_block);
+
+ pred_info = get_block_info(pred_block);
+
+ DBG((dbg, LEVEL_2, "Taking end state from %+F: %+F\n", pred_block, pred_info->end_state));
+ block_info->start_state = pred_info->end_state;
+ return block_info;
+ }
+
+ /* Collect all values living at start of block */
+ DBG((dbg, LEVEL_2, "Living at start of %+F:\n", block));
+ first = sched_first(block);
+ loop = get_irn_loop(block);
+ best_starter = NULL;
+ best_time = USES_INFINITY;
+ outer_loop_allowed = 1;
+
+ /* check all Phis first */
+ sched_foreach(block, node) {
+ if (!is_Phi(node))
+ break;
+ if (arch_get_irn_register(env->arch_env, node) != env->reg)
+ continue;
+
+ DBG((dbg, LEVEL_2, "\t...checking %+F\n", node));
+ next_use = be_get_next_use(env->uses, first, 0, node, 0);
+
+ if(USES_IS_INFINITE(next_use.time)) {
+ DBG((dbg, LEVEL_2, "\tnot taken (dead)\n"));
+ continue;
+ }
+
+ if(next_use.outermost_loop >= get_loop_depth(loop)) {
+ if(outer_loop_allowed || next_use.time < best_time) {
+ DBG((dbg, LEVEL_2, "\ttaken (%u, loop %d)\n", next_use.time,
+ next_use.outermost_loop));
+
+ if(best_starter != NULL) {
+ /* spill the phi as it is not used */
+ spill_phi(env, best_starter);
+ }
+ best_starter = node;
+ best_time = next_use.time;
+ outer_loop_allowed = 0;
+ }
+ } else {
+ if(outer_loop_allowed && next_use.time < best_time) {
+ DBG((dbg, LEVEL_2, "\ttaken (%u, loop %d)\n", next_use.time,
+ next_use.outermost_loop));
+ if(best_starter != NULL) {
+ /* spill the phi as it is not used */
+ spill_phi(env, best_starter);
+ }
+ best_starter = node;
+ best_time = next_use.time;
+ }
+ }
+
+ if(best_starter != node) {
+ /* spill the phi as it is not used */
+ spill_phi(env, best_starter);
+ }
+ }
+
+ /* check all Live-Ins */
+ be_lv_foreach(env->lv, block, be_lv_state_in, i) {
+ node = be_lv_get_irn(env->lv, block, i);
+
+ if (arch_get_irn_register(env->arch_env, node) != env->reg)
+ continue;
+
+ DBG((dbg, LEVEL_2, "\t...checking %+F\n", node));
+ next_use = be_get_next_use(env->uses, first, 0, node, 0);
+
+ if(USES_IS_INFINITE(next_use.time)) {
+ DBG((dbg, LEVEL_2, "\tnot taken (dead)\n"));
+ continue;
+ }
+
+ if(next_use.outermost_loop >= get_loop_depth(loop)) {
+ if(outer_loop_allowed || next_use.time < best_time) {
+ DBG((dbg, LEVEL_2, "\ttaken (%u, loop %d)\n", next_use.time,
+ next_use.outermost_loop));
+
+ if(best_starter != NULL && is_Phi(best_starter)) {
+ /* spill the phi as it is not used */
+ spill_phi(env, best_starter);
+ }
+ best_starter = node;
+ best_time = next_use.time;
+ outer_loop_allowed = 0;
+ }
+ } else {
+ if(outer_loop_allowed && next_use.time < best_time) {
+ DBG((dbg, LEVEL_2, "\ttaken (%u, loop %d)\n", next_use.time,
+ next_use.outermost_loop));
+ if(best_starter != NULL && is_Phi(best_starter)) {
+ /* spill the phi as it is not used */
+ spill_phi(env, best_starter);
+ }
+ best_starter = node;
+ best_time = next_use.time;
+ }
+ }
+ }
+
+ /* TODO: spill phis */
+
+ block_info->start_state = best_starter;
+
+ return block_info;
+}
+
+/**
+ * For the given block @p block, decide for each values
+ * whether it is used from a register or is reloaded
+ * before the use.
+ */
+static
+void belady(minibelady_env_t *env, ir_node *block)
+{
+ ir_node *current_state;
+ ir_node *node;
+ block_info_t *block_info;
+
+ /* Don't do a block twice */
+ if(irn_visited(block))
+ return;
+
+ /* compute value to start with */
+ block_info = compute_block_start_state(env, block);
+
+ /* get the starting workset for this block */
+ DBG((dbg, LEVEL_3, "\n"));
+ DBG((dbg, LEVEL_3, "Decide for %+F\n", block));
+
+ current_state = block_info->start_state;
+ DBG((dbg, LEVEL_3, "Start value: %+F\n", current_state));
+
+ /* process the block from start to end */
+ DBG((dbg, LEVEL_3, "Processing...\n"));
+
+ sched_foreach(block, node) {
+ int i, arity;
+ ir_node *need_val = NULL;
+
+ /* projs are handled with the tuple value.
+ * Phis are no real instr (see insert_starters()) */
+ if (is_Proj(node) || is_Phi(node)) {
+ continue;
+ }
+
+ /* check which state is desired for the node */
+ arity = get_irn_arity(node);
+ for(i = 0; i < arity; ++i) {
+ ir_node *in = get_irn_n(node, i);
+ const arch_register_t *reg =
+ arch_get_irn_register(env->arch_env, in);
+ if(reg == env->reg) {
+ assert(need_val == NULL);
+ need_val = in;
+ DBG((dbg, LEVEL_3, "\t... need state %+F\n", need_val));
+ }
+ }
+ /* create a reload to match state if necessary */
+ if(need_val != NULL && need_val != current_state) {
+ create_reload(env, need_val, node);
+ }
+
+ DBG((dbg, LEVEL_3, " ...%+F\n", node));
+
+ /* record state changes by the node */
+ if (get_irn_mode(node) == mode_T) {
+ ir_node *proj;
+ for(proj = sched_next(node); is_Proj(proj);
+ proj = sched_next(proj)) {
+ const arch_register_t *reg =
+ arch_get_irn_register(env->arch_env, proj);
+ if(reg == env->reg) {
+ current_state = proj;
+ DBG((dbg, LEVEL_3, "\t... current_state <- %+F\n", current_state));
+ }
+ }
+ } else {
+ const arch_register_t *reg =
+ arch_get_irn_register(env->arch_env, node);
+ if(reg == env->reg) {
+ current_state = node;
+ DBG((dbg, LEVEL_3, "\t... current_state <- %+F\n", current_state));
+ }
+ }
+ }
+
+ /* Remember end-workset for this block */
+ block_info->end_state = current_state;
+ DBG((dbg, LEVEL_3, "End value for %+F: %+F\n", block, current_state));
+}
+
+static
+void belady_walker(ir_node *block, void *data)
+{
+ belady((minibelady_env_t*) data, block);
+}
+
+static
+ir_node *get_end_of_block_insertion_point(ir_node *block)
+{
+ ir_node *last = sched_last(block);
+
+ /* skip projs and keepanies behind the jump... */
+ while(is_Proj(last) || be_is_Keep(last)) {
+ last = sched_prev(last);
+ }
+
+ if(!is_cfop(last)) {
+ last = sched_next(last);
+ // last node must be a cfop, only exception is the start block
+ assert(last == get_irg_start_block(get_irn_irg(block)));
+ }
+
+ return last;
+}
+
+/**
+ * We must adapt the live-outs to the live-ins at each block-border.
+ */
+static
+void fix_block_borders(ir_node *block, void *data) {
+ minibelady_env_t *env = data;
+ ir_graph *irg = get_irn_irg(block);
+ ir_node *startblock = get_irg_start_block(irg);
+ int i;
+ int arity;
+ block_info_t *block_info;
+
+ if(block == startblock)
+ return;
+
+ DBG((dbg, LEVEL_3, "\n"));
+ DBG((dbg, LEVEL_3, "Fixing %+F\n", block));
+
+ block_info = get_block_info(block);
+
+ /* process all pred blocks */
+ arity = get_irn_arity(block);
+ for (i = 0; i < arity; ++i) {
+ ir_node *pred = get_Block_cfgpred_block(block, i);
+ block_info_t *pred_info = get_block_info(pred);
+
+ DBG((dbg, LEVEL_3, " Pred %+F\n", pred));
+
+ if(pred_info->end_state != block_info->start_state &&
+ block_info->start_state != NULL) {
+ ir_node *need_state = block_info->start_state;
+ ir_node *insert_point =
+ get_end_of_block_insertion_point(pred);
+
+ create_reload(env, need_state, insert_point);
+ }
+ }
+}
+
+void be_assure_state(be_irg_t *birg, const arch_register_t *reg, void *func_env,
+ create_spill_func create_spill,
+ create_reload_func create_reload) {
+ minibelady_env_t env;
+ ir_graph *irg = be_get_birg_irg(birg);
+ spill_info_t *info;
+
+ be_assure_liveness(birg);
+ be_assure_dom_front(birg);
+ /* construct control flow loop tree */
+ if(! (get_irg_loopinfo_state(irg) & loopinfo_cf_consistent)) {
+ construct_cf_backedges(irg);
+ }
+
+ obstack_init(&env.obst);
+ env.arch_env = birg->main_env->arch_env;
+ env.reg = reg;
+ env.func_env = func_env;
+ env.create_spill = create_spill;
+ env.create_reload = create_reload;
+ env.lv = be_get_birg_liveness(birg);
+ env.uses = be_begin_uses(irg, env.lv);
+ env.spills = NULL;
+
+ set_using_visited(irg);
+ set_using_irn_link(irg);
+ inc_irg_visited(irg);
+
+ /* process blocks */
+ irg_block_walk_graph(irg, NULL, belady_walker, &env);
+
+ /* fix block end_states that don't match the next blocks start_state */
+ irg_block_walk_graph(irg, fix_block_borders, NULL, &env);
+
+ clear_using_visited(irg);
+ clear_using_irn_link(irg);
+
+ /* reconstruct ssa-form */
+ info = env.spills;
+ while(info != NULL) {
+ int i, len;
+ ir_node **phis;
+ phis = be_ssa_construction(be_get_birg_dom_front(birg),
+ be_get_birg_liveness(birg),
+ info->value,
+ ARR_LEN(info->reloads), info->reloads,
+ NULL, 1);
+
+ /* set register requirements for phis */
+ len = ARR_LEN(phis);
+ for(i = 0; i < len; ++i) {
+ ir_node *phi = phis[i];
+ be_set_phi_flags(env.arch_env, phi, arch_irn_flags_ignore);
+ arch_set_irn_register(env.arch_env, phi, env.reg);
+ }
+ DEL_ARR_F(phis);
+
+ info = info->next;
+ }
+
+ /* some nodes might be dead now. */
+ be_remove_dead_nodes_from_schedule(irg);
+
+ be_end_uses(env.uses);
+ obstack_free(&env.obst, NULL);
+}
+
+void be_init_state(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.state");
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_state);
--- /dev/null
+/**
+ * @file
+ * @brief Handles state switching. This is basically the belady spill
+ * algorithm optimized for the 1-register case.
+ * @author Matthias Braun
+ * @date 26.03.2007
+ * @version $Id$
+ * Copyright: (c) Universitaet Karlsruhe
+ * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ */
+#ifndef FIRM_BE_BESTATE_H
+#define FIRM_BE_BESTATE_H
+
+#include "irnode.h"
+#include "beirg.h"
+#include "bearch.h"
+
+/**
+ * Callback that should create a spill for a certain value. Can return NULL
+ * if @p force == 0 and the value can be easily rematerialized
+ */
+typedef ir_node* (*create_spill_func) (void *env, ir_node *value, int force);
+
+/**
+ * Callback that should create a reload for a certain value
+ */
+typedef ir_node* (*create_reload_func) (void *env, ir_node *value,
+ ir_node *spill, ir_node *before);
+
+/**
+ * Some state is expressed as a register. nodes defining a value for this
+ * register are known states. You can connect these to nodes to express that a
+ * node needs the processor to be in a certain state.
+ * This functions asserts that the state is switched to fullfill all state
+ * requirements of nodes.
+ */
+void be_assure_state(be_irg_t *birg, const arch_register_t *reg, void *func_env,
+ create_spill_func spill_func,
+ create_reload_func reload_func);
+
+#endif
* Released under the GPL
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
* CVS-Id: $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
* ISA implementation for Firm IR nodes.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "bitset.h"
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_MALLOC_H
#include "../bespillslots.h"
#include "../bemodule.h"
#include "../begnuas.h"
+#include "../bestate.h"
#include "bearch_ia32_t.h"
&ia32_xmm_regs[REG_XMM_UKNWN]);
}
+ir_node *ia32_new_Fpu_truncate(ia32_code_gen_t *cg) {
+ return create_const(cg, &cg->fpu_trunc_mode, new_rd_ia32_ChangeCW,
+ &ia32_fp_cw_regs[REG_FPCW]);
+}
+
/**
* Returns gp_noreg or fp_noreg, depending in input requirements.
remove_unused_nodes(irn, env);
}
+static ir_node *create_fpu_mode_spill(void *env, ir_node *value, int force)
+{
+ ia32_code_gen_t *cg = env;
+ ir_graph *irg = get_irn_irg(value);
+ ir_node *block = get_nodes_block(value);
+ ir_node *noreg = ia32_new_NoReg_gp(cg);
+ ir_node *nomem = new_NoMem();
+ ir_node *spill = NULL;
+
+ if(force == 1 || !is_ia32_ChangeCW(value)) {
+ spill = new_rd_ia32_FnstCW(NULL, irg, block, noreg, noreg, value,
+ nomem);
+ set_ia32_am_support(spill, ia32_am_Dest);
+ set_ia32_op_type(spill, ia32_AddrModeD);
+ set_ia32_am_flavour(spill, ia32_B);
+ set_ia32_ls_mode(spill, ia32_reg_classes[CLASS_ia32_fp_cw].mode);
+ set_ia32_use_frame(spill);
+
+ sched_add_after(value, spill);
+ }
+
+ ir_fprintf(stderr, "Created spill of %+F (forced %d)\n", value, force);
+ return spill;
+}
+
+static ir_node *create_fpu_mode_reload(void *env, ir_node *value,
+ ir_node *spill, ir_node *before)
+{
+ ia32_code_gen_t *cg = env;
+ ir_graph *irg = get_irn_irg(value);
+ ir_node *block = get_nodes_block(before);
+ ir_node *noreg = ia32_new_NoReg_gp(cg);
+ ir_node *reload = NULL;
+
+ if(spill != NULL) {
+ reload = new_rd_ia32_FldCW(NULL, irg, block, noreg, noreg, spill);
+ set_ia32_am_support(reload, ia32_am_Source);
+ set_ia32_op_type(reload, ia32_AddrModeS);
+ set_ia32_am_flavour(reload, ia32_B);
+ set_ia32_ls_mode(reload, ia32_reg_classes[CLASS_ia32_fp_cw].mode);
+ set_ia32_use_frame(reload);
+
+ sched_add_before(before, reload);
+ } else {
+ ir_mode *lsmode = ia32_reg_classes[CLASS_ia32_fp_cw].mode;
+ ir_node *nomem = new_NoMem();
+ ir_node *cwstore, *load, *load_res, *or, *store, *fldcw;
+
+ /* TODO: value is not correct... */
+ /* TODO: reuse existing spills... */
+ cwstore = new_rd_ia32_FnstCW(NULL, irg, block, noreg, noreg, value,
+ nomem);
+ set_ia32_am_support(cwstore, ia32_am_Dest);
+ set_ia32_op_type(cwstore, ia32_AddrModeD);
+ set_ia32_am_flavour(cwstore, ia32_B);
+ set_ia32_ls_mode(cwstore, lsmode);
+ set_ia32_use_frame(cwstore);
+ sched_add_before(before, cwstore);
+
+ load = new_rd_ia32_Load(NULL, irg, block, noreg, noreg, cwstore);
+ set_ia32_am_support(load, ia32_am_Source);
+ set_ia32_op_type(load, ia32_AddrModeS);
+ set_ia32_am_flavour(load, ia32_B);
+ set_ia32_ls_mode(load, lsmode);
+ set_ia32_use_frame(load);
+ sched_add_before(before, load);
+
+ load_res = new_r_Proj(irg, block, load, mode_Iu, pn_ia32_Load_res);
+ sched_add_before(before, load_res);
+
+ /* TODO: make the actual mode configurable in ChangeCW... */
+ or = new_rd_ia32_Or(NULL, irg, block, noreg, noreg, load_res, noreg,
+ nomem);
+ set_ia32_Immop_tarval(or, new_tarval_from_long(0x3072, mode_Iu));
+ sched_add_before(before, or);
+
+ store = new_rd_ia32_Store(NULL, irg, block, noreg, noreg, or, nomem);
+ set_ia32_am_support(store, ia32_am_Dest);
+ set_ia32_op_type(store, ia32_AddrModeD);
+ set_ia32_am_flavour(store, ia32_B);
+ set_ia32_ls_mode(store, lsmode);
+ set_ia32_use_frame(store);
+ sched_add_before(before, store);
+
+ fldcw = new_rd_ia32_FldCW(NULL, irg, block, noreg, noreg, store);
+ set_ia32_am_support(fldcw, ia32_am_Source);
+ set_ia32_op_type(fldcw, ia32_AddrModeS);
+ set_ia32_am_flavour(fldcw, ia32_B);
+ set_ia32_ls_mode(fldcw, lsmode);
+ set_ia32_use_frame(fldcw);
+ sched_add_before(before, fldcw);
+
+ reload = fldcw;
+ }
+
+ ir_fprintf(stderr, "Create reload of %+F (spill %+F) before %+F\n",
+ value, spill, before);
+ return reload;
+}
+
/**
* Called before the register allocator.
* Calculate a block schedule here. We need it for the x87
after removing the Load from schedule.
*/
irg_walk_graph(cg->irg, NULL, remove_unused_loads_walker, already_visited);
+
+ be_assure_state(cg->birg, &ia32_fp_cw_regs[REG_FPCW],
+ cg, create_fpu_mode_spill, create_fpu_mode_reload);
+ be_dump(cg->irg, "-assure-state", dump_ir_block_graph_sched);
}
* - the SSE vector register set
*/
static int ia32_get_n_reg_class(const void *self) {
- return 3;
+ return 4;
}
/**
return &ia32_reg_classes[CLASS_ia32_xmm];
case 2:
return &ia32_reg_classes[CLASS_ia32_vfp];
-#if 0
case 3:
return &ia32_reg_classes[CLASS_ia32_fp_cw];
-#endif
default:
assert(0 && "Invalid ia32 register class requested.");
return NULL;
ir_node *noreg_vfp; /**< unique NoReg_VFP node */
ir_node *noreg_xmm; /**< unique NoReg_XMM node */
+ ir_node *fpu_trunc_mode; /**< truncate fpu mode */
+
ir_node ***initial_regs; /**< proj nodes that represent the initial register
values initial_regs[regclass][reg] */
struct obstack *obst;
*/
ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg);
+/**
+ * Returns the uniqure per irg FPU truncation mode node.
+ */
+ir_node *ia32_new_Fpu_truncate(ia32_code_gen_t *cg);
+
/**
* Returns gp_noreg or fp_noreg, depending on input requirements.
*/
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_MALLOC_H
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "irnode.h"
units => [ "GP" ],
},
-FstCW => {
+FnstCW => {
op_flags => "L|F",
state => "exc_pinned",
comment => "store floating point control word: FstCW(ptr, mem) = ST ptr -> reg",
- reg_req => { in => [ "gp", "gp", "fp_cw", "none" ] },
+ reg_req => { in => [ "gp", "gp", "fp_cw", "none" ], out => [ "none" ] },
latency => 5,
- emit => ". fstcw %AM",
+ emit => ". fnstcw %AM",
mode => "mode_M",
units => [ "GP" ],
},
vfist => {
comment => "virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val",
- reg_req => { in => [ "gp", "gp", "vfp", "none" ] },
+ reg_req => { in => [ "gp", "gp", "vfp", "fpcw", "none" ] },
latency => 4,
units => [ "VFP" ],
mode => "mode_M",
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
static ir_node *gen_Eor(ia32_transform_env_t *env, ir_node *node) {
ir_node *op1 = get_Eor_left(node);
ir_node *op2 = get_Eor_right(node);
- ir_mode *mode = get_irn_mode(node);
- assert(! mode_is_float(mode));
+ assert(! mode_is_float(get_irn_mode(node)));
return gen_binop(env, node, op1, op2, new_rd_ia32_Xor);
}
if (mode_is_float(mode)) {
FP_USED(env->cg);
- if (USE_SSE2(env->cg))
+ if (USE_SSE2(env->cg)) {
new_op = gen_binop_float(env, node, new_op1, new_op2, new_rd_ia32_xMax);
- else {
- assert(0);
+ } else {
+ panic("Can't create Max node");
}
- }
- else {
+ } else {
long pnc = pn_Cmp_Gt;
if(!mode_is_signed(op_mode)) {
pnc |= ia32_pn_Cmp_Unsigned;
if (mode_is_float(mode)) {
FP_USED(env->cg);
- if (USE_SSE2(env->cg))
+ if (USE_SSE2(env->cg)) {
new_op = gen_binop_float(env, node, op1, op2, new_rd_ia32_xMin);
- else {
- assert(0);
+ } else {
+ panic("can't create Min node");
}
- }
- else {
+ } else {
long pnc = pn_Cmp_Lt;
if(!mode_is_signed(op_mode)) {
pnc |= ia32_pn_Cmp_Unsigned;
mode = proj_div ? get_irn_mode(proj_div) : get_irn_mode(proj_mod);
break;
default:
- assert(0);
+ panic("invalid divmod flavour!");
}
new_mem = transform_node(env, mem);
* @return The created ia32 Not node
*/
static ir_node *gen_Not(ia32_transform_env_t *env, ir_node *node) {
- ir_mode *mode = get_irn_mode(node);
ir_node *op = get_Not_op(node);
- assert (! mode_is_float(mode));
+ assert (! mode_is_float(get_irn_mode(node)));
return gen_unop(env, node, op, new_rd_ia32_Not);
}
ir_graph *irg = env->irg;
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *block = transform_node(env, get_nodes_block(node));
- ir_node *noreg = ia32_new_NoReg_gp(env->cg);
+ ir_node *noreg = ia32_new_NoReg_gp(cg);
ir_node *op = get_Conv_op(node);
ir_node *new_op = transform_node(env, op);
ir_node *fist, *load;
+ ir_node *trunc_mode = ia32_new_Fpu_truncate(cg);
/* do a fist */
- fist = new_rd_ia32_vfist(dbg, irg, block, get_irg_frame(irg), noreg, new_op, new_NoMem());
+ fist = new_rd_ia32_vfist(dbg, irg, block,
+ get_irg_frame(irg), noreg, new_op, trunc_mode, new_NoMem());
set_ia32_use_frame(fist);
set_ia32_am_support(fist, ia32_am_Dest);
* Create a conversion from general purpose to x87 register
*/
static ir_node *gen_x87_gp_to_fp(ia32_transform_env_t *env, ir_node *node, ir_mode *src_mode) {
+#ifndef NDEBUG
ia32_code_gen_t *cg = env->cg;
+#endif
ir_graph *irg = env->irg;
dbg_info *dbg = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node);
ir_node *count) {
ir_node *new_op = NULL;
ir_graph *irg = env->irg;
- ir_mode *mode = get_irn_mode(node);
dbg_info *dbg = get_irn_dbg_info(node);
ir_node *block = transform_node(env, get_nodes_block(node));
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
tarval *tv;
DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;)
- assert(! mode_is_float(mode) && "Shift/Rotate with float not supported");
+ assert(! mode_is_float(get_irn_mode(node)) && "Shift/Rotate with float not supported");
/* Check if immediate optimization is on and */
/* if it's an operation with immediate. */
ir_node *sse_load;
ir_node *call = get_Proj_pred(node);
ir_node *new_call = transform_node(env, call);
+ const arch_register_class_t *cls;
/* The following is kinda tricky: If we're using SSE, then we have to
* move the result value of the call in floating point registers to an
}
/* transform call modes to the mode_Iu or mode_E */
- if(mode_is_float(mode)) {
- mode = mode_E;
- } else if(mode != mode_M) {
- mode = mode_Iu;
+ if(mode != mode_M) {
+ cls = arch_get_irn_reg_class(env->cg->arch_env, node, -1);
+ mode = cls->mode;
}
return new_rd_Proj(dbg, irg, block, new_call, mode, proj);
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <assert.h>
/* The main mips backend driver file. */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "pseudo_irg.h"
/* mips emitter */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <limits.h>
/* Mips implementation of list scheduler selector */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
/* The main ppc backend driver file. */
/* $Id$ */
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "pseudo_irg.h"
* $Id$
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#ifdef _WIN32
* date: $creation_time
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdio.h>
* date: $creation_time
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include <stdio.h>
* date: $creation_time
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "gen_$arch\_machine.h"
* date: $creation_time
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
#include "gen_${arch}_regalloc_if.h"