- change #include <config.h> back to "config.h"
authorMatthias Braun <matze@braunis.de>
Thu, 29 Mar 2007 10:49:57 +0000 (10:49 +0000)
committerMatthias Braun <matze@braunis.de>
Thu, 29 Mar 2007 10:49:57 +0000 (10:49 +0000)
- more work on state registers for x87 fpu rounding modes

61 files changed:
ir/be/TEMPLATE/TEMPLATE_emitter.c
ir/be/TEMPLATE/TEMPLATE_map_regs.c
ir/be/TEMPLATE/TEMPLATE_new_nodes.c
ir/be/TEMPLATE/TEMPLATE_transform.c
ir/be/TEMPLATE/bearch_TEMPLATE.c
ir/be/arm/arm_new_nodes.c
ir/be/beabi.c
ir/be/beabi.h
ir/be/bearch.c
ir/be/beblocksched.c
ir/be/bechordal.c
ir/be/bechordal_main.c
ir/be/becopyheur.c
ir/be/becopyheur2.c
ir/be/becopyheur3.c
ir/be/becopyopt.c
ir/be/bedomfront.c
ir/be/beemitter.c
ir/be/begnuas.c
ir/be/beinsn.c
ir/be/beirgmod.c
ir/be/belistsched.c
ir/be/belive.c
ir/be/beloopana.c
ir/be/belower.c
ir/be/bemain.c
ir/be/bemodule.c
ir/be/benode.c
ir/be/beraextern.c
ir/be/beschedregpress.c
ir/be/beschedrss.c
ir/be/beschedtrace.c
ir/be/beschedtrivial.c
ir/be/bespill.c
ir/be/bespillbelady.c
ir/be/bespillmorgan.c
ir/be/bespillremat.c
ir/be/bespillslots.c
ir/be/bestabs.c
ir/be/bestate.c [new file with mode: 0644]
ir/be/bestate.h [new file with mode: 0644]
ir/be/beuses.c
ir/be/beverify.c
ir/be/firm/bearch_firm.c
ir/be/ia32/bearch_ia32.c
ir/be/ia32/bearch_ia32_t.h
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_new_nodes.c
ir/be/ia32/ia32_optimize.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c
ir/be/ia32/ia32_x87.c
ir/be/mips/bearch_mips.c
ir/be/mips/mips_emitter.c
ir/be/mips/mips_scheduler.c
ir/be/ppc32/bearch_ppc32.c
ir/be/ppc32/ppc32_new_nodes.c
ir/be/scripts/generate_emitter.pl
ir/be/scripts/generate_emitter_new.pl
ir/be/scripts/generate_machine.pl
ir/be/scripts/generate_regalloc_if.pl

index 28c5c4b..61d6465 100644 (file)
@@ -1,7 +1,7 @@
 /* TEMPLATE emitter */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
index ea3762b..cd2d0f5 100644 (file)
@@ -3,7 +3,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index f870d6d..ba1af80 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef _WIN32
index 0d99457..9cd411d 100644 (file)
@@ -1,7 +1,7 @@
 /* The codegenrator (transform FIRM into TEMPLATE FIRM */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "irnode_t.h"
index 2cb771d..c100231 100644 (file)
@@ -1,7 +1,7 @@
 /* The main TEMPLATE backend driver file. */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "pseudo_irg.h"
index 688b2cd..5ffd020 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_MALLOC_H
index 4ff9cbd..69723d8 100644 (file)
@@ -6,7 +6,7 @@
  * @cvsid  $Id$
  */
 #ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
 #endif
 
 #include "obst.h"
@@ -93,14 +93,6 @@ struct _be_abi_irg_t {
        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 */
@@ -389,7 +381,8 @@ static INLINE int is_on_stack(be_abi_call_t *call, int pos)
 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);
@@ -698,6 +691,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp, i
 
                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);
@@ -1985,11 +1979,6 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
        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. */
@@ -2023,10 +2012,6 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
                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;
@@ -2038,9 +2023,6 @@ void be_abi_free(be_abi_irg_t *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);
 }
 
@@ -2068,8 +2050,12 @@ const be_stack_layout_t *be_abi_get_stack_layout(const be_abi_irg_t *abi) {
 
 */
 
+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;
 
@@ -2085,29 +2071,59 @@ static void collect_stack_nodes_walker(ir_node *node, void *data)
 
        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 */
@@ -2119,7 +2135,30 @@ void be_abi_fix_stack_nodes(be_abi_irg_t *env, be_lv_t *lv)
        }
 
        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)
@@ -2223,107 +2262,6 @@ ir_node *be_abi_get_start_barrier(be_abi_irg_t *abi)
        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.
index 943a098..e5b23ee 100644 (file)
@@ -127,10 +127,8 @@ void be_abi_free(be_abi_irg_t *abi);
 /**
  * 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.
index db45736..101c6e4 100644 (file)
@@ -6,7 +6,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_ALLOCA_H
index 95bb266..3a0ed11 100644 (file)
@@ -6,7 +6,7 @@
  * CVS-Id:      $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "beblocksched.h"
index 0f2b6a4..db5b1a8 100644 (file)
@@ -8,7 +8,7 @@
  * Released under the GPL
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_MALLOC_H
index 0c9d4af..364b159 100644 (file)
@@ -10,7 +10,7 @@
  * Driver for the chordal register allocator.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <time.h>
@@ -441,7 +441,7 @@ static void post_spill(post_spill_env_t *pse, int iteration) {
        */
        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);
index 233a749..28205e5 100644 (file)
@@ -13,7 +13,7 @@
  * conflicts is the best one.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_ALLOCA_H
index 80a8c70..3034d56 100644 (file)
@@ -4,7 +4,7 @@
  * @date   14.04.2006
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <libcore/lc_opts.h>
index d22a6f4..f5db944 100644 (file)
@@ -4,7 +4,7 @@
  * @date   25.07.2006
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <libcore/lc_opts.h>
index 1b9ccd4..07ff224 100644 (file)
@@ -5,7 +5,7 @@
  * 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
index 0397d2a..c2f3703 100644 (file)
@@ -7,7 +7,7 @@
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "bedomfront.h"
index c531a23..2111b84 100644 (file)
@@ -5,7 +5,7 @@
  * 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"
index 0d68ca5..2fa023a 100644 (file)
@@ -5,7 +5,7 @@
  * @version $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "begnuas.h"
index 74a997e..7840410 100644 (file)
@@ -1,5 +1,5 @@
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "irgraph_t.h"
index 1fbef3d..ae92810 100644 (file)
@@ -15,7 +15,7 @@
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index 6c713fb..e92a4fa 100644 (file)
@@ -6,7 +6,7 @@
  * @cvs-id $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdio.h>
index e2d4dd3..8c6c3d0 100644 (file)
@@ -4,7 +4,7 @@
  * @date 6.12.2004
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "impl.h"
index 60a8a4e..9acc156 100644 (file)
@@ -8,7 +8,7 @@
  * Compute register pressure in loops
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "set.h"
index 7f42e42..9449977 100644 (file)
@@ -8,7 +8,7 @@
  * Performs lowering of perm nodes and spill/reload optimization.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index 70e0a4c..13f536c 100644 (file)
@@ -567,7 +567,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
 
                /* 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);
@@ -614,7 +614,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
 
                /* 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);
index bd9be66..75b353b 100644 (file)
@@ -6,7 +6,7 @@
  * CVS-Id:      $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif /* HAVE_CONFIG_H */
 
 #include <stdlib.h>
@@ -41,6 +41,7 @@ void be_init_irgmod(void);
 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);
 
@@ -73,6 +74,7 @@ void be_init_modules(void)
        be_init_ra();
        be_init_spillbelady();
        be_init_spillmorgan();
+       be_init_state();
        be_init_ifg();
 
        be_init_arch_ia32();
index c767d07..399dc92 100644 (file)
@@ -11,7 +11,7 @@
  * Released under the GPL
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index 5ffa98f..b48acb4 100644 (file)
@@ -755,7 +755,7 @@ static void be_ra_extern_main(be_irg_t *birg) {
                        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);
index 14063cf..c418968 100644 (file)
@@ -6,7 +6,7 @@
  * @cvs-id $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index adb258f..350a7df 100644 (file)
@@ -9,7 +9,7 @@
  * @cvs-id  $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
index 1bd47ec..8ccfdeb 100644 (file)
@@ -6,7 +6,7 @@
  * @cvs-id $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index 645fe18..9b95865 100644 (file)
@@ -5,7 +5,7 @@
  * @cvs-id $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index c6a5358..40c467f 100644 (file)
@@ -7,7 +7,7 @@
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index 3551332..1bc57e6 100644 (file)
@@ -6,7 +6,7 @@
  *
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_ALLOCA_H
index 204cafa..b30ea6e 100644 (file)
@@ -6,7 +6,7 @@
  *
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "bespillmorgan.h"
index c54f3f4..882e951 100644 (file)
@@ -1588,6 +1588,7 @@ luke_endwalker(ir_node * bb, void * data)
        del_pset(use_end);
 }
 
+#ifndef NDEBUG
 /**
  * Find a remat of value @p value in the epilog of @p pos
  */
@@ -1615,6 +1616,7 @@ find_post_remat(const ir_node * value, const ir_node * pos)
 
        return NULL;
 }
+#endif
 
 static spill_t *
 add_to_spill_bb(spill_ilp_t * si, ir_node * bb, ir_node * irn)
@@ -2439,11 +2441,13 @@ skip_one_must_die:
                        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);
index 955b5dc..a60d6c2 100644 (file)
@@ -5,7 +5,7 @@
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdlib.h>
index 1821838..9c0f29d 100644 (file)
@@ -6,7 +6,7 @@
  * @cvsid  $Id$
  */
 #ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
 #endif
 
 #include <stdio.h>
diff --git a/ir/be/bestate.c b/ir/be/bestate.c
new file mode 100644 (file)
index 0000000..0c93320
--- /dev/null
@@ -0,0 +1,541 @@
+/**
+ * @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);
diff --git a/ir/be/bestate.h b/ir/be/bestate.h
new file mode 100644 (file)
index 0000000..3fb9d6f
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * @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
index f511839..bdb9875 100644 (file)
@@ -9,7 +9,7 @@
  * Released under the GPL
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
index 86e472e..954fdf8 100644 (file)
@@ -6,7 +6,7 @@
  * CVS-Id:    $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
index 8b4b599..c60d23b 100644 (file)
@@ -2,7 +2,7 @@
  * ISA implementation for Firm IR nodes.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "bitset.h"
index 0e98ad9..e48f5db 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_MALLOC_H
@@ -50,6 +50,7 @@
 #include "../bespillslots.h"
 #include "../bemodule.h"
 #include "../begnuas.h"
+#include "../bestate.h"
 
 #include "bearch_ia32_t.h"
 
@@ -137,6 +138,11 @@ ir_node *ia32_new_Unknown_xmm(ia32_code_gen_t *cg) {
                            &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.
@@ -1205,6 +1211,106 @@ static void remove_unused_loads_walker(ir_node *irn, void *env) {
                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
@@ -1221,6 +1327,10 @@ static void ia32_before_ra(void *self) {
                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);
 }
 
 
@@ -1844,7 +1954,7 @@ static void ia32_done(void *self) {
  *  - the SSE vector register set
  */
 static int ia32_get_n_reg_class(const void *self) {
-       return 3;
+       return 4;
 }
 
 /**
@@ -1858,10 +1968,8 @@ static const arch_register_class_t *ia32_get_reg_class(const void *self, int i)
                        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;
index a67cc18..6526dae 100644 (file)
@@ -112,6 +112,8 @@ typedef struct _ia32_code_gen_t {
        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;
@@ -173,6 +175,11 @@ ir_node *ia32_new_Unknown_vfp(ia32_code_gen_t *cg);
  */
 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.
  */
index 9e267d4..c124a68 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
index fb614d9..a3b7333 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_MALLOC_H
index bfaa352..2f8e020 100644 (file)
@@ -8,7 +8,7 @@
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "irnode.h"
index cdb2e50..0b8557a 100644 (file)
@@ -788,13 +788,13 @@ FldCW => {
        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" ],
 },
@@ -1461,7 +1461,7 @@ l_vfild => {
 
 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",
index 005311f..c957432 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
@@ -954,9 +954,8 @@ static ir_node *gen_Or(ia32_transform_env_t *env, ir_node *node) {
 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);
 }
 
@@ -984,13 +983,12 @@ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *node) {
 
        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;
@@ -1026,13 +1024,12 @@ static ir_node *gen_Min(ia32_transform_env_t *env, ir_node *node) {
 
        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;
@@ -1223,7 +1220,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *node,
                        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);
 
@@ -1548,10 +1545,9 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *node) {
  * @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);
 }
 
@@ -2197,13 +2193,15 @@ static ir_node *gen_x87_fp_to_gp(ia32_transform_env_t *env, ir_node *node) {
        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);
@@ -2229,7 +2227,9 @@ static ir_node *gen_x87_fp_to_gp(ia32_transform_env_t *env, ir_node *node) {
  * 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);
@@ -3030,7 +3030,6 @@ static ir_node *gen_lowered_64bit_shifts(ia32_transform_env_t *env, ir_node *nod
                                          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);
@@ -3042,7 +3041,7 @@ static ir_node *gen_lowered_64bit_shifts(ia32_transform_env_t *env, ir_node *nod
        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.      */
@@ -3529,6 +3528,7 @@ static ir_node *gen_Proj_be_Call(ia32_transform_env_t *env, ir_node *node) {
        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
@@ -3606,10 +3606,9 @@ static ir_node *gen_Proj_be_Call(ia32_transform_env_t *env, ir_node *node) {
        }
 
        /* 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);
index 9c7d60b..5eebfe0 100644 (file)
@@ -7,7 +7,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <assert.h>
index bdd65d3..d80bdb4 100644 (file)
@@ -1,7 +1,7 @@
 /* The main mips backend driver file. */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "pseudo_irg.h"
index 8abeeb7..f3359ac 100644 (file)
@@ -1,7 +1,7 @@
 /* mips emitter */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <limits.h>
index 154d266..749cec3 100644 (file)
@@ -1,7 +1,7 @@
 /* Mips implementation of list scheduler selector */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef HAVE_STDLIB_H
index 3a6124e..757aad8 100644 (file)
@@ -1,7 +1,7 @@
 /* The main ppc backend driver file. */
 /* $Id$ */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "pseudo_irg.h"
index 32ab4eb..3d11026 100644 (file)
@@ -4,7 +4,7 @@
  * $Id$
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #ifdef _WIN32
index 42d1d8b..1326d9a 100755 (executable)
@@ -192,7 +192,7 @@ print OUT<<EOF;
  * date:       $creation_time
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdio.h>
index 154fb2e..28aa150 100755 (executable)
@@ -131,7 +131,7 @@ print OUT<<EOF;
  * date:       $creation_time
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include <stdio.h>
index 4272be0..ac15b64 100755 (executable)
@@ -129,7 +129,7 @@ print OUT<<EOF;
  * date:       $creation_time
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "gen_$arch\_machine.h"
index 8e64e32..a379169 100755 (executable)
@@ -257,7 +257,7 @@ print OUT<<EOF;
  * date:       $creation_time
  */
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "gen_${arch}_regalloc_if.h"