Merge Fix: Spills have ProjMs now
authorAndreas Zwinkau <zwinkau@kit.edu>
Fri, 24 Jun 2011 15:33:47 +0000 (17:33 +0200)
committerAndreas Zwinkau <zwinkau@kit.edu>
Fri, 24 Jun 2011 15:35:02 +0000 (17:35 +0200)
134 files changed:
Makefile
include/libfirm/adt/array.h
include/libfirm/be.h
include/libfirm/irhooks.h
include/libfirm/irloop.h
include/libfirm/lowering.h
ir/ana/analyze_irg_args.c
ir/ana/cgana.c
ir/ana/dfs.c
ir/ana/execfreq.c
ir/ana/irbackedge.c
ir/ana/irconsconfirm.c
ir/ana/irmemory.c
ir/ana/structure.c
ir/be/TEMPLATE/TEMPLATE_spec.pl
ir/be/TEMPLATE/bearch_TEMPLATE.c
ir/be/amd64/amd64_spec.pl
ir/be/amd64/bearch_amd64.c
ir/be/arm/arm_cconv.c
ir/be/arm/arm_cconv.h
ir/be/arm/arm_emitter.c
ir/be/arm/arm_optimize.c
ir/be/arm/arm_transform.c
ir/be/arm/bearch_arm.c
ir/be/beabi.c
ir/be/bearch.h
ir/be/beblocksched.c
ir/be/bechordal_draw.c
ir/be/bechordal_main.c
ir/be/becopyilp.c
ir/be/becopyilp2.c
ir/be/becopyilp_t.h
ir/be/becopystat.c
ir/be/becopystat.h
ir/be/beemitter_binary.c
ir/be/begnuas.c
ir/be/begnuas.h
ir/be/bemachine.c
ir/be/bemain.c
ir/be/bemodule.c
ir/be/benode.c
ir/be/beprefalloc.c
ir/be/beschednormal.c
ir/be/bespillslots.c
ir/be/bespillutil.c
ir/be/bestabs.c
ir/be/bestate.c
ir/be/beuses.c
ir/be/beverify.c
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_common_transform.c
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_finish.c
ir/be/ia32/ia32_fpu.c
ir/be/ia32/ia32_intrinsics.c
ir/be/ia32/ia32_nodes_attr.h
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/scripts/generate_machine.pl
ir/be/scripts/generate_regalloc_if.pl
ir/be/sparc/bearch_sparc.c
ir/be/sparc/sparc_cconv.c
ir/be/sparc/sparc_cconv.h
ir/be/sparc/sparc_emitter.c
ir/be/sparc/sparc_new_nodes.c
ir/be/sparc/sparc_transform.c
ir/common/timing.c
ir/ir/irarch.c
ir/ir/ircons.c
ir/ir/irdump.c
ir/ir/irdumptxt.c
ir/ir/iredges.c
ir/ir/irhooks.c
ir/ir/irio.c
ir/ir/irmode.c
ir/ir/iropt.c
ir/ir/irverify.c
ir/ir/irverify_t.h
ir/kaps/brute_force.c
ir/kaps/optimal.c
ir/kaps/pbqp_t.h
ir/libcore/lc_appendable.c
ir/libcore/lc_common_t.h [deleted file]
ir/libcore/lc_config.h
ir/libcore/lc_opts.c
ir/libcore/lc_opts_enum.c
ir/libcore/lc_opts_t.h
ir/libcore/lc_printf.c
ir/lower/lower_calls.c
ir/lower/lower_dw.c
ir/lower/lower_hl.c
ir/lower/lower_mode_b.c
ir/lower/lower_switch.c
ir/lpp/lpp.c [new file with mode: 0644]
ir/lpp/lpp.h [new file with mode: 0644]
ir/lpp/lpp_comm.c [new file with mode: 0644]
ir/lpp/lpp_comm.h [new file with mode: 0644]
ir/lpp/lpp_cplex.c [new file with mode: 0644]
ir/lpp/lpp_cplex.h [new file with mode: 0644]
ir/lpp/lpp_gurobi.c [new file with mode: 0644]
ir/lpp/lpp_gurobi.h [new file with mode: 0644]
ir/lpp/lpp_net.c [new file with mode: 0644]
ir/lpp/lpp_net.h [new file with mode: 0644]
ir/lpp/lpp_remote.c [new file with mode: 0644]
ir/lpp/lpp_remote.h [new file with mode: 0644]
ir/lpp/lpp_solvers.c [new file with mode: 0644]
ir/lpp/lpp_solvers.h [new file with mode: 0644]
ir/lpp/lpp_t.h [new file with mode: 0644]
ir/lpp/mps.c [new file with mode: 0644]
ir/lpp/mps.h [new file with mode: 0644]
ir/lpp/sp_matrix.c [new file with mode: 0644]
ir/lpp/sp_matrix.h [new file with mode: 0644]
ir/opt/cfopt.c
ir/opt/escape_ana.c
ir/opt/jumpthreading.c
ir/opt/ldstopt.c
ir/opt/loop.c
ir/opt/opt_blocks.c
ir/opt/opt_confirms.c
ir/opt/opt_polymorphy.c
ir/opt/reassoc.c
ir/stat/firmstat.c
ir/stat/statev.h
ir/tr/tr_inheritance.c
ir/tr/trverify.c
ir/tr/type.c
ir/tv/fltcalc.c
ir/tv/tv.c
scripts/gen_ir.py
scripts/jinja2/nodes.py
support/lpp_server/lpp_server.c [new file with mode: 0644]
support/lpp_server/lpp_server.h [new file with mode: 0644]

index c74a65d..d643a08 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,7 @@ libfirm_DIRS := \
        ir/ir      \
        ir/lower   \
        ir/libcore \
+       ir/lpp     \
        ir/opt     \
        ir/st      \
        ir/stat    \
index 642fc6c..73fabae 100644 (file)
  * @remark  This macro may change arr, so update all references!
  */
 #define ARR_EXTO(type, arr, n) \
-  ((n) >= ARR_LEN((arr)) ? ARR_RESIZE(type, (arr), (n)+1) : (arr))
+       do { \
+               if ((n) >= ARR_LEN(arr)) { ARR_RESIZE(type, arr, (n)+1); } \
+       } while(0)
 
 /**
  * Append one element to a flexible array.
index 2d71276..1131763 100644 (file)
@@ -78,12 +78,19 @@ typedef struct backend_params {
        /** Backend settings for if-conversion. */
        arch_allow_ifconv_func allow_ifconv;
 
+       /** size of machine words. This is usually the size of the general purpose
+        * integer registers. */
+       unsigned machine_size;
+
        /**
         * some backends like x87 can only do arithmetic in a specific float
-        * mode (but convert to/from other float modes).
+        * mode (load/store are still done in the "normal" float/double modes).
         */
        ir_mode *mode_float_arithmetic;
 
+       /** size of a long double floating mode in bits (or 0 if not supported) */
+       unsigned long_double_size;
+
        /** Size of the trampoline code. */
        unsigned trampoline_size;
 
index 9df478d..c981f63 100644 (file)
@@ -242,49 +242,49 @@ FIRM_API hook_entry_t *hooks[hook_last];
 #define hook_exec(what, args) do {           \
   hook_entry_t *_p;                          \
   for (_p = hooks[what]; _p; _p = _p->next){ \
-    void *ctx = _p->context;                 \
+    void *hook_ctx_ = _p->context;           \
     _p->hook._##what args;                   \
   }                                          \
 } while (0)
 
-#define hook_new_ir_op(op)                hook_exec(hook_new_ir_op, (ctx, op))
-#define hook_free_ir_op(op)               hook_exec(hook_free_ir_op, (ctx, op))
-#define hook_new_node(graph, node)        hook_exec(hook_new_node, (ctx, graph, node))
+#define hook_new_ir_op(op)                hook_exec(hook_new_ir_op, (hook_ctx_, op))
+#define hook_free_ir_op(op)               hook_exec(hook_free_ir_op, (hook_ctx_, op))
+#define hook_new_node(graph, node)        hook_exec(hook_new_node, (hook_ctx_, graph, node))
 #define hook_set_irn_n(src, pos, tgt, old_tgt) \
-  hook_exec(hook_set_irn_n, (ctx, src, pos, tgt, old_tgt))
-#define hook_replace(old, nw)             hook_exec(hook_replace, (ctx, old, nw))
-#define hook_turn_into_id(node)           hook_exec(hook_turn_into_id, (ctx, node))
-#define hook_normalize(node)              hook_exec(hook_normalize, (ctx, node))
-#define hook_new_graph(irg, ent)          hook_exec(hook_new_graph, (ctx, irg, ent))
-#define hook_free_graph(irg)              hook_exec(hook_free_graph, (ctx, irg))
-#define hook_irg_walk(irg, pre, post)     hook_exec(hook_irg_walk, (ctx, irg, pre, post))
+  hook_exec(hook_set_irn_n, (hook_ctx_, src, pos, tgt, old_tgt))
+#define hook_replace(old, nw)             hook_exec(hook_replace, (hook_ctx_, old, nw))
+#define hook_turn_into_id(node)           hook_exec(hook_turn_into_id, (hook_ctx_, node))
+#define hook_normalize(node)              hook_exec(hook_normalize, (hook_ctx_, node))
+#define hook_new_graph(irg, ent)          hook_exec(hook_new_graph, (hook_ctx_, irg, ent))
+#define hook_free_graph(irg)              hook_exec(hook_free_graph, (hook_ctx_, irg))
+#define hook_irg_walk(irg, pre, post)     hook_exec(hook_irg_walk, (hook_ctx_, irg, pre, post))
 #define hook_irg_walk_blkwise(irg, pre, post) \
-  hook_exec(hook_irg_walk_blkwise, (ctx, irg, pre, post))
+  hook_exec(hook_irg_walk_blkwise, (hook_ctx_, irg, pre, post))
 #define hook_irg_block_walk(irg, node, pre, post) \
-  hook_exec(hook_irg_block_walk, (ctx, irg, node, pre, post))
+  hook_exec(hook_irg_block_walk, (hook_ctx_, irg, node, pre, post))
 #define hook_merge_nodes(new_node_array, new_num_entries, old_node_array, old_num_entries, opt) \
-  hook_exec(hook_merge_nodes, (ctx, new_node_array, new_num_entries, old_node_array, old_num_entries, opt))
-#define hook_reassociate(start)           hook_exec(hook_reassociate, (ctx, start))
-#define hook_lower(node)                  hook_exec(hook_lower, (ctx, node))
-#define hook_inline(call, irg)            hook_exec(hook_inline, (ctx, call, irg))
-#define hook_tail_rec(irg, n_calls)       hook_exec(hook_tail_rec, (ctx, irg, n_calls))
+  hook_exec(hook_merge_nodes, (hook_ctx_, new_node_array, new_num_entries, old_node_array, old_num_entries, opt))
+#define hook_reassociate(start)           hook_exec(hook_reassociate, (hook_ctx_, start))
+#define hook_lower(node)                  hook_exec(hook_lower, (hook_ctx_, node))
+#define hook_inline(call, irg)            hook_exec(hook_inline, (hook_ctx_, call, irg))
+#define hook_tail_rec(irg, n_calls)       hook_exec(hook_tail_rec, (hook_ctx_, irg, n_calls))
 #define hook_strength_red(irg, node) \
-  hook_exec(hook_strength_red, (ctx, irg, node))
-#define hook_dead_node_elim(irg, start)   hook_exec(hook_dead_node_elim, (ctx, irg, start))
+  hook_exec(hook_strength_red, (hook_ctx_, irg, node))
+#define hook_dead_node_elim(irg, start)   hook_exec(hook_dead_node_elim, (hook_ctx_, irg, start))
 #define hook_dead_node_elim_subst(irg, old, nw) \
-   hook_exec(hook_dead_node_elim_subst, (ctx, irg, old, nw))
+   hook_exec(hook_dead_node_elim_subst, (hook_ctx_, irg, old, nw))
 #define hook_if_conversion(irg, phi, pos, mux, reason) \
-  hook_exec(hook_if_conversion, (ctx, irg, phi, pos, mux, reason))
+  hook_exec(hook_if_conversion, (hook_ctx_, irg, phi, pos, mux, reason))
 #define hook_func_call(irg, call) \
-  hook_exec(hook_func_call, (ctx, irg, call))
+  hook_exec(hook_func_call, (hook_ctx_, irg, call))
 #define hook_arch_dep_replace_mul_with_shifts(irn) \
-  hook_exec(hook_arch_dep_replace_mul_with_shifts, (ctx, irn))
+  hook_exec(hook_arch_dep_replace_mul_with_shifts, (hook_ctx_, irn))
 #define hook_arch_dep_replace_division_by_const(irn) \
-  hook_exec(hook_arch_dep_replace_division_by_const, (ctx, irn))
-#define hook_new_mode(tmpl, mode)         hook_exec(hook_new_mode, (ctx, tmpl, mode))
-#define hook_new_entity(ent)              hook_exec(hook_new_entity, (ctx, ent))
-#define hook_new_type(tp)                 hook_exec(hook_new_type, (ctx, tp))
-#define hook_node_info(F, node)           hook_exec(hook_node_info, (ctx, F, node))
+  hook_exec(hook_arch_dep_replace_division_by_const, (hook_ctx_, irn))
+#define hook_new_mode(tmpl, mode)         hook_exec(hook_new_mode, (hook_ctx_, tmpl, mode))
+#define hook_new_entity(ent)              hook_exec(hook_new_entity, (hook_ctx_, ent))
+#define hook_new_type(tp)                 hook_exec(hook_new_type, (hook_ctx_, tp))
+#define hook_node_info(F, node)           hook_exec(hook_node_info, (hook_ctx_, F, node))
 
 #include "end.h"
 
index 7c6db43..f0d9cbe 100644 (file)
 /* ------------------------------------------------------------------- */
 
 /** Returns non-zero if the predecessor pos is a backedge. */
-FIRM_API int is_backedge(ir_node *n, int pos);
+FIRM_API int is_backedge(const ir_node *n, int pos);
 /** Marks edge pos as a backedge. */
 FIRM_API void set_backedge(ir_node *n, int pos);
 /** Marks edge pos as a non-backedge. */
 FIRM_API void set_not_backedge(ir_node *n, int pos);
 /** Returns non-zero if n has backedges. */
-FIRM_API int has_backedges(ir_node *n);
+FIRM_API int has_backedges(const ir_node *n);
 /** Clears all backedge information. */
 FIRM_API void clear_backedges(ir_node *n);
 
index 149a6c7..6d3d749 100644 (file)
@@ -160,14 +160,15 @@ FIRM_API void lower_CopyB(ir_graph *irg, unsigned max_size,
  * They will either remain the same or be converted into if-cascades.
  *
  * @param irg        The ir graph to be lowered.
+ * @param small_switch  If switch has <= cases then change it to an if-cascade.
  * @param spare_size Allowed spare size for table switches in machine words.
  *                   (Default in edgfe: 128)
  * @param allow_out_of_bounds   backend can handle out-of-bounds values
  *                              (values bigger than minimum and maximum proj
  *                               number)
  */
-FIRM_API void lower_switch(ir_graph *irg, unsigned spare_size,
-                           int allow_out_of_bounds);
+FIRM_API void lower_switch(ir_graph *irg, unsigned small_switch,
+                           unsigned spare_size, int allow_out_of_bounds);
 
 /**
  * Replaces SymConsts by a real constant if possible.
@@ -232,13 +233,13 @@ typedef ir_node* (*create_set_func)(ir_node *cond);
 /**
  * implementation of create_set_func which produces a Mux node with 0/1 input
  */
-ir_node *ir_create_mux_set(ir_node *cond, ir_mode *dest_mode);
+FIRM_API ir_node *ir_create_mux_set(ir_node *cond, ir_mode *dest_mode);
 
 /**
  * implementation of create_set_func which produces a cond with control
  * flow
  */
-ir_node *ir_create_cond_set(ir_node *cond, ir_mode *dest_mode);
+FIRM_API ir_node *ir_create_cond_set(ir_node *cond, ir_mode *dest_mode);
 
 typedef struct lower_mode_b_config_t {
        /* mode that is used to transport 0/1 values */
index 17b8c69..82a0406 100644 (file)
@@ -91,11 +91,12 @@ static ptr_access_kind analyze_arg(ir_node *arg, ptr_access_kind bits)
                                        }
                                } else if (is_Sel(ptr) && get_irp_callee_info_state() == irg_callee_info_consistent) {
                                        /* is be a polymorphic call but callee information is available */
-                                       int i, n_params = get_Call_n_params(succ);
+                                       int n_params = get_Call_n_params(succ);
+                                       int c;
 
                                        /* simply look into ALL possible callees */
-                                       for (i = get_Call_n_callees(succ) - 1; i >= 0; --i) {
-                                               meth_ent = get_Call_callee(succ, i);
+                                       for (c = get_Call_n_callees(succ) - 1; c >= 0; --c) {
+                                               meth_ent = get_Call_callee(succ, c);
 
                                                /* unknown_entity is used to signal that we don't know what is called */
                                                if (meth_ent == unknown_entity) {
index 0ffdd8b..a089d35 100644 (file)
@@ -350,8 +350,6 @@ static void free_mark_proj(ir_node * node, long n, eset * set)
  */
 static void free_mark(ir_node *node, eset * set)
 {
-       size_t i, n;
-
        if (get_irn_link(node) == MARK)
                return; /* already visited */
 
@@ -361,6 +359,7 @@ static void free_mark(ir_node *node, eset * set)
        case iro_Sel: {
                ir_entity *ent = get_Sel_entity(node);
                if (is_method_entity(ent)) {
+                       size_t i, n;
                        for (i = 0, n = get_Sel_n_methods(node); i < n; ++i) {
                                eset_insert(set, get_Sel_method(node, i));
                        }
@@ -399,7 +398,6 @@ static void free_mark(ir_node *node, eset * set)
 static void free_ana_walker(ir_node *node, void *env)
 {
        eset *set = (eset*) env;
-       int i;
 
        if (get_irn_link(node) == MARK) {
                /* already visited */
@@ -430,7 +428,8 @@ static void free_ana_walker(ir_node *node, void *env)
                }
                break;
        }
-       default:
+       default: {
+               int i;
                /* other nodes: Alle anderen Knoten nehmen wir als Verr�ter an, bis
                 * jemand das Gegenteil implementiert. */
                set_irn_link(node, MARK);
@@ -442,6 +441,7 @@ static void free_ana_walker(ir_node *node, void *env)
                }
                break;
        }
+       }
 }
 
 /**
@@ -518,10 +518,10 @@ static void add_method_address(ir_entity *ent, eset *set)
 
                        /* let's check if it's the address of a function */
                        if (is_Global(irn)) {
-                               ir_entity *ent = get_Global_entity(irn);
+                               ir_entity *ent2 = get_Global_entity(irn);
 
-                               if (is_Method_type(get_entity_type(ent)))
-                                       eset_insert(set, ent);
+                               if (is_Method_type(get_entity_type(ent2)))
+                                       eset_insert(set, ent2);
                        }
                }
        }
index cf96c45..70fdf54 100644 (file)
@@ -274,7 +274,7 @@ void dfs_dump(const dfs_t *dfs, FILE *file)
        }
 
        for (i = 0; i < n; ++i) {
-               dfs_node_t *node = nodes[i];
+               node = nodes[i];
                ir_fprintf(file, "\tn%d [label=\"%d\"]\n", node->pre_num, get_Block_dom_tree_pre_num((ir_node*) node->node));
 #if 0
                ir_fprintf(file, "\tn%d [shape=box,label=\"%+F\\l%d %d/%d %d\"];\n",
index a655a76..84abaf1 100644 (file)
@@ -295,7 +295,6 @@ ir_exec_freq *compute_execfreq(ir_graph *irg, double loop_weight)
 
        for (idx = dfs_get_n_nodes(dfs) - 1; idx >= 0; --idx) {
                ir_node *bb = (ir_node *) dfs_get_post_num_node(dfs, size - idx - 1);
-               freq_t *freq;
                int i;
 
                freq = set_insert_freq(freqs, bb);
@@ -354,7 +353,7 @@ ir_exec_freq *compute_execfreq(ir_graph *irg, double loop_weight)
 
        ef->max = 0.0;
        set_foreach(freqs, freq_t*, freq) {
-               int idx = freq->idx;
+               idx = freq->idx;
 
                /* take abs because it sometimes can be -0 in case of endless loops */
                freq->freq = fabs(x[idx]) * norm;
index 13fee32..6607f21 100644 (file)
@@ -44,7 +44,7 @@
  * Does not assert whether the backarray is correct -- use
  * very careful!
  */
-static bitset_t *mere_get_backarray(ir_node *n)
+static bitset_t *mere_get_backarray(const ir_node *n)
 {
        switch (get_irn_opcode(n)) {
        case iro_Block:
@@ -65,7 +65,7 @@ static bitset_t *mere_get_backarray(ir_node *n)
  * Returns backarray if the node can have backedges, else returns
  * NULL.
  */
-static bitset_t *get_backarray(ir_node *n)
+static bitset_t *get_backarray(const ir_node *n)
 {
        bitset_t *ba = mere_get_backarray(n);
 
@@ -85,7 +85,7 @@ static bitset_t *get_backarray(ir_node *n)
  * Returns non-zero if node has no backarray, or
  *                  if size of backarray == size of in array.
  */
-static int legal_backarray(ir_node *n)
+static int legal_backarray(const ir_node *n)
 {
        bitset_t *ba = mere_get_backarray(n);
        if (ba && (bitset_size(ba) != (unsigned) get_irn_arity(n)))
@@ -119,7 +119,7 @@ void fix_backedges(struct obstack *obst, ir_node *n)
 }
 
 /* Returns non-zero if the predecessor pos is a backedge. */
-int is_backedge(ir_node *n, int pos)
+int is_backedge(const ir_node *n, int pos)
 {
        bitset_t *ba = get_backarray(n);
        if (ba)
@@ -144,7 +144,7 @@ void set_not_backedge(ir_node *n, int pos)
 }
 
 /* Returns non-zero if n has backedges. */
-int has_backedges(ir_node *n)
+int has_backedges(const ir_node *n)
 {
        bitset_t *ba = get_backarray(n);
        if (ba != NULL) {
index fb5174c..9994472 100644 (file)
@@ -308,14 +308,14 @@ static void handle_if(ir_node *block, ir_node *cmp, ir_relation rel, env_t *env)
                                 * left == Const and we found a movable user of left in a
                                 * dominator of the Cond block
                                 */
-                               const ir_edge_t *edge, *next;
-                               for (edge = get_irn_out_edge_first(user); edge; edge = next) {
-                                       ir_node *usr_of_usr = get_edge_src_irn(edge);
-                                       int      npos = get_edge_src_pos(edge);
-                                       ir_node *blk  = get_effective_use_block(usr_of_usr, npos);
-
-                                       next = get_irn_out_edge_next(user, edge);
-                                       if (block_dominates(block, blk)) {
+                               const ir_edge_t *user_edge;
+                               const ir_edge_t *user_next;
+                               foreach_out_edge_safe(user, user_edge, user_next) {
+                                       ir_node *usr_of_usr = get_edge_src_irn(user_edge);
+                                       int      npos       = get_edge_src_pos(user_edge);
+                                       ir_node *user_blk   = get_effective_use_block(usr_of_usr, npos);
+
+                                       if (block_dominates(block, user_blk)) {
                                                /*
                                                 * The user of the user is dominated by our true/false
                                                 * block. So, create a copy of user WITH the constant
index 52afe1b..c0b3e5e 100644 (file)
@@ -597,6 +597,16 @@ static ir_alias_relation _get_alias_relation(
        class1 = get_base_sc(mod1);
        class2 = get_base_sc(mod2);
 
+       /* struct-access cannot alias with variables */
+       if (ent1 == NULL && ent2 != NULL && is_compound_type(get_entity_owner(ent2))
+               && (class1 == ir_sc_globalvar || class1 == ir_sc_localvar || class1 == ir_sc_tls || class1 == ir_sc_globaladdr)) {
+               return ir_no_alias;
+       }
+       if (ent2 == NULL && ent1 != NULL && is_compound_type(get_entity_owner(ent1))
+               && (class2 == ir_sc_globalvar || class2 == ir_sc_localvar || class2 == ir_sc_tls || class2 == ir_sc_globaladdr)) {
+               return ir_no_alias;
+       }
+
        if (class1 == ir_sc_pointer || class2 == ir_sc_pointer) {
                /* swap pointer class to class1 */
                if (class2 == ir_sc_pointer) {
@@ -886,14 +896,14 @@ static ir_entity_usage determine_entity_usage(const ir_node *irn, ir_entity *ent
                        res |= determine_entity_usage(succ, entity);
                        break;
                case iro_Sel: {
-                       ir_entity *entity = get_Sel_entity(succ);
+                       ir_entity *sel_entity = get_Sel_entity(succ);
                        /* this analysis can't handle unions correctly */
-                       if (is_Union_type(get_entity_owner(entity))) {
+                       if (is_Union_type(get_entity_owner(sel_entity))) {
                                res |= ir_usage_unknown;
                                break;
                        }
                        /* Check the successor of irn. */
-                       res |= determine_entity_usage(succ, entity);
+                       res |= determine_entity_usage(succ, sel_entity);
                        break;
                }
 
@@ -1130,8 +1140,8 @@ static void check_initializer(ir_entity *ent)
 
                        /* let's check if it's an address */
                        if (is_Global(irn)) {
-                               ir_entity *ent = get_Global_entity(irn);
-                               set_entity_usage(ent, ir_usage_unknown);
+                               ir_entity *symconst_ent = get_Global_entity(irn);
+                               set_entity_usage(symconst_ent, ir_usage_unknown);
                        }
                }
        }
index cf55444..c36e6af 100644 (file)
@@ -431,7 +431,6 @@ static ir_region *new_SwitchCase(struct obstack *obst, ir_region_kind type, ir_r
        reg->succ[0] = exit;
 
        DEBUG_ONLY({
-               size_t i;
                DB((dbg, LEVEL_2, " Created %s(%u)\n", reg->type == ir_rk_Switch ? "Switch" : "Case", reg->nr));
                for (i = 1; i < ARR_LEN(reg->parts); ++i) {
                        DB((dbg, LEVEL_2, "  Case(%lu)\n", reg->parts[i].region->nr));
@@ -841,7 +840,7 @@ static ir_region *acyclic_region_type(struct obstack *obst, ir_region *node)
        /* check for Switch, case */
        if (k > 0) {
                ir_region *rexit = NULL;
-               size_t i, p = 0;
+               size_t i, pos = 0;
                nset = NULL; nset_len = 0;
                for (i = k; i > 0;) {
                        n = get_region_succ(node, i--);
@@ -849,12 +848,12 @@ static ir_region *acyclic_region_type(struct obstack *obst, ir_region *node)
                        if (get_region_n_succs(n) != 1) {
                                /* must be the exit */
                                rexit = n;
-                               ++p;
-                               if (p > 1)
+                               ++pos;
+                               if (pos > 1)
                                        break;
                        }
                }
-               if (p <= 1) {
+               if (pos <= 1) {
                        ir_region_kind kind = ir_rk_Case;
                        ir_region *pos_exit_1 = NULL;
                        ir_region *pos_exit_2 = NULL;
index 678c10c..63ed205 100644 (file)
@@ -61,47 +61,48 @@ $mode_fp  = "mode_E";  # mode used by floatingpoint registers
 #
 # register types:
 #   0 - no special type
-#   1 - caller save (register must be saved by the caller of a function)
-#   2 - callee save (register must be saved by the called function)
-#   4 - ignore (do not assign this register)
+#   1 - ignore (do not assign this register)
+#   2 - emitter can choose an arbitrary register of this class
+#   4 - the register is a virtual one
+#   8 - register represents a state
 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
 %reg_classes = (
        gp => [
-               { name => "r0", type => 1 },
-               { name => "r1", type => 1 },
-               { name => "r2", type => 1 },
-               { name => "r3", type => 1 },
-               { name => "r4", type => 1 },
-               { name => "r5", type => 1 },
-               { name => "r6", type => 1 },
-               { name => "r7", type => 2 },
-               { name => "r8", type => 2 },
-               { name => "r9", type => 2 },
-               { name => "r10", type => 2 },
-               { name => "r11", type => 2 },
-               { name => "r12", type => 2 },
-               { name => "r13", type => 2 },
-               { name => "sp", realname => "r14", type => 4 },  # stackpointer
-               { name => "bp", realname => "r15", type => 4 },  # basepointer
+               { name => "r0" },
+               { name => "r1" },
+               { name => "r2" },
+               { name => "r3" },
+               { name => "r4" },
+               { name => "r5" },
+               { name => "r6" },
+               { name => "r7" },
+               { name => "r8" },
+               { name => "r9" },
+               { name => "r10" },
+               { name => "r11" },
+               { name => "r12" },
+               { name => "r13" },
+               { name => "sp", realname => "r14", type => 1 },  # stackpointer
+               { name => "bp", realname => "r15", type => 1 },  # basepointer
                { mode => $mode_gp }
        ],
        fp => [
-               { name => "f0", type => 1 },
-               { name => "f1", type => 1 },
-               { name => "f2", type => 1 },
-               { name => "f3", type => 1 },
-               { name => "f4", type => 1 },
-               { name => "f5", type => 1 },
-               { name => "f6", type => 1 },
-               { name => "f7", type => 1 },
-               { name => "f8", type => 1 },
-               { name => "f9", type => 1 },
-               { name => "f10", type => 1 },
-               { name => "f11", type => 1 },
-               { name => "f12", type => 1 },
-               { name => "f13", type => 1 },
-               { name => "f14", type => 1 },
-               { name => "f15", type => 1 },
+               { name => "f0" },
+               { name => "f1" },
+               { name => "f2" },
+               { name => "f3" },
+               { name => "f4" },
+               { name => "f5" },
+               { name => "f6" },
+               { name => "f7" },
+               { name => "f8" },
+               { name => "f9" },
+               { name => "f10" },
+               { name => "f11" },
+               { name => "f12" },
+               { name => "f13" },
+               { name => "f14" },
+               { name => "f15" },
                { mode => $mode_fp }
        ]
 );
index 527a8a3..1596442 100644 (file)
@@ -322,7 +322,9 @@ static const backend_params *TEMPLATE_get_backend_params(void)
                0,     /* 0: little-endian, 1: big-endian */
                NULL,  /* architecture dependent settings, will be set later */
                TEMPLATE_is_mux_allowed,  /* parameter for if conversion */
+               32,    /* machine size - a 32bit CPU */
                NULL,  /* float arithmetic mode */
+               0,     /* size of long double */
                0,     /* no trampoline support: size 0 */
                0,     /* no trampoline support: align 0 */
                NULL,  /* no trampoline support: no trampoline builder */
@@ -351,6 +353,50 @@ static int TEMPLATE_is_valid_clobber(const char *clobber)
        return 0;
 }
 
+/**
+ * Check if the given register is callee or caller save.
+ */
+static int TEMPLATE_register_saved_by(const arch_register_t *reg, int callee)
+{
+       if (callee) {
+               /* check for callee saved */
+               if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp]) {
+                       switch (reg->index) {
+                       case REG_GP_R7:
+                       case REG_GP_R8:
+                       case REG_GP_R9:
+                       case REG_GP_R10:
+                       case REG_GP_R11:
+                       case REG_GP_R12:
+                       case REG_GP_R13:
+                               return 1;
+                       default:
+                               return 0;
+                       }
+               }
+       } else {
+               /* check for caller saved */
+               if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp]) {
+                       switch (reg->index) {
+                       case REG_GP_R0:
+                       case REG_GP_R1:
+                       case REG_GP_R2:
+                       case REG_GP_R3:
+                       case REG_GP_R4:
+                       case REG_GP_R5:
+                       case REG_GP_R6:
+                               return 1;
+                       default:
+                               return 0;
+                       }
+               } else if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_fp]) {
+                       /* all FP registers are caller save */
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 const arch_isa_if_t TEMPLATE_isa_if = {
        TEMPLATE_init,
        TEMPLATE_lower_for_target,
@@ -373,6 +419,7 @@ const arch_isa_if_t TEMPLATE_isa_if = {
        TEMPLATE_after_ra,
        TEMPLATE_finish_irg,
        TEMPLATE_emit_routine,
+       TEMPLATE_register_saved_by,
 };
 
 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE)
index 8091083..6a90fed 100644 (file)
@@ -55,55 +55,53 @@ $arch = "amd64";
 #
 # register types:
 $normal      =  0; # no special type
-$caller_save =  1; # caller save (register must be saved by the caller of a function)
-$callee_save =  2; # callee save (register must be saved by the called function)
-$ignore      =  4; # ignore (do not assign this register)
-$arbitrary   =  8; # emitter can choose an arbitrary register of this class
-$virtual     = 16; # the register is a virtual one
-$state       = 32; # register represents a state
+$ignore      =  1; # ignore (do not assign this register)
+$arbitrary   =  2; # emitter can choose an arbitrary register of this class
+$virtual     =  4; # the register is a virtual one
+$state       =  8; # register represents a state
 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
 %reg_classes = (
        gp => [
-               { name => "rax", type => $caller_save },
-               { name => "rcx", type => $caller_save },
-               { name => "rdx", type => $caller_save },
-               { name => "rsi", type => $caller_save },
-               { name => "rdi", type => $caller_save },
-               { name => "rbx", type => $callee_save },
-               { name => "rbp", type => $callee_save },
-               { name => "rsp", type => 4 }, # stackpointer?
-               { name => "r8",  type => $caller_save },
-               { name => "r9",  type => $caller_save },
-               { name => "r10", type => $caller_save },
-               { name => "r11", type => $caller_save },
-               { name => "r12", type => $callee_save },
-               { name => "r13", type => $callee_save },
-               { name => "r14", type => $callee_save },
-               { name => "r15", type => $callee_save },
+               { name => "rax" },
+               { name => "rcx" },
+               { name => "rdx" },
+               { name => "rsi" },
+               { name => "rdi" },
+               { name => "rbx" },
+               { name => "rbp" },
+               { name => "rsp", type => $ignore }, # stackpointer?
+               { name => "r8" },
+               { name => "r9" },
+               { name => "r10" },
+               { name => "r11" },
+               { name => "r12" },
+               { name => "r13" },
+               { name => "r14" },
+               { name => "r15" },
 #              { name => "gp_NOREG", type => $ignore }, # we need a dummy register for NoReg nodes
                { mode => "mode_Lu" }
        ],
 #      fp => [
-#              { name => "xmm0", type => $caller_save },
-#              { name => "xmm1", type => $caller_save },
-#              { name => "xmm2", type => $caller_save },
-#              { name => "xmm3", type => $caller_save },
-#              { name => "xmm4", type => $caller_save },
-#              { name => "xmm5", type => $caller_save },
-#              { name => "xmm6", type => $caller_save },
-#              { name => "xmm7", type => $caller_save },
-#              { name => "xmm8", type => $caller_save },
-#              { name => "xmm9", type => $caller_save },
-#              { name => "xmm10", type => $caller_save },
-#              { name => "xmm11", type => $caller_save },
-#              { name => "xmm12", type => $caller_save },
-#              { name => "xmm13", type => $caller_save },
-#              { name => "xmm14", type => $caller_save },
-#              { name => "xmm15", type => $caller_save },
+#              { name => "xmm0" },
+#              { name => "xmm1" },
+#              { name => "xmm2" },
+#              { name => "xmm3" },
+#              { name => "xmm4" },
+#              { name => "xmm5" },
+#              { name => "xmm6" },
+#              { name => "xmm7" },
+#              { name => "xmm8" },
+#              { name => "xmm9" },
+#              { name => "xmm10" },
+#              { name => "xmm11" },
+#              { name => "xmm12" },
+#              { name => "xmm13" },
+#              { name => "xmm14" },
+#              { name => "xmm15" },
 #              { mode => "mode_D" }
 #      ]
        flags => [
-               { name => "eflags", type => 0 },
+               { name => "eflags" },
                { mode => "mode_Iu", flags => "manual_ra" }
        ],
 );
index 4972ded..7775e2f 100644 (file)
@@ -453,7 +453,7 @@ static void amd64_get_call_abi(const void *self, ir_type *method_type,
 
                /* FIXME: No floating point yet */
                /* be_abi_call_res_reg(abi, 0,
-                       mode_is_float(mode) ? &amd64_fp_regs[REG_F0] : &amd64_registers[REG_R0], ABI_CONTEXT_BOTH) */;
+                       mode_is_float(mode) ? &amd64_fp_regs[REG_F0] : &amd64_registers[REG_R0], ABI_CONTEXT_BOTH); */
 
                be_abi_call_res_reg(abi, 0,
                        &amd64_registers[REG_RAX], ABI_CONTEXT_BOTH);
@@ -502,7 +502,9 @@ static const backend_params *amd64_get_backend_params(void) {
                0,     /* little endian */
                NULL,  /* will be set later */
                amd64_is_mux_allowed,  /* parameter for if conversion */
+               64,    /* machine size */
                NULL,  /* float arithmetic mode */
+               0,     /* size of long double */
                0,     /* no trampoline support: size 0 */
                0,     /* no trampoline support: align 0 */
                NULL,  /* no trampoline support: no trampoline builder */
@@ -531,6 +533,45 @@ static int amd64_is_valid_clobber(const char *clobber)
        return 0;
 }
 
+static int amd64_register_saved_by(const arch_register_t *reg, int callee)
+{
+       if (callee) {
+               /* check for callee saved */
+               if (reg->reg_class == &amd64_reg_classes[CLASS_amd64_gp]) {
+                       switch (reg->index) {
+                       case REG_GP_RBX:
+                       case REG_GP_RBP:
+                       case REG_GP_R12:
+                       case REG_GP_R13:
+                       case REG_GP_R14:
+                       case REG_GP_R15:
+                               return 1;
+                       default:
+                               return 0;
+                       }
+               }
+       } else {
+               /* check for caller saved */
+               if (reg->reg_class == &amd64_reg_classes[CLASS_amd64_gp]) {
+                       switch (reg->index) {
+                       case REG_GP_RAX:
+                       case REG_GP_RCX:
+                       case REG_GP_RDX:
+                       case REG_GP_RSI:
+                       case REG_GP_RDI:
+                       case REG_GP_R8:
+                       case REG_GP_R9:
+                       case REG_GP_R10:
+                       case REG_GP_R11:
+                               return 1;
+                       default:
+                               return 0;
+                       }
+               }
+       }
+       return 0;
+}
+
 const arch_isa_if_t amd64_isa_if = {
        amd64_init,
        amd64_lower_for_target,
@@ -553,6 +594,7 @@ const arch_isa_if_t amd64_isa_if = {
        amd64_after_ra,
        amd64_finish_irg,
        amd64_gen_routine,
+       amd64_register_saved_by,
 };
 
 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_amd64)
index a237b36..da53ffd 100644 (file)
@@ -39,11 +39,30 @@ static const unsigned ignore_regs[] = {
        REG_FL,
 };
 
-/* determine how function parameters and return values are passed. */
+static const arch_register_t* const param_regs[] = {
+       &arm_registers[REG_R0],
+       &arm_registers[REG_R1],
+       &arm_registers[REG_R2],
+       &arm_registers[REG_R3]
+};
+
+static const arch_register_t* const result_regs[] = {
+       &arm_registers[REG_R0],
+       &arm_registers[REG_R1],
+       &arm_registers[REG_R2],
+       &arm_registers[REG_R3]
+};
+
+static const arch_register_t* const float_result_regs[] = {
+       &arm_registers[REG_F0],
+       &arm_registers[REG_F1]
+};
+
 calling_convention_t *arm_decide_calling_convention(const ir_graph *irg,
                                                     ir_type *function_type)
 {
-       int                   stack_offset = 0;
+       unsigned              stack_offset      = 0;
+       unsigned              n_param_regs_used = 0;
        reg_or_stackslot_t   *params;
        reg_or_stackslot_t   *results;
        int                   n_param_regs
@@ -90,15 +109,16 @@ calling_convention_t *arm_decide_calling_convention(const ir_graph *irg,
                                const arch_register_t *reg = param_regs[regnum++];
                                param->reg1 = reg;
                        } else {
-                               ir_mode *mode = param_regs[0]->reg_class->mode;
-                               ir_type *type = get_type_for_mode(mode);
-                               param->type   = type;
-                               param->offset = stack_offset;
-                               assert(get_mode_size_bits(mode) == 32);
+                               ir_mode *pmode = param_regs[0]->reg_class->mode;
+                               ir_type *type  = get_type_for_mode(pmode);
+                               param->type    = type;
+                               param->offset  = stack_offset;
+                               assert(get_mode_size_bits(pmode) == 32);
                                stack_offset += 4;
                        }
                }
        }
+       n_param_regs_used = regnum;
 
        n_results    = get_method_n_ress(function_type);
        regnum       = 0;
@@ -133,6 +153,7 @@ calling_convention_t *arm_decide_calling_convention(const ir_graph *irg,
        cconv                   = XMALLOCZ(calling_convention_t);
        cconv->parameters       = params;
        cconv->param_stack_size = stack_offset;
+       cconv->n_reg_params     = n_param_regs_used;
        cconv->results          = results;
 
        /* setup allocatable registers */
index 9e2b017..880afc4 100644 (file)
 #include "../be_types.h"
 #include "gen_arm_regalloc_if.h"
 
-static const arch_register_t *const callee_saves[] = {
-       &arm_registers[REG_R4],
-       &arm_registers[REG_R5],
-       &arm_registers[REG_R6],
-       &arm_registers[REG_R7],
-       &arm_registers[REG_R8],
-       &arm_registers[REG_R9],
-       &arm_registers[REG_R10],
-       &arm_registers[REG_R11],
-       &arm_registers[REG_LR],
-};
-
-static const arch_register_t *const caller_saves[] = {
-       &arm_registers[REG_R0],
-       &arm_registers[REG_R1],
-       &arm_registers[REG_R2],
-       &arm_registers[REG_R3],
-       &arm_registers[REG_LR],
-
-       &arm_registers[REG_F0],
-       &arm_registers[REG_F1],
-       &arm_registers[REG_F2],
-       &arm_registers[REG_F3],
-       &arm_registers[REG_F4],
-       &arm_registers[REG_F5],
-       &arm_registers[REG_F6],
-       &arm_registers[REG_F7],
-};
-
-static const arch_register_t* const param_regs[] = {
-       &arm_registers[REG_R0],
-       &arm_registers[REG_R1],
-       &arm_registers[REG_R2],
-       &arm_registers[REG_R3]
-};
-
-static const arch_register_t* const result_regs[] = {
-       &arm_registers[REG_R0],
-       &arm_registers[REG_R1],
-       &arm_registers[REG_R2],
-       &arm_registers[REG_R3]
-};
-
-static const arch_register_t* const float_result_regs[] = {
-       &arm_registers[REG_F0],
-       &arm_registers[REG_F1]
-};
-
 /** information about a single parameter or result */
 typedef struct reg_or_stackslot_t
 {
@@ -85,7 +37,7 @@ typedef struct reg_or_stackslot_t
        const arch_register_t *reg1;   /**< if != NULL, the second register used. */
        ir_type               *type;   /**< indicates that an entity of the specific
                                                                            type is needed */
-       int                    offset; /**< if transmitted via stack, the offset for this parameter. */
+       unsigned               offset; /**< if transmitted via stack, the offset for this parameter. */
        ir_entity             *entity; /**< entity in frame type */
 } reg_or_stackslot_t;
 
@@ -93,7 +45,8 @@ typedef struct reg_or_stackslot_t
 typedef struct calling_convention_t
 {
        reg_or_stackslot_t *parameters;        /**< parameter info. */
-       int                 param_stack_size;  /**< needed stack size for parameters */
+       unsigned            param_stack_size;  /**< needed stack size for parameters */
+       unsigned            n_reg_params;
        reg_or_stackslot_t *results;           /**< result info. */
 } calling_convention_t;
 
index 035be5b..dc7e632 100644 (file)
@@ -1130,16 +1130,17 @@ void arm_gen_routine(ir_graph *irg)
                                be_emit_write_line();
                        } else {
                                ir_tarval *tv = entry->u.tv;
-                               int i, size = get_mode_size_bytes(get_tarval_mode(tv));
-                               unsigned v;
+                               int vi;
+                               int size = get_mode_size_bytes(get_tarval_mode(tv));
 
                                /* beware: ARM fpa uses big endian format */
-                               for (i = ((size + 3) & ~3) - 4; i >= 0; i -= 4) {
+                               for (vi = ((size + 3) & ~3) - 4; vi >= 0; vi -= 4) {
                                        /* get 32 bits */
-                                       v =            get_tarval_sub_bits(tv, i+3);
-                                       v = (v << 8) | get_tarval_sub_bits(tv, i+2);
-                                       v = (v << 8) | get_tarval_sub_bits(tv, i+1);
-                                       v = (v << 8) | get_tarval_sub_bits(tv, i+0);
+                                       unsigned v;
+                                       v =            get_tarval_sub_bits(tv, vi+3);
+                                       v = (v << 8) | get_tarval_sub_bits(tv, vi+2);
+                                       v = (v << 8) | get_tarval_sub_bits(tv, vi+1);
+                                       v = (v << 8) | get_tarval_sub_bits(tv, vi+0);
                                        be_emit_irprintf("\t.word\t%u\n", v);
                                        be_emit_write_line();
                                }
index aa57547..d267954 100644 (file)
@@ -120,11 +120,11 @@ static void peephole_be_IncSP(ir_node *node)
        first = node;
        block = get_nodes_block(node);
        for (cnt = 1; cnt < v.ops; ++cnt) {
-               int value = sign * arm_ror(v.values[cnt], v.rors[cnt]);
-               ir_node *next = be_new_IncSP(&arm_registers[REG_SP], block, node,
+               int      value = sign * arm_ror(v.values[cnt], v.rors[cnt]);
+               ir_node *incsp = be_new_IncSP(&arm_registers[REG_SP], block, node,
                                             value, 1);
-               sched_add_after(node, next);
-               node = next;
+               sched_add_after(node, incsp);
+               node = incsp;
        }
 
        /* reattach IncSP users */
index 2aa3e04..36e7da7 100644 (file)
@@ -67,6 +67,35 @@ static arm_isa_t             *isa;
 
 static pmap                  *node_to_stack;
 
+static const arch_register_t *const callee_saves[] = {
+       &arm_registers[REG_R4],
+       &arm_registers[REG_R5],
+       &arm_registers[REG_R6],
+       &arm_registers[REG_R7],
+       &arm_registers[REG_R8],
+       &arm_registers[REG_R9],
+       &arm_registers[REG_R10],
+       &arm_registers[REG_R11],
+       &arm_registers[REG_LR],
+};
+
+static const arch_register_t *const caller_saves[] = {
+       &arm_registers[REG_R0],
+       &arm_registers[REG_R1],
+       &arm_registers[REG_R2],
+       &arm_registers[REG_R3],
+       &arm_registers[REG_LR],
+
+       &arm_registers[REG_F0],
+       &arm_registers[REG_F1],
+       &arm_registers[REG_F2],
+       &arm_registers[REG_F3],
+       &arm_registers[REG_F4],
+       &arm_registers[REG_F5],
+       &arm_registers[REG_F6],
+       &arm_registers[REG_F7],
+};
+
 static bool mode_needs_gp_reg(ir_mode *mode)
 {
        return mode_is_int(mode) || mode_is_reference(mode);
@@ -395,7 +424,7 @@ static ir_node *gen_int_binop(ir_node *node, match_flags_t flags,
        }
 
        if (try_encode_as_immediate(op2, &imm)) {
-               ir_node *new_op1 = be_transform_node(op1);
+               new_op1 = be_transform_node(op1);
                return factory->new_binop_imm(dbgi, block, new_op1, imm.imm_8, imm.rot);
        }
        new_op2 = be_transform_node(op2);
@@ -1635,9 +1664,9 @@ static ir_node *gen_Unknown(ir_node *node)
        /* just produce a 0 */
        ir_mode *mode = get_irn_mode(node);
        if (mode_is_float(mode)) {
-               ir_tarval *tv   = get_mode_null(mode);
-               ir_node   *node = new_bd_arm_fConst(dbgi, new_block, tv);
-               return node;
+               ir_tarval *tv     = get_mode_null(mode);
+               ir_node   *fconst = new_bd_arm_fConst(dbgi, new_block, tv);
+               return fconst;
        } else if (mode_needs_gp_reg(mode)) {
                return create_const_graph_value(dbgi, new_block, 0);
        }
@@ -1825,7 +1854,7 @@ static ir_node *gen_Call(ir_node *node)
        ir_type              *type         = get_Call_type(node);
        calling_convention_t *cconv        = arm_decide_calling_convention(NULL, type);
        size_t                n_params     = get_Call_n_params(node);
-       size_t                n_param_regs = sizeof(param_regs)/sizeof(param_regs[0]);
+       size_t                n_param_regs = cconv->n_reg_params;
        /* max inputs: memory, callee, register arguments */
        int                   max_inputs   = 2 + n_param_regs;
        ir_node             **in           = ALLOCAN(ir_node*, max_inputs);
index 6c47932..01f82d0 100644 (file)
@@ -78,8 +78,8 @@ static ir_entity *arm_get_frame_entity(const ir_node *irn)
        const arm_attr_t *attr = get_arm_attr_const(irn);
 
        if (is_arm_FrameAddr(irn)) {
-               const arm_SymConst_attr_t *attr = get_arm_SymConst_attr_const(irn);
-               return attr->entity;
+               const arm_SymConst_attr_t *frame_attr = get_arm_SymConst_attr_const(irn);
+               return frame_attr->entity;
        }
        if (attr->is_load_store) {
                const arm_load_store_attr_t *load_store_attr
@@ -549,7 +549,7 @@ static void arm_lower_for_target(void)
 
        for (i = 0; i < n_irgs; ++i) {
                ir_graph *irg = get_irp_irg(i);
-               lower_switch(irg, 256, true);
+               lower_switch(irg, 4, 256, true);
        }
 }
 
@@ -573,7 +573,9 @@ static const backend_params *arm_get_libfirm_params(void)
                1,     /* big endian */
                &ad,   /* will be set later */
                arm_is_mux_allowed, /* allow_ifconv function */
+               32,    /* machine size */
                NULL,  /* float arithmetic mode (TODO) */
+               0,     /* size of long double */
                0,     /* no trampoline support: size 0 */
                0,     /* no trampoline support: align 0 */
                NULL,  /* no trampoline support: no trampoline builder */
@@ -625,6 +627,7 @@ const arch_isa_if_t arm_isa_if = {
        arm_after_ra,
        arm_finish_irg,
        arm_gen_routine,
+       NULL, /* register_saved_by */
 };
 
 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm)
index 5ec10b4..97b7cec 100644 (file)
@@ -536,7 +536,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                                 * checking */
                                continue;
                        }
-                       if (destroy_all_regs || (reg->type & arch_register_type_caller_save)) {
+                       if (destroy_all_regs || arch_register_is_caller_save(arch_env, reg)) {
                                if (!(reg->type & arch_register_type_ignore)) {
                                        ARR_APP1(const arch_register_t*, destroyed_regs, reg);
                                }
@@ -1274,7 +1274,7 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
        /* Add uses of the callee save registers. */
        foreach_pmap(env->regs, ent) {
                const arch_register_t *reg = (const arch_register_t*)ent->key;
-               if (reg->type & (arch_register_type_callee_save | arch_register_type_ignore))
+               if ((reg->type & arch_register_type_ignore) || arch_register_is_callee_save(arch_env, reg))
                        pmap_insert(reg_map, ent->key, ent->value);
        }
 
@@ -1787,7 +1787,7 @@ static void modify_irg(ir_graph *irg)
                const arch_register_class_t *cls = &arch_env->register_classes[i];
                for (j = 0; j < cls->n_regs; ++j) {
                        const arch_register_t *reg = &cls->regs[j];
-                       if (reg->type & (arch_register_type_callee_save | arch_register_type_state)) {
+                       if ((reg->type & arch_register_type_state) || arch_register_is_callee_save(arch_env, reg)) {
                                pmap_insert(env->regs, (void *) reg, NULL);
                        }
                }
index 6a68866..a46ff53 100644 (file)
@@ -58,24 +58,18 @@ ENUM_BITSET(arch_register_class_flags_t)
 
 typedef enum arch_register_type_t {
        arch_register_type_none         = 0,
-       /** The register must be saved by the caller upon a function call. It thus
-        * can be overwritten in the called function. */
-       arch_register_type_caller_save  = 1U << 0,
-       /** The register must be saved by the caller upon a function call. It thus
-        * can be overwritten in the called function. */
-       arch_register_type_callee_save  = 1U << 1,
        /** Do not consider this register when allocating. */
-       arch_register_type_ignore       = 1U << 2,
+       arch_register_type_ignore       = 1U << 0,
        /** The emitter can choose an arbitrary register. The register fulfills any
         * register constraints as long as the register class matches */
-       arch_register_type_joker        = 1U << 3,
+       arch_register_type_joker        = 1U << 1,
        /** This is just a virtual register. Virtual registers fulfill any register
         * constraints as long as the register class matches. It is a allowed to
         * have multiple definitions for the same virtual register at a point */
-       arch_register_type_virtual      = 1U << 4,
+       arch_register_type_virtual      = 1U << 2,
        /** The register represents a state that should be handled by bestate
         * code */
-       arch_register_type_state        = 1U << 5,
+       arch_register_type_state        = 1U << 3,
 } arch_register_type_t;
 ENUM_BITSET(arch_register_type_t)
 
@@ -588,6 +582,11 @@ struct arch_isa_if_t {
         * The code generator must also be de-allocated here.
         */
        void (*emit)(ir_graph *irg);
+
+       /**
+        * Checks if the given register is callee/caller saved.
+        */
+       int (*register_saved_by)(const arch_register_t *reg, int callee);
 };
 
 #define arch_env_done(env)                             ((env)->impl->done(env))
@@ -728,6 +727,30 @@ static inline const arch_register_req_t **arch_get_in_register_reqs(
        return info->in_reqs;
 }
 
+/**
+ * Check if the given register is callee save, ie. will be save by the callee.
+ */
+static inline bool arch_register_is_callee_save(
+       const arch_env_t      *arch_env,
+       const arch_register_t *reg)
+{
+       if (arch_env->impl->register_saved_by)
+               return arch_env->impl->register_saved_by(reg, /*callee=*/1);
+       return false;
+}
+
+/**
+ * Check if the given register is caller save, ie. must be save by the caller.
+ */
+static inline bool arch_register_is_caller_save(
+       const arch_env_t      *arch_env,
+       const arch_register_t *reg)
+{
+       if (arch_env->impl->register_saved_by)
+               return arch_env->impl->register_saved_by(reg, /*callee=*/0);
+       return false;
+}
+
 /**
  * Iterate over all values defined by an instruction.
  * Only looks at values in a certain register class where the requirements
index 54c5bf2..55a2b67 100644 (file)
 #include "lc_opts.h"
 #include "lc_opts_enum.h"
 
-#ifdef WITH_ILP
-#include <lpp/lpp.h>
-#include <lpp/lpp_net.h>
-#endif /* WITH_ILP */
+#include "lpp.h"
+#include "lpp_net.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
@@ -77,9 +75,7 @@ static int algo = BLOCKSCHED_GREEDY;
 static const lc_opt_enum_int_items_t blockschedalgo_items[] = {
        { "naiv",   BLOCKSCHED_NAIV },
        { "greedy", BLOCKSCHED_GREEDY },
-#ifdef WITH_ILP
        { "ilp",    BLOCKSCHED_ILP },
-#endif /* WITH_ILP */
        { NULL,     0 }
 };
 
@@ -389,7 +385,7 @@ static void pick_block_successor(blocksched_entry_t *entry, blocksched_env_t *en
                                break;
                        }
                        succ_entry = succ_entry->prev;
-               };
+               }
 
                if (irn_visited(succ_entry->block))
                        continue;
@@ -534,7 +530,6 @@ static ir_node **create_block_schedule_greedy(ir_graph *irg, ir_exec_freq *execf
  *
  */
 
-#ifdef WITH_ILP
 typedef struct ilp_edge_t {
        ir_node *block;   /**< source block */
        int     pos;      /**< number of cfg predecessor (target) */
@@ -712,7 +707,6 @@ static ir_node **create_block_schedule_ilp(ir_graph *irg, ir_exec_freq *execfreq
 
        return block_list;
 }
-#endif /* WITH_ILP */
 
 /*
  *  __  __       _
@@ -740,10 +734,8 @@ ir_node **be_create_block_schedule(ir_graph *irg)
        case BLOCKSCHED_GREEDY:
        case BLOCKSCHED_NAIV:
                return create_block_schedule_greedy(irg, execfreqs);
-#ifdef WITH_ILP
        case BLOCKSCHED_ILP:
                return create_block_schedule_ilp(irg, execfreqs);
-#endif /* WITH_ILP */
        }
 
        panic("unknown blocksched algo");
index 84bfc6e..140c7f3 100644 (file)
@@ -151,7 +151,7 @@ static void ps_finish(plotter_t *_self)
        fclose(self->f);
 }
 
-const plotter_if_t ps_plotter_vtab = {
+static const plotter_if_t ps_plotter_vtab = {
        ps_begin,
        ps_setcolor,
        get_color,
index 67c5bfd..7755ac7 100644 (file)
@@ -105,10 +105,6 @@ static const lc_opt_enum_int_items_t lower_perm_items[] = {
        { NULL, 0 }
 };
 
-static const lc_opt_enum_int_items_t lower_perm_stat_items[] = {
-       { NULL, 0 }
-};
-
 static const lc_opt_enum_int_items_t dump_items[] = {
        { "none",       BE_CH_DUMP_NONE       },
        { "spill",      BE_CH_DUMP_SPILL      },
@@ -254,7 +250,9 @@ static void pre_spill(post_spill_env_t *pse, const arch_register_class_t *cls)
        be_assure_liveness(irg);
        be_liveness_assure_chk(be_get_irg_liveness(irg));
 
-       stat_ev_do(pse->pre_spill_cost = be_estimate_irg_costs(irg, exec_freq));
+       if (stat_ev_enabled) {
+               pse->pre_spill_cost = be_estimate_irg_costs(irg, exec_freq);
+       }
 
        /* put all ignore registers into the ignore register set. */
        be_put_allocatable_regs(irg, pse->cls, chordal_env->allocatable_regs);
@@ -317,7 +315,7 @@ static void post_spill(post_spill_env_t *pse, int iteration)
                chordal_env->ifg = be_create_ifg(chordal_env);
                be_timer_pop(T_RA_IFG);
 
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        be_ifg_stat_t   stat;
                        be_node_stats_t node_stats;
 
@@ -395,7 +393,7 @@ static void be_ra_chordal_main(ir_graph *irg)
 
        be_timer_pop(T_RA_PROLOG);
 
-       stat_ev_if {
+       if (stat_ev_enabled) {
                be_collect_node_stats(&last_node_stats, irg);
        }
 
@@ -412,7 +410,7 @@ static void be_ra_chordal_main(ir_graph *irg)
 
                stat_ev_ctx_push_str("bechordal_cls", cls->name);
 
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        be_do_stat_reg_pressure(irg, cls);
                }
 
@@ -428,7 +426,7 @@ static void be_ra_chordal_main(ir_graph *irg)
 
                post_spill(&pse, 0);
 
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        be_node_stats_t node_stats;
 
                        be_collect_node_stats(&node_stats, irg);
index 57fdab4..6c0d410 100644 (file)
 #include "bemodule.h"
 #include "error.h"
 
+#include "lpp.h"
+
 #include "lc_opts.h"
 #include "lc_opts_enum.h"
 
-#ifdef WITH_ILP
-
 #define DUMP_ILP 1
 #define DUMP_SOL 2
 
@@ -63,7 +63,7 @@ static const lc_opt_table_entry_t options[] = {
        LC_OPT_LAST
 };
 
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp)
 void be_init_copyilp(void)
 {
        lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
@@ -231,7 +231,7 @@ lpp_sol_state_t ilp_go(ilp_env_t *ienv)
        if (solve_log)
                lpp_set_log(ienv->lp, stdout);
 
-       lpp_solve_net(ienv->lp, options->ilp_server, options->ilp_solver);
+       lpp_solve(ienv->lp, options->ilp_server, options->ilp_solver);
 
        //be_stat_ev_dbl("co_ilp_objval",     ienv->lp->objval);
        //be_stat_ev_dbl("co_ilp_best_bound", ienv->lp->best_bound);
@@ -265,11 +265,3 @@ void free_ilp_env(ilp_env_t *ienv)
        free_lpp(ienv->lp);
        free(ienv);
 }
-
-#else /* WITH_ILP */
-
-static inline void only_that_you_can_compile_without_WITH_ILP_defined(void)
-{
-}
-
-#endif /* WITH_ILP */
index 36dad10..45cb64b 100644 (file)
@@ -46,8 +46,6 @@
  */
 #include "config.h"
 
-#ifdef WITH_ILP
-
 #include "bitset.h"
 #include "raw_bitset.h"
 #include "pdeq.h"
@@ -106,7 +104,7 @@ static void build_coloring_cstr(ilp_env_t *ienv)
                        cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0);
 
                        bitset_foreach(colors, col) {
-                               int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, col), lpp_binary, 0.0);
+                               int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, (int)col), lpp_binary, 0.0);
                                lpp_set_start_value(ienv->lp, var_idx, (col == (unsigned) curr_node_color) ? 1.0 : 0.0);
                                lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
 
@@ -118,7 +116,7 @@ static void build_coloring_cstr(ilp_env_t *ienv)
                        /* add register constraint constraints */
                        bitset_foreach_clear(colors, col) {
                                int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 0.0);
-                               int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, col), lpp_binary, 0.0);
+                               int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, (int)col), lpp_binary, 0.0);
                                lpp_set_start_value(ienv->lp, var_idx, 0.0);
                                lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
 
@@ -331,8 +329,8 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
                        int growed;
 
                        /* get 2 starting nodes to form a clique */
-                       for (e=set_first(edges); !e->n1; e=set_next(edges))
-                               /*nothing*/ ;
+                       for (e=set_first(edges); !e->n1; e=set_next(edges)) {
+                       }
 
                        /* we could be stepped out of the loop before the set iterated to the end */
                        set_break(edges);
@@ -518,7 +516,7 @@ static void ilp2_apply(ilp_env_t *ienv)
                lpp_sol_state_t  state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var);
 
                if (state != lpp_optimal) {
-                       printf("WARNING %s: Solution state is not 'optimal': %d\n", ienv->co->name, state);
+                       printf("WARNING %s: Solution state is not 'optimal': %d\n", ienv->co->name, (int)state);
                        assert(state >= lpp_feasible && "The solution should at least be feasible!");
                }
 
@@ -551,7 +549,7 @@ static void ilp2_apply(ilp_env_t *ienv)
 #endif
 }
 
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp2);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp2)
 void be_init_copyilp2(void)
 {
        static co_algo_info copyheur = {
@@ -590,11 +588,3 @@ int co_solve_ilp2(copy_opt_t *co)
 
        return sol_state == lpp_optimal;
 }
-
-#else /* WITH_ILP */
-
-static inline void only_that_you_can_compile_without_WITH_ILP_defined(void)
-{
-}
-
-#endif /* WITH_ILP */
index a73d07e..5f31c12 100644 (file)
@@ -115,9 +115,8 @@ static inline int co_ilp_get_costs(copy_opt_t *co, ir_node *root, ir_node *arg)
 
  *****************************************************************************/
 
-#ifdef WITH_ILP
-#include <lpp/lpp.h>
-#include <lpp/lpp_net.h>
+#include "lpp.h"
+#include "lpp_net.h"
 
 #define EPSILON 0.00001
 
@@ -148,5 +147,3 @@ void free_ilp_env(ilp_env_t *ienv);
                        name_cdd(buf, char1, MIN(int1, int2), MAX(int1, int2))
 
 #endif
-
-#endif
index d3447c4..c8e3070 100644 (file)
@@ -108,7 +108,7 @@ enum vals_t {
 /**
  * Holds current values. Values are added till next copystat_reset
  */
-int curr_vals[ASIZE];
+static int curr_vals[ASIZE];
 
 static ir_nodeset_t *all_phi_nodes;
 static ir_nodeset_t *all_copy_nodes;
@@ -186,8 +186,6 @@ void copystat_add_heur_time(int time)
        curr_vals[I_HEUR_TIME] += time;
 }
 
-#ifdef WITH_ILP
-
 void copystat_add_ilp_5_sec_costs(int costs)
 {
        curr_vals[I_COPIES_5SEC] += costs;
@@ -213,8 +211,6 @@ void copystat_add_ilp_iter(int iters)
        curr_vals[I_ILP_ITER] += iters;
 }
 
-#endif /* WITH_ILP */
-
 /**
  * Opens a file named base.ext with the mode mode.
  */
index d02f51a..7474693 100644 (file)
@@ -40,8 +40,6 @@ void copystat_add_heur_time(int time);
 void copystat_dump(ir_graph *irg);
 void copystat_dump_pretty(ir_graph *irg);
 
-#ifdef WITH_ILP
-
 void copystat_add_ilp_5_sec_costs(int costs);
 void copystat_add_ilp_30_sec_costs(int costs);
 void copystat_add_ilp_time(int time);
@@ -49,6 +47,4 @@ void copystat_add_ilp_vars(int vars);
 void copystat_add_ilp_csts(int csts);
 void copystat_add_ilp_iter(int iters);
 
-#endif /* WITH_ILP */
-
 #endif
index 596659e..aca0e17 100644 (file)
@@ -107,7 +107,7 @@ static void emit(FILE *file, const unsigned char *buffer, size_t len)
                size_t i2;
                fputs("\t.byte ", file);
                for (i2 = i; i2 < i + 30 && i2 < len; ++i2) {
-                       fprintf(file, "0x%02X", buffer[i2]);
+                       fprintf(file, "0x%02X", (unsigned)buffer[i2]);
                }
                i = i2;
                fputs("\n", file);
index 2315169..5d82616 100644 (file)
@@ -1659,3 +1659,65 @@ void be_gas_emit_decls(const be_main_env_t *main_env)
                be_emit_write_line();
        }
 }
+
+void emit_jump_table(const ir_node *node, long default_pn, ir_entity *entity,
+                     get_cfop_target_func get_cfop_target)
+{
+       long             switch_max    = LONG_MIN;
+       ir_node         *default_block = NULL;
+       unsigned long    length;
+       const ir_edge_t *edge;
+       unsigned         i;
+       ir_node        **table;
+
+       /* go over all proj's and collect them */
+       foreach_out_edge(node, edge) {
+               ir_node *proj = get_edge_src_irn(edge);
+               long     pn   = get_Proj_proj(proj);
+
+               /* check for default proj */
+               if (pn == default_pn) {
+                       assert(default_block == NULL); /* more than 1 default_pn? */
+                       default_block = get_cfop_target(proj);
+               } else {
+                       switch_max = pn > switch_max ? pn : switch_max;
+               }
+       }
+       assert(switch_max > LONG_MIN);
+
+       length = (unsigned long) switch_max + 1;
+       /* the 16000 isn't a real limit of the architecture. But should protect us
+        * from seamingly endless compiler runs */
+       if (length > 16000) {
+               /* switch lowerer should have broken this monster to pieces... */
+               panic("too large switch encountered");
+       }
+
+       table = XMALLOCNZ(ir_node*, length);
+       foreach_out_edge(node, edge) {
+               ir_node *proj = get_edge_src_irn(edge);
+               long     pn   = get_Proj_proj(proj);
+               if (pn == default_pn)
+                       continue;
+
+               table[pn] = get_cfop_target(proj);
+       }
+
+       /* emit table */
+       be_gas_emit_switch_section(GAS_SECTION_RODATA);
+       be_emit_cstring("\t.align 4\n");
+       be_gas_emit_entity(entity);
+       be_emit_cstring(":\n");
+       for (i = 0; i < length; ++i) {
+               ir_node *block = table[i];
+               if (block == NULL)
+                       block = default_block;
+               be_emit_cstring("\t.long ");
+               be_gas_emit_block_name(block);
+               be_emit_char('\n');
+               be_emit_write_line();
+       }
+       be_gas_emit_switch_section(GAS_SECTION_TEXT);
+
+       xfree(table);
+}
index ba17185..b2192d6 100644 (file)
@@ -107,4 +107,12 @@ void be_gas_emit_block_name(const ir_node *block);
  */
 const char *be_gas_insn_label_prefix(void);
 
+typedef ir_node* (*get_cfop_target_func)(const ir_node *cfop);
+
+/**
+ * Emits a jump table for switch operations
+ */
+void emit_jump_table(const ir_node *node, long default_pn, ir_entity *table,
+                     get_cfop_target_func get_cfop_target);
+
 #endif
index c617e50..3077f1a 100644 (file)
@@ -31,7 +31,7 @@
 /* We define a generic dummy unit */
 be_execution_unit_t be_machine_execution_units_DUMMY[1];
 
-be_execution_unit_type_t be_machine_execution_unit_types[] = {
+static be_execution_unit_type_t be_machine_execution_unit_types[] = {
        { 1, 1, "DUMMY", be_machine_execution_units_DUMMY },
 };
 
index e64c25a..af2cfe0 100644 (file)
@@ -86,7 +86,7 @@ static be_options_t be_options = {
        0,                                 /* try to omit frame pointer */
        0,                                 /* create PIC code */
        BE_VERIFY_WARN,                    /* verification level: warn */
-       "i44pc52.info.uni-karlsruhe.de",   /* ilp server */
+       "",                                /* ilp server */
        "cplex",                           /* ilp solver */
        0,                                 /* enable statistic event dumping */
        "",                                /* print stat events */
@@ -136,10 +136,8 @@ static const lc_opt_table_entry_t be_main_options[] = {
        LC_OPT_ENT_BOOL     ("statev",     "dump statistic events",                               &be_options.statev),
        LC_OPT_ENT_STR      ("filtev",     "filter for stat events (regex if support is active",  &be_options.filtev, sizeof(be_options.filtev)),
 
-#ifdef WITH_ILP
-       LC_OPT_ENT_STR ("ilp.server", "the ilp server name", be_options.ilp_server, sizeof(be_options.ilp_server)),
-       LC_OPT_ENT_STR ("ilp.solver", "the ilp solver name", be_options.ilp_solver, sizeof(be_options.ilp_solver)),
-#endif /* WITH_ILP */
+       LC_OPT_ENT_STR ("ilp.server", "the ilp server name", &be_options.ilp_server, sizeof(be_options.ilp_server)),
+       LC_OPT_ENT_STR ("ilp.solver", "the ilp solver name", &be_options.ilp_solver, sizeof(be_options.ilp_solver)),
        LC_OPT_LAST
 };
 
@@ -575,7 +573,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
                /* set the current graph (this is important for several firm functions) */
                current_ir_graph = irg;
 
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        stat_ev_ctx_push_fobj("bemain_irg", irg);
                        be_stat_ev("bemain_insns_start", be_count_insns(irg));
                        be_stat_ev("bemain_blocks_start", be_count_blocks(irg));
@@ -610,10 +608,11 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
                        dump(DUMP_ABI, irg, "abi");
                }
 
-               /* we have to do cfopt+remove_critical_edges as we can't have Bad-blocks
-                * or critical edges in the backend */
-               optimize_cf(irg);
+               /* We can't have Bad-blocks or critical edges in the backend.
+                * Before removing Bads, we remove unreachable code. */
+               optimize_graph_df(irg);
                remove_critical_cf_edges(irg);
+               remove_bads(irg);
 
                /* We often have dead code reachable through out-edges here. So for
                 * now we rebuild edges (as we need correct user count for code
@@ -705,7 +704,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
                be_sched_verify(irg, be_options.verify_option);
                be_timer_pop(T_VERIFY);
 
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        stat_ev_dbl("bemain_costs_before_ra",
                                        be_estimate_irg_costs(irg, birg->exec_freq));
                        be_stat_ev("bemain_insns_before_ra", be_count_insns(irg));
@@ -741,7 +740,7 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
 
                dump(DUMP_FINAL, irg, "finish");
 
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        be_stat_ev("bemain_insns_finish", be_count_insns(irg));
                        be_stat_ev("bemain_blocks_finish", be_count_blocks(irg));
                }
@@ -851,7 +850,7 @@ void be_main(FILE *file_handle, const char *cup_name)
        if (be_options.timing == BE_TIME_ON) {
                ir_timer_stop(t);
                ir_timer_leave_high_priority();
-               stat_ev_if {
+               if (stat_ev_enabled) {
                        stat_ev_dbl("bemain_backend_time", ir_timer_elapsed_msec(t));
                } else {
                        double val = ir_timer_elapsed_usec(t) / 1000.0;
index 7ba3f57..2495898 100644 (file)
@@ -116,9 +116,7 @@ void be_init_modules(void)
        be_init_copyheur4();
        be_init_copyheur();
        be_init_copyheur2();
-#ifdef WITH_ILP
        be_init_copyilp2();
-#endif
        be_init_pbqp_coloring();
        be_init_copynone();
        be_init_copystat();
@@ -137,9 +135,7 @@ void be_init_modules(void)
        be_init_arch_amd64();
        be_init_arch_TEMPLATE();
 
-#ifdef WITH_ILP
        be_init_copyilp();
-#endif /* WITH_ILP */
 
 #if PLUGIN_IR_BE_STA
        be_init_arch_sta();
@@ -232,7 +228,7 @@ static int dump_opt_module_vals(char *buf, size_t buflen, const char *name,
        (void) len;
 
        for (module = *(moddata->list_head); module != NULL; module = module->next) {
-               size_t len = strlen(module->name);
+               size_t name_len = strlen(module->name);
 
                if (module != *(moddata->list_head)) {
                        p       = strncat(p, ", ", buflen - 1);
@@ -241,10 +237,10 @@ static int dump_opt_module_vals(char *buf, size_t buflen, const char *name,
 
                p = strncat(p, module->name, buflen - 1);
 
-               if (len >= buflen)
+               if (name_len >= buflen)
                        break;
 
-               buflen -= len;
+               buflen -= name_len;
        }
 
        return strlen(buf);
index 3d7c285..e798492 100644 (file)
@@ -895,7 +895,6 @@ void be_set_constr_single_reg_out(ir_node *node, int pos,
        if (additional_types == 0) {
                req = reg->single_req;
        } else {
-               ir_graph       *irg  = get_irn_irg(node);
                struct obstack *obst = be_get_be_obst(irg);
                req = be_create_reg_req(obst, reg, additional_types);
        }
index b35947d..5a80f9c 100644 (file)
@@ -859,7 +859,7 @@ static void assign_reg(const ir_node *block, ir_node *node,
  * First we count how many destinations a single value has. At the same time
  * we can be sure that each destination register has at most 1 source register
  * (it can have 0 which means we don't care what value is in it).
- * We ignore all fullfilled permuations (like 7->7)
+ * We ignore all fulfilled permuations (like 7->7)
  * In a first pass we create as much copy instructions as possible as they
  * are generally cheaper than exchanges. We do this by counting into how many
  * destinations a register has to be copied (in the example it's 2 for register
@@ -867,8 +867,8 @@ static void assign_reg(const ir_node *block, ir_node *node,
  * We can then create a copy into every destination register when the usecount
  * of that register is 0 (= noone else needs the value in the register).
  *
- * After this step we should have cycles left. We implement a cyclic permutation
- * of n registers with n-1 transpositions.
+ * After this step we should only have cycles left. We implement a cyclic
+ * permutation of n registers with n-1 transpositions.
  *
  * @param live_nodes   the set of live nodes, updated due to live range split
  * @param before       the node before we add the permutation
index 2b39047..ffa7788 100644 (file)
@@ -152,7 +152,6 @@ static int normal_tree_cost(ir_node* irn, instance_t *inst)
 
        if (fc == NULL) {
                irn_cost_pair* costs;
-               int            i;
                ir_node*       block = get_nodes_block(irn);
 
                fc = OALLOCF(&inst->obst, flag_and_cost, costs, arity);
@@ -161,7 +160,6 @@ static int normal_tree_cost(ir_node* irn, instance_t *inst)
 
                for (i = 0; i < arity; ++i) {
                        ir_node* pred = get_irn_n(irn, i);
-                       int cost;
 
                        if (is_Phi(irn) || get_irn_mode(pred) == mode_M || is_Block(pred)) {
                                cost = 0;
index b5a78e1..dbea532 100644 (file)
@@ -368,7 +368,7 @@ static void do_greedy_coalescing(be_fec_env_t *env)
 
        DEBUG_ONLY(
                memset(spilllist, 0, spillcount * sizeof(spilllist[0]));
-       );
+       )
 
        i = 0;
        foreach_set(env->spills, spill_t*, spill) {
index 7c04690..d594a34 100644 (file)
@@ -614,7 +614,7 @@ static int check_remat_conditions_costs(spill_env_t *env,
 /**
  * Re-materialize a node.
  *
- * @param senv      the spill environment
+ * @param env       the spill environment
  * @param spilled   the node that was spilled
  * @param reloader  a irn that requires a reload
  */
@@ -639,8 +639,8 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
                        ins[i] = arg;
                } else {
                        ins[i] = do_remat(env, arg, reloader);
-                       /* don't count the recursive call as remat */
-                       env->remat_count--;
+                       /* don't count the argument rematerialization as an extra remat */
+                       --env->remat_count;
                }
        }
 
@@ -657,7 +657,7 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
                /* insert in schedule */
                sched_reset(res);
                sched_add_before(reloader, res);
-               env->remat_count++;
+               ++env->remat_count;
        }
 
        return res;
index 02c243d..eca305a 100644 (file)
@@ -244,10 +244,12 @@ static void gen_primitive_type(stabs_handle *h, ir_type *tp)
                return;
        }  /* if */
 
-       if (0 && get_mode_size_bits(mode) & 7) {
+#if 0
+       if (get_mode_size_bits(mode) & 7) {
                /* this is a bitfield type, ignore it */
                return;
        }  /* if */
+#endif
 
        type_num = get_type_number(h, tp);
 
@@ -426,19 +428,20 @@ static void gen_struct_union_type(wenv_t *env, ir_type *tp)
                ofs  = get_entity_offset(ent);
                if (is_Struct_type(mtp) && get_type_mode(mtp) != NULL) {
                        /* this structure is a bitfield, skip */
-                       int i, n;
+                       int m;
+                       int n_members = get_struct_n_members(mtp);
 
-                       for (i = 0, n = get_struct_n_members(mtp); i < n; ++i) {
-                               ir_entity *ent = get_struct_member(mtp, i);
-                               ir_type *tp = get_entity_type(ent);
+                       for (m = 0; m < n_members; ++m) {
+                               ir_entity *member    = get_struct_member(mtp, m);
+                               ir_type   *member_tp = get_entity_type(member);
                                int bofs;
 
-                               type_num = get_type_number(h, tp);
-                               size = get_type_size_bytes(tp) * 8;
-                               bofs = (ofs + get_entity_offset(ent)) * 8 + get_entity_offset_bits_remainder(ent);
+                               type_num = get_type_number(h, member_tp);
+                               size = get_type_size_bytes(member_tp) * 8;
+                               bofs = (ofs + get_entity_offset(member)) * 8 + get_entity_offset_bits_remainder(member);
 
                                /* name:type, bit offset from the start of the struct', number of bits in the element. */
-                               be_emit_irprintf("%s:%u,%d,%u;", get_entity_name(ent), type_num, bofs, size);
+                               be_emit_irprintf("%s:%u,%d,%u;", get_entity_name(member), type_num, bofs, size);
                        }
                } else {
                        /* no bitfield */
@@ -719,7 +722,6 @@ static void stabs_method_begin(dbg_handle *handle, const ir_entity *ent)
        for (i = 0, n = get_method_n_params(mtp); i < n; ++i) {
                ir_type *ptp      = get_method_param_type(mtp, i);
         const char *name  = NULL;
-               unsigned type_num = get_type_number(h, ptp);
         char buf[16];
         int ofs = 0;
                ir_entity *stack_ent;
@@ -768,24 +770,24 @@ static void stabs_method_end(dbg_handle *handle)
        /* create entries for automatic variables on the stack */
        frame_size = get_type_size_bytes(layout->frame_type);
        for (i = 0, n = get_compound_n_members(layout->frame_type); i < n; ++i) {
-               ir_entity *ent = get_compound_member(layout->frame_type, i);
+               ir_entity *member = get_compound_member(layout->frame_type, i);
                ir_type *tp;
                int ofs;
                unsigned type_num;
 
                /* ignore spill slots and other helper objects */
-               if (is_entity_compiler_generated(ent))
+               if (is_entity_compiler_generated(member))
                        continue;
 
-               tp = get_entity_type(ent);
+               tp = get_entity_type(member);
                /* should not happen in backend but ... */
                if (is_Method_type(tp))
                        continue;
                type_num = get_type_number(h, tp);
-               ofs      = -frame_size + get_entity_offset(ent);
+               ofs      = -frame_size + get_entity_offset(member);
 
                be_emit_irprintf("\t.stabs\t\"%s:%u\",%d,0,0,%d\n",
-                       get_entity_name(ent), type_num, N_LSYM, ofs);
+                                get_entity_name(member), type_num, N_LSYM, ofs);
                be_emit_write_line();
        }
        /* we need a lexical block here */
index 69e3e09..7f831ea 100644 (file)
@@ -161,7 +161,7 @@ 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           arity         = get_irn_arity(phi);
-       ir_node     **in            = ALLOCAN(ir_node*, arity);
+       ir_node     **phi_in        = ALLOCAN(ir_node*, arity);
        ir_node      *dummy         = new_r_Dummy(irg, mode_M);
        ir_node      *spill_to_kill = NULL;
        spill_info_t *spill_info;
@@ -177,13 +177,13 @@ static void spill_phi(minibelady_env_t *env, ir_node *phi)
 
        /* create a new phi-M with bad preds */
        for (i = 0; i < arity; ++i) {
-               in[i] = dummy;
+               phi_in[i] = dummy;
        }
 
        DBG((dbg, LEVEL_2, "\tcreate Phi-M for %+F\n", phi));
 
        /* create a Phi-M */
-       spill_info->spill = be_new_Phi(block, arity, in, mode_M, NULL);
+       spill_info->spill = be_new_Phi(block, arity, phi_in, mode_M, NULL);
        sched_add_after(block, spill_info->spill);
 
        if (spill_to_kill != NULL) {
index 497c136..d3b6012 100644 (file)
@@ -223,7 +223,7 @@ static be_next_use_t get_next_use(be_uses_t *env, ir_node *from,
 {
        unsigned  step;
        ir_node  *block = get_nodes_block(from);
-       ir_node  *next_use;
+       ir_node  *next_use_node;
        ir_node  *node;
        unsigned  timestep;
        unsigned  next_use_step;
@@ -234,12 +234,12 @@ static be_next_use_t get_next_use(be_uses_t *env, ir_node *from,
                from = sched_next(from);
        }
 
-       next_use      = NULL;
+       next_use_node = NULL;
        next_use_step = INT_MAX;
        timestep      = get_step(from);
        foreach_out_edge(def, edge) {
-               ir_node  *node = get_edge_src_irn(edge);
-               unsigned  node_step;
+               node = get_edge_src_irn(edge);
+               unsigned node_step;
 
                if (is_Anchor(node))
                        continue;
@@ -252,16 +252,16 @@ static be_next_use_t get_next_use(be_uses_t *env, ir_node *from,
                if (node_step < timestep)
                        continue;
                if (node_step < next_use_step) {
-                       next_use      = node;
+                       next_use_node = node;
                        next_use_step = node_step;
                }
        }
 
-       if (next_use != NULL) {
+       if (next_use_node != NULL) {
                be_next_use_t result;
                result.time           = next_use_step - timestep + skip_from_uses;
                result.outermost_loop = get_loop_depth(get_irn_loop(block));
-               result.before         = next_use;
+               result.before         = next_use_node;
                return result;
        }
 
index 7ef7183..3dbc79f 100644 (file)
@@ -169,7 +169,6 @@ static void verify_schedule_walker(ir_node *block, void *data)
         *       (except mode_X projs)
         */
        sched_foreach(block, node) {
-               int i, arity;
                int timestep;
 
                /* this node is scheduled */
@@ -226,6 +225,8 @@ static void verify_schedule_walker(ir_node *block, void *data)
 
                /* Check that all uses come before their definitions */
                if (!is_Phi(node)) {
+                       int i;
+                       int arity;
                        sched_timestep_t nodetime = sched_get_time_step(node);
                        for (i = 0, arity = get_irn_arity(node); i < arity; ++i) {
                                ir_node *arg = get_irn_n(node, i);
@@ -258,6 +259,7 @@ static void verify_schedule_walker(ir_node *block, void *data)
                                prev = sched_prev(prev);
 
                        while (true) {
+                               int i;
                                for (i = 0; i < arity; ++i) {
                                        ir_node *in = get_irn_n(node, i);
                                        in = skip_Proj(in);
@@ -727,8 +729,6 @@ static void check_input_constraints(ir_node *node)
        /* phis should be NOPs at this point, which means all input regs
         * must be the same as the output reg */
        if (is_Phi(node)) {
-               int i, arity;
-
                reg = arch_get_irn_register(node);
 
                arity = get_irn_arity(node);
@@ -816,8 +816,8 @@ static void verify_block_register_allocation(ir_node *block, void *data)
                registers = ALLOCANZ(ir_node*, n_regs);
 
                be_lv_foreach(lv, block, be_lv_state_end, idx) {
-                       ir_node *node = be_lv_get_irn(lv, block, idx);
-                       value_used(block, node);
+                       ir_node *lv_node = be_lv_get_irn(lv, block, idx);
+                       value_used(block, lv_node);
                }
 
                sched_foreach_reverse(block, node) {
@@ -848,8 +848,8 @@ static void verify_block_register_allocation(ir_node *block, void *data)
                }
 
                be_lv_foreach(lv, block, be_lv_state_in, idx) {
-                       ir_node *node = be_lv_get_irn(lv, block, idx);
-                       value_def(node);
+                       ir_node *lv_node = be_lv_get_irn(lv, block, idx);
+                       value_def(lv_node);
                }
 
                /* set must be empty now */
index 0b36118..7dc3931 100644 (file)
@@ -94,9 +94,7 @@
 transformer_t be_transformer = TRANSFORMER_DEFAULT;
 #endif
 
-DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
-
-ir_mode         *ia32_mode_fpcw       = NULL;
+ir_mode *ia32_mode_fpcw = NULL;
 
 /** The current omit-fp state */
 static ir_type *omit_fp_between_type   = NULL;
@@ -118,7 +116,7 @@ static ia32_intrinsic_env_t intrinsic_env = {
 };
 
 
-typedef ir_node *(*create_const_node_func) (dbg_info *dbg, ir_node *block);
+typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
 
 /**
  * Used to create per-graph unique pseudo nodes.
@@ -396,7 +394,7 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_
        ir_mode  *mode;
        ir_mode  *irn_mode;
        ir_node  *block, *noreg, *nomem;
-       dbg_info *dbg;
+       dbg_info *dbgi;
 
        /* we cannot invert non-ia32 irns */
        if (! is_ia32_irn(irn))
@@ -420,7 +418,7 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_
        irn_mode = get_irn_mode(irn);
        noreg    = get_irn_n(irn, 0);
        nomem    = get_irg_no_mem(irg);
-       dbg      = get_irn_dbg_info(irn);
+       dbgi     = get_irn_dbg_info(irn);
 
        /* initialize structure */
        inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0]));
@@ -432,7 +430,7 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_
                        if (get_ia32_immop_type(irn) == ia32_ImmConst) {
                                /* we have an add with a const here */
                                /* invers == add with negated const */
-                               inverse->nodes[0] = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
+                               inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
                                inverse->costs   += 1;
                                copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
                                set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn)));
@@ -441,13 +439,13 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_
                        else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) {
                                /* we have an add with a symconst here */
                                /* invers == sub with const */
-                               inverse->nodes[0] = new_bd_ia32_Sub(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
+                               inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
                                inverse->costs   += 2;
                                copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
                        }
                        else {
                                /* normal add: inverse == sub */
-                               inverse->nodes[0] = new_bd_ia32_Sub(dbg, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, i ^ 1));
+                               inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, i ^ 1));
                                inverse->costs   += 2;
                        }
                        break;
@@ -455,17 +453,17 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_
                        if (get_ia32_immop_type(irn) != ia32_ImmNone) {
                                /* we have a sub with a const/symconst here */
                                /* invers == add with this const */
-                               inverse->nodes[0] = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
+                               inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
                                inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
                                copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
                        }
                        else {
                                /* normal sub */
                                if (i == n_ia32_binary_left) {
-                                       inverse->nodes[0] = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, 3));
+                                       inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, 3));
                                }
                                else {
-                                       inverse->nodes[0] = new_bd_ia32_Sub(dbg, block, noreg, noreg, nomem, get_irn_n(irn, n_ia32_binary_left), (ir_node*) irn);
+                                       inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, n_ia32_binary_left), (ir_node*) irn);
                                }
                                inverse->costs += 1;
                        }
@@ -473,23 +471,23 @@ static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_
                case iro_ia32_Xor:
                        if (get_ia32_immop_type(irn) != ia32_ImmNone) {
                                /* xor with const: inverse = xor */
-                               inverse->nodes[0] = new_bd_ia32_Xor(dbg, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
+                               inverse->nodes[0] = new_bd_ia32_Xor(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
                                inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
                                copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
                        }
                        else {
                                /* normal xor */
-                               inverse->nodes[0] = new_bd_ia32_Xor(dbg, block, noreg, noreg, nomem, (ir_node *) irn, get_irn_n(irn, i));
+                               inverse->nodes[0] = new_bd_ia32_Xor(dbgi, block, noreg, noreg, nomem, (ir_node *) irn, get_irn_n(irn, i));
                                inverse->costs   += 1;
                        }
                        break;
                case iro_ia32_Not: {
-                       inverse->nodes[0] = new_bd_ia32_Not(dbg, block, (ir_node*) irn);
+                       inverse->nodes[0] = new_bd_ia32_Not(dbgi, block, (ir_node*) irn);
                        inverse->costs   += 1;
                        break;
                }
                case iro_ia32_Neg: {
-                       inverse->nodes[0] = new_bd_ia32_Neg(dbg, block, (ir_node*) irn);
+                       inverse->nodes[0] = new_bd_ia32_Neg(dbgi, block, (ir_node*) irn);
                        inverse->costs   += 1;
                        break;
                }
@@ -709,11 +707,11 @@ ir_node *ia32_turn_back_am(ir_node *node)
        ir_graph *irg   = get_irn_irg(node);
        ir_node  *block = get_nodes_block(node);
        ir_node  *base  = get_irn_n(node, n_ia32_base);
-       ir_node  *index = get_irn_n(node, n_ia32_index);
+       ir_node  *idx   = get_irn_n(node, n_ia32_index);
        ir_node  *mem   = get_irn_n(node, n_ia32_mem);
        ir_node  *noreg;
 
-       ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, index, mem);
+       ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, idx, mem);
        ir_node  *load_res = new_rd_Proj(dbgi, load, mode_Iu, pn_ia32_Load_res);
 
        ia32_copy_am_attrs(load, node);
@@ -787,7 +785,6 @@ static ir_node *flags_remat(ir_node *node, ir_node *after)
                case ia32_AddrModeD:
                        /* TODO implement this later... */
                        panic("found DestAM with flag user %+F this should not happen", node);
-                       break;
 
                default: assert(type == ia32_Normal); break;
        }
@@ -821,7 +818,7 @@ static void ia32_before_ra(ir_graph *irg)
 static void transform_to_Load(ir_node *node)
 {
        ir_graph *irg        = get_irn_irg(node);
-       dbg_info *dbg        = get_irn_dbg_info(node);
+       dbg_info *dbgi       = get_irn_dbg_info(node);
        ir_node *block       = get_nodes_block(node);
        ir_entity *ent       = be_get_frame_entity(node);
        ir_mode *mode        = get_irn_mode(node);
@@ -839,16 +836,16 @@ static void transform_to_Load(ir_node *node)
 
        if (mode_is_float(spillmode)) {
                if (ia32_cg_config.use_sse2)
-                       new_op = new_bd_ia32_xLoad(dbg, block, ptr, noreg, mem, spillmode);
+                       new_op = new_bd_ia32_xLoad(dbgi, block, ptr, noreg, mem, spillmode);
                else
-                       new_op = new_bd_ia32_vfld(dbg, block, ptr, noreg, mem, spillmode);
+                       new_op = new_bd_ia32_vfld(dbgi, block, ptr, noreg, mem, spillmode);
        }
        else if (get_mode_size_bits(spillmode) == 128) {
                /* Reload 128 bit SSE registers */
-               new_op = new_bd_ia32_xxLoad(dbg, block, ptr, noreg, mem);
+               new_op = new_bd_ia32_xxLoad(dbgi, block, ptr, noreg, mem);
        }
        else
-               new_op = new_bd_ia32_Load(dbg, block, ptr, noreg, mem);
+               new_op = new_bd_ia32_Load(dbgi, block, ptr, noreg, mem);
 
        set_ia32_op_type(new_op, ia32_AddrModeS);
        set_ia32_ls_mode(new_op, spillmode);
@@ -858,7 +855,7 @@ static void transform_to_Load(ir_node *node)
 
        DBG_OPT_RELOAD2LD(node, new_op);
 
-       proj = new_rd_Proj(dbg, new_op, mode, pn_ia32_Load_res);
+       proj = new_rd_Proj(dbgi, new_op, mode, pn_ia32_Load_res);
 
        if (sched_point) {
                sched_add_after(sched_point, new_op);
@@ -880,7 +877,7 @@ static void transform_to_Load(ir_node *node)
 static void transform_to_Store(ir_node *node)
 {
        ir_graph *irg  = get_irn_irg(node);
-       dbg_info *dbg  = get_irn_dbg_info(node);
+       dbg_info *dbgi = get_irn_dbg_info(node);
        ir_node *block = get_nodes_block(node);
        ir_entity *ent = be_get_frame_entity(node);
        const ir_node *spillval = get_irn_n(node, n_be_Spill_val);
@@ -899,21 +896,21 @@ static void transform_to_Store(ir_node *node)
 
        if (mode_is_float(mode)) {
                if (ia32_cg_config.use_sse2) {
-                       store = new_bd_ia32_xStore(dbg, block, ptr, noreg, nomem, val);
+                       store = new_bd_ia32_xStore(dbgi, block, ptr, noreg, nomem, val);
                        res   = new_r_Proj(store, mode_M, pn_ia32_xStore_M);
                } else {
-                       store = new_bd_ia32_vfst(dbg, block, ptr, noreg, nomem, val, mode);
+                       store = new_bd_ia32_vfst(dbgi, block, ptr, noreg, nomem, val, mode);
                        res   = new_r_Proj(store, mode_M, pn_ia32_vfst_M);
                }
        } else if (get_mode_size_bits(mode) == 128) {
                /* Spill 128 bit SSE registers */
-               store = new_bd_ia32_xxStore(dbg, block, ptr, noreg, nomem, val);
+               store = new_bd_ia32_xxStore(dbgi, block, ptr, noreg, nomem, val);
                res   = new_r_Proj(store, mode_M, pn_ia32_xxStore_M);
        } else if (get_mode_size_bits(mode) == 8) {
-               store = new_bd_ia32_Store8Bit(dbg, block, ptr, noreg, nomem, val);
+               store = new_bd_ia32_Store8Bit(dbgi, block, ptr, noreg, nomem, val);
                res   = new_r_Proj(store, mode_M, pn_ia32_Store8Bit_M);
        } else {
-               store = new_bd_ia32_Store(dbg, block, ptr, noreg, nomem, val);
+               store = new_bd_ia32_Store(dbgi, block, ptr, noreg, nomem, val);
                res   = new_r_Proj(store, mode_M, pn_ia32_Store_M);
        }
 
@@ -935,13 +932,13 @@ static void transform_to_Store(ir_node *node)
 
 static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_node *mem, ir_entity *ent)
 {
-       dbg_info *dbg = get_irn_dbg_info(node);
-       ir_node *block = get_nodes_block(node);
-       ir_graph *irg = get_irn_irg(node);
-       ir_node *noreg = ia32_new_NoReg_gp(irg);
-       ir_node *frame = get_irg_frame(irg);
+       dbg_info *dbg = get_irn_dbg_info(node);
+       ir_node  *block = get_nodes_block(node);
+       ir_graph *irg   = get_irn_irg(node);
+       ir_node  *noreg = ia32_new_NoReg_gp(irg);
+       ir_node  *frame = get_irg_frame(irg);
 
-       ir_node *push = new_bd_ia32_Push(dbg, block, frame, noreg, mem, noreg, sp);
+       ir_node *push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem, noreg, sp);
 
        set_ia32_frame_ent(push, ent);
        set_ia32_use_frame(push);
@@ -955,13 +952,13 @@ static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_
 
 static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_entity *ent)
 {
-       dbg_info *dbg   = get_irn_dbg_info(node);
+       dbg_info *dbgi  = get_irn_dbg_info(node);
        ir_node  *block = get_nodes_block(node);
        ir_graph *irg   = get_irn_irg(node);
        ir_node  *noreg = ia32_new_NoReg_gp(irg);
        ir_node  *frame = get_irg_frame(irg);
 
-       ir_node *pop = new_bd_ia32_PopMem(dbg, block, frame, noreg,
+       ir_node *pop = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
                                          get_irg_no_mem(irg), sp);
 
        set_ia32_frame_ent(pop, ent);
@@ -977,12 +974,12 @@ static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_e
 
 static ir_node* create_spproj(ir_node *node, ir_node *pred, int pos)
 {
-       dbg_info *dbg = get_irn_dbg_info(node);
-       ir_mode *spmode = mode_Iu;
+       dbg_info *dbgi   = get_irn_dbg_info(node);
+       ir_mode  *spmode = mode_Iu;
        const arch_register_t *spreg = &ia32_registers[REG_ESP];
        ir_node *sp;
 
-       sp = new_rd_Proj(dbg, pred, spmode, pos);
+       sp = new_rd_Proj(dbgi, pred, spmode, pos);
        arch_set_irn_register(sp, spreg);
 
        return sp;
@@ -1662,8 +1659,6 @@ static const arch_register_t *ia32_get_RegParam_reg(unsigned cc, unsigned nr,
 static void ia32_get_call_abi(const void *self, ir_type *method_type,
                               be_abi_call_t *abi)
 {
-       ir_type  *tp;
-       ir_mode  *mode;
        unsigned  cc;
        int       n, i, regnum;
        int                 pop_amount = 0;
@@ -1701,11 +1696,10 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
 
        n = get_method_n_params(method_type);
        for (i = regnum = 0; i < n; i++) {
-               ir_mode               *mode;
-               const arch_register_t *reg = NULL;
+               const arch_register_t *reg  = NULL;
+               ir_type               *tp   = get_method_param_type(method_type, i);
+               ir_mode               *mode = get_type_mode(tp);
 
-               tp   = get_method_param_type(method_type, i);
-               mode = get_type_mode(tp);
                if (mode != NULL) {
                        reg  = ia32_get_RegParam_reg(cc, regnum, mode);
                }
@@ -1740,8 +1734,8 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
 
        /* In case of 64bit returns, we will have two 32bit values */
        if (n == 2) {
-               tp   = get_method_res_type(method_type, 0);
-               mode = get_type_mode(tp);
+               ir_type *tp   = get_method_res_type(method_type, 0);
+               ir_mode *mode = get_type_mode(tp);
 
                assert(!mode_is_float(mode) && "two FP results not supported");
 
@@ -1754,11 +1748,10 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type,
                be_abi_call_res_reg(abi, 1, &ia32_registers[REG_EDX], ABI_CONTEXT_BOTH);
        }
        else if (n == 1) {
+               ir_type *tp   = get_method_res_type(method_type, 0);
+               ir_mode *mode = get_type_mode(tp);
                const arch_register_t *reg;
-
-               tp   = get_method_res_type(method_type, 0);
                assert(is_atomic_type(tp));
-               mode = get_type_mode(tp);
 
                reg = mode_is_float(mode) ? &ia32_registers[REG_VF0] : &ia32_registers[REG_EAX];
 
@@ -2046,7 +2039,7 @@ static void ia32_lower_for_target(void)
                /* lower for mode_b stuff */
                ir_lower_mode_b(irg, &lower_mode_b_config);
                /* break up switches with wide ranges */
-               lower_switch(irg, 256, true);
+               lower_switch(irg, 4, 256, false);
        }
 }
 
@@ -2099,7 +2092,9 @@ static const backend_params *ia32_get_libfirm_params(void)
                0,     /* little endian */
                NULL,  /* will be set later */
                ia32_is_mux_allowed,
+               32,    /* machine_size */
                NULL,  /* float arithmetic mode, will be set below */
+               0,     /* size of long double */
                12,    /* size of trampoline code */
                4,     /* alignment of trampoline code */
                ia32_create_trampoline_fkt,
@@ -2113,11 +2108,56 @@ static const backend_params *ia32_get_libfirm_params(void)
        init_asm_constraints();
 
        p.dep_param    = &ad;
-       if (! ia32_cg_config.use_sse2)
+       if (! ia32_cg_config.use_sse2) {
                p.mode_float_arithmetic = mode_E;
+               p.long_double_size = 96;
+       } else {
+               p.mode_float_arithmetic = NULL;
+               p.long_double_size = 64;
+       }
        return &p;
 }
 
+/**
+ * Check if the given register is callee or caller save.
+ */
+static int ia32_register_saved_by(const arch_register_t *reg, int callee)
+{
+       if (callee) {
+               /* check for callee saved */
+               if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_gp]) {
+                       switch (reg->index) {
+                       case REG_GP_EBX:
+                       case REG_GP_ESI:
+                       case REG_GP_EDI:
+                       case REG_GP_EBP:
+                               return 1;
+                       default:
+                               return 0;
+                       }
+               }
+       } else {
+               /* check for caller saved */
+               if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_gp]) {
+                       switch (reg->index) {
+                       case REG_GP_EDX:
+                       case REG_GP_ECX:
+                       case REG_GP_EAX:
+                               return 1;
+                       default:
+                               return 0;
+                       }
+               } else if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_xmm]) {
+                       /* all XMM registers are caller save */
+                       return reg->index != REG_XMM_NOREG;
+               } else if (reg->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]) {
+                       /* all VFP registers are caller save */
+                       return reg->index != REG_VFP_NOREG;
+               }
+       }
+       return 0;
+}
+
 static const lc_opt_enum_int_items_t gas_items[] = {
        { "elf",   OBJECT_FILE_FORMAT_ELF    },
        { "mingw", OBJECT_FILE_FORMAT_COFF   },
@@ -2175,6 +2215,7 @@ const arch_isa_if_t ia32_isa_if = {
        ia32_after_ra,       /* after register allocation hook */
        ia32_finish,         /* called before codegen */
        ia32_emit,           /* emit && done */
+       ia32_register_saved_by,
 };
 
 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_ia32)
@@ -2186,8 +2227,6 @@ void be_init_arch_ia32(void)
        lc_opt_add_table(ia32_grp, ia32_options);
        be_register_isa_if("ia32", &ia32_isa_if);
 
-       FIRM_DBG_REGISTER(dbg, "firm.be.ia32.cg");
-
        ia32_init_emitter();
        ia32_init_finish();
        ia32_init_optimize();
index 06d2f43..f9a40ac 100644 (file)
@@ -371,11 +371,9 @@ static void parse_asm_constraints(constraint_t *constraint, const char *c,
                case 'e': /* not available in 32 bit mode */
                        panic("unsupported asm constraint '%c' found in (%+F)",
                              *c, current_ir_graph);
-                       break;
                default:
                        panic("unknown asm constraint '%c' found in (%+F)", *c,
                              current_ir_graph);
-                       break;
                }
                ++c;
        }
@@ -562,7 +560,6 @@ ir_node *ia32_gen_ASM(ir_node *node)
                }
 
                if (input == NULL) {
-                       ir_node *pred = get_irn_n(node, i);
                        input = get_new_node(pred);
 
                        if (parsed_constraint.cls == NULL
@@ -597,8 +594,8 @@ ir_node *ia32_gen_ASM(ir_node *node)
        /* count inputs which are real values (and not memory) */
        value_arity = 0;
        for (i = 0; i < arity; ++i) {
-               ir_node *in = get_irn_n(node, i);
-               if (get_irn_mode(in) == mode_M)
+               ir_node *node_in = get_irn_n(node, i);
+               if (get_irn_mode(node_in) == mode_M)
                        continue;
                ++value_arity;
        }
@@ -621,7 +618,6 @@ ir_node *ia32_gen_ASM(ir_node *node)
                int       o;
                bitset_t *used_ins = bitset_alloca(arity);
                for (o = 0; o < out_arity; ++o) {
-                       int   i;
                        const arch_register_req_t *outreq = out_reg_reqs[o];
 
                        if (outreq->cls == NULL) {
@@ -665,7 +661,6 @@ ir_node *ia32_gen_ASM(ir_node *node)
                        ++arity;
                }
        } else {
-               int       i;
                bitset_t *used_outs = bitset_alloca(out_arity);
                int       orig_out_arity = out_arity;
                for (i = 0; i < arity; ++i) {
index d3ee2b7..6aef8b4 100644 (file)
@@ -557,8 +557,8 @@ void ia32_emit_am(const ir_node *node)
        int        offs      = get_ia32_am_offs_int(node);
        ir_node   *base      = get_irn_n(node, n_ia32_base);
        int        has_base  = !is_ia32_NoReg_GP(base);
-       ir_node   *index     = get_irn_n(node, n_ia32_index);
-       int        has_index = !is_ia32_NoReg_GP(index);
+       ir_node   *idx       = get_irn_n(node, n_ia32_index);
+       int        has_index = !is_ia32_NoReg_GP(idx);
 
        /* just to be sure... */
        assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
@@ -675,6 +675,9 @@ static void ia32_emitf(const ir_node *node, const char *fmt, ...)
 end_of_mods:
 
                switch (*fmt++) {
+                       arch_register_t const *reg;
+                       ir_node         const *imm;
+
                        case '%':
                                be_emit_char('%');
                                break;
@@ -688,17 +691,13 @@ emit_AM:
                                                ia32_emit_am(node);
                                                break;
 
-                                       case 'R': {
-                                               const arch_register_t *reg = va_arg(ap, const arch_register_t*);
+                                       case 'R':
+                                               reg = va_arg(ap, const arch_register_t*);
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
                                                        goto emit_AM;
                                                } else {
-                                                       if (mod & EMIT_ALTERNATE_AM)
-                                                               be_emit_char('*');
-                                                       emit_register(reg, NULL);
+                                                       goto emit_R;
                                                }
-                                               break;
-                                       }
 
                                        case 'S':
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
@@ -708,40 +707,33 @@ emit_AM:
                                                        assert(get_ia32_op_type(node) == ia32_Normal);
                                                        goto emit_S;
                                                }
-                                               break;
 
                                        default: goto unknown;
                                }
                                break;
                        }
 
-                       case 'D': {
-                               unsigned               pos;
-                               const arch_register_t *reg;
-
+                       case 'D':
                                if (*fmt < '0' || '9' <= *fmt)
                                        goto unknown;
-
-                               pos = *fmt++ - '0';
-                               reg = get_out_reg(node, pos);
-                               emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
-                               break;
-                       }
+                               reg = get_out_reg(node, *fmt++ - '0');
+                               goto emit_R;
 
                        case 'I':
+                               imm = node;
+emit_I:
                                if (!(mod & EMIT_ALTERNATE_AM))
                                        be_emit_char('$');
-                               emit_ia32_Immediate_no_prefix(node);
+                               emit_ia32_Immediate_no_prefix(imm);
                                break;
 
                        case 'L':
                                ia32_emit_cfop_target(node);
                                break;
 
-                       case 'M': {
+                       case 'M':
                                ia32_emit_mode_suffix_mode(get_ia32_ls_mode(node));
                                break;
-                       }
 
                        case 'P': {
                                ia32_condition_code_t cc = va_arg(ap, ia32_condition_code_t);
@@ -749,8 +741,11 @@ emit_AM:
                                break;
                        }
 
-                       case 'R': {
-                               const arch_register_t *reg = va_arg(ap, const arch_register_t*);
+                       case 'R':
+                               reg = va_arg(ap, const arch_register_t*);
+emit_R:
+                               if (mod & EMIT_ALTERNATE_AM)
+                                       be_emit_char('*');
                                if (mod & EMIT_HIGH_REG) {
                                        emit_8bit_register_high(reg);
                                } else if (mod & EMIT_LOW_REG) {
@@ -759,31 +754,22 @@ emit_AM:
                                        emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
                                }
                                break;
-                       }
 
 emit_S:
                        case 'S': {
-                               unsigned       pos;
-                               const ir_node *in;
+                               unsigned pos;
 
                                if (*fmt < '0' || '9' <= *fmt)
                                        goto unknown;
 
                                pos = *fmt++ - '0';
-                               in  = get_irn_n(node, pos);
-                               if (is_ia32_Immediate(in)) {
-                                       if (!(mod & EMIT_ALTERNATE_AM))
-                                               be_emit_char('$');
-                                       emit_ia32_Immediate_no_prefix(in);
+                               imm = get_irn_n(node, pos);
+                               if (is_ia32_Immediate(imm)) {
+                                       goto emit_I;
                                } else {
-                                       const arch_register_t *reg;
-
-                                       if (mod & EMIT_ALTERNATE_AM)
-                                               be_emit_char('*');
                                        reg = get_in_reg(node, pos);
-                                       emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
+                                       goto emit_R;
                                }
-                               break;
                        }
 
                        case 's': {
@@ -1134,127 +1120,16 @@ static void emit_ia32_CMovcc(const ir_node *node)
        ia32_emitf(node, "\tcmov%P %#AR, %#R\n", cc, in_true, out);
 }
 
-
-/* jump table entry (target and corresponding number) */
-typedef struct branch_t {
-       ir_node *target;
-       int      value;
-} branch_t;
-
-/* jump table for switch generation */
-typedef struct jmp_tbl_t {
-       ir_node  *defProj;                 /**< default target */
-       long      min_value;               /**< smallest switch case */
-       long      max_value;               /**< largest switch case */
-       long      num_branches;            /**< number of jumps */
-       char      label[SNPRINTF_BUF_LEN]; /**< label of the jump table */
-       branch_t *branches;                /**< jump array */
-} jmp_tbl_t;
-
 /**
- * Compare two variables of type branch_t. Used to sort all switch cases
- */
-static int ia32_cmp_branch_t(const void *a, const void *b)
-{
-       branch_t *b1 = (branch_t *)a;
-       branch_t *b2 = (branch_t *)b;
-
-       if (b1->value <= b2->value)
-               return -1;
-       else
-               return 1;
-}
-
-static void generate_jump_table(jmp_tbl_t *tbl, const ir_node *node)
-{
-       int                 i;
-       long                default_pn = get_ia32_default_pn(node);
-       ir_node            *proj;
-       const ir_edge_t    *edge;
-
-       /* fill the table structure */
-       get_unique_label(tbl->label, SNPRINTF_BUF_LEN, "TBL_");
-       tbl->defProj      = NULL;
-       tbl->num_branches = get_irn_n_edges(node) - 1;
-       tbl->branches     = XMALLOCNZ(branch_t, tbl->num_branches);
-       tbl->min_value    = LONG_MAX;
-       tbl->max_value    = LONG_MIN;
-
-       i = 0;
-       /* go over all proj's and collect them */
-       foreach_out_edge(node, edge) {
-               long pn;
-               proj = get_edge_src_irn(edge);
-               assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
-
-               pn = get_Proj_proj(proj);
-
-               /* check for default proj */
-               if (pn == default_pn) {
-                       assert(tbl->defProj == NULL && "found two default Projs at SwitchJmp");
-                       tbl->defProj = proj;
-               } else {
-                       tbl->min_value = pn < tbl->min_value ? pn : tbl->min_value;
-                       tbl->max_value = pn > tbl->max_value ? pn : tbl->max_value;
-
-                       /* create branch entry */
-                       tbl->branches[i].target = proj;
-                       tbl->branches[i].value  = pn;
-                       ++i;
-               }
-
-       }
-       assert(i == tbl->num_branches);
-
-       /* sort the branches by their number */
-       qsort(tbl->branches, tbl->num_branches, sizeof(tbl->branches[0]), ia32_cmp_branch_t);
-}
-
-/**
- * Emits code for a SwitchJmp (creates a jump table if
- * possible otherwise a cmp-jmp cascade). Port from
- * cggg ia32 backend
+ * Emits code for a SwitchJmp
  */
 static void emit_ia32_SwitchJmp(const ir_node *node)
 {
-       unsigned long       interval;
-       int                 last_value, i;
-       jmp_tbl_t           tbl;
-
-       /* fill the table structure */
-       generate_jump_table(&tbl, node);
-
-       /* two-complement's magic make this work without overflow */
-       interval = tbl.max_value - tbl.min_value;
-
-       /* emit the table */
-       ia32_emitf(node,        "\tcmpl $%u, %S0\n", interval);
-       ia32_emitf(tbl.defProj, "\tja %L\n");
+       ir_entity *jump_table = get_ia32_am_sc(node);
+       long       default_pn = get_ia32_default_pn(node);
 
-       if (tbl.num_branches > 1) {
-               /* create table */
-               ia32_emitf(node, "\tjmp *%s(,%S0,4)\n", tbl.label);
-
-               be_gas_emit_switch_section(GAS_SECTION_RODATA);
-               ia32_emitf(NULL, "\t.align 4\n");
-               ia32_emitf(NULL, "%s:\n", tbl.label);
-
-               last_value = tbl.branches[0].value;
-               for (i = 0; i != tbl.num_branches; ++i) {
-                       while (last_value != tbl.branches[i].value) {
-                               ia32_emitf(tbl.defProj, ".long %L\n");
-                               ++last_value;
-                       }
-                       ia32_emitf(tbl.branches[i].target, ".long %L\n");
-                       ++last_value;
-               }
-               be_gas_emit_switch_section(GAS_SECTION_TEXT);
-       } else {
-               /* one jump is enough */
-               ia32_emitf(tbl.branches[0].target, "\tjmp %L\n");
-       }
-
-       free(tbl.branches);
+       ia32_emitf(node, "\tjmp %*AM\n");
+       emit_jump_table(node, default_pn, jump_table, get_cfop_target_block);
 }
 
 /**
@@ -1495,8 +1370,8 @@ static void emit_ia32_Conv_FP2FP(const ir_node *node)
  */
 static void emit_ia32_Conv_I2I(const ir_node *node)
 {
-       ir_mode *smaller_mode = get_ia32_ls_mode(node);
-       int      signed_mode  = mode_is_signed(smaller_mode);
+       ir_mode    *smaller_mode = get_ia32_ls_mode(node);
+       int         signed_mode  = mode_is_signed(smaller_mode);
        const char *sign_suffix;
 
        assert(!mode_is_float(smaller_mode));
@@ -1924,10 +1799,10 @@ static int should_align_block(const ir_node *block)
  */
 static void ia32_emit_block_header(ir_node *block)
 {
-       ir_graph     *irg = current_ir_graph;
+       ir_graph     *irg        = current_ir_graph;
        int           need_label = block_needs_label(block);
-       int           i, arity;
-       ir_exec_freq *exec_freq = be_get_irg_exec_freq(irg);
+       ir_exec_freq *exec_freq  = be_get_irg_exec_freq(irg);
+       int           arity;
 
        if (block == get_irg_end_block(irg))
                return;
@@ -1977,6 +1852,7 @@ static void ia32_emit_block_header(ir_node *block)
        if (arity <= 0) {
                be_emit_cstring(" none");
        } else {
+               int i;
                for (i = 0; i < arity; ++i) {
                        ir_node *predblock = get_Block_cfgpred_block(block, i);
                        be_emit_irprintf(" %d", get_irn_node_nr(predblock));
@@ -2106,14 +1982,14 @@ void ia32_gen_routine(ir_graph *irg)
           Those are ascending with ascending addresses. */
        qsort(exc_list, ARR_LEN(exc_list), sizeof(exc_list[0]), cmp_exc_entry);
        {
-               size_t i;
+               size_t e;
 
-               for (i = 0; i < ARR_LEN(exc_list); ++i) {
+               for (e = 0; e < ARR_LEN(exc_list); ++e) {
                        be_emit_cstring("\t.long ");
-                       ia32_emit_exc_label(exc_list[i].exc_instr);
+                       ia32_emit_exc_label(exc_list[e].exc_instr);
                        be_emit_char('\n');
                        be_emit_cstring("\t.long ");
-                       be_gas_emit_block_name(exc_list[i].block);
+                       be_gas_emit_block_name(exc_list[e].block);
                        be_emit_char('\n');
                }
        }
@@ -2319,8 +2195,8 @@ static void bemit_mod_am(unsigned reg, const ir_node *node)
        int        offs      = get_ia32_am_offs_int(node);
        ir_node   *base      = get_irn_n(node, n_ia32_base);
        int        has_base  = !is_ia32_NoReg_GP(base);
-       ir_node   *index     = get_irn_n(node, n_ia32_index);
-       int        has_index = !is_ia32_NoReg_GP(index);
+       ir_node   *idx       = get_irn_n(node, n_ia32_index);
+       int        has_index = !is_ia32_NoReg_GP(idx);
        unsigned   modrm     = 0;
        unsigned   sib       = 0;
        unsigned   emitoffs  = 0;
@@ -2355,7 +2231,7 @@ static void bemit_mod_am(unsigned reg, const ir_node *node)
 
        /* Determine if we need a SIB byte. */
        if (has_index) {
-               const arch_register_t *reg_index = arch_get_irn_register(index);
+               const arch_register_t *reg_index = arch_get_irn_register(idx);
                int                    scale     = get_ia32_am_scale(node);
                assert(scale < 4);
                /* R/M set to ESP means SIB in 32bit mode. */
@@ -3178,8 +3054,8 @@ static void bemit_load(const ir_node *node)
        if (out->index == REG_GP_EAX) {
                ir_node   *base      = get_irn_n(node, n_ia32_base);
                int        has_base  = !is_ia32_NoReg_GP(base);
-               ir_node   *index     = get_irn_n(node, n_ia32_index);
-               int        has_index = !is_ia32_NoReg_GP(index);
+               ir_node   *idx       = get_irn_n(node, n_ia32_index);
+               int        has_index = !is_ia32_NoReg_GP(idx);
                if (!has_base && !has_index) {
                        ir_entity *ent  = get_ia32_am_sc(node);
                        int        offs = get_ia32_am_offs_int(node);
@@ -3223,8 +3099,8 @@ static void bemit_store(const ir_node *node)
                if (in->index == REG_GP_EAX) {
                        ir_node   *base      = get_irn_n(node, n_ia32_base);
                        int        has_base  = !is_ia32_NoReg_GP(base);
-                       ir_node   *index     = get_irn_n(node, n_ia32_index);
-                       int        has_index = !is_ia32_NoReg_GP(index);
+                       ir_node   *idx       = get_irn_n(node, n_ia32_index);
+                       int        has_index = !is_ia32_NoReg_GP(idx);
                        if (!has_base && !has_index) {
                                ir_entity *ent  = get_ia32_am_sc(node);
                                int        offs = get_ia32_am_offs_int(node);
@@ -3415,63 +3291,13 @@ static void bemit_ia32_jcc(const ir_node *node)
 
 static void bemit_switchjmp(const ir_node *node)
 {
-       unsigned long          interval;
-       int                    last_value;
-       int                    i;
-       jmp_tbl_t              tbl;
-       const arch_register_t *in;
-
-       /* fill the table structure */
-       generate_jump_table(&tbl, node);
-
-       /* two-complement's magic make this work without overflow */
-       interval = tbl.max_value - tbl.min_value;
-
-       in = get_in_reg(node, 0);
-       /* emit the table */
-       if (get_signed_imm_size(interval) == 1) {
-               bemit8(0x83); // cmpl $imm8, %in
-               bemit_modru(in, 7);
-               bemit8(interval);
-       } else {
-               bemit8(0x81); // cmpl $imm32, %in
-               bemit_modru(in, 7);
-               bemit32(interval);
-       }
-       bemit8(0x0F); // ja tbl.defProj
-       bemit8(0x87);
-       ia32_emitf(tbl.defProj, ".long %L - . - 4\n");
-
-       if (tbl.num_branches > 1) {
-               /* create table */
-               bemit8(0xFF); // jmp *tbl.label(,%in,4)
-               bemit8(MOD_IND | ENC_REG(4) | ENC_RM(0x04));
-               bemit8(ENC_SIB(2, reg_gp_map[in->index], 0x05));
-               be_emit_irprintf("\t.long %s\n", tbl.label);
-
-               be_gas_emit_switch_section(GAS_SECTION_RODATA);
-               be_emit_cstring(".align 4\n");
-               be_emit_irprintf("%s:\n", tbl.label);
-
-               last_value = tbl.branches[0].value;
-               for (i = 0; i != tbl.num_branches; ++i) {
-                       while (last_value != tbl.branches[i].value) {
-                               ia32_emitf(tbl.defProj, ".long %L\n");
-                               ++last_value;
-                       }
-                       ia32_emitf(tbl.branches[i].target, ".long %L\n");
-                       ++last_value;
-               }
-               be_gas_emit_switch_section(GAS_SECTION_TEXT);
-       } else {
-               /* one jump is enough */
-               panic("switch only has one case");
-               //ia32_emitf(tbl.branches[0].target, "\tjmp %L\n");
-       }
+       ir_entity *jump_table = get_ia32_am_sc(node);
+       long       default_pn = get_ia32_default_pn(node);
 
-       be_emit_write_line();
+       bemit8(0xFF); // jmp *tbl.label(,%in,4)
+       bemit_mod_am(0x05, node);
 
-       free(tbl.branches);
+       emit_jump_table(node, default_pn, jump_table, get_cfop_target_block);
 }
 
 /**
index 66508b1..b7f2403 100644 (file)
@@ -58,7 +58,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
        ir_graph *irg;
        ir_node *in1, *in2, *noreg, *nomem, *res;
        ir_node *noreg_fp, *block;
-       dbg_info *dbg;
+       dbg_info *dbgi;
        const arch_register_t *in1_reg, *in2_reg, *out_reg;
 
        /* fix_am will solve this for AddressMode variants */
@@ -83,7 +83,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
                return;
 
        block = get_nodes_block(irn);
-       dbg   = get_irn_dbg_info(irn);
+       dbgi   = get_irn_dbg_info(irn);
 
        /* generate the neg src2 */
        if (is_ia32_xSub(irn)) {
@@ -93,7 +93,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
 
                assert(get_irn_mode(irn) != mode_T);
 
-               res = new_bd_ia32_xXor(dbg, block, noreg, noreg, nomem, in2, noreg_fp);
+               res = new_bd_ia32_xXor(dbgi, block, noreg, noreg, nomem, in2, noreg_fp);
                size = get_mode_size_bits(op_mode);
                entity = ia32_gen_fp_known_const(size == 32 ? ia32_SSIGN : ia32_DSIGN);
                set_ia32_am_sc(res, entity);
@@ -106,7 +106,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
                sched_add_before(irn, res);
 
                /* generate the add */
-               res = new_bd_ia32_xAdd(dbg, block, noreg, noreg, nomem, res, in1);
+               res = new_bd_ia32_xAdd(dbgi, block, noreg, noreg, nomem, res, in1);
                set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
 
                /* exchange the add and the sub */
@@ -136,14 +136,14 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
                }
 
                if (flags_proj == NULL) {
-                       res = new_bd_ia32_Neg(dbg, block, in2);
+                       res = new_bd_ia32_Neg(dbgi, block, in2);
                        arch_set_irn_register(res, in2_reg);
 
                        /* add to schedule */
                        sched_add_before(irn, res);
 
                        /* generate the add */
-                       res = new_bd_ia32_Add(dbg, block, noreg, noreg, nomem, res, in1);
+                       res = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, res, in1);
                        arch_set_irn_register(res, out_reg);
                        set_ia32_commutative(res);
 
@@ -165,15 +165,15 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
                         *
                         * a + -b = a + (~b + 1)  would set the carry flag IF a == b ...
                         */
-                       nnot = new_bd_ia32_Not(dbg, block, in2);
+                       nnot = new_bd_ia32_Not(dbgi, block, in2);
                        arch_set_irn_register(nnot, in2_reg);
                        sched_add_before(irn, nnot);
 
-                       stc = new_bd_ia32_Stc(dbg, block);
+                       stc = new_bd_ia32_Stc(dbgi, block);
                        arch_set_irn_register(stc, &ia32_registers[REG_EFLAGS]);
                        sched_add_before(irn, stc);
 
-                       adc = new_bd_ia32_Adc(dbg, block, noreg, noreg, nomem, nnot, in1, stc);
+                       adc = new_bd_ia32_Adc(dbgi, block, noreg, noreg, nomem, nnot, in1, stc);
                        arch_set_irn_register(adc, out_reg);
                        sched_add_before(irn, adc);
 
@@ -181,7 +181,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn)
                        adc_flags = new_r_Proj(adc, mode_Iu, pn_ia32_Adc_flags);
                        arch_set_irn_register(adc_flags, &ia32_registers[REG_EFLAGS]);
 
-                       cmc = new_bd_ia32_Cmc(dbg, block, adc_flags);
+                       cmc = new_bd_ia32_Cmc(dbgi, block, adc_flags);
                        arch_set_irn_register(cmc, &ia32_registers[REG_EFLAGS]);
                        sched_add_before(irn, cmc);
 
@@ -287,14 +287,14 @@ static void assure_should_be_same_requirements(ir_node *node)
                uses_out_reg_pos = -1;
                for (i2 = 0; i2 < arity; ++i2) {
                        ir_node               *in     = get_irn_n(node, i2);
-                       const arch_register_t *in_reg;
+                       const arch_register_t *other_in_reg;
 
                        if (!mode_is_data(get_irn_mode(in)))
                                continue;
 
-                       in_reg = arch_get_irn_register(in);
+                       other_in_reg = arch_get_irn_register(in);
 
-                       if (in_reg != out_reg)
+                       if (other_in_reg != out_reg)
                                continue;
 
                        if (uses_out_reg != NULL && in != uses_out_reg) {
index 5e3b547..b6bafb5 100644 (file)
@@ -87,7 +87,6 @@ static void create_fpcw_entities(void)
 static ir_node *create_fpu_mode_spill(void *env, ir_node *state, int force,
                                       ir_node *after)
 {
-       ir_node *spill = NULL;
        (void) env;
 
        /* we don't spill the fpcw in unsafe mode */
@@ -107,17 +106,18 @@ static ir_node *create_fpu_mode_spill(void *env, ir_node *state, int force,
                ir_node *noreg = ia32_new_NoReg_gp(irg);
                ir_node *nomem = get_irg_no_mem(irg);
                ir_node *frame = get_irg_frame(irg);
-
-               spill = new_bd_ia32_FnstCW(NULL, block, frame, noreg, nomem, state);
+               ir_node *spill
+                       = new_bd_ia32_FnstCW(NULL, block, frame, noreg, nomem, state);
                set_ia32_op_type(spill, ia32_AddrModeD);
                /* use mode_Iu, as movl has a shorter opcode than movw */
                set_ia32_ls_mode(spill, mode_Iu);
                set_ia32_use_frame(spill);
 
                sched_add_after(skip_Proj(after), spill);
+               return spill;
        }
 
-       return spill;
+       return NULL;
 }
 
 static ir_node *create_fldcw_ent(ir_node *block, ir_entity *entity)
index 4495c9c..118f89c 100644 (file)
@@ -67,15 +67,15 @@ void ia32_handle_intrinsics(void)
 /**
  * Reroute edges from the pn_Call_T_result proj of a call.
  *
- * @param proj   the pn_Call_T_result Proj
- * @param l_res  the lower 32 bit result
- * @param h_res  the upper 32 bit result or NULL
+ * @param resproj  the pn_Call_T_result Proj
+ * @param l_res    the lower 32 bit result
+ * @param h_res    the upper 32 bit result or NULL
  */
-static void reroute_result(ir_node *proj, ir_node *l_res, ir_node *h_res)
+static void reroute_result(ir_node *resproj, ir_node *l_res, ir_node *h_res)
 {
        const ir_edge_t *edge, *next;
 
-       foreach_out_edge_safe(proj, edge, next) {
+       foreach_out_edge_safe(resproj, edge, next) {
                ir_node *proj = get_edge_src_irn(edge);
                long    pn    = get_Proj_proj(proj);
 
index 5e232c5..4b4eb66 100644 (file)
@@ -237,6 +237,7 @@ typedef struct ia32_switch_attr_t ia32_switch_attr_t;
 struct ia32_switch_attr_t {
        ia32_attr_t  attr;        /**< generic attribute */
        long         default_pn;
+       ir_entity   *jump_table;
 };
 
 /**
index a09ead1..1d02081 100644 (file)
@@ -314,16 +314,16 @@ static void peephole_ia32_Test(ir_node *node)
                        if ((offset & 0xFFFFFF00) == 0) {
                                /* attr->am_offs += 0; */
                        } else if ((offset & 0xFFFF00FF) == 0) {
-                               ir_node *imm = ia32_create_Immediate(NULL, 0, offset >>  8);
-                               set_irn_n(node, n_ia32_Test_right, imm);
+                               ir_node *imm_node = ia32_create_Immediate(NULL, 0, offset>>8);
+                               set_irn_n(node, n_ia32_Test_right, imm_node);
                                attr->am_offs += 1;
                        } else if ((offset & 0xFF00FFFF) == 0) {
-                               ir_node *imm = ia32_create_Immediate(NULL, 0, offset >> 16);
-                               set_irn_n(node, n_ia32_Test_right, imm);
+                               ir_node *imm_node = ia32_create_Immediate(NULL, 0, offset>>16);
+                               set_irn_n(node, n_ia32_Test_right, imm_node);
                                attr->am_offs += 2;
                        } else if ((offset & 0x00FFFFFF) == 0) {
-                               ir_node *imm = ia32_create_Immediate(NULL, 0, offset >> 24);
-                               set_irn_n(node, n_ia32_Test_right, imm);
+                               ir_node *imm_node = ia32_create_Immediate(NULL, 0, offset>>24);
+                               set_irn_n(node, n_ia32_Test_right, imm_node);
                                attr->am_offs += 3;
                        } else {
                                return;
@@ -483,8 +483,6 @@ static void peephole_IncSP_Store_to_push(ir_node *irn)
                ir_node *val, *mem, *mem_proj;
                ir_node *store = stores[i];
                ir_node *noreg = ia32_new_NoReg_gp(irg);
-               const ir_edge_t *edge;
-               const ir_edge_t *next;
 
                val = get_irn_n(store, n_ia32_unary_op);
                mem = get_irn_n(store, n_ia32_mem);
index 667cf9e..d67f80f 100644 (file)
@@ -6,22 +6,20 @@ $arch = "ia32";
 
 # register types:
 $normal      =  0; # no special type
-$caller_save =  1; # caller save (register must be saved by the caller of a function)
-$callee_save =  2; # callee save (register must be saved by the called function)
-$ignore      =  4; # ignore (do not assign this register)
-$arbitrary   =  8; # emitter can choose an arbitrary register of this class
-$virtual     = 16; # the register is a virtual one
-$state       = 32; # register represents a state
+$ignore      =  1; # ignore (do not assign this register)
+$arbitrary   =  2; # emitter can choose an arbitrary register of this class
+$virtual     =  4; # the register is a virtual one
+$state       =  8; # register represents a state
 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
 %reg_classes = (
        gp => [
-               { name => "edx", type => $caller_save },
-               { name => "ecx", type => $caller_save },
-               { name => "eax", type => $caller_save },
-               { name => "ebx", type => $callee_save },
-               { name => "esi", type => $callee_save },
-               { name => "edi", type => $callee_save },
-               { name => "ebp", type => $callee_save },
+               { name => "edx" },
+               { name => "ecx" },
+               { name => "eax" },
+               { name => "ebx" },
+               { name => "esi" },
+               { name => "edi" },
+               { name => "ebp" },
                { name => "esp", type => $ignore },
                { name => "gp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes
                { mode => "mode_Iu" }
@@ -38,26 +36,26 @@ $state       = 32; # register represents a state
                { mode => "mode_E", flags => "manual_ra" }
        ],
        xmm => [
-               { name => "xmm0", type => $caller_save },
-               { name => "xmm1", type => $caller_save },
-               { name => "xmm2", type => $caller_save },
-               { name => "xmm3", type => $caller_save },
-               { name => "xmm4", type => $caller_save },
-               { name => "xmm5", type => $caller_save },
-               { name => "xmm6", type => $caller_save },
-               { name => "xmm7", type => $caller_save },
+               { name => "xmm0" },
+               { name => "xmm1" },
+               { name => "xmm2" },
+               { name => "xmm3" },
+               { name => "xmm4" },
+               { name => "xmm5" },
+               { name => "xmm6" },
+               { name => "xmm7" },
                { name => "xmm_NOREG", type => $ignore | $virtual },     # we need a dummy register for NoReg nodes
                { mode => "mode_E" }
        ],
        vfp => [
-               { name => "vf0", type => $caller_save },
-               { name => "vf1", type => $caller_save },
-               { name => "vf2", type => $caller_save },
-               { name => "vf3", type => $caller_save },
-               { name => "vf4", type => $caller_save },
-               { name => "vf5", type => $caller_save },
-               { name => "vf6", type => $caller_save },
-               { name => "vf7", type => $caller_save },
+               { name => "vf0" },
+               { name => "vf1" },
+               { name => "vf2" },
+               { name => "vf3" },
+               { name => "vf4" },
+               { name => "vf5" },
+               { name => "vf6" },
+               { name => "vf7" },
                { name => "vfp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes
                { mode => "mode_E" }
        ],
@@ -1044,13 +1042,13 @@ Jcc => {
 SwitchJmp => {
        state     => "pinned",
        op_flags  => [ "labeled", "cfopcode", "forking" ],
-       reg_req   => { in => [ "gp" ] },
+       reg_req   => { in => [ "gp", "gp" ] },
+       ins       => [ "base", "index" ],
        mode      => "mode_T",
        attr_type => "ia32_switch_attr_t",
        attr      => "long default_pn",
-       latency   => 3,
+       latency   => 2,
        units     => [ "BRANCH" ],
-       modified_flags => $status_flags,
        init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
 },
 
index ca8b7ea..d7eaaa1 100644 (file)
@@ -225,7 +225,6 @@ static ir_node *gen_Const(ir_node *node)
        if (mode_is_float(mode)) {
                ir_node   *res   = NULL;
                ir_node   *load;
-               ir_node   *base;
                ir_entity *floatent;
 
                if (ia32_cg_config.use_sse2) {
@@ -260,6 +259,7 @@ static ir_node *gen_Const(ir_node *node)
                                set_ia32_ls_mode(load, mode);
                                res = load;
                        } else {
+                               ir_node *base;
 #ifdef CONSTRUCT_SSE_CONST
                                if (mode == mode_D) {
                                        unsigned val = get_tarval_sub_bits(tv, 0) |
@@ -881,7 +881,6 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                }
                am->op_type = ia32_AddrModeS;
        } else {
-               ir_mode *mode;
                am->op_type = ia32_Normal;
 
                if (flags & match_try_am) {
@@ -1190,7 +1189,9 @@ static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func,
 static ir_node *create_lea_from_address(dbg_info *dbgi, ir_node *block,
                                         ia32_address_t *addr)
 {
-       ir_node *base, *index, *res;
+       ir_node *base;
+       ir_node *idx;
+       ir_node *res;
 
        base = addr->base;
        if (base == NULL) {
@@ -1199,11 +1200,11 @@ static ir_node *create_lea_from_address(dbg_info *dbgi, ir_node *block,
                base = be_transform_node(base);
        }
 
-       index = addr->index;
-       if (index == NULL) {
-               index = noreg_GP;
+       idx = addr->index;
+       if (idx == NULL) {
+               idx = noreg_GP;
        } else {
-               index = be_transform_node(index);
+               idx = be_transform_node(idx);
        }
 
        /* segment overrides are ineffective for Leas :-( so we have to patch
@@ -1218,7 +1219,7 @@ static ir_node *create_lea_from_address(dbg_info *dbgi, ir_node *block,
                addr->tls_segment = false;
        }
 
-       res = new_bd_ia32_Lea(dbgi, block, base, index);
+       res = new_bd_ia32_Lea(dbgi, block, base, idx);
        set_address(res, addr);
 
        return res;
@@ -1962,43 +1963,41 @@ static ir_node *gen_Not(ir_node *node)
        return gen_unop(node, op, new_bd_ia32_Not, match_mode_neutral);
 }
 
-static ir_node *create_abs(dbg_info *dbgi, ir_node *block, ir_node *op,
-                           bool negate, ir_node *node)
+static ir_node *create_float_abs(dbg_info *dbgi, ir_node *block, ir_node *op,
+                                 bool negate, ir_node *node)
 {
        ir_node   *new_block = be_transform_node(block);
        ir_mode   *mode      = get_irn_mode(op);
-       ir_node   *new_op;
+       ir_node   *new_op    = be_transform_node(op);
        ir_node   *new_node;
        int        size;
        ir_entity *ent;
 
-       if (mode_is_float(mode)) {
-               new_op = be_transform_node(op);
+       assert(mode_is_float(mode));
 
-               if (ia32_cg_config.use_sse2) {
-                       ir_node *noreg_fp = ia32_new_NoReg_xmm(current_ir_graph);
-                       new_node = new_bd_ia32_xAnd(dbgi, new_block, get_symconst_base(),
-                                                   noreg_GP, nomem, new_op, noreg_fp);
+       if (ia32_cg_config.use_sse2) {
+               ir_node *noreg_fp = ia32_new_NoReg_xmm(current_ir_graph);
+               new_node = new_bd_ia32_xAnd(dbgi, new_block, get_symconst_base(),
+                                                                       noreg_GP, nomem, new_op, noreg_fp);
 
-                       size = get_mode_size_bits(mode);
-                       ent  = ia32_gen_fp_known_const(size == 32 ? ia32_SABS : ia32_DABS);
+               size = get_mode_size_bits(mode);
+               ent  = ia32_gen_fp_known_const(size == 32 ? ia32_SABS : ia32_DABS);
 
-                       set_ia32_am_sc(new_node, ent);
+               set_ia32_am_sc(new_node, ent);
 
-                       SET_IA32_ORIG_NODE(new_node, node);
+               SET_IA32_ORIG_NODE(new_node, node);
 
-                       set_ia32_op_type(new_node, ia32_AddrModeS);
-                       set_ia32_ls_mode(new_node, mode);
+               set_ia32_op_type(new_node, ia32_AddrModeS);
+               set_ia32_ls_mode(new_node, mode);
 
-                       /* TODO, implement -Abs case */
-                       assert(!negate);
-               } else {
-                       new_node = new_bd_ia32_vfabs(dbgi, new_block, new_op);
+               /* TODO, implement -Abs case */
+               assert(!negate);
+       } else {
+               new_node = new_bd_ia32_vfabs(dbgi, new_block, new_op);
+               SET_IA32_ORIG_NODE(new_node, node);
+               if (negate) {
+                       new_node = new_bd_ia32_vfchs(dbgi, new_block, new_node);
                        SET_IA32_ORIG_NODE(new_node, node);
-                       if (negate) {
-                               new_node = new_bd_ia32_vfchs(dbgi, new_block, new_node);
-                               SET_IA32_ORIG_NODE(new_node, node);
-                       }
                }
        }
 
@@ -2189,15 +2188,15 @@ static ir_node *gen_Load(ir_node *node)
        ir_mode  *mode      = get_Load_mode(node);
        int       throws_exception = ir_throws_exception(node);
        ir_node  *base;
-       ir_node  *index;
+       ir_node  *idx;
        ir_node  *new_node;
        ia32_address_t addr;
 
        /* construct load address */
        memset(&addr, 0, sizeof(addr));
        ia32_create_address_mode(&addr, ptr, ia32_create_am_normal);
-       base  = addr.base;
-       index = addr.index;
+       base = addr.base;
+       idx  = addr.index;
 
        if (base == NULL) {
                base = noreg_GP;
@@ -2205,18 +2204,18 @@ static ir_node *gen_Load(ir_node *node)
                base = be_transform_node(base);
        }
 
-       if (index == NULL) {
-               index = noreg_GP;
+       if (idx == NULL) {
+               idx = noreg_GP;
        } else {
-               index = be_transform_node(index);
+               idx = be_transform_node(idx);
        }
 
        if (mode_is_float(mode)) {
                if (ia32_cg_config.use_sse2) {
-                       new_node = new_bd_ia32_xLoad(dbgi, block, base, index, new_mem,
+                       new_node = new_bd_ia32_xLoad(dbgi, block, base, idx, new_mem,
                                                     mode);
                } else {
-                       new_node = new_bd_ia32_vfld(dbgi, block, base, index, new_mem,
+                       new_node = new_bd_ia32_vfld(dbgi, block, base, idx, new_mem,
                                                    mode);
                }
        } else {
@@ -2224,10 +2223,10 @@ static ir_node *gen_Load(ir_node *node)
 
                /* create a conv node with address mode for smaller modes */
                if (get_mode_size_bits(mode) < 32) {
-                       new_node = new_bd_ia32_Conv_I2I(dbgi, block, base, index,
+                       new_node = new_bd_ia32_Conv_I2I(dbgi, block, base, idx,
                                                        new_mem, noreg_GP, mode);
                } else {
-                       new_node = new_bd_ia32_Load(dbgi, block, base, index, new_mem);
+                       new_node = new_bd_ia32_Load(dbgi, block, base, idx, new_mem);
                }
        }
        ir_set_throws_exception(new_node, throws_exception);
@@ -2642,7 +2641,7 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns)
 
                ir_node *new_node = new_bd_ia32_Store(dbgi, new_block, addr.base,
                        addr.index, addr.mem, imm);
-               ir_node *mem      = new_r_Proj(new_node, mode_M, pn_ia32_Store_M);
+               ir_node *new_mem  = new_r_Proj(new_node, mode_M, pn_ia32_Store_M);
 
                ir_set_throws_exception(new_node, throws_exception);
                set_irn_pinned(new_node, get_irn_pinned(node));
@@ -2652,7 +2651,7 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns)
                SET_IA32_ORIG_NODE(new_node, node);
 
                assert(i < 4);
-               ins[i++] = mem;
+               ins[i++] = new_mem;
 
                size        -= 4;
                ofs         += 4;
@@ -2815,46 +2814,31 @@ static ir_node *gen_Store(ir_node *node)
  */
 static ir_node *create_Switch(ir_node *node)
 {
-       dbg_info *dbgi       = get_irn_dbg_info(node);
-       ir_node  *block      = be_transform_node(get_nodes_block(node));
-       ir_node  *sel        = get_Cond_selector(node);
-       ir_node  *new_sel    = be_transform_node(sel);
-       long      switch_min = LONG_MAX;
-       long      switch_max = LONG_MIN;
-       long      default_pn = get_Cond_default_proj(node);
-       ir_node  *new_node;
-       const ir_edge_t *edge;
+       dbg_info  *dbgi       = get_irn_dbg_info(node);
+       ir_node   *block      = be_transform_node(get_nodes_block(node));
+       ir_node   *sel        = get_Cond_selector(node);
+       ir_node   *new_sel    = be_transform_node(sel);
+       long       default_pn = get_Cond_default_proj(node);
+       ir_node   *new_node;
+       ir_entity *entity;
 
        assert(get_mode_size_bits(get_irn_mode(sel)) == 32);
 
-       /* determine the smallest switch case value */
-       foreach_out_edge(node, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               long     pn   = get_Proj_proj(proj);
-               if (pn == default_pn)
-                       continue;
-
-               if (pn < switch_min)
-                       switch_min = pn;
-               if (pn > switch_max)
-                       switch_max = pn;
-       }
+       entity = new_entity(NULL, id_unique("TBL%u"), get_unknown_type());
+       set_entity_visibility(entity, ir_visibility_private);
+       add_entity_linkage(entity, IR_LINKAGE_CONSTANT);
 
-       if ((unsigned long) (switch_max - switch_min) > 128000) {
-               panic("Size of switch %+F bigger than 128000", node);
-       }
-
-       if (switch_min != 0) {
-               /* if smallest switch case is not 0 we need an additional sub */
-               new_sel = new_bd_ia32_Lea(dbgi, block, new_sel, noreg_GP);
-               add_ia32_am_offs_int(new_sel, -switch_min);
-               set_ia32_op_type(new_sel, ia32_AddrModeS);
-
-               SET_IA32_ORIG_NODE(new_sel, node);
-       }
-
-       new_node = new_bd_ia32_SwitchJmp(dbgi, block, new_sel, default_pn);
+       /* TODO: we could perform some more matching here to also use the base
+        * register of the address mode */
+       new_node
+               = new_bd_ia32_SwitchJmp(dbgi, block, noreg_GP, new_sel, default_pn);
+       set_ia32_am_scale(new_node, 2);
+       set_ia32_am_sc(new_node, entity);
+       set_ia32_op_type(new_node, ia32_AddrModeS);
+       set_ia32_ls_mode(new_node, mode_Iu);
        SET_IA32_ORIG_NODE(new_node, node);
+       // FIXME This seems wrong. GCC uses PIC for switch on OS X.
+       get_ia32_attr(new_node)->data.am_sc_no_pic_adjust = true;
 
        return new_node;
 }
@@ -3421,11 +3405,11 @@ static void find_const_transform(ia32_condition_code_t cc,
                                ++step;
                                res->steps[step].transform = SETCC_TR_NEG;
                        } else {
-                               int v = get_tarval_lowest_bit(t);
-                               assert(v >= 0);
+                               int val = get_tarval_lowest_bit(t);
+                               assert(val >= 0);
 
                                res->steps[step].transform = SETCC_TR_SHL;
-                               res->steps[step].scale     = v;
+                               res->steps[step].scale     = val;
                        }
                }
                ++step;
@@ -3464,7 +3448,7 @@ static ir_node *gen_Mux(ir_node *node)
                                   node);
                } else {
                        ir_node *op = ir_get_abs_op(sel, mux_true, mux_false);
-                       return create_abs(dbgi, block, op, is_abs < 0, node);
+                       return create_float_abs(dbgi, block, op, is_abs < 0, node);
                }
        }
 
@@ -5013,7 +4997,7 @@ static ir_node *gen_frame_address(ir_node *node)
 static ir_node *gen_prefetch(ir_node *node)
 {
        dbg_info       *dbgi;
-       ir_node        *ptr, *block, *mem, *base, *index;
+       ir_node        *ptr, *block, *mem, *base, *idx;
        ir_node        *param,  *new_node;
        long           rw, locality;
        ir_tarval      *tv;
@@ -5032,8 +5016,8 @@ static ir_node *gen_prefetch(ir_node *node)
        memset(&addr, 0, sizeof(addr));
        ptr = get_Builtin_param(node, 0);
        ia32_create_address_mode(&addr, ptr, ia32_create_am_normal);
-       base  = addr.base;
-       index = addr.index;
+       base = addr.base;
+       idx  = addr.index;
 
        if (base == NULL) {
                base = noreg_GP;
@@ -5041,10 +5025,10 @@ static ir_node *gen_prefetch(ir_node *node)
                base = be_transform_node(base);
        }
 
-       if (index == NULL) {
-               index = noreg_GP;
+       if (idx == NULL) {
+               idx = noreg_GP;
        } else {
-               index = be_transform_node(index);
+               idx = be_transform_node(idx);
        }
 
        dbgi     = get_irn_dbg_info(node);
@@ -5053,7 +5037,7 @@ static ir_node *gen_prefetch(ir_node *node)
 
        if (rw == 1 && ia32_cg_config.use_3dnow_prefetch) {
                /* we have 3DNow!, this was already checked above */
-               new_node = new_bd_ia32_PrefetchW(dbgi, block, base, index, mem);
+               new_node = new_bd_ia32_PrefetchW(dbgi, block, base, idx, mem);
        } else if (ia32_cg_config.use_sse_prefetch) {
                /* note: rw == 1 is IGNORED in that case */
                param    = get_Builtin_param(node, 2);
@@ -5063,22 +5047,22 @@ static ir_node *gen_prefetch(ir_node *node)
                /* SSE style prefetch */
                switch (locality) {
                case 0:
-                       new_node = new_bd_ia32_PrefetchNTA(dbgi, block, base, index, mem);
+                       new_node = new_bd_ia32_PrefetchNTA(dbgi, block, base, idx, mem);
                        break;
                case 1:
-                       new_node = new_bd_ia32_Prefetch2(dbgi, block, base, index, mem);
+                       new_node = new_bd_ia32_Prefetch2(dbgi, block, base, idx, mem);
                        break;
                case 2:
-                       new_node = new_bd_ia32_Prefetch1(dbgi, block, base, index, mem);
+                       new_node = new_bd_ia32_Prefetch1(dbgi, block, base, idx, mem);
                        break;
                default:
-                       new_node = new_bd_ia32_Prefetch0(dbgi, block, base, index, mem);
+                       new_node = new_bd_ia32_Prefetch0(dbgi, block, base, idx, mem);
                        break;
                }
        } else {
                assert(ia32_cg_config.use_3dnow_prefetch);
                /* 3DNow! style prefetch */
-               new_node = new_bd_ia32_Prefetch(dbgi, block, base, index, mem);
+               new_node = new_bd_ia32_Prefetch(dbgi, block, base, idx, mem);
        }
 
        set_irn_pinned(new_node, get_irn_pinned(node));
@@ -5856,14 +5840,14 @@ static void postprocess_fp_call_results(void)
                        ir_type *res_tp = get_method_res_type(mtp, j);
                        ir_node *res, *new_res;
                        const ir_edge_t *edge, *next;
-                       ir_mode *mode;
+                       ir_mode *res_mode;
 
                        if (! is_atomic_type(res_tp)) {
                                /* no floating point return */
                                continue;
                        }
-                       mode = get_type_mode(res_tp);
-                       if (! mode_is_float(mode)) {
+                       res_mode = get_type_mode(res_tp);
+                       if (! mode_is_float(res_mode)) {
                                /* no floating point return */
                                continue;
                        }
@@ -5884,12 +5868,12 @@ static void postprocess_fp_call_results(void)
                                        dbg_info *db    = get_irn_dbg_info(succ);
                                        ir_node  *block = get_nodes_block(succ);
                                        ir_node  *base  = get_irn_n(succ, n_ia32_xStore_base);
-                                       ir_node  *index = get_irn_n(succ, n_ia32_xStore_index);
+                                       ir_node  *idx   = get_irn_n(succ, n_ia32_xStore_index);
                                        ir_node  *mem   = get_irn_n(succ, n_ia32_xStore_mem);
                                        ir_node  *value = get_irn_n(succ, n_ia32_xStore_val);
                                        ir_mode  *mode  = get_ia32_ls_mode(succ);
 
-                                       ir_node  *st = new_bd_ia32_vfst(db, block, base, index, mem, value, mode);
+                                       ir_node  *st = new_bd_ia32_vfst(db, block, base, idx, mem, value, mode);
                                        //ir_node  *mem = new_r_Proj(st, mode_M, pn_ia32_vfst_M);
                                        set_ia32_am_offs_int(st, get_ia32_am_offs_int(succ));
                                        if (is_ia32_use_frame(succ))
@@ -5914,7 +5898,7 @@ static void postprocess_fp_call_results(void)
 
                                        /* store st(0) on stack */
                                        vfst = new_bd_ia32_vfst(db, block, frame, noreg_GP, call_mem,
-                                                               res, mode);
+                                                               res, res_mode);
                                        set_ia32_op_type(vfst, ia32_AddrModeD);
                                        set_ia32_use_frame(vfst);
 
@@ -5922,11 +5906,11 @@ static void postprocess_fp_call_results(void)
 
                                        /* load into SSE register */
                                        xld = new_bd_ia32_xLoad(db, block, frame, noreg_GP, vfst_mem,
-                                                               mode);
+                                                               res_mode);
                                        set_ia32_op_type(xld, ia32_AddrModeS);
                                        set_ia32_use_frame(xld);
 
-                                       new_res = new_r_Proj(xld, mode, pn_ia32_xLoad_res);
+                                       new_res = new_r_Proj(xld, res_mode, pn_ia32_xLoad_res);
                                        new_mem = new_r_Proj(xld, mode_M, pn_ia32_xLoad_M);
 
                                        if (old_mem != NULL) {
index c31e587..4457de1 100644 (file)
@@ -1783,8 +1783,6 @@ static int sim_Copy(x87_state *state, ir_node *n)
        op1_idx = x87_on_stack(state, arch_register_get_index(op1));
 
        if (is_vfp_live(arch_register_get_index(op1), live)) {
-               ir_node *pred = get_irn_n(n, 0);
-
                /* Operand is still live, a real copy. We need here an fpush that can
                   hold a a register, so use the fpushCopy or recreate constants */
                node = create_Copy(state, n);
index 9378169..3724b00 100755 (executable)
@@ -81,7 +81,6 @@ foreach my $unit_type (keys(%cpu)) {
        push(@obst_unit_tp_defs, "\t$tp_name,\n");
        push(@obst_init, "\n\t\t/* init of execution unit type $tp_name */\n");
        push(@obst_init, "\t\tcur_unit_tp = &$arch\_execution_unit_types[$tp_name];\n");
-       push(@obst_init, "\t\t(void) cur_unit_tp; /* avoid warning */\n");
 
        push(@obst_unit_defs, "/* enum for execution units of type $unit_type */\n");
        push(@obst_unit_defs, "enum $arch\_execunit_tp_$unit_type\_vals {\n");
@@ -161,7 +160,7 @@ print OUT @obst_execunits;
 if ($num_unit_types > 0) {
 print OUT<<EOF;
 
-be_execution_unit_type_t $arch\_execution_unit_types[] = {
+static be_execution_unit_type_t $arch\_execution_unit_types[] = {
 EOF
 }
 
@@ -176,7 +175,7 @@ if ($num_unit_types > 0) {
 }
 
 print OUT<<EOF;
-be_machine_t $arch\_cpu = {
+static be_machine_t $arch\_cpu = {
        $bundle_size,
        $bundles_per_cycle,
        $num_unit_types,
@@ -190,7 +189,7 @@ const be_machine_t *$arch\_init_machine_description(void) {
        static int initialized = 0;
 
        if (! initialized) {
-               be_execution_unit_type_t *cur_unit_tp;
+               be_execution_unit_type_t *cur_unit_tp = NULL;
                (void) cur_unit_tp; /* avoid warning */
 
                be_machine_init_dummy_unit();
index c754c58..284ca6b 100755 (executable)
@@ -61,26 +61,18 @@ sub translate_reg_type {
                my @types;
 
                if ($t & 1) {
-                       push(@types, "arch_register_type_caller_save");
-               }
-
-               if ($t & 2) {
-                       push(@types, "arch_register_type_callee_save");
-               }
-
-               if ($t & 4) {
                        push(@types, "arch_register_type_ignore");
                }
 
-               if ($t & 8) {
+               if ($t & 2) {
                        push(@types, "arch_register_type_joker");
                }
 
-               if ($t & 16) {
+               if ($t & 4) {
                        push(@types, "arch_register_type_virtual");
                }
 
-               if ($t & 32) {
+               if ($t & 8) {
                        push(@types, "arch_register_type_state");
                }
 
index e342111..d37c804 100644 (file)
@@ -563,7 +563,7 @@ static void sparc_lower_for_target(void)
        for (i = 0; i < n_irgs; ++i) {
                ir_graph *irg = get_irp_irg(i);
                ir_lower_mode_b(irg, &lower_mode_b_config);
-               lower_switch(irg, 256, false);
+               lower_switch(irg, 4, 256, false);
        }
 }
 
@@ -604,7 +604,9 @@ static const backend_params *sparc_get_backend_params(void)
                1,     /* big endian */
                &arch_dep,              /* will be set later */
                sparc_is_mux_allowed,   /* parameter for if conversion */
+               32,    /* machine size */
                NULL,  /* float arithmetic mode */
+               128,   /* size of long double */
                0,     /* no trampoline support: size 0 */
                0,     /* no trampoline support: align 0 */
                NULL,  /* no trampoline support: no trampoline builder */
@@ -655,9 +657,10 @@ const arch_isa_if_t sparc_isa_if = {
        sparc_after_ra,
        sparc_finish,
        sparc_emit_routine,
+       NULL, /* register_saved_by */
 };
 
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_sparc)
 void be_init_arch_sparc(void)
 {
        be_register_isa_if("sparc", &sparc_isa_if);
index 7e7af83..47604d4 100644 (file)
@@ -51,6 +51,22 @@ static const unsigned ignore_regs[] = {
        REG_Y,
 };
 
+static const arch_register_t* const param_regs[] = {
+       &sparc_registers[REG_I0],
+       &sparc_registers[REG_I1],
+       &sparc_registers[REG_I2],
+       &sparc_registers[REG_I3],
+       &sparc_registers[REG_I4],
+       &sparc_registers[REG_I5],
+};
+
+static const arch_register_t* const float_result_regs[] = {
+       &sparc_registers[REG_F0],
+       &sparc_registers[REG_F1],
+       &sparc_registers[REG_F2],
+       &sparc_registers[REG_F3],
+};
+
 /**
  * Maps an input register representing the i'th register input
  * to the i'th register output.
@@ -82,7 +98,8 @@ static void check_omit_fp(ir_node *node, void *env)
 calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
                                                       ir_graph *irg)
 {
-       int                   stack_offset        = 0;
+       unsigned              stack_offset        = 0;
+       unsigned              n_param_regs_used   = 0;
        int                   n_param_regs        = ARRAY_SIZE(param_regs);
        int                   n_float_result_regs = ARRAY_SIZE(float_result_regs);
        bool                  omit_fp             = false;
@@ -136,15 +153,16 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
                                        reg = map_i_to_o_reg(reg);
                                param->reg1 = reg;
                        } else {
-                               ir_mode *mode = param_regs[0]->reg_class->mode;
-                               ir_type *type = get_type_for_mode(mode);
-                               param->type   = type;
-                               param->offset = stack_offset;
-                               assert(get_mode_size_bits(mode) == 32);
+                               ir_mode *regmode = param_regs[0]->reg_class->mode;
+                               ir_type *type    = get_type_for_mode(regmode);
+                               param->type      = type;
+                               param->offset    = stack_offset;
+                               assert(get_mode_size_bits(regmode) == 32);
                                stack_offset += 4;
                        }
                }
        }
+       n_param_regs_used = regnum;
 
        /* determine how results are passed */
        n_results    = get_method_n_ress(function_type);
@@ -182,6 +200,7 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type,
        cconv                   = XMALLOCZ(calling_convention_t);
        cconv->parameters       = params;
        cconv->param_stack_size = stack_offset;
+       cconv->n_param_regs     = n_param_regs_used;
        cconv->results          = results;
        cconv->omit_fp          = omit_fp;
 
index bbe33f3..365e8ab 100644 (file)
 #include "../be_types.h"
 #include "gen_sparc_regalloc_if.h"
 
-static const arch_register_t *const caller_saves[] = {
-       &sparc_registers[REG_G1],
-       &sparc_registers[REG_G2],
-       &sparc_registers[REG_G3],
-       &sparc_registers[REG_G4],
-       &sparc_registers[REG_O0],
-       &sparc_registers[REG_O1],
-       &sparc_registers[REG_O2],
-       &sparc_registers[REG_O3],
-       &sparc_registers[REG_O4],
-       &sparc_registers[REG_O5],
-
-       &sparc_registers[REG_F0],
-       &sparc_registers[REG_F1],
-       &sparc_registers[REG_F2],
-       &sparc_registers[REG_F3],
-       &sparc_registers[REG_F4],
-       &sparc_registers[REG_F5],
-       &sparc_registers[REG_F6],
-       &sparc_registers[REG_F7],
-       &sparc_registers[REG_F8],
-       &sparc_registers[REG_F9],
-       &sparc_registers[REG_F10],
-       &sparc_registers[REG_F11],
-       &sparc_registers[REG_F12],
-       &sparc_registers[REG_F13],
-       &sparc_registers[REG_F14],
-       &sparc_registers[REG_F15],
-       &sparc_registers[REG_F16],
-       &sparc_registers[REG_F17],
-       &sparc_registers[REG_F18],
-       &sparc_registers[REG_F19],
-       &sparc_registers[REG_F20],
-       &sparc_registers[REG_F21],
-       &sparc_registers[REG_F22],
-       &sparc_registers[REG_F23],
-       &sparc_registers[REG_F24],
-       &sparc_registers[REG_F25],
-       &sparc_registers[REG_F26],
-       &sparc_registers[REG_F27],
-       &sparc_registers[REG_F28],
-       &sparc_registers[REG_F29],
-       &sparc_registers[REG_F30],
-       &sparc_registers[REG_F31],
-};
-
-static const arch_register_t *const omit_fp_callee_saves[] = {
-       &sparc_registers[REG_L0],
-       &sparc_registers[REG_L1],
-       &sparc_registers[REG_L2],
-       &sparc_registers[REG_L3],
-       &sparc_registers[REG_L4],
-       &sparc_registers[REG_L5],
-       &sparc_registers[REG_L6],
-       &sparc_registers[REG_L7],
-       &sparc_registers[REG_I0],
-       &sparc_registers[REG_I1],
-       &sparc_registers[REG_I2],
-       &sparc_registers[REG_I3],
-       &sparc_registers[REG_I4],
-       &sparc_registers[REG_I5],
-};
-
-static const arch_register_t* const param_regs[] = {
-       &sparc_registers[REG_I0],
-       &sparc_registers[REG_I1],
-       &sparc_registers[REG_I2],
-       &sparc_registers[REG_I3],
-       &sparc_registers[REG_I4],
-       &sparc_registers[REG_I5],
-};
-
-static const arch_register_t* const float_result_regs[] = {
-       &sparc_registers[REG_F0],
-       &sparc_registers[REG_F1],
-       &sparc_registers[REG_F2],
-       &sparc_registers[REG_F3],
-};
-
 /** information about a single parameter or result */
 typedef struct reg_or_stackslot_t
 {
@@ -117,7 +38,7 @@ typedef struct reg_or_stackslot_t
        const arch_register_t *reg1;   /**< if != NULL, the second register used. */
        ir_type               *type;   /**< indicates that an entity of the specific
                                                                            type is needed */
-       int                    offset; /**< if transmitted via stack, the offset for
+       unsigned               offset; /**< if transmitted via stack, the offset for
                                            this parameter. */
        ir_entity             *entity; /**< entity in frame type */
 } reg_or_stackslot_t;
@@ -128,7 +49,9 @@ typedef struct calling_convention_t
        bool                omit_fp;          /**< do not use frame pointer (and no
                                                   save/restore) */
        reg_or_stackslot_t *parameters;       /**< parameter info. */
-       int                 param_stack_size; /**< stack size for parameters */
+       unsigned            param_stack_size; /**< stack size for parameters */
+       unsigned            n_param_regs;     /**< number of values passed in a
+                                                  register */
        reg_or_stackslot_t *results;          /**< result info. */
 } calling_convention_t;
 
index d9734a6..9f78eaf 100644 (file)
@@ -845,78 +845,17 @@ static void emit_sparc_Ba(const ir_node *node)
        be_emit_finish_line_gas(node);
 }
 
-static void emit_jump_table(const ir_node *node)
+static void emit_sparc_SwitchJmp(const ir_node *node)
 {
        const sparc_switch_jmp_attr_t *attr = get_sparc_switch_jmp_attr_const(node);
-       long             switch_max    = LONG_MIN;
-       long             default_pn    = attr->default_proj_num;
-       ir_entity       *entity        = attr->jump_table;
-       ir_node         *default_block = NULL;
-       unsigned long    length;
-       const ir_edge_t *edge;
-       unsigned         i;
-       ir_node        **table;
-
-       /* go over all proj's and collect them */
-       foreach_out_edge(node, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               long     pn   = get_Proj_proj(proj);
-
-               /* check for default proj */
-               if (pn == default_pn) {
-                       assert(default_block == NULL); /* more than 1 default_pn? */
-                       default_block = get_jump_target(proj);
-               } else {
-                       switch_max = pn > switch_max ? pn : switch_max;
-               }
-       }
-       assert(switch_max > LONG_MIN);
-
-       length = (unsigned long) switch_max + 1;
-       /* the 16000 isn't a real limit of the architecture. But should protect us
-        * from seamingly endless compiler runs */
-       if (length > 16000) {
-               /* switch lowerer should have broken this monster to pieces... */
-               panic("too large switch encountered");
-       }
-
-       table = XMALLOCNZ(ir_node*, length);
-       foreach_out_edge(node, edge) {
-               ir_node *proj = get_edge_src_irn(edge);
-               long     pn   = get_Proj_proj(proj);
-               if (pn == default_pn)
-                       continue;
-
-               table[pn] = get_jump_target(proj);
-       }
-
-       /* emit table */
-       be_gas_emit_switch_section(GAS_SECTION_RODATA);
-       be_emit_cstring("\t.align 4\n");
-       be_gas_emit_entity(entity);
-       be_emit_cstring(":\n");
-       for (i = 0; i < length; ++i) {
-               ir_node *block = table[i];
-               if (block == NULL)
-                       block = default_block;
-               be_emit_cstring("\t.long ");
-               be_gas_emit_block_name(block);
-               be_emit_char('\n');
-               be_emit_write_line();
-       }
-       be_gas_emit_switch_section(GAS_SECTION_TEXT);
-
-       xfree(table);
-}
 
-static void emit_sparc_SwitchJmp(const ir_node *node)
-{
        be_emit_cstring("\tjmp ");
        sparc_emit_source_register(node, 0);
        be_emit_finish_line_gas(node);
        fill_delay_slot();
 
-       emit_jump_table(node);
+       emit_jump_table(node, attr->default_proj_num, attr->jump_table,
+                       get_jump_target);
 }
 
 static void emit_fmov(const ir_node *node, const arch_register_t *src_reg,
@@ -931,11 +870,11 @@ static void emit_fmov(const ir_node *node, const arch_register_t *src_reg,
 
 static const arch_register_t *get_next_fp_reg(const arch_register_t *reg)
 {
-       unsigned index = reg->global_index;
-       assert(reg == &sparc_registers[index]);
-       index++;
-       assert(index - REG_F0 < N_sparc_fp_REGS);
-       return &sparc_registers[index];
+       unsigned idx = reg->global_index;
+       assert(reg == &sparc_registers[idx]);
+       idx++;
+       assert(idx - REG_F0 < N_sparc_fp_REGS);
+       return &sparc_registers[idx];
 }
 
 static void emit_be_Copy(const ir_node *node)
index 6a58960..a5ef74d 100644 (file)
@@ -82,7 +82,7 @@ static bool has_fp_conv_attr(const ir_node *node)
  */
 static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
 {
-       const sparc_attr_t *attr;
+       const sparc_attr_t *sparc_attr;
 
        switch (reason) {
        case dump_node_opcode_txt:
@@ -97,12 +97,13 @@ static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason)
                        break;
 
                arch_dump_reqs_and_registers(F, n);
-               attr = get_sparc_attr_const(n);
-               if (attr->immediate_value_entity) {
+               sparc_attr = get_sparc_attr_const(n);
+               if (sparc_attr->immediate_value_entity) {
                        ir_fprintf(F, "entity: %+F (offset %d)\n",
-                                  attr->immediate_value_entity, attr->immediate_value);
+                                  sparc_attr->immediate_value_entity,
+                                  sparc_attr->immediate_value);
                } else {
-                       ir_fprintf(F, "immediate value: %d\n", attr->immediate_value);
+                       ir_fprintf(F, "immediate value: %d\n", sparc_attr->immediate_value);
                }
                if (sparc_has_load_store_attr(n)) {
                        const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(n);
@@ -371,7 +372,7 @@ static int cmp_attr_sparc_fp_conv(const ir_node *a, const ir_node *b)
                return 1;
 
        return attr_a->src_mode != attr_b->src_mode
-           || attr_a->dest_mode != attr_b->dest_mode;;
+           || attr_a->dest_mode != attr_b->dest_mode;
 }
 
 /* Include the generated constructor functions */
index 16fa11e..7894cf1 100644 (file)
@@ -64,7 +64,7 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 static beabi_helper_env_t    *abihelper;
 static const arch_register_t *sp_reg = &sparc_registers[REG_SP];
 static const arch_register_t *fp_reg = &sparc_registers[REG_FRAME_POINTER];
-static calling_convention_t  *cconv  = NULL;
+static calling_convention_t  *current_cconv = NULL;
 static ir_mode               *mode_gp;
 static ir_mode               *mode_flags;
 static ir_mode               *mode_fp;
@@ -72,6 +72,69 @@ static ir_mode               *mode_fp2;
 //static ir_mode               *mode_fp4;
 static pmap                  *node_to_stack;
 
+static const arch_register_t *const caller_saves[] = {
+       &sparc_registers[REG_G1],
+       &sparc_registers[REG_G2],
+       &sparc_registers[REG_G3],
+       &sparc_registers[REG_G4],
+       &sparc_registers[REG_O0],
+       &sparc_registers[REG_O1],
+       &sparc_registers[REG_O2],
+       &sparc_registers[REG_O3],
+       &sparc_registers[REG_O4],
+       &sparc_registers[REG_O5],
+
+       &sparc_registers[REG_F0],
+       &sparc_registers[REG_F1],
+       &sparc_registers[REG_F2],
+       &sparc_registers[REG_F3],
+       &sparc_registers[REG_F4],
+       &sparc_registers[REG_F5],
+       &sparc_registers[REG_F6],
+       &sparc_registers[REG_F7],
+       &sparc_registers[REG_F8],
+       &sparc_registers[REG_F9],
+       &sparc_registers[REG_F10],
+       &sparc_registers[REG_F11],
+       &sparc_registers[REG_F12],
+       &sparc_registers[REG_F13],
+       &sparc_registers[REG_F14],
+       &sparc_registers[REG_F15],
+       &sparc_registers[REG_F16],
+       &sparc_registers[REG_F17],
+       &sparc_registers[REG_F18],
+       &sparc_registers[REG_F19],
+       &sparc_registers[REG_F20],
+       &sparc_registers[REG_F21],
+       &sparc_registers[REG_F22],
+       &sparc_registers[REG_F23],
+       &sparc_registers[REG_F24],
+       &sparc_registers[REG_F25],
+       &sparc_registers[REG_F26],
+       &sparc_registers[REG_F27],
+       &sparc_registers[REG_F28],
+       &sparc_registers[REG_F29],
+       &sparc_registers[REG_F30],
+       &sparc_registers[REG_F31],
+};
+
+static const arch_register_t *const omit_fp_callee_saves[] = {
+       &sparc_registers[REG_L0],
+       &sparc_registers[REG_L1],
+       &sparc_registers[REG_L2],
+       &sparc_registers[REG_L3],
+       &sparc_registers[REG_L4],
+       &sparc_registers[REG_L5],
+       &sparc_registers[REG_L6],
+       &sparc_registers[REG_L7],
+       &sparc_registers[REG_I0],
+       &sparc_registers[REG_I1],
+       &sparc_registers[REG_I2],
+       &sparc_registers[REG_I3],
+       &sparc_registers[REG_I4],
+       &sparc_registers[REG_I5],
+};
+
 static inline bool mode_needs_gp_reg(ir_mode *mode)
 {
        if (mode_is_int(mode) || mode_is_reference(mode)) {
@@ -251,8 +314,8 @@ static ir_node *gen_helper_binop_args(ir_node *node,
        assert(get_mode_size_bits(mode2) <= 32);
 
        if (is_imm_encodeable(op2)) {
-               ir_node *new_op1   = be_transform_node(op1);
                int32_t  immediate = get_tarval_long(get_Const_tarval(op2));
+               new_op1 = be_transform_node(op1);
                if (! (flags & MATCH_MODE_NEUTRAL) && needs_extension(mode1)) {
                        new_op1 = gen_extension(dbgi, block, new_op1, mode1);
                }
@@ -362,8 +425,8 @@ static ir_node *gen_helper_binopx(ir_node *node, match_flags_t match_flags,
        assert(match_flags & MATCH_MODE_NEUTRAL);
 
        if (is_imm_encodeable(op2)) {
-               ir_node *new_op1   = be_transform_node(op1);
                int32_t  immediate = get_tarval_long(get_Const_tarval(op2));
+               new_op1 = be_transform_node(op1);
                return new_binopx_imm(dbgi, block, new_op1, new_flags, NULL, immediate);
        }
        new_op2 = be_transform_node(op2);
@@ -994,7 +1057,7 @@ static ir_node *gen_SwitchJmp(ir_node *node)
        long             default_pn   = get_Cond_default_proj(node);
        ir_entity       *entity;
        ir_node         *table_address;
-       ir_node         *index;
+       ir_node         *idx;
        ir_node         *load;
        ir_node         *address;
 
@@ -1005,17 +1068,12 @@ static ir_node *gen_SwitchJmp(ir_node *node)
        set_entity_visibility(entity, ir_visibility_private);
        add_entity_linkage(entity, IR_LINKAGE_CONSTANT);
 
-       /* TODO: this code does not construct code to check for access
-        * out-of bounds of the jumptable yet. I think we should put this stuff
-        * into the switch_lowering phase to get some additional optimisations
-        * done. */
-
        /* construct base address */
        table_address = make_address(dbgi, block, entity, 0);
        /* scale index */
-       index = new_bd_sparc_Sll_imm(dbgi, block, new_selector, NULL, 2);
+       idx = new_bd_sparc_Sll_imm(dbgi, block, new_selector, NULL, 2);
        /* load from jumptable */
-       load = new_bd_sparc_Ld_reg(dbgi, block, table_address, index,
+       load = new_bd_sparc_Ld_reg(dbgi, block, table_address, idx,
                                   get_irg_no_mem(current_ir_graph),
                                   mode_gp);
        address = new_r_Proj(load, mode_gp, pn_sparc_Ld_res);
@@ -1216,7 +1274,7 @@ static ir_node *gen_Conv(ir_node *node)
        ir_node  *op       = get_Conv_op(node);
        ir_mode  *src_mode = get_irn_mode(op);
        ir_mode  *dst_mode = get_irn_mode(node);
-       dbg_info *dbg      = get_irn_dbg_info(node);
+       dbg_info *dbgi     = get_irn_dbg_info(node);
        ir_node  *new_op;
 
        int src_bits = get_mode_size_bits(src_mode);
@@ -1235,21 +1293,21 @@ static ir_node *gen_Conv(ir_node *node)
                if (mode_is_float(src_mode)) {
                        if (mode_is_float(dst_mode)) {
                                /* float -> float conv */
-                               return create_fftof(dbg, block, new_op, src_mode, dst_mode);
+                               return create_fftof(dbgi, block, new_op, src_mode, dst_mode);
                        } else {
                                /* float -> int conv */
                                if (!mode_is_signed(dst_mode))
                                        panic("float to unsigned not implemented yet");
-                               return create_ftoi(dbg, block, new_op, src_mode);
+                               return create_ftoi(dbgi, block, new_op, src_mode);
                        }
                } else {
                        /* int -> float conv */
                        if (src_bits < 32) {
-                               new_op = gen_extension(dbg, block, new_op, src_mode);
+                               new_op = gen_extension(dbgi, block, new_op, src_mode);
                        } else if (src_bits == 32 && !mode_is_signed(src_mode)) {
                                panic("unsigned to float not lowered!");
                        }
-                       return create_itof(dbg, block, new_op, dst_mode);
+                       return create_itof(dbgi, block, new_op, dst_mode);
                }
        } else if (src_mode == mode_b) {
                panic("ConvB not lowered %+F", node);
@@ -1275,9 +1333,9 @@ static ir_node *gen_Conv(ir_node *node)
                }
 
                if (mode_is_signed(min_mode)) {
-                       return gen_sign_extension(dbg, block, new_op, min_bits);
+                       return gen_sign_extension(dbgi, block, new_op, min_bits);
                } else {
-                       return gen_zero_extension(dbg, block, new_op, min_bits);
+                       return gen_zero_extension(dbgi, block, new_op, min_bits);
                }
        }
 }
@@ -1305,7 +1363,7 @@ static ir_type *sparc_get_between_type(void)
        static ir_type *between_type  = NULL;
        static ir_type *between_type0 = NULL;
 
-       if (cconv->omit_fp) {
+       if (current_cconv->omit_fp) {
                if (between_type0 == NULL) {
                        between_type0
                                = new_type_class(new_id_from_str("sparc_between_type"));
@@ -1332,13 +1390,13 @@ static void create_stacklayout(ir_graph *irg)
        int                n_params;
 
        /* calling conventions must be decided by now */
-       assert(cconv != NULL);
+       assert(current_cconv != NULL);
 
        /* construct argument type */
        arg_type = new_type_struct(id_mangle_u(get_entity_ident(entity), new_id_from_chars("arg_type", 8)));
        n_params = get_method_n_params(function_type);
        for (p = 0; p < n_params; ++p) {
-               reg_or_stackslot_t *param = &cconv->parameters[p];
+               reg_or_stackslot_t *param = &current_cconv->parameters[p];
                char                buf[128];
                ident              *id;
 
@@ -1358,7 +1416,7 @@ static void create_stacklayout(ir_graph *irg)
        layout->arg_type       = arg_type;
        layout->initial_offset = 0;
        layout->initial_bias   = 0;
-       layout->sp_relative    = cconv->omit_fp;
+       layout->sp_relative    = current_cconv->omit_fp;
 
        assert(N_FRAME_TYPES == 3);
        layout->order[0] = layout->frame_type;
@@ -1387,7 +1445,7 @@ static ir_node *gen_Start(ir_node *node)
                arch_register_req_type_ignore);
        /* function parameters in registers */
        for (i = 0; i < get_method_n_params(function_type); ++i) {
-               const reg_or_stackslot_t *param = &cconv->parameters[i];
+               const reg_or_stackslot_t *param = &current_cconv->parameters[i];
                if (param->reg0 != NULL) {
                        be_prolog_add_reg(abihelper, param->reg0,
                                          arch_register_req_type_none);
@@ -1399,7 +1457,7 @@ static ir_node *gen_Start(ir_node *node)
        }
        /* we need the values of the callee saves (Note: non omit-fp mode has no
         * callee saves) */
-       if (cconv->omit_fp) {
+       if (current_cconv->omit_fp) {
                size_t n_callee_saves = ARRAY_SIZE(omit_fp_callee_saves);
                size_t c;
                for (c = 0; c < n_callee_saves; ++c) {
@@ -1463,16 +1521,15 @@ static ir_node *gen_Return(ir_node *node)
        for (i = 0; i < n_res; ++i) {
                ir_node                  *res_value     = get_Return_res(node, i);
                ir_node                  *new_res_value = be_transform_node(res_value);
-               const reg_or_stackslot_t *slot          = &cconv->results[i];
+               const reg_or_stackslot_t *slot          = &current_cconv->results[i];
                const arch_register_t    *reg           = slot->reg0;
                assert(slot->reg1 == NULL);
                be_epilog_add_reg(abihelper, reg, arch_register_req_type_none,
                                  new_res_value);
        }
        /* callee saves */
-       if (cconv->omit_fp) {
+       if (current_cconv->omit_fp) {
                size_t n_callee_saves = ARRAY_SIZE(omit_fp_callee_saves);
-               size_t i;
                for (i = 0; i < n_callee_saves; ++i) {
                        const arch_register_t *reg   = omit_fp_callee_saves[i];
                        ir_node               *value
@@ -1560,16 +1617,16 @@ static ir_node *gen_Call(ir_node *node)
        dbg_info        *dbgi         = get_irn_dbg_info(node);
        ir_type         *type         = get_Call_type(node);
        size_t           n_params     = get_Call_n_params(node);
-       size_t           n_param_regs = sizeof(param_regs)/sizeof(param_regs[0]);
        /* max inputs: memory, callee, register arguments */
-       int              max_inputs   = 2 + n_param_regs;
-       ir_node        **in           = ALLOCAN(ir_node*, max_inputs);
        ir_node        **sync_ins     = ALLOCAN(ir_node*, n_params);
        struct obstack  *obst         = be_get_be_obst(irg);
-       const arch_register_req_t **in_req
-               = OALLOCNZ(obst, const arch_register_req_t*, max_inputs);
        calling_convention_t *cconv
                = sparc_decide_calling_convention(type, NULL);
+       size_t           n_param_regs = cconv->n_param_regs;
+       unsigned         max_inputs   = 2 + n_param_regs;
+       ir_node        **in           = ALLOCAN(ir_node*, max_inputs);
+       const arch_register_req_t **in_req
+               = OALLOCNZ(obst, const arch_register_req_t*, max_inputs);
        int              in_arity     = 0;
        int              sync_arity   = 0;
        int              n_caller_saves
@@ -1654,7 +1711,7 @@ static ir_node *gen_Call(ir_node *node)
                set_irn_pinned(str, op_pin_state_floats);
                sync_ins[sync_arity++] = str;
        }
-       assert(in_arity <= max_inputs);
+       assert(in_arity <= (int)max_inputs);
 
        /* construct memory input */
        if (sync_arity == 0) {
@@ -1904,7 +1961,7 @@ static ir_node *gen_Proj_Div(ir_node *node)
 
 static ir_node *get_frame_base(void)
 {
-       const arch_register_t *reg = cconv->omit_fp ? sp_reg : fp_reg;
+       const arch_register_t *reg = current_cconv->omit_fp ? sp_reg : fp_reg;
        return be_prolog_get_reg_value(abihelper, reg);
 }
 
@@ -1943,7 +2000,7 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
        /* Proj->Proj->Start must be a method argument */
        assert(get_Proj_proj(get_Proj_pred(node)) == pn_Start_T_args);
 
-       param = &cconv->parameters[pn];
+       param = &current_cconv->parameters[pn];
 
        if (param->reg0 != NULL) {
                /* argument transmitted in register */
@@ -2167,13 +2224,14 @@ void sparc_transform_graph(ir_graph *irg)
 
        abihelper = be_abihelper_prepare(irg);
        be_collect_stacknodes(abihelper);
-       cconv = sparc_decide_calling_convention(get_entity_type(entity), irg);
+       current_cconv
+               = sparc_decide_calling_convention(get_entity_type(entity), irg);
        create_stacklayout(irg);
 
        be_transform_graph(irg, NULL);
 
        be_abihelper_finish(abihelper);
-       sparc_free_calling_convention(cconv);
+       sparc_free_calling_convention(current_cconv);
 
        frame_type = get_irg_frame_type(irg);
        if (get_type_state(frame_type) == layout_undefined)
index f11e73c..9ec076f 100644 (file)
@@ -62,13 +62,7 @@ typedef struct timeval ir_timer_val_t;
 
 #include <stddef.h>
 
-static inline void _time_get(ir_timer_val_t *val);
 static inline void _time_reset(ir_timer_val_t *val);
-static inline unsigned long _time_to_msec(const ir_timer_val_t *val);
-static inline ir_timer_val_t *_time_add(ir_timer_val_t *res,
-               const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
-static inline ir_timer_val_t *_time_sub(ir_timer_val_t *res,
-               const ir_timer_val_t *lhs, const ir_timer_val_t *rhs);
 
 /**
  * A timer.
index 4b1ab62..89d541b 100644 (file)
@@ -829,7 +829,7 @@ static ir_node *replace_div_by_mulh(ir_node *div, ir_tarval *tv)
        ir_node *block = get_irn_n(div, -1);
        ir_mode *mode  = get_irn_mode(n);
        int bits       = get_mode_size_bits(mode);
-       ir_node *q, *t, *c;
+       ir_node *q;
 
        /* Beware: do not transform bad code */
        if (is_Bad(n) || is_Bad(block))
@@ -840,7 +840,8 @@ static ir_node *replace_div_by_mulh(ir_node *div, ir_tarval *tv)
                struct ms mag = magic(tv);
 
                /* generate the Mulh instruction */
-               c = new_r_Const(irg, mag.M);
+               ir_node *c = new_r_Const(irg, mag.M);
+               ir_node *t;
                q = new_rd_Mulh(dbg, block, n, c, mode);
 
                /* do we need an Add or Sub */
@@ -862,17 +863,16 @@ static ir_node *replace_div_by_mulh(ir_node *div, ir_tarval *tv)
                q = new_rd_Add(dbg, block, q, t, mode);
        } else {
                struct mu mag = magicu(tv);
-               ir_node *c;
                ir_graph *irg = get_irn_irg(div);
 
                /* generate the Mulh instruction */
-               c = new_r_Const(irg, mag.M);
+               ir_node *c = new_r_Const(irg, mag.M);
                q = new_rd_Mulh(dbg, block, n, c, mode);
 
                if (mag.need_add) {
                        if (mag.s > 0) {
                                /* use the GM scheme */
-                               t = new_rd_Sub(dbg, block, n, q, mode);
+                               ir_node *t = new_rd_Sub(dbg, block, n, q, mode);
 
                                c = new_r_Const(irg, get_mode_one(mode_Iu));
                                t = new_rd_Shr(dbg, block, t, c, mode);
@@ -974,8 +974,6 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn)
                                res    = new_rd_Shrs(dbg, block, curr, k_node, mode);
 
                                if (n_flag) { /* negate the result */
-                                       ir_node *k_node;
-
                                        k_node = new_r_Const(irg, get_mode_null(mode));
                                        res = new_rd_Sub(dbg, block, k_node, res, mode);
                                }
index d878c1d..9394e98 100644 (file)
@@ -87,8 +87,8 @@ ir_node *new_rd_ASM(dbg_info *db, ir_node *block, int arity, ir_node *in[],
        memcpy(res->attr.assem.output_constraints, outputs, sizeof(outputs[0]) * n_outs);
        memcpy(res->attr.assem.clobbers, clobber, sizeof(clobber[0]) * n_clobber);
 
-       res = optimize_node(res);
        irn_verify_irg(res, irg);
+       res = optimize_node(res);
        return res;
 }
 
@@ -106,8 +106,8 @@ ir_node *new_rd_SymConst(dbg_info *db, ir_graph *irg, ir_mode *mode,
        res->attr.symc.kind = symkind;
        res->attr.symc.sym  = value;
 
-       res = optimize_node(res);
        irn_verify_irg(res, irg);
+       res = optimize_node(res);
        return res;
 }
 
@@ -295,7 +295,6 @@ static ir_node *get_r_value_internal(ir_node *block, int pos, ir_mode *mode)
                int arity = get_irn_arity(block);
                /* no predecessors: use unknown value */
                if (arity == 0 && block == get_irg_start_block(get_irn_irg(block))) {
-                       ir_graph *irg = get_irn_irg(block);
                        if (default_initialize_local_variable != NULL) {
                                ir_node *rem = get_r_cur_block(irg);
                                set_r_cur_block(irg, block);
@@ -377,8 +376,8 @@ void mature_immBlock(ir_node *block)
           nodes refer to the unoptimized node.
           We can call optimize_in_place_2(), as global cse has no effect on blocks.
         */
-       block = optimize_in_place_2(block);
        irn_verify_irg(block, irg);
+       block = optimize_in_place_2(block);
 }
 
 ir_node *new_d_Const_long(dbg_info *db, ir_mode *mode, long value)
@@ -433,8 +432,8 @@ ir_node *new_rd_strictConv(dbg_info *dbgi, ir_node *block, ir_node * irn_op, ir_
 
        res = new_ir_node(dbgi, irg, block, op_Conv, mode, 1, in);
        res->attr.conv.strict = 1;
-       res = optimize_node(res);
        irn_verify_irg(res, irg);
+       res = optimize_node(res);
        return res;
 }
 
@@ -470,8 +469,8 @@ ir_node *new_rd_DivRL(dbg_info *dbgi, ir_node *block, ir_node * irn_mem, ir_node
        res->attr.div.resmode = resmode;
        res->attr.div.no_remainder = 1;
        res->attr.div.exc.pin_state = pin_state;
-       res = optimize_node(res);
        irn_verify_irg(res, irg);
+       res = optimize_node(res);
        return res;
 }
 
index b1377a8..b2ab4c6 100644 (file)
@@ -1004,7 +1004,7 @@ static void dump_node_nodeattr(FILE *F, ir_node *n)
                break;
 
        default:
-               ;
+               break;
        } /* end switch */
 }
 
@@ -2181,12 +2181,12 @@ static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
         * from irg.
         */
        for (i = get_irp_n_irgs(); i > 0;) {
-               ir_graph *irg = get_irp_irg(--i);
-               ir_node **arr = (ir_node**)ird_get_irg_link(irg);
+               ir_graph *other_irg = get_irp_irg(--i);
+               ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
                if (arr == NULL)
                        continue;
 
-               dump_graph_from_list(out, irg);
+               dump_graph_from_list(out, other_irg);
                DEL_ARR_F(arr);
        }
 }
@@ -2255,20 +2255,20 @@ static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
        print_dbg_info(F, get_entity_dbg_info(ent));
 
        for (i = get_irp_n_irgs(); i > 0;) {
-               ir_graph *irg     = get_irp_irg(--i);
-               list_tuple *lists = (list_tuple*)ird_get_irg_link(irg);
+               ir_graph   *other_irg = get_irp_irg(--i);
+               list_tuple *lists     = (list_tuple*)ird_get_irg_link(other_irg);
 
                if (lists) {
                        /* dump the extended blocks first */
                        if (ARR_LEN(lists->extbb_list)) {
-                               ird_set_irg_link(irg, lists->extbb_list);
-                               dump_extblock_graph(F, irg);
+                               ird_set_irg_link(other_irg, lists->extbb_list);
+                               dump_extblock_graph(F, other_irg);
                        }
 
                        /* we may have blocks without extended blocks, bad for instance */
                        if (ARR_LEN(lists->blk_list)) {
-                               ird_set_irg_link(irg, lists->blk_list);
-                               dump_block_graph(F, irg);
+                               ird_set_irg_link(other_irg, lists->blk_list);
+                               dump_block_graph(F, other_irg);
                        }
 
                        DEL_ARR_F(lists->extbb_list);
@@ -2330,7 +2330,6 @@ static void dump_block_to_cfg(ir_node *block, void *env)
 {
        FILE *F = (FILE*)env;
        int i;
-       ir_node *pred;
 
        if (is_Bad(block) && get_irn_mode(block) == mode_X) {
                dump_node(F, block);
@@ -2376,7 +2375,7 @@ static void dump_block_to_cfg(ir_node *block, void *env)
                /* Dump dominator/postdominator edge */
                if (ir_get_dump_flags() & ir_dump_flag_dominance) {
                        if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
-                               pred = get_Block_idom(block);
+                               ir_node *pred = get_Block_idom(block);
                                fprintf(F, "edge: { sourcename: \"");
                                PRINT_NODEID(block);
                                fprintf(F, "\" targetname: \"");
@@ -2384,7 +2383,7 @@ static void dump_block_to_cfg(ir_node *block, void *env)
                                fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
                        }
                        if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
-                               pred = get_Block_ipostdom(block);
+                               ir_node *pred = get_Block_ipostdom(block);
                                fprintf(F, "edge: { sourcename: \"");
                                PRINT_NODEID(block);
                                fprintf(F, "\" targetname: \"");
index f8918b8..d567281 100644 (file)
@@ -61,7 +61,6 @@ ir_dump_verbosity_t ir_get_dump_verbosity(void)
 /* Write the irnode and all its attributes to the file passed. */
 void dump_irnode_to_file(FILE *F, ir_node *n)
 {
-       int      i;
        char     comma;
        ir_graph *irg;
        vrp_attr *vrp_info;
@@ -73,7 +72,7 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
        if (ir_get_dump_flags() & ir_dump_flag_analysed_types)
                fprintf (F, "  addr:    %p\n", (void *)n);
        fprintf (F, "  mode:    %s\n", get_mode_name(get_irn_mode(n)));
-       fprintf (F, "  visited: %ld\n", get_irn_visited(n));
+       fprintf (F, "  visited: %lu\n", get_irn_visited(n));
        irg = get_irn_irg(n);
        if (irg != get_const_code_irg())
                fprintf (F, "  irg:     %s\n", get_ent_dump_name(get_irg_entity(irg)));
@@ -93,10 +92,14 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
                dump_node_opcode(F, get_irn_n(n, -1));
                fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, -1)));
        }
-       for ( i = 0; i < get_irn_arity(n); ++i) {
-               fprintf(F, "     %d: %s ", i, is_backedge(n, i) ? "be" : "  ");
-               dump_node_opcode(F, get_irn_n(n, i));
-               fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
+
+       {
+               int i;
+               for (i = 0; i < get_irn_arity(n); ++i) {
+                       fprintf(F, "     %d: %s ", i, is_backedge(n, i) ? "be" : "  ");
+                       dump_node_opcode(F, get_irn_n(n, i));
+                       fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
+               }
        }
 
        fprintf(F, "  Private Attributes:\n");
@@ -110,8 +113,8 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
        }
 
        /* This is not nice, output it as a marker in the predecessor list. */
-       if (is_Block(n)             ||
-           get_irn_op(n) == op_Phi) {
+       if (is_Block(n) || get_irn_op(n) == op_Phi) {
+           int i;
                fprintf(F, "  backedges:");
                comma = ' ';
                for (i = 0; i < get_irn_arity(n); i++)
@@ -133,17 +136,17 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
        case iro_Block: {
                if (has_Block_entity(n))
                        fprintf(F, "  Label: %lu\n", get_entity_label(get_Block_entity(n)));
-               fprintf(F, "  block visited: %ld\n", get_Block_block_visited(n));
+               fprintf(F, "  block visited: %lu\n", get_Block_block_visited(n));
                fprintf(F, "  block marked: %u\n", get_Block_mark(n));
                if (get_irg_dom_state(get_irn_irg(n)) == dom_consistent) {
                        fprintf(F, "  dom depth %d\n", get_Block_dom_depth(n));
-                       fprintf(F, "  domtree pre num %d\n", get_Block_dom_tree_pre_num(n));
-                       fprintf(F, "  max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(n));
+                       fprintf(F, "  domtree pre num %u\n", get_Block_dom_tree_pre_num(n));
+                       fprintf(F, "  max subtree pre num %u\n", get_Block_dom_max_subtree_pre_num(n));
                }
                if (get_irg_postdom_state(get_irn_irg(n)) == dom_consistent) {
                        fprintf(F, "  pdom depth %d\n", get_Block_postdom_depth(n));
-                       fprintf(F, "  pdomtree pre num %d\n", get_Block_pdom_tree_pre_num(n));
-                       fprintf(F, "  max pdomsubtree pre num %d\n", get_Block_pdom_max_subtree_pre_num(n));
+                       fprintf(F, "  pdomtree pre num %u\n", get_Block_pdom_tree_pre_num(n));
+                       fprintf(F, "  max pdomsubtree pre num %u\n", get_Block_pdom_max_subtree_pre_num(n));
                }
 
                fprintf(F, "  Execution frequency statistics:\n");
@@ -274,6 +277,7 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
                fprintf(F, "  assembler text: %s", get_id_str(get_ASM_text(n)));
                l = get_ASM_n_input_constraints(n);
                if (l > 0) {
+                       int i;
                        fprintf(F, "\n  inputs:  ");
                        cons = get_ASM_input_constraints(n);
                        for (i = 0; i < l; ++i)
@@ -281,6 +285,7 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
                }
                l = get_ASM_n_output_constraints(n);
                if (l > 0) {
+                       int i;
                        fprintf(F, "\n  outputs: ");
                        cons = get_ASM_output_constraints(n);
                        for (i = 0; i < l; ++i)
@@ -288,6 +293,7 @@ void dump_irnode_to_file(FILE *F, ir_node *n)
                }
                l = get_ASM_n_clobbers(n);
                if (l > 0) {
+                       int i;
                        fprintf(F, "\n  clobber: ");
                        clobber = get_ASM_clobbers(n);
                        for (i = 0; i < l; ++i)
@@ -592,7 +598,7 @@ static void dump_entity_to_file_prefix(FILE *F, ir_entity *ent, const char *pref
                                size_t j;
                                compound_graph_path *path = get_compound_ent_value_path(ent, i);
                                ir_entity *ent0 = get_compound_graph_path_node(path, 0);
-                               fprintf(F, "\n%s    %3d:%u ", prefix, get_entity_offset(ent0), get_entity_offset_bits_remainder(ent0));
+                               fprintf(F, "\n%s    %3d:%d ", prefix, get_entity_offset(ent0), get_entity_offset_bits_remainder(ent0));
                                if (get_type_state(type) == layout_fixed)
                                        fprintf(F, "(%3u:%u) ",   get_compound_ent_value_offset_bytes(ent, i), get_compound_ent_value_offset_bit_remainder(ent, i));
                                fprintf(F, "%s", get_entity_name(ent));
@@ -725,7 +731,7 @@ void dump_type_to_file(FILE *F, ir_type *tp)
 
        case tpo_array:
                if (verbosity & dump_verbosity_typeattrs) {
-                       size_t i, n_dim;
+                       size_t n_dim;
                        ir_type *elem_tp = get_array_element_type(tp);
 
                        fprintf(F, "\n  array ");
index 56c9f7e..799dada 100644 (file)
@@ -313,7 +313,6 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt,
        irg_edge_info_t *info;
        ir_edgeset_t    *edges;
        ir_edge_t        templ;
-       ir_edge_t       *edge;
 
        assert(edges_activated_kind(irg, kind));
 
@@ -335,7 +334,7 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt,
         */
        if (tgt == NULL) {
                /* search the edge in the set. */
-               edge = ir_edgeset_find(edges, &templ);
+               ir_edge_t *edge = ir_edgeset_find(edges, &templ);
 
                /* mark the edge invalid if it was found */
                if (edge) {
@@ -365,7 +364,7 @@ void edges_notify_edge_kind(ir_node *src, int pos, ir_node *tgt,
 
                /* If the old target is not null, the edge is moved. */
                if (old_tgt) {
-                       edge = ir_edgeset_find(edges, &templ);
+                       ir_edge_t *edge = ir_edgeset_find(edges, &templ);
                        assert(edge && "edge to redirect not found!");
                        assert(! edge->invalid && "Invalid edge encountered");
 
@@ -441,11 +440,11 @@ void edges_notify_edge(ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt,
                        const ir_edge_t *next;
                        foreach_out_edge_kind_safe(old_tgt, edge, next, EDGE_KIND_BLOCK) {
                                ir_node *succ       = get_edge_src_irn(edge);
-                               int      pos        = get_edge_src_pos(edge);
-                               ir_node *block_pred = get_Block_cfgpred(succ, pos);
+                               int      succ_pos   = get_edge_src_pos(edge);
+                               ir_node *block_pred = get_Block_cfgpred(succ, succ_pos);
                                if (block_pred != src)
                                        continue;
-                               edges_notify_edge_kind(succ, pos, tgt, old_tgt,
+                               edges_notify_edge_kind(succ, succ_pos, tgt, old_tgt,
                                                       EDGE_KIND_BLOCK, irg);
                        }
                }
index e5b6bcf..490b77e 100644 (file)
@@ -52,7 +52,8 @@ void unregister_hook(hook_type_t hook, hook_entry_t *entry)
     return;
   }
 
-  for (p = hooks[hook]; p && p->next != entry; p = p->next);
+  for (p = hooks[hook]; p && p->next != entry; p = p->next) {
+  }
 
   if (p) {
     p->next     = entry->next;
index c1b6e9d..ea72867 100644 (file)
@@ -689,7 +689,6 @@ static void export_type_or_ent_post(type_or_ent tore, void *ctx)
 
        default:
                panic("export_type_or_ent_post: Unknown type or entity.");
-               break;
        }
 }
 
@@ -1051,7 +1050,6 @@ static char *read_string(io_env_t *env)
                        default:
                                parse_error(env, "Unknown escape sequence '\\%c'\n", env->c);
                                exit(1);
-                               break;
                        }
                } else {
                        obstack_1grow(&env->obst, env->c);
@@ -1417,14 +1415,14 @@ static void import_type(io_env_t *env)
                type = new_type_method(nparams, nresults);
 
                for (i = 0; i < nparams; i++) {
-                       long     typenr = read_long(env);
-                       ir_type *paramtype = get_type(env, typenr);
+                       long ptypenr = read_long(env);
+                       ir_type *paramtype = get_type(env, ptypenr);
 
                        set_method_param_type(type, i, paramtype);
                }
                for (i = 0; i < nresults; i++) {
-                       long typenr = read_long(env);
-                       ir_type *restype = get_type(env, typenr);
+                       long ptypenr = read_long(env);
+                       ir_type *restype = get_type(env, ptypenr);
 
                        set_method_res_type(type, i, restype);
                }
@@ -1500,23 +1498,23 @@ static void import_entity(io_env_t *env)
 
        skip_ws(env);
        while (!isdigit(env->c)) {
-               char     *str = read_word(env);
+               char     *vstr = read_word(env);
                unsigned  v;
 
                skip_ws(env);
 
-               v = symbol(str, tt_visibility);
+               v = symbol(vstr, tt_visibility);
                if (v != SYMERROR) {
                        visibility = (ir_visibility)v;
                        continue;
                }
-               v = symbol(str, tt_linkage);
+               v = symbol(vstr, tt_linkage);
                if (v != SYMERROR) {
                        linkage |= (ir_linkage)v;
                        continue;
                }
                printf("Parser error, expected visibility or linkage, got '%s'\n",
-                      str);
+                      vstr);
                break;
        }
 
index 09fa052..225f3ed 100644 (file)
@@ -567,7 +567,6 @@ int smaller_mode(const ir_mode *sm, const ir_mode *lm)
                                }
                                return sm_bits <= lm_bits;
                        }
-                       break;
 
                case irms_float_number:
                        /* int to float works if the float is large enough */
index f5aef5f..9f9f0e7 100644 (file)
@@ -352,7 +352,7 @@ static ir_tarval *computed_value_Not(const ir_node *n)
 }  /* computed_value_Not */
 
 /**
- * Tests wether a shift shifts more bits than available in the mode
+ * Tests whether a shift shifts more bits than available in the mode
  */
 static bool is_oversize_shift(const ir_node *n)
 {
@@ -957,7 +957,7 @@ static ir_node *equivalent_node_Sub(ir_node *n)
 
 
 /**
- * Optimize an "self-inverse unary op", ie op(op(n)) = n.
+ * Optimize an "self-inverse unary op", i.e. op(op(n)) = n.
  *
  * @todo
  *   -(-a) == a, but might overflow two times.
@@ -2048,9 +2048,9 @@ static ir_node *transform_node_Add(ir_node *n)
        b_vrp = vrp_get_info(b);
 
        if (a_vrp && b_vrp) {
-               ir_tarval *c = tarval_and(a_vrp->bits_not_set, b_vrp->bits_not_set);
+               ir_tarval *vrp_val = tarval_and(a_vrp->bits_not_set, b_vrp->bits_not_set);
 
-               if (tarval_is_null(c)) {
+               if (tarval_is_null(vrp_val)) {
                        dbg_info *dbgi  = get_irn_dbg_info(n);
                        return new_rd_Or(dbgi, get_nodes_block(n), a, b, mode);
                }
@@ -3099,7 +3099,7 @@ static ir_node *transform_node_bitop_shift(ir_node *n)
                new_shift = new_rd_Shl(dbg_shift, block, new_bitop, shift_right, mode);
        } else if (is_Shr(left)) {
                new_shift = new_rd_Shr(dbg_shift, block, new_bitop, shift_right, mode);
-       } else if (is_Rotl(left)) {
+       } else {
                assert(is_Rotl(left));
                new_shift = new_rd_Rotl(dbg_shift, block, new_bitop, shift_right, mode);
        }
@@ -5147,7 +5147,7 @@ typedef ir_node*(*new_shift_func)(dbg_info *dbgi, ir_node *block,
  * then we can use that to minimize the value of Add(x, const) or
  * Sub(Const, x). In particular this often avoids 1 instruction in some
  * backends for the Shift(x, Sub(Const, y)) case because it can be replaced
- * by Shift(x, Minus(y)) which doesnt't need an explicit Const constructed.
+ * by Shift(x, Minus(y)) which does not need an explicit Const constructed.
  */
 static ir_node *transform_node_shift_modulo(ir_node *n,
                                             new_shift_func new_shift)
@@ -5384,7 +5384,7 @@ static ir_node *transform_node_End(ir_node *n)
                /* no need to keep Bad */
                if (is_Bad(ka))
                        continue;
-               /* dont keep unreachable code */
+               /* do not keep unreachable code */
                block = is_Block(ka) ? ka : get_nodes_block(ka);
                if (is_block_unreachable(block))
                        continue;
@@ -6012,7 +6012,7 @@ static ir_op_ops *firm_set_default_transform_node(ir_opcode code, ir_op_ops *ops
        CASE_PROJ_EX(Load);
        CASE_PROJ_EX(Mod);
        default:
-         /* leave NULL */;
+               break;
        }
 
        return ops;
@@ -6316,10 +6316,23 @@ int identities_cmp(const void *elt, const void *key)
                /* for pinned nodes, the block inputs must be equal */
                if (get_irn_n(a, -1) != get_irn_n(b, -1))
                        return 1;
-       } else if (! get_opt_global_cse()) {
-               /* for block-local CSE both nodes must be in the same Block */
-               if (get_nodes_block(a) != get_nodes_block(b))
-                       return 1;
+       } else {
+               ir_node *block_a = get_nodes_block(a);
+               ir_node *block_b = get_nodes_block(b);
+               if (! get_opt_global_cse()) {
+                       /* for block-local CSE both nodes must be in the same Block */
+                       if (block_a != block_b)
+                               return 1;
+               } else {
+                       /* The optimistic approach would be to do nothing here.
+                        * However doing GCSE optimistically produces a lot of partially dead code which appears
+                        * to be worse in practice than the missed opportunities.
+                        * So we use a very conservative variant here and only CSE if 1 value dominates the
+                        * other. */
+                       if (!block_dominates(block_a, block_b)
+                           && !block_dominates(block_b, block_a))
+                           return 1;
+               }
        }
 
        /* compare a->in[0..ins] with b->in[0..ins] */
index 5b2353c..b3ded8c 100644 (file)
@@ -988,14 +988,14 @@ static int verify_node_Sel(const ir_node *n)
        ASSERT_AND_RET_DBG(
                /* Sel: BB x M x ref x int^n --> ref */
                (op1mode == mode_M && op2mode == mymode && mode_is_reference(mymode)),
-               "Sel node", 0, show_node_failure(n)
+               "Sel node", 0, show_node_failure(n);
        );
 
        for (i = get_Sel_n_indexs(n) - 1; i >= 0; --i) {
-               ASSERT_AND_RET_DBG(mode_is_int(get_irn_mode(get_Sel_index(n, i))), "Sel node", 0, show_node_failure(n));
+               ASSERT_AND_RET_DBG(mode_is_int(get_irn_mode(get_Sel_index(n, i))), "Sel node", 0, show_node_failure(n););
        }
        ent = get_Sel_entity(n);
-       ASSERT_AND_RET_DBG(ent, "Sel node with empty entity", 0, show_node_failure(n));
+       ASSERT_AND_RET_DBG(ent, "Sel node with empty entity", 0, show_node_failure(n););
        return 1;
 }
 
@@ -1575,7 +1575,7 @@ static int verify_node_Sync(const ir_node *n)
        /* Sync: BB x M^n --> M */
        for (i = get_Sync_n_preds(n) - 1; i >= 0; --i) {
                ASSERT_AND_RET( get_irn_mode(get_Sync_pred(n, i)) == mode_M, "Sync node", 0 );
-       };
+       }
        ASSERT_AND_RET( mymode == mode_M, "Sync node", 0 );
        return 1;
 }
@@ -1748,7 +1748,8 @@ int irn_verify_irg(const ir_node *n, ir_graph *irg)
                unsigned idx           = get_irn_idx(n);
                ir_node *node_from_map = get_idx_irn(irg, idx);
                ASSERT_AND_RET_DBG(node_from_map == n, "Node index and index map entry differ", 0,
-                       ir_printf("node %+F node in map %+F(%p)\n", n, node_from_map, node_from_map));
+                       ir_printf("node %+F node in map %+F(%p)\n", n, node_from_map, node_from_map);
+               );
        }
 
        op = get_irn_op(n);
@@ -1759,12 +1760,14 @@ int irn_verify_irg(const ir_node *n, ir_graph *irg)
                        state == op_pin_state_floats ||
                        state == op_pin_state_pinned,
                        "invalid pin state", 0,
-                       ir_printf("node %+F", n));
+                       ir_printf("node %+F", n);
+               );
        } else if (!is_Block(n) && is_irn_pinned_in_irg(n)
                   && !is_irg_state(irg, IR_GRAPH_STATE_BAD_BLOCK)) {
                ASSERT_AND_RET_DBG(is_Block(get_nodes_block(n)) || is_Anchor(n),
                                "block input is not a block", 0,
-                               ir_printf("node %+F", n));
+                               ir_printf("node %+F", n);
+               );
        }
 
        if (op->ops.verify_node)
@@ -1832,7 +1835,8 @@ static int check_block_cfg(const ir_node *block, check_cfg_env_t *env)
 
        ASSERT_AND_RET_DBG(ir_nodeset_contains(&env->reachable_blocks, block),
                           "Block is not reachable by blockwalker (endless loop with no kept block?)", 0,
-                          ir_printf("block %+F\n", block));
+                          ir_printf("block %+F\n", block);
+       );
 
        n_cfgpreds   = get_Block_n_cfgpreds(block);
        branch_nodes = env->branch_nodes;
@@ -1850,7 +1854,8 @@ static int check_block_cfg(const ir_node *block, check_cfg_env_t *env)
                former_dest = pmap_get(branch_nodes, branch);
                ASSERT_AND_RET_DBG(former_dest==NULL || is_unknown_jump(skip_Proj(branch)),
                                                   "Multiple users on mode_X node", 0,
-                                                  ir_printf("node %+F\n", branch));
+                                                  ir_printf("node %+F\n", branch);
+               );
                pmap_insert(branch_nodes, branch, (void*)block);
 
                /* check that there's only 1 branching instruction in each block */
@@ -1864,7 +1869,8 @@ static int check_block_cfg(const ir_node *block, check_cfg_env_t *env)
                ASSERT_AND_RET_DBG(former_branch == NULL || former_branch == branch,
                                                   "Multiple branching nodes in a block", 0,
                                                   ir_printf("nodes %+F,%+F in block %+F\n",
-                                                                        branch, former_branch, branch_block));
+                                                                        branch, former_branch, branch_block);
+               );
                pmap_insert(branch_nodes, branch_block, branch);
 
                if (is_Cond(branch)) {
@@ -1875,7 +1881,7 @@ static int check_block_cfg(const ir_node *block, check_cfg_env_t *env)
                                if (pn == pn_Cond_false)
                                        ir_nodeset_insert(&env->false_projs, branch);
                        } else {
-                               int default_pn = get_Cond_default_proj(branch);
+                               long default_pn = get_Cond_default_proj(branch);
                                if (pn == default_pn)
                                        ir_nodeset_insert(&env->true_projs, branch);
                        }
@@ -1900,7 +1906,8 @@ static int verify_block_branch(const ir_node *block, check_cfg_env_t *env)
                           || ir_nodeset_contains(&env->kept_nodes, block)
                           || block == get_irg_end_block(get_irn_irg(block)),
                           "block contains no cfop", 0,
-                          ir_printf("block %+F\n", block));
+                          ir_printf("block %+F\n", block);
+       );
        return 1;
 }
 
@@ -1909,14 +1916,17 @@ static int verify_cond_projs(const ir_node *cond, check_cfg_env_t *env)
        if (get_irn_mode(get_Cond_selector(cond)) == mode_b) {
                ASSERT_AND_RET_DBG(ir_nodeset_contains(&env->true_projs, cond),
                                                   "Cond node lacks true proj", 0,
-                                                  ir_printf("Cond %+F\n", cond));
+                                                  ir_printf("Cond %+F\n", cond);
+               );
                ASSERT_AND_RET_DBG(ir_nodeset_contains(&env->false_projs, cond),
                                                   "Cond node lacks false proj", 0,
-                                                  ir_printf("Cond %+F\n", cond));
+                                                  ir_printf("Cond %+F\n", cond);
+               );
        } else {
                ASSERT_AND_RET_DBG(ir_nodeset_contains(&env->true_projs, cond),
                                   "Cond node lacks default Proj", 0,
-                                  ir_printf("Cond %+F\n", cond));
+                                  ir_printf("Cond %+F\n", cond);
+               );
        }
        return 1;
 }
@@ -2245,7 +2255,7 @@ void firm_set_default_verifier(unsigned code, ir_op_ops *ops)
        CASE(CopyB);
        CASE(Bound);
        default:
-               /* leave NULL */;
+               break;
        }
 #undef CASE
 
@@ -2270,7 +2280,7 @@ void firm_set_default_verifier(unsigned code, ir_op_ops *ops)
        CASE(CopyB);
        CASE(Bound);
        default:
-               /* leave NULL */;
+               break;
        }
 #undef CASE
 }
index bbf3787..0a36583 100644 (file)
@@ -65,7 +65,7 @@ do { \
 do { \
   if (!(expr)) { \
     firm_verify_failure_msg = #expr " && " string; \
-    if (opt_do_node_verification != FIRM_VERIFICATION_ERROR_ONLY) { blk; } \
+    if (opt_do_node_verification != FIRM_VERIFICATION_ERROR_ONLY) { blk } \
     if (opt_do_node_verification == FIRM_VERIFICATION_REPORT) \
       fprintf(stderr, #expr " : " string "\n"); \
     else if (opt_do_node_verification == FIRM_VERIFICATION_ON) { \
index a819107..32a1488 100644 (file)
@@ -337,7 +337,6 @@ static void back_propagate_brute_force(pbqp_t *pbqp)
                                break;
                        default:
                                panic("Only nodes with degree one or two should be in this bucket");
-                               break;
                }
        }
 }
index a37bc2f..221bdda 100644 (file)
@@ -47,7 +47,7 @@
 #include "timing.h"
 
 pbqp_edge_t **edge_bucket;
-pbqp_edge_t **rm_bucket;
+static pbqp_edge_t **rm_bucket;
 pbqp_node_t **node_buckets[4];
 pbqp_node_t **reduced_bucket = NULL;
 pbqp_node_t  *merged_node = NULL;
@@ -271,7 +271,6 @@ static void merge_source_into_target(pbqp_t *pbqp, pbqp_edge_t *edge)
        unsigned       *mapping;
        unsigned        src_len;
        unsigned        tgt_len;
-       unsigned        src_index;
        unsigned        tgt_index;
        unsigned        edge_index;
        unsigned        edge_len;
@@ -296,6 +295,7 @@ static void merge_source_into_target(pbqp_t *pbqp, pbqp_edge_t *edge)
        /* Check that each column has at most one zero entry. */
        for (tgt_index = 0; tgt_index < tgt_len; ++tgt_index) {
                unsigned onlyOneZero = 0;
+               unsigned src_index;
 
                if (tgt_vec->entries[tgt_index].data == INF_COSTS)
                        continue;
@@ -343,7 +343,6 @@ static void merge_source_into_target(pbqp_t *pbqp, pbqp_edge_t *edge)
                vector_t      *other_vec;
                unsigned       other_len;
                unsigned       other_index;
-               unsigned       tgt_index;
 
                assert(old_edge);
                if (old_edge == edge)
@@ -435,7 +434,6 @@ static void merge_target_into_source(pbqp_t *pbqp, pbqp_edge_t *edge)
        unsigned        src_len;
        unsigned        tgt_len;
        unsigned        src_index;
-       unsigned        tgt_index;
        unsigned        edge_index;
        unsigned        edge_len;
 
@@ -459,6 +457,7 @@ static void merge_target_into_source(pbqp_t *pbqp, pbqp_edge_t *edge)
        /* Check that each row has at most one zero entry. */
        for (src_index = 0; src_index < src_len; ++src_index) {
                unsigned onlyOneZero = 0;
+               unsigned tgt_index;
 
                if (src_vec->entries[src_index].data == INF_COSTS)
                        continue;
@@ -506,7 +505,6 @@ static void merge_target_into_source(pbqp_t *pbqp, pbqp_edge_t *edge)
                vector_t      *other_vec;
                unsigned       other_len;
                unsigned       other_index;
-               unsigned       src_index;
 
                assert(old_edge);
 
@@ -967,7 +965,6 @@ void back_propagate(pbqp_t *pbqp)
                                break;
                        default:
                                panic("Only nodes with degree one or two should be in this bucket");
-                               break;
                }
        }
 }
index 11cb51c..b2db379 100644 (file)
 
 #if KAPS_USE_UNSIGNED
        typedef unsigned num;
-       static const num INF_COSTS = UINT_MAX;
+       #define INF_COSTS UINT_MAX
 #else
        typedef intmax_t num;
-       static const num INF_COSTS = INTMAX_MAX;
+       #define INF_COSTS INTMAX_MAX
 #endif
 
 #include "matrix_t.h"
index a2806ed..ed27d63 100644 (file)
@@ -22,7 +22,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "lc_common_t.h"
 #include "lc_defines.h"
 #include "lc_printf.h"
 
@@ -61,12 +60,14 @@ void lc_appendable_init(lc_appendable_t *env, const lc_appendable_funcs_t *app,
        app->init(env);
 }
 
-static void default_init(UNUSED(lc_appendable_t *env))
+static void default_init(lc_appendable_t *env)
 {
+       (void) env;
 }
 
-static void default_finish(UNUSED(lc_appendable_t *env))
+static void default_finish(lc_appendable_t *env)
 {
+       (void) env;
 }
 
 /*
diff --git a/ir/libcore/lc_common_t.h b/ir/libcore/lc_common_t.h
deleted file mode 100644 (file)
index 0c910b1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-  libcore: library for basic data structures and algorithms.
-  Copyright (C) 2005  IPD Goos, Universit"at Karlsruhe, Germany
-
-  This library is free software; you can redistribute it and/or
-  modify it under the terms of the GNU Lesser General Public
-  License as published by the Free Software Foundation; either
-  version 2.1 of the License, or (at your option) any later version.
-
-  This library is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with this library; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _COMMON_T_H
-#define _COMMON_T_H
-
-#include <obstack.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#define obstack_chunk_alloc malloc
-#define obstack_chunk_free free
-
-#define bcopy(src,dest,n) memcpy(dest,src,n)
-
-#include "lc_config.h"
-
-#define FUNCNAME     LC_FUNCNAME
-#define UNUSED(x)    LC_UNUSED(x)
-#define LONGLONG     long /* LC_LONGLONG */
-#define LONGDOUBLE   double /* LC_LONGDOUBLE */
-
-#ifdef _WIN32
-/* Windows names for non-POSIX calls */
-#define snprintf  _snprintf
-#define vsnprintf _vsnprintf
-#endif /* WIN32 */
-
-#endif /* _COMMON_T_H */
index a4c9027..2ccf020 100644 (file)
@@ -30,7 +30,6 @@
 
 #define inline         __inline__
 #define LC_FUNCNAME    __FUNCTION__
-#define LC_UNUSED(x)   x __attribute__((__unused__))
 #define LC_PRINTF(m) __attribute__((format(printf,m,(m)+1)))
 
 #ifdef __STRICT_ANSI__
@@ -44,7 +43,6 @@
 #elif defined(_MSC_VER)
 
 #define LC_FUNCNAME    "<unknown>"
-#define LC_UNUSED(x)   x
 #define LC_PRINTF(m)
 
 #define LC_LONGLONG    __int64
@@ -73,7 +71,6 @@ typedef unsigned __int64   uint64;
 
 #define inline
 #define LC_FUNCNAME "<unknown>"
-#define LC_UNUSED(x)
 #define LC_LONGLONG long
 #define LC_LONGDOUBLE double
 #define LC_PRINTF(m)
index 34deeda..b7b0e30 100644 (file)
 #include <string.h>
 #include <ctype.h>
 
-#ifdef _WIN32
-#include <malloc.h>
-#endif
-
-/* Includes to determine user's home directory */
-#ifdef _WIN32
-#include <shlobj.h>
-#else
-#include <sys/types.h>
-#include <unistd.h>
-#include <pwd.h>
-#endif
-
-/* maximum length of a path. */
-#ifndef MAX_PATH
-#define MAX_PATH 2048
-#endif
-
-
-#include "lc_common_t.h"
 #include "lc_opts_t.h"
 #include "lc_opts_enum.h"
 #include "hashptr.h"
 #include "lc_printf.h"
 #include "xmalloc.h"
+#include "obst.h"
 
 #define ERR_STRING "In argument \"%s\": "
 
@@ -358,11 +339,12 @@ static char *strtolower(char *buf, size_t n, const char *str)
        return buf;
 }
 
-int lc_opt_std_cb(UNUSED(const char *name), lc_opt_type_t type, void *data, size_t length, ...)
+int lc_opt_std_cb(const char *name, lc_opt_type_t type, void *data, size_t length, ...)
 {
        va_list args;
        int res = 0;
        int integer;
+       (void) name;
 
        va_start(args, length);
 
@@ -413,9 +395,11 @@ int lc_opt_std_cb(UNUSED(const char *name), lc_opt_type_t type, void *data, size
        return res;
 }
 
-int lc_opt_std_dump(char *buf, size_t n, UNUSED(const char *name), lc_opt_type_t type, void *data, UNUSED(size_t length))
+int lc_opt_std_dump(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t length)
 {
        int res;
+       (void) name;
+       (void) length;
 
        if (data) {
                switch (type) {
@@ -451,8 +435,12 @@ int lc_opt_std_dump(char *buf, size_t n, UNUSED(const char *name), lc_opt_type_t
        return res;
 }
 
-int lc_opt_bool_dump_vals(char *buf, size_t n, UNUSED(const char *name), UNUSED(lc_opt_type_t type), UNUSED(void *data), UNUSED(size_t length))
+int lc_opt_bool_dump_vals(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t length)
 {
+       (void) name;
+       (void) type;
+       (void) data;
+       (void) length;
        strncpy(buf, "true, false", n);
        return n;
 }
@@ -802,8 +790,9 @@ int lc_opt_from_argv(const lc_opt_entry_t *root,
        return options_set;
 }
 
-static int opt_arg_type(UNUSED(const lc_arg_occ_t *occ))
+static int opt_arg_type(const lc_arg_occ_t *occ)
 {
+       (void) occ;
        return lc_arg_type_ptr;
 }
 
index ebcb034..c286f97 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#ifdef _WIN32
-#include <malloc.h>
-#endif
-
 #include "lc_opts_t.h"
 #include "lc_opts_enum.h"
+#include "xmalloc.h"
 
 static const char *delim = " \t|,";
 
 #define DECL_CB(N, op) \
-int lc_opt_enum_ ## N ## _cb(LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, size_t len, ...) \
+int lc_opt_enum_ ## N ## _cb(const char *name, lc_opt_type_t type, void *data, size_t len, ...) \
 { \
        lc_opt_enum_ ## N ## _var_t *var           = (lc_opt_enum_ ## N ## _var_t*)data; \
        const lc_opt_enum_ ## N ## _items_t *items = var->items; \
@@ -36,6 +33,8 @@ int lc_opt_enum_ ## N ## _cb(LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_
        const char *arg; \
        int res = 0; \
  \
+       (void) name; \
+       (void) type; \
        va_start(args, len); \
        arg = va_arg(args, const char *); \
        va_end(args); \
@@ -72,7 +71,7 @@ DECL_CB(const_ptr, =)
 DECL_CB(func_ptr, =)
 
 #define DECL_DUMP(T, N, cond) \
-int lc_opt_enum_ ## N ## _dump(char *buf, size_t n, LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, LC_UNUSED(size_t len)) \
+int lc_opt_enum_ ## N ## _dump(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t len) \
 { \
        lc_opt_enum_ ## N ## _var_t *var           = (lc_opt_enum_ ## N ## _var_t*)data;       \
        const lc_opt_enum_ ## N ## _items_t *items = var->items; \
@@ -80,6 +79,9 @@ int lc_opt_enum_ ## N ## _dump(char *buf, size_t n, LC_UNUSED(const char *name),
        TYPE(value) = *var->value; \
        int i; \
        size_t l = strlen(buf); \
+       (void) name; \
+       (void) type; \
+       (void) len; \
  \
        if (l >= n) \
                return (int)l; \
@@ -104,13 +106,16 @@ int lc_opt_enum_ ## N ## _dump(char *buf, size_t n, LC_UNUSED(const char *name),
 
 
 #define DECL_DUMP_VALS(T, N) \
-int lc_opt_enum_ ## N ## _dump_vals(char *buf, size_t n, LC_UNUSED(const char *name), LC_UNUSED(lc_opt_type_t type), void *data, LC_UNUSED(size_t len)) \
+int lc_opt_enum_ ## N ## _dump_vals(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t len) \
 { \
        lc_opt_enum_ ## N ## _var_t *var           = (lc_opt_enum_ ## N ## _var_t*) data;       \
        const lc_opt_enum_ ## N ## _items_t *items = var->items; \
        const char *prefix                         = "";         \
        int i; \
        size_t l = strlen(buf); \
+       (void) name; \
+       (void) type; \
+       (void) len; \
  \
        if (l >= n) \
                return (int)l; \
index 28cc0ce..46f6d46 100644 (file)
@@ -27,7 +27,6 @@
 #include "lc_opts.h"
 #include "list.h"
 
-#include "lc_common_t.h"
 #include "lc_defines.h"
 
 typedef struct {
index 1ac0cfa..471f751 100644 (file)
@@ -33,7 +33,6 @@
 #include <assert.h>
 #include <ctype.h>
 
-#include "lc_common_t.h"
 #include "xmalloc.h"
 #include "lc_printf.h"
 #include "lc_defines.h"
@@ -72,10 +71,11 @@ lc_arg_env_t *lc_arg_get_default_env(void)
        return _lc_arg_get_default_env();
 }
 
-static int lc_arg_cmp(const void *p1, const void *p2, UNUSED(size_t size))
+static int lc_arg_cmp(const void *p1, const void *p2, size_t size)
 {
        const lc_arg_t *a1 = (const lc_arg_t*)p1;
        const lc_arg_t *a2 = (const lc_arg_t*)p2;
+       (void) size;
        return strcmp(a1->name, a2->name);
 }
 
@@ -121,8 +121,10 @@ int lc_arg_register(lc_arg_env_t *env, const char *name, char letter, const lc_a
        return ent != NULL;
 }
 
-void lc_arg_unregister(UNUSED(lc_arg_env_t *env), UNUSED(const char *name))
+void lc_arg_unregister(lc_arg_env_t *env, const char *name)
 {
+       (void) env;
+       (void) name;
 }
 
 int lc_arg_append(lc_appendable_t *app, const lc_arg_occ_t *occ, const char *str, size_t len)
@@ -238,7 +240,7 @@ static int std_get_lc_arg_type(const lc_arg_occ_t *occ)
                                return modlen > 1 && mod[1] == 'h' ? lc_arg_type_char : lc_arg_type_short;
                        case 'l':
                                return modlen > 1 && mod[1] == 'l' ? lc_arg_type_long_long : lc_arg_type_long;
-#define TYPE_CASE(letter,type) case letter: return lc_arg_type_ ## type;
+#define TYPE_CASE(letter,type) case letter: return lc_arg_type_ ## type
                        TYPE_CASE('j', intmax_t);
                        TYPE_CASE('z', size_t);
                        TYPE_CASE('t', ptrdiff_t);
@@ -398,12 +400,12 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
 
                /* read the precision if given */
                if (*s == '.') {
-                       int val;
-                       s = read_int(s + 1, &val);
+                       int precision;
+                       s = read_int(s + 1, &precision);
 
                        /* Negative or lacking precision after a '.' is treated as
                         * precision 0. */
-                       occ.precision = LC_MAX(0, val);
+                       occ.precision = LC_MAX(0, precision);
                }
 
                /*
@@ -423,7 +425,8 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                                        const char *named = ++s;
 
                                        /* Read until the closing brace or end of the string. */
-                                       for (ch = *s; ch != '}' && ch != '\0'; ch = *++s);
+                                       for (ch = *s; ch != '}' && ch != '\0'; ch = *++s) {
+                                       }
 
                                        if (s - named) {
                                                size_t n = s - named;
index a3eca0b..b27b0f5 100644 (file)
@@ -221,7 +221,7 @@ static cl_entry *get_Call_entry(ir_node *call, wlk_env *env)
 {
        cl_entry *res = (cl_entry*)get_irn_link(call);
        if (res == NULL) {
-               cl_entry *res = OALLOC(&env->obst, cl_entry);
+               res = OALLOC(&env->obst, cl_entry);
                res->next  = env->cl_list;
                res->call  = call;
                res->copyb = NULL;
@@ -748,12 +748,13 @@ static void transform_irg(const lower_params_t *lp, ir_graph *irg)
                        set_irn_in(ret, j, new_in);
 
                        if (n_cr_opt > 0) {
-                               size_t i, n;
+                               size_t c;
+                               size_t n;
 
                                irg_walk_graph(irg, NULL, do_copy_return_opt, cr_opt);
 
-                               for (i = 0, n = ARR_LEN(cr_opt); i < n; ++i) {
-                                       free_entity(cr_opt[i].ent);
+                               for (c = 0, n = ARR_LEN(cr_opt); c < n; ++c) {
+                                       free_entity(cr_opt[c].ent);
                                }
                        }
                }
index 484f9da..cc75855 100644 (file)
@@ -336,7 +336,9 @@ static void lower_Load(ir_node *node, ir_mode *mode)
        ir_graph   *irg = get_irn_irg(node);
        ir_node    *adr = get_Load_ptr(node);
        ir_node    *mem = get_Load_mem(node);
-       ir_node    *low, *high, *proj;
+       ir_node    *low;
+       ir_node    *high;
+       ir_node    *proj_m;
        dbg_info   *dbg;
        ir_node    *block = get_nodes_block(node);
        ir_cons_flags volatility = get_Load_volatility(node) == volatility_is_volatile
@@ -353,10 +355,10 @@ static void lower_Load(ir_node *node, ir_mode *mode)
        }
 
        /* create two loads */
-       dbg  = get_irn_dbg_info(node);
-       low  = new_rd_Load(dbg, block, mem,  low,  low_mode, volatility);
-       proj = new_r_Proj(low, mode_M, pn_Load_M);
-       high = new_rd_Load(dbg, block, proj, high, mode, volatility);
+       dbg    = get_irn_dbg_info(node);
+       low    = new_rd_Load(dbg, block, mem,  low,  low_mode, volatility);
+       proj_m = new_r_Proj(low, mode_M, pn_Load_M);
+       high   = new_rd_Load(dbg, block, proj_m, high, mode, volatility);
 
        foreach_out_edge_safe(node, edge, next) {
                ir_node *proj = get_edge_src_irn(edge);
@@ -394,7 +396,7 @@ static void lower_Store(ir_node *node, ir_mode *mode)
 {
        ir_graph              *irg;
        ir_node               *block, *adr, *mem;
-       ir_node               *low, *high, *proj;
+       ir_node               *low, *high, *proj_m;
        dbg_info              *dbg;
        ir_node               *value = get_Store_value(node);
        const lower64_entry_t *entry = get_node_entry(value);
@@ -426,10 +428,10 @@ static void lower_Store(ir_node *node, ir_mode *mode)
        }
 
        /* create two Stores */
-       dbg = get_irn_dbg_info(node);
-       low  = new_rd_Store(dbg, block, mem, low,  entry->low_word, volatility);
-       proj = new_r_Proj(low, mode_M, pn_Store_M);
-       high = new_rd_Store(dbg, block, proj, high, entry->high_word, volatility);
+       dbg    = get_irn_dbg_info(node);
+       low    = new_rd_Store(dbg, block, mem, low,  entry->low_word, volatility);
+       proj_m = new_r_Proj(low, mode_M, pn_Store_M);
+       high   = new_rd_Store(dbg, block, proj_m, high, entry->high_word, volatility);
 
        foreach_out_edge_safe(node, edge, next) {
                ir_node *proj = get_edge_src_irn(edge);
@@ -816,13 +818,14 @@ static void lower_shr_helper(ir_node *node, ir_mode *mode,
                panic("Shr lowering only implemented for two-complement modes");
        }
 
+       block = get_nodes_block(node);
+
        /* if the right operand is a 64bit value, we're only interested in the
         * lower word */
        if (get_irn_mode(right) == env->high_unsigned) {
                right = get_lowered_low(right);
        } else {
                /* shift should never have signed mode on the right */
-               ir_node *block = get_nodes_block(node);
                assert(get_irn_mode(right) != env->high_signed);
                right = create_conv(block, right, low_unsigned);
        }
@@ -879,10 +882,10 @@ static void lower_shr_helper(ir_node *node, ir_mode *mode,
                ir_node *res_low     = new_rd_shrs(dbgi, block_false, conv, right,
                                                   low_unsigned);
                int      cnsti       = modulo_shift2-1;
-               ir_node *cnst        = new_r_Const_long(irg, low_unsigned, cnsti);
+               ir_node *cnst2       = new_r_Const_long(irg, low_unsigned, cnsti);
                ir_node *res_high;
                if (new_rd_shrs == new_rd_Shrs) {
-                       res_high = new_rd_shrs(dbgi, block_false, left_high, cnst, mode);
+                       res_high = new_rd_shrs(dbgi, block_false, left_high, cnst2, mode);
                } else {
                        res_high = new_r_Const(irg, get_mode_null(mode));
                }
@@ -1201,14 +1204,14 @@ static ir_node *get_cfop_destination(const ir_node *cfop)
 /**
  * Translate a Cond.
  */
-static void lower_Cond(ir_node *node, ir_mode *mode)
+static void lower_Cond(ir_node *node, ir_mode *high_mode)
 {
        ir_node *left, *right, *block;
        ir_node *sel = get_Cond_selector(node);
        ir_mode *m = get_irn_mode(sel);
        ir_mode *cmp_mode;
        const lower64_entry_t *lentry, *rentry;
-       ir_node  *proj, *projT = NULL, *projF = NULL;
+       ir_node  *projT = NULL, *projF = NULL;
        ir_node  *new_bl, *irn;
        ir_node  *projHF, *projHT;
        ir_node  *dst_blk;
@@ -1218,7 +1221,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode)
        const ir_edge_t *edge;
        const ir_edge_t *next;
 
-       (void) mode;
+       (void) high_mode;
 
        if (m != mode_b) {
                if (m == env->high_signed || m == env->high_unsigned) {
@@ -1289,6 +1292,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode)
        }
 
        if (relation == ir_relation_equal) {
+               ir_node *proj;
                /* simple case:a == b <==> a_h == b_h && a_l == b_l */
                dst_blk = get_cfop_destination(projF);
 
@@ -1320,6 +1324,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode)
                mark_irn_visited(proj);
                exchange(projT, proj);
        } else if (relation == ir_relation_less_greater) {
+               ir_node *proj;
                /* simple case:a != b <==> a_h != b_h || a_l != b_l */
                dst_blk = get_cfop_destination(projT);
 
@@ -1351,6 +1356,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode)
                mark_irn_visited(proj);
                exchange(projF, proj);
        } else {
+               ir_node *proj;
                /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
                ir_node *dstT, *dstF, *newbl_eq, *newbl_l;
                ir_node *projEqF;
@@ -1514,8 +1520,8 @@ static void lower_Conv_from_Ll(ir_node *node)
  */
 static void lower_Cmp(ir_node *cmp, ir_mode *m)
 {
-       ir_node  *l    = get_Cmp_left(cmp);
-       ir_mode  *mode = get_irn_mode(l);
+       ir_node  *l        = get_Cmp_left(cmp);
+       ir_mode  *cmp_mode = get_irn_mode(l);
        ir_node  *r, *low, *high, *t, *res;
        ir_relation relation;
        ir_node  *block;
@@ -1524,7 +1530,7 @@ static void lower_Cmp(ir_node *cmp, ir_mode *m)
        const lower64_entry_t *rentry;
        (void) m;
 
-       if (mode != env->high_signed && mode != env->high_unsigned)
+       if (cmp_mode != env->high_signed && cmp_mode != env->high_unsigned)
                return;
 
        r        = get_Cmp_right(cmp);
@@ -1760,10 +1766,10 @@ static void lower_Return(ir_node *node, ir_mode *mode)
 
        /* check if this return must be lowered */
        for (i = 0, n = get_Return_n_ress(node); i < n; ++i) {
-               ir_node *pred = get_Return_res(node, i);
-               ir_mode *mode = get_irn_op_mode(pred);
+               ir_node *pred  = get_Return_res(node, i);
+               ir_mode *rmode = get_irn_op_mode(pred);
 
-               if (mode == env->high_signed || mode == env->high_unsigned)
+               if (rmode == env->high_signed || rmode == env->high_unsigned)
                        need_conv = 1;
        }
        if (! need_conv)
@@ -1803,7 +1809,7 @@ static void lower_Return(ir_node *node, ir_mode *mode)
 /**
  * Translate the parameters.
  */
-static void lower_Start(ir_node *node, ir_mode *mode)
+static void lower_Start(ir_node *node, ir_mode *high_mode)
 {
        ir_graph  *irg = get_irn_irg(node);
        ir_entity *ent = get_irg_entity(irg);
@@ -1813,7 +1819,7 @@ static void lower_Start(ir_node *node, ir_mode *mode)
        size_t    i, j, n_params;
        const ir_edge_t *edge;
        const ir_edge_t *next;
-       (void) mode;
+       (void) high_mode;
 
        if (!mtp_must_be_lowered(tp))
                return;
@@ -1828,9 +1834,8 @@ static void lower_Start(ir_node *node, ir_mode *mode)
 
                new_projs[i] = j;
                if (is_Primitive_type(ptp)) {
-                       ir_mode *mode = get_type_mode(ptp);
-
-                       if (mode == env->high_signed || mode == env->high_unsigned)
+                       ir_mode *amode = get_type_mode(ptp);
+                       if (amode == env->high_signed || amode == env->high_unsigned)
                                ++j;
                }
        }
@@ -1913,9 +1918,8 @@ static void lower_Call(ir_node *node, ir_mode *mode)
                ir_type *ptp = get_method_param_type(tp, p);
 
                if (is_Primitive_type(ptp)) {
-                       ir_mode *mode = get_type_mode(ptp);
-
-                       if (mode == env->high_signed || mode == env->high_unsigned) {
+                       ir_mode *pmode = get_type_mode(ptp);
+                       if (pmode == env->high_signed || pmode == env->high_unsigned) {
                                need_lower = true;
                                break;
                        }
@@ -1930,9 +1934,8 @@ static void lower_Call(ir_node *node, ir_mode *mode)
 
                        res_numbers[i] = j;
                        if (is_Primitive_type(ptp)) {
-                               ir_mode *mode = get_type_mode(ptp);
-
-                               if (mode == env->high_signed || mode == env->high_unsigned) {
+                               ir_mode *rmode = get_type_mode(ptp);
+                               if (rmode == env->high_signed || rmode == env->high_unsigned) {
                                        need_lower = true;
                                        ++j;
                                }
@@ -2190,7 +2193,6 @@ static void lower_ASM(ir_node *asmn, ir_mode *mode)
                ir_node           *block      = get_nodes_block(asmn);
                int                arity      = get_irn_arity(asmn);
                ir_node          **in         = get_irn_in(asmn) + 1;
-               int                n_outs     = get_ASM_n_output_constraints(asmn);
                int                new_n_outs = 0;
                int                n_clobber  = get_ASM_n_clobbers(asmn);
                long              *proj_map   = ALLOCAN(long, n_outs);
@@ -2574,6 +2576,7 @@ static void lower_irg(ir_graph *irg)
                        set_irg_doms_inconsistent(irg);
                        set_irg_extblk_inconsistent(irg);
                }
+               edges_deactivate(irg);
        }
 
        ir_free_resources(irg, IR_RESOURCE_PHI_LIST | IR_RESOURCE_IRN_LINK);
index cffbf59..ab4f599 100644 (file)
@@ -297,7 +297,7 @@ static int is_integral_size(int size)
 static void lower_bitfields_loads(ir_node *proj, ir_node *load)
 {
        ir_node *sel = get_Load_ptr(load);
-       ir_node *block, *n_proj, *res, *ptr;
+       ir_node *block, *res, *ptr;
        ir_graph *irg;
        ir_entity *ent;
        ir_type *bf_type;
@@ -350,7 +350,7 @@ static void lower_bitfields_loads(ir_node *proj, ir_node *load)
        /* create new proj, switch off CSE or we may get the old one back */
        old_cse = get_opt_cse();
        set_opt_cse(0);
-       res = n_proj = new_r_Proj(load, mode, pn_Load_res);
+       res = new_r_Proj(load, mode, pn_Load_res);
        set_opt_cse(old_cse);
 
        if (mode_is_signed(mode)) { /* signed */
index ca2c1d0..948e8c8 100644 (file)
@@ -341,10 +341,8 @@ synth_zero_one:
                        set_irn_mode(node, mode);
                        res = node;
                        goto own_replacement;
-               } else {
-                       panic("unexpected projb: %+F (pred: %+F)", node, pred);
                }
-               break;
+               panic("unexpected projb: %+F (pred: %+F)", node, pred);
        }
 
        case iro_Const: {
index d4daf0a..4ff2737 100644 (file)
@@ -44,6 +44,7 @@
 
 typedef struct walk_env_t {
        unsigned      spare_size; /**< the allowed spare size for table switches */
+       unsigned      small_switch;
        bool          allow_out_of_bounds;
        bool          changed;    /**< indicates whether a change was performed */
        ir_nodeset_t  processed;
@@ -206,7 +207,7 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond)
        ir_node       *block         = get_nodes_block(cond);
        ir_mode       *cmp_mode      = get_irn_mode(sel);
        ir_node      **default_preds = NEW_ARR_F(ir_node*, 0);
-       unsigned long  default_pn    = get_Cond_default_proj(cond);
+       long           default_pn    = get_Cond_default_proj(cond);
        long           delta         = 0;
        ir_node       *max_const;
        ir_node       *proj_true;
@@ -251,16 +252,10 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond)
 
        /* adapt projs */
        foreach_out_irn(cond, i, proj) {
-               unsigned long pn     = get_Proj_proj(proj);
-               unsigned long new_pn = pn - delta;
+               long pn     = get_Proj_proj(proj);
+               long new_pn = pn - delta;
                if (pn == default_pn) {
-                       /* we might have to choose a new default_pn */
-                       if (pn < (unsigned long) env->switch_max) {
-                               new_pn = env->switch_max + 1;
-                               set_Cond_default_proj(cond, new_pn);
-                       } else {
-                               new_pn = default_pn;
-                       }
+                       set_Cond_default_proj(cond, new_pn);
                        ARR_APP1(ir_node*, default_preds, proj);
                }
 
@@ -271,18 +266,18 @@ static void create_out_of_bounds_check(cond_env_t *env, ir_node *cond)
        /* adapt default block */
        n_default_preds = ARR_LEN(default_preds);
        if (n_default_preds > 1) {
-               size_t i;
+               size_t p;
 
                /* create new intermediate blocks so we don't have critical edges */
-               for (i = 0; i < n_default_preds; ++i) {
-                       ir_node *proj = default_preds[i];
-                       ir_node *block;
-                       ir_node *in[1];
+               for (p = 0; p < n_default_preds; ++p) {
+                       ir_node *pred = default_preds[p];
+                       ir_node *split_block;
+                       ir_node *block_in[1];
 
-                       in[0] = proj;
-                       block = new_r_Block(irg, 1, in);
+                       block_in[0] = pred;
+                       split_block = new_r_Block(irg, 1, block_in);
 
-                       default_preds[i] = new_r_Jmp(block);
+                       default_preds[p] = new_r_Jmp(split_block);
                }
        }
        set_irn_in(env->default_block, n_default_preds, default_preds);
@@ -311,6 +306,7 @@ static void find_cond_nodes(ir_node *block, void *ctx)
        dbg_info    *dbgi;
        cond_env_t   cond_env;
        unsigned long spare;
+       bool         lower_switch = false;
 
        /* because we split critical blocks only blocks with 1 predecessors may
         * contain Proj->Cond nodes */
@@ -349,7 +345,10 @@ static void find_cond_nodes(ir_node *block, void *ctx)
        spare = (unsigned long) cond_env.switch_max
                - (unsigned long) cond_env.switch_min
                - (unsigned long) cond_env.num_cases + 1;
-       if (spare < env->spare_size) {
+       lower_switch |= spare >= env->spare_size;
+       lower_switch |= cond_env.num_cases <= env->small_switch;
+
+       if (!lower_switch) {
                /* we won't decompose the switch. But we might have to add
                 * out-of-bounds checking */
                if (!env->allow_out_of_bounds) {
@@ -405,11 +404,13 @@ static void find_cond_nodes(ir_node *block, void *ctx)
        DEL_ARR_F(cond_env.defusers);
 }
 
-void lower_switch(ir_graph *irg, unsigned spare_size, int allow_out_of_bounds)
+void lower_switch(ir_graph *irg, unsigned small_switch, unsigned spare_size,
+                  int allow_out_of_bounds)
 {
        walk_env_t env;
        env.changed             = false;
        env.spare_size          = spare_size;
+       env.small_switch        = small_switch;
        env.allow_out_of_bounds = allow_out_of_bounds;
        ir_nodeset_init(&env.processed);
 
diff --git a/ir/lpp/lpp.c b/ir/lpp/lpp.c
new file mode 100644 (file)
index 0000000..82ea74c
--- /dev/null
@@ -0,0 +1,619 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        Fri 13.05.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * CVS-Id:      $Id: lpp.c 27353 2010-04-07 13:33:16Z matze $
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "assert.h"
+#include "obst.h"
+#include "hashptr.h"
+#include "debug.h"
+#include "set.h"
+
+#include "sp_matrix.h"
+#include "mps.h"
+#include "lpp_t.h"
+#include "lpp_comm.h"
+#include "lpp_solvers.h"
+#include "lpp_net.h"
+
+#define HASH_NAME_T(n) HASH_STR((n)->name, strlen((n)->name))
+
+static firm_dbg_module_t *dbg = NULL;
+
+static inline char *obst_xstrdup(struct obstack *obst, const char *str)
+{
+       return obstack_copy0(obst, str, strlen(str));
+}
+
+static int cmp_name_t(const void *x, const void *y, size_t size)
+{
+       const lpp_name_t *n = x;
+       const lpp_name_t *m = y;
+       (void)size; /* stop warnings */
+       return strcmp(n->name, m->name);
+}
+
+/**
+ * Update statistic information about matrix usage.
+ */
+static void update_stats(lpp_t *lpp)
+{
+       lpp->n_elems    = matrix_get_entries(lpp->m);
+       lpp->matrix_mem = lpp->n_elems * matrix_get_elem_size();
+       lpp->density    = (double)lpp->n_elems / (double)(lpp->cst_next * lpp->var_next) * 100.0;
+}
+
+#define INITIAL_SIZE 64
+
+lpp_t *new_lpp(const char *name, lpp_opt_t opt_type)
+{
+       return new_lpp_userdef(name, opt_type, INITIAL_SIZE, INITIAL_SIZE, 2.0);
+}
+
+lpp_t *new_lpp_userdef(const char *name, lpp_opt_t opt_type,
+                          int estimated_vars, int estimated_csts, double grow_factor)
+{
+       lpp_t *lpp;
+       int   idx;
+
+       dbg = firm_dbg_register("lpp");
+       lpp = XMALLOCZ(lpp_t);
+       obstack_init(&lpp->obst);
+
+       lpp->name        = obst_xstrdup(&lpp->obst, name);
+       lpp->opt_type    = opt_type;
+       lpp->grow_factor = grow_factor;
+       lpp->cst2nr      = new_set(cmp_name_t, estimated_csts);
+       lpp->var2nr      = new_set(cmp_name_t, estimated_vars);
+       lpp->cst_size    = estimated_csts;
+       lpp->var_size    = estimated_vars;
+       lpp->csts        = XMALLOCNZ(lpp_name_t *, estimated_csts);
+       lpp->vars        = XMALLOCNZ(lpp_name_t *, estimated_vars);
+       lpp->m           = new_matrix(estimated_csts, estimated_vars);
+       lpp->emphasis    = lpp_balanced;
+       idx              = lpp_add_cst(lpp, "obj", lpp_objective, 0);
+       assert(idx == 0);
+       idx              = lpp_add_var(lpp, "rhs", lpp_rhs, 0);
+       assert(idx == 0);
+
+       return lpp;
+}
+
+void free_lpp_matrix(lpp_t *lpp)
+{
+       del_matrix(lpp->m);
+       lpp->m = NULL;
+}
+
+void free_lpp(lpp_t *lpp)
+{
+       obstack_free(&lpp->obst, NULL);
+
+       del_set(lpp->cst2nr);
+       del_set(lpp->var2nr);
+
+       /* matrix might have been already deleted */
+       if (lpp->m)
+               del_matrix(lpp->m);
+
+       free(lpp->csts);
+       free(lpp->vars);
+
+       free(lpp);
+}
+
+double lpp_get_fix_costs(lpp_t *lpp)
+{
+       return matrix_get(lpp->m, 0, 0);
+}
+
+void lpp_set_fix_costs(lpp_t *lpp, double value)
+{
+       matrix_set(lpp->m, 0, 0, value);
+}
+
+static inline int name2nr(set *where, const char *name)
+{
+       lpp_name_t find, *found;
+       find.name = name;
+       found = set_find(where, &find, sizeof(find), HASH_NAME_T(&find));
+       return (found ? found->nr : -1);
+}
+
+#define cst_nr(lpp, name) name2nr(lpp->cst2nr, name)
+#define var_nr(lpp, name) name2nr(lpp->var2nr, name)
+
+static inline char *get_next_name(lpp_t *lpp)
+{
+       char *res = obstack_alloc(&lpp->obst, 12);
+       snprintf(res, 12, "_%u", lpp->next_name_number++);
+       return res;
+}
+
+int lpp_add_cst(lpp_t *lpp, const char *cst_name, lpp_cst_t cst_type, double rhs)
+{
+       lpp_name_t n, *inner;
+
+       DBG((dbg, LEVEL_2, "%s %d %g\n", cst_name, cst_type, rhs));
+
+       if (cst_name && cst_name[0] == '_')
+               return ERR_NAME_NOT_ALLOWED;
+
+       if (cst_name)
+               n.name = obst_xstrdup(&lpp->obst, cst_name);
+       else
+               n.name = get_next_name(lpp);
+
+       n.nr  = -1;
+       inner = set_insert(lpp->cst2nr, &n, sizeof(n), HASH_NAME_T(&n));
+       assert(inner);
+
+       if (inner->nr == -1) {
+               inner->value_kind    = lpp_none;
+               inner->value         = 0.0;
+               inner->nr            = lpp->cst_next;
+               inner->type.cst_type = cst_type;
+
+               if (lpp->cst_next == lpp->cst_size) {
+                       lpp->cst_size = (int)((double)lpp->cst_size * lpp->grow_factor) + 1;
+                       lpp->csts     = XREALLOC(lpp->csts, lpp_name_t *, lpp->cst_size);
+               }
+
+               lpp->csts[lpp->cst_next] = inner;
+               lpp->cst_next++;
+               matrix_set(lpp->m, inner->nr, 0, rhs);
+       }
+
+       update_stats(lpp);
+       return inner->nr;
+}
+
+int lpp_add_cst_uniq(lpp_t *lpp, const char *cst_name, lpp_cst_t cst_type, double rhs)
+{
+       if (cst_name) {
+               lpp_name_t n;
+
+               n.name = cst_name;
+               n.nr   = -1;
+               assert(!set_find(lpp->cst2nr, &n, sizeof(n), HASH_NAME_T(&n)) &&
+                   "constraint already exists");
+       }
+       return lpp_add_cst(lpp, cst_name, cst_type, rhs);
+}
+
+int lpp_get_cst_idx(lpp_t *lpp, const char *cst_name)
+{
+       DBG((dbg, LEVEL_2, "%s --> %d\n", cst_name, cst_nr(lpp, cst_name)));
+       return cst_nr(lpp, cst_name);
+}
+
+void lpp_get_cst_name(lpp_t *lpp, int index, char *buf, size_t buf_size)
+{
+       DBG((dbg, LEVEL_2, "%d --> %s\n", index, lpp->csts[index]->name));
+       strncpy(buf, lpp->csts[index]->name, buf_size);
+}
+
+int lpp_add_var_default(lpp_t *lpp, const char *var_name, lpp_var_t var_type, double obj, double startval)
+{
+       int val;
+
+       val = lpp_add_var(lpp, var_name, var_type, obj);
+       lpp_set_start_value(lpp, val, startval);
+
+       return val;
+}
+
+int lpp_add_var(lpp_t *lpp, const char *var_name, lpp_var_t var_type, double obj)
+{
+       lpp_name_t n, *inner;
+
+       DBG((dbg, LEVEL_2, "%s %d %g\n", var_name, var_type, obj));
+
+       assert(var_type != lpp_invalid && "invalid is for internal use only");
+
+       if (var_name && var_name[0] == '_')
+               return ERR_NAME_NOT_ALLOWED;
+
+       if (var_name)
+               n.name = obst_xstrdup(&lpp->obst, var_name);
+       else
+               n.name = get_next_name(lpp);
+
+       n.nr  = -1;
+       inner = set_insert(lpp->var2nr, &n, sizeof(n), HASH_NAME_T(&n));
+       assert(inner);
+
+       if (inner->nr == -1) {
+               inner->nr            = lpp->var_next;
+               inner->value_kind    = 0;
+               inner->value         = 0;
+               inner->type.var_type = var_type;
+
+               if (lpp->var_next == lpp->var_size) {
+                       lpp->var_size = (int)((double)lpp->var_size * lpp->grow_factor) + 1;
+                       lpp->vars     = XREALLOC(lpp->vars, lpp_name_t *, lpp->var_size);
+               }
+
+               lpp->vars[lpp->var_next] = inner;
+               lpp->var_next++;
+               matrix_set(lpp->m, 0, inner->nr, obj);
+       }
+
+       update_stats(lpp);
+       return inner->nr;
+}
+
+int lpp_get_var_idx(lpp_t *lpp, const char *var_name)
+{
+       DBG((dbg, LEVEL_2, "%s --> %d\n", var_name, var_nr(lpp, var_name)));
+       return var_nr(lpp, var_name);
+}
+
+void lpp_get_var_name(lpp_t *lpp, int index, char *buf, size_t buf_size)
+{
+       DBG((dbg, LEVEL_2, "%d --> %s\n", index, lpp->vars[index]->name));
+       strncpy(buf, lpp->vars[index]->name, buf_size);
+}
+
+int lpp_set_factor(lpp_t *lpp, const char *cst_name, const char *var_name, double value)
+{
+       int cst, var;
+
+       cst = cst_nr(lpp, cst_name);
+       var = var_nr(lpp, var_name);
+       assert(cst != -1 && var != -1);
+       DBG((dbg, LEVEL_2, "%s[%d] %s[%d] %g\n", cst_name, cst, var_name, var, value));
+       matrix_set(lpp->m, cst, var, value);
+       update_stats(lpp);
+       return 0;
+}
+
+int lpp_set_factor_fast(lpp_t *lpp, int cst_idx, int var_idx, double value)
+{
+       assert(cst_idx >= 0 && var_idx >= 0);
+       assert(cst_idx < lpp->cst_next && var_idx < lpp->var_next);
+       DBG((dbg, LEVEL_2, "%s[%d] %s[%d] %g\n", lpp->csts[cst_idx]->name, cst_idx, lpp->vars[var_idx]->name, var_idx, value));
+       matrix_set(lpp->m, cst_idx, var_idx, value);
+       update_stats(lpp);
+       return 0;
+}
+
+int lpp_set_factor_fast_bulk(lpp_t *lpp, int cst_idx, int *var_idx, int num_vars, double value)
+{
+       assert(cst_idx >= 0 && cst_idx < lpp->cst_next);
+       assert(num_vars < lpp->var_next);
+       DBG((dbg, LEVEL_2, "row %s[%d] %d vars %g\n", lpp->csts[cst_idx]->name, cst_idx, num_vars, value));
+       matrix_set_row_bulk(lpp->m, cst_idx, var_idx, num_vars, value);
+       update_stats(lpp);
+       return 0;
+}
+
+void lpp_set_start_value(lpp_t *lpp, int var_idx, double value)
+{
+       assert(var_idx > 0 && var_idx < lpp->var_next);
+       DBG((dbg, LEVEL_2, "%d %s %g\n", var_idx, lpp->vars[var_idx]->name, value));
+       lpp->vars[var_idx]->value = value;
+       lpp->vars[var_idx]->value_kind = lpp_value_start;
+}
+
+lpp_sol_state_t lpp_get_solution(lpp_t *lpp, double *values, int begin, int end)
+{
+       int i;
+
+       if (lpp->sol_state < lpp_feasible)
+               return lpp->sol_state;
+
+       /* here we are feasible or optimal */
+       for (i = 0; i < end - begin + 1; ++i)
+               values[i] = lpp->vars[begin + i]->value;
+
+       return lpp->sol_state;
+}
+
+void lpp_check_startvals(lpp_t *lpp)
+{
+       int cst_idx;
+
+       for (cst_idx = 1; cst_idx < lpp->cst_next; ++cst_idx) {
+               double     sum     = 0.0;
+               lpp_name_t *cst    = lpp->csts[cst_idx];
+               double     cst_val = matrix_get(lpp->m, cst_idx, 0);
+               int        var_idx;
+
+               for (var_idx = 1; var_idx < lpp->var_next; ++var_idx) {
+                               if (lpp->vars[var_idx]->value_kind != lpp_value_start)
+                                       goto next;
+
+                               sum += lpp->vars[var_idx]->value *
+                                       matrix_get(lpp->m, cst_idx, var_idx);
+               }
+               switch(cst->type.cst_type) {
+                       case lpp_equal:
+                               if(sum != cst_val) {
+                                       fprintf(stderr, "constraint %s unsatisfied: %g != %g\n", cst->name, sum, cst_val);
+                               }
+                               break;
+                       case lpp_less:
+                               if(sum > cst_val) {
+                                       fprintf(stderr, "constraint %s unsatisfied: %g > %g\n", cst->name, sum, cst_val);
+                               }
+                               break;
+                       case lpp_greater:
+                               if(sum < cst_val) {
+                                       fprintf(stderr, "constraint %s unsatisfied: %g < %g\n", cst->name, sum, cst_val);
+                               }
+                               break;
+                       default:
+                               assert(0 && "unknown constraint type");
+               }
+next: ;
+       }
+}
+
+void lpp_dump(lpp_t *lpp, const char *filename)
+{
+       FILE *out = fopen(filename, "wt");
+       mps_write_mps(lpp, s_mps_fixed, out);
+       fclose(out);
+}
+
+void lpp_set_log(lpp_t *lpp, FILE *log)
+{
+       lpp->log = log;
+}
+
+
+static const char *lpp_cst_op_to_str(lpp_cst_t cst)
+{
+       switch(cst) {
+       case lpp_equal:
+               return "=";
+       case lpp_less:
+               return "<=";
+       case lpp_greater:
+               return ">=";
+       default:
+               return "";
+       }
+}
+
+void lpp_dump_plain(lpp_t *lpp, FILE *f)
+{
+       int i;
+
+       for(i = 0; i < lpp->cst_next; ++i) {
+               const matrix_elem_t *elm;
+               lpp_name_t *cst = lpp->csts[i];
+
+               fprintf(f, "%16s: ", cst->name);
+               matrix_foreach_in_row(lpp->m, cst->nr, elm) {
+                       lpp_name_t *var = lpp->vars[elm->col];
+                       /* TODO Perhaps better a define LPP_COL_RHS */
+                       if(elm->col > 0)
+                               fprintf(f, "%+4.1f*%-16s ", elm->val, var->name);
+               }
+
+               fprintf(f, "%3s %+4.1f\n",
+                               lpp_cst_op_to_str(cst->type.cst_type), matrix_get(lpp->m, cst->nr, 0));
+       }
+}
+
+/**
+ * Serialize a lpp to a file descriptor.
+ * @param comm The file descriptor.
+ * @param lpp The lpp.
+ */
+void lpp_serialize(lpp_comm_t *comm, const lpp_t *lpp, int with_names)
+{
+       int n, i;
+
+       lpp_writel(comm, with_names);
+       lpp_writel(comm, lpp->cst_next);
+       lpp_writel(comm, lpp->var_next);
+       lpp_writel(comm, lpp->opt_type);
+       lpp_writes(comm, lpp->name);
+
+       /* write options */
+       lpp_writel(comm, lpp->set_bound);
+       lpp_writed(comm, lpp->bound);
+       lpp_writed(comm, lpp->time_limit_secs);
+       lpp_writed(comm, lpp->emphasis);
+
+       for(i = 0; i < lpp->cst_next; ++i) {
+               lpp_name_t *name = lpp->csts[i];
+               lpp_writel(comm, name->nr);
+               lpp_writel(comm, name->value_kind);
+               lpp_writel(comm, name->type.cst_type);
+
+               if(with_names)
+                       lpp_writes(comm, name->name);
+       }
+
+       for(i = 0; i < lpp->var_next; ++i) {
+               lpp_name_t *name = lpp->vars[i];
+               lpp_writel(comm, name->nr);
+               lpp_writel(comm, name->value_kind);
+               lpp_writel(comm, name->type.var_type);
+
+               if(with_names)
+                       lpp_writes(comm, name->name);
+       }
+
+       {
+               const matrix_elem_t *elm;
+               n = 0;
+
+               matrix_foreach(lpp->m, elm)
+                       n++;
+
+               assert(n == matrix_get_entries(lpp->m));
+               lpp_writel(comm, n);
+               matrix_foreach(lpp->m, elm) {
+                       lpp_writel(comm, elm->row);
+                       lpp_writel(comm, elm->col);
+                       lpp_writed(comm, elm->val);
+               }
+       }
+}
+
+#define NAMELEN 64
+
+/**
+ * Deserialize an lpp from a file descriptor.
+ * @param comm The file descriptor.
+ * @return The Problem.
+ */
+lpp_t *lpp_deserialize(lpp_comm_t *comm)
+{
+       int i, n;
+       int with_names;
+
+       lpp_t *lpp = XMALLOCZ(lpp_t);
+
+       /* read general settings */
+       with_names    = lpp_readl(comm);
+       lpp->cst_next = lpp_readl(comm);
+       lpp->var_next = lpp_readl(comm);
+       lpp->opt_type = lpp_readl(comm);
+       lpp->name     = lpp_reads(comm);
+
+       /* read options */
+       lpp->set_bound       = lpp_readl(comm);
+       lpp->bound           = lpp_readd(comm);
+       lpp->time_limit_secs = lpp_readd(comm);
+       lpp->emphasis        = lpp_readd(comm);
+
+       lpp->cst_size = lpp->cst_next;
+       lpp->var_size = lpp->var_next;
+
+       lpp->cst2nr   = new_set(cmp_name_t, lpp->cst_next);
+       lpp->var2nr   = new_set(cmp_name_t, lpp->var_next);
+
+       lpp->csts     = XMALLOCNZ(lpp_name_t*, lpp->cst_next);
+       lpp->vars     = XMALLOCNZ(lpp_name_t*, lpp->var_next);
+       lpp->m        = new_matrix(lpp->cst_next, lpp->var_next);
+
+       for(i = 0; i < lpp->cst_next; ++i) {
+               lpp_name_t name, *res;
+
+               name.nr            = lpp_readl(comm);
+               name.value_kind    = lpp_readl(comm);
+               name.type.cst_type = lpp_readl(comm);
+
+               if(with_names) {
+                       name.name = lpp_reads(comm);
+               } else {
+                       char* buf = XMALLOCN(char, NAMELEN);
+                       snprintf(buf, NAMELEN, "c%d\n", name.nr);
+                       name.name = buf;
+               }
+
+               res = set_insert(lpp->cst2nr, &name, sizeof(name), HASH_NAME_T(&name));
+               lpp->csts[name.nr] = res;
+       }
+
+       for(i = 0; i < lpp->var_next; ++i) {
+               lpp_name_t name, *res;
+
+               name.nr            = lpp_readl(comm);
+               name.value_kind    = lpp_readl(comm);
+               name.type.var_type = lpp_readl(comm);
+
+               if(with_names) {
+                       name.name = lpp_reads(comm);
+               } else {
+                       char* buf = XMALLOCN(char, NAMELEN);
+                       snprintf(buf, NAMELEN, "v%d\n", name.nr);
+                       name.name = buf;
+               }
+
+               res = set_insert(lpp->var2nr, &name, sizeof(name), HASH_NAME_T(&name));
+               lpp->vars[name.nr] = res;
+       }
+
+       n = lpp_readl(comm);
+       for(i = 0; i < n; ++i) {
+               matrix_elem_t elm;
+               elm.row = lpp_readl(comm);
+               elm.col = lpp_readl(comm);
+               elm.val = lpp_readd(comm);
+               matrix_set(lpp->m, elm.row, elm.col, elm.val);
+       }
+
+       return lpp;
+}
+
+void lpp_serialize_values(lpp_comm_t *comm, const lpp_t *lpp, lpp_value_kind_t value_kind)
+{
+       int i, n;
+
+       for(i = 0, n = 0; i < lpp->var_next; ++i)
+               n += lpp->vars[i]->value_kind == value_kind;
+
+       /* Write the number of values to expect */
+       lpp_writel(comm, n);
+
+       /* send the values */
+       for(i = 0, n = lpp->var_next; i < n; ++i) {
+               const lpp_name_t *name = lpp->vars[i];
+               if(name->value_kind == value_kind) {
+                       lpp_writel(comm, name->nr);
+                       lpp_writed(comm, name->value);
+               }
+       }
+}
+
+void lpp_deserialize_values(lpp_comm_t *comm, lpp_t *lpp, lpp_value_kind_t value_kind)
+{
+       int i, n;
+
+       /* Get the number of values to read */
+       n = lpp_readl(comm);
+
+       for(i = 0; i < n; ++i) {
+               int nr = lpp_readl(comm);
+               lpp_name_t *name = lpp->vars[nr];
+
+               name->value_kind = value_kind;
+               name->value = lpp_readd(comm);
+       }
+}
+
+void lpp_serialize_stats(lpp_comm_t *comm, const lpp_t *lpp)
+{
+       lpp_writel(comm, lpp->sol_state);
+       lpp_writel(comm, lpp->iterations);
+       lpp_writed(comm, lpp->sol_time);
+       lpp_writed(comm, lpp->objval);
+       lpp_writed(comm, lpp->best_bound);
+}
+
+void lpp_deserialize_stats(lpp_comm_t *comm, lpp_t *lpp)
+{
+       lpp->sol_state  = lpp_readl(comm);
+       lpp->iterations = lpp_readl(comm);
+       lpp->sol_time   = lpp_readd(comm);
+       lpp->objval     = lpp_readd(comm);
+       lpp->best_bound = lpp_readd(comm);
+}
+
+void lpp_solve(lpp_t *lpp, const char* host, const char* solver)
+{
+       if (host == NULL || strlen(host) == 0) {
+               lpp_solver_func_t* f = lpp_find_solver(solver);
+               if (f != NULL)
+                       f(lpp);
+       } else {
+               lpp_solve_net(lpp, host, solver);
+       }
+}
+
diff --git a/ir/lpp/lpp.h b/ir/lpp/lpp.h
new file mode 100644 (file)
index 0000000..4bff2e3
--- /dev/null
@@ -0,0 +1,311 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        16.05.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * CVS-Id:      $Id: lpp.h 16112 2007-10-07 15:50:49Z mallon $
+ *
+ * Interface for specifying an milp. Does not define a solution method.
+ */
+#ifndef _LPP_H
+#define _LPP_H
+
+#include <stdio.h>
+#include <obstack.h>
+
+#include "set.h"
+
+#include "sp_matrix.h"
+
+typedef enum _lpp_opt_t {
+       lpp_minimize,
+       lpp_maximize
+} lpp_opt_t;
+
+typedef enum _lpp_cst_t {
+       lpp_objective,
+       lpp_equal,
+       lpp_less,
+       lpp_greater
+} lpp_cst_t;
+
+typedef enum _lpp_var_t {
+       lpp_invalid,
+       lpp_rhs,
+       lpp_continous,
+       lpp_binary
+} lpp_var_t;
+
+typedef enum _lpp_sol_state_t {
+       lpp_unknown,
+       lpp_infeasible,
+       lpp_inforunb,
+       lpp_unbounded,
+       lpp_feasible,
+       lpp_optimal
+} lpp_sol_state_t;
+
+typedef enum _lpp_value_kind_t {
+       lpp_none,
+       lpp_value_start,
+       lpp_value_solution,
+} lpp_value_kind_t;
+
+typedef enum _lpp_emphasis_t {
+       lpp_balanced,
+       lpp_feasability,
+       lpp_optimality,
+       lpp_bestbound,
+       lpp_hiddenfeasibility
+} lpp_emphasis_t;
+
+typedef struct _name_t {
+       const char *name;           /**< the name of the var/constraint supplied by user */
+       int nr;                     /**< the col/row number in the matrix */
+       lpp_value_kind_t value_kind;
+       double value;
+       union _type {
+               lpp_var_t var_type;
+               lpp_cst_t cst_type;
+       } type;
+} lpp_name_t;
+
+typedef struct _lpp_t {
+       /* The problem data */
+       const char     *name;            /**< A textual name for this problem */
+       FILE           *log;             /**< The log file. */
+       lpp_opt_t      opt_type;         /**< Optimization direction */
+       struct obstack obst;             /**< Obstack for variable names */
+       sp_matrix_t    *m;               /**< The matrix holding objective, constraints and rhs */
+
+       /* Cst/Var to Nr mapping */
+       set *cst2nr;                     /**< Holds name_t's for constraints */
+       set *var2nr;                     /**< Holds name_t's for variables */
+
+       /* Nr to Cst/Var mapping */
+       int        cst_size, var_size;   /**< Size of the csts/vars-arrays below */
+       int        cst_next, var_next;   /**< Next free position in arrays below */
+       lpp_name_t **csts;               /**< Pointers to the elements in the cst2nr set */
+       lpp_name_t **vars;               /**< Pointers to the elements in the var2nr set */
+       double     objval;               /**< OUT: Value of the objective function. */
+       double     best_bound;           /**< OUT: best bound to the integer solution. */
+       double     grow_factor;          /**< The factor by which the vars and constraints are enlarged */
+
+       /* Solving options */
+       int    set_bound;                /**< IN: Boolean flag to set a bound for the objective function. */
+       double bound;                    /**< IN: The bound. Only valid if set_bound == 1. */
+       double time_limit_secs;          /**< IN: Time limit to obey while solving (0.0 means no time limit) */
+
+       /* Solution stuff */
+       lpp_sol_state_t sol_state;       /**< State of the solution */
+       double          sol_time;        /**< Time in seconds */
+       unsigned        iterations;      /**< Number of iterations CPLEX needed to solve the ILP (whatever this means) */
+
+       char           *error;
+       unsigned       next_name_number; /**< for internal use only */
+       lpp_emphasis_t emphasis;         /**< On what should CPLEX concentrate (feasibility, bestbound, ...) */
+
+       /* some statistic stuff */
+       unsigned       send_time;        /**< in case of solve_net: send time in usec */
+       unsigned       recv_time;        /**< in case of solve_net: recv time in usec */
+       unsigned       n_elems;          /**< number of elements stored in the matrix */
+       unsigned       matrix_mem;       /**< memory used by matrix elements (in bytes) */
+       double         density;          /**< density of the matrix (percentage) */
+} lpp_t;
+
+#define ERR_NAME_NOT_ALLOWED -2
+
+/**
+ * Creates a new problem. Optimization type is minimize or maximize.
+ * Implicit row with name "obj" is inserted.
+ * Implicit col with name "rhs" is inserted.
+ */
+lpp_t *new_lpp(const char *name, lpp_opt_t opt_type);
+
+/**
+ * Creates a new problem. Optimization type is minimize or maximize.
+ * Implicit row with name "obj" is inserted.
+ * Implicit col with name "rhs" is inserted.
+ * @param estimated_vars   The estimated number of variables for the problem
+ * @param estimated_csts   The estimated number of constraints for the problem
+ * @param grow_factor      By which factor should the problem grow, if there are
+ *                         more variables or constraints than estimated.
+ */
+lpp_t *new_lpp_userdef(const char *name, lpp_opt_t opt_type,
+                                          int estimated_vars, int estimated_csts, double grow_factor);
+
+/**
+ * Frees the matrix embedded in the LPP.
+ */
+void free_lpp_matrix(lpp_t *lpp);
+
+/**
+ * Frees all memory allocated for LPP data structure.
+ */
+void free_lpp(lpp_t *lpp);
+
+/**
+ * @return The constant term in the objective function
+ */
+double lpp_get_fix_costs(lpp_t *lpp);
+
+/**
+ * Sets the constant term in the objective function to @p value
+ */
+void lpp_set_fix_costs(lpp_t *lpp, double value);
+
+/**
+ * Adds a constraint to a problem. If a constraint with the same name already
+ * exists nothing is altered, and the index of the existing entry is returned.
+ * @param cst_name The name of the constraint (1st char only alpha-numeric!). If NULL, a default name will be used.
+ * @param cst_type The type of constraint: objective, equality, less-or-equal, greater-or-equal
+ * @param rhs The right hand side value to set for this constraint.
+ * @return The (new or existing) index of the constraint
+ */
+int lpp_add_cst(lpp_t *lpp, const char *cst_name, lpp_cst_t cst_type, double rhs);
+
+/**
+ * Adds a constraint to a problem. If a constraint with the same name already
+ * exists it dies a horribly cruel death
+ * @param cst_name The name of the constraint (1st char only alpha-numeric!). If NULL, a default name will be used.
+ * @param cst_type The type of constraint: objective, equality, less-or-equal, greater-or-equal
+ * @param rhs The right hand side value to set for this constraint.
+ * @return The (new or existing) index of the constraint
+ */
+int lpp_add_cst_uniq(lpp_t *lpp, const char *cst_name, lpp_cst_t cst_type, double rhs);
+
+/**
+ * Returns the internal index of a constraint.
+ * @param cst_name The name of the constraint
+ * @return The internal index of constraint @p cst_name or -1 if it does not exist.
+ */
+int lpp_get_cst_idx(lpp_t *lpp, const char *cst_name);
+
+/**
+ * Returns the name of a constraint.
+ * @param index The internal index of a constraint.
+ * @param buf A buffer to hold the name of the constraint
+ * @param buf_size Size of the buffer
+ */
+void lpp_get_cst_name(lpp_t *lpp, int index, char *buf, size_t buf_size);
+
+/**
+ * Adds a variable to a problem. If a variable with the same name already
+ * exists nothing is altered, and the index of the existing entry is returned.
+ * @param var_name The name of the constraint (1st char only alpha-numeric!). If NULL, a default name will be used.
+ * @param var_type The type of variable: real, binary
+ * @param obj The objective value coefficient for this variable.
+ * @return The (new or existing) index of the variable
+ *
+ * NOTE: common integer or semi-continuous vars are not (yet) implemented
+ */
+int lpp_add_var(lpp_t *lpp, const char *var_name, lpp_var_t var_type, double obj);
+
+/**
+ * Same as lpp_add_var() but the user can supply a default value.
+ */
+int lpp_add_var_default(lpp_t *lpp, const char *var_name, lpp_var_t var_type, double obj, double startval);
+
+/**
+ * Returns the internal index of a variable.
+ * @param cst_name The name of the variable
+ * @return The internal index of variable @p var_name or -1 if it does not exist.
+ */
+int lpp_get_var_idx(lpp_t *lpp, const char *var_name);
+
+/**
+ * Returns the name of a variable.
+ * @param index The internal index of a variable.
+ * @param buf A buffer to hold the name of the variable
+ * @param buf_size Size of the buffer
+ */
+void lpp_get_var_name(lpp_t *lpp, int index, char *buf, size_t buf_size);
+
+/**
+ * Sets the factor of the variable @p var_name in constraint @p cst_name to @p value.
+ * @return -1 if constraint or variable name does not exist.
+ *          0 otherwise
+ */
+int lpp_set_factor(lpp_t *lpp, const char *cst_name, const char *var_name, double value);
+
+/**
+ * Same as lpp_set_factor but uses the internal indices instead of names.
+ * @return -1 if an index was invalid
+ *          0 otherwise
+ */
+int lpp_set_factor_fast(lpp_t *lpp, int cst_idx, int var_idx, double value);
+
+int lpp_set_factor_fast_bulk(lpp_t *lpp, int cst_idx, int *var_idx, int num_vars, double value);
+
+/**
+ * Set a starting value for a var.
+ * @param var_idx The index of the variable to set the value for.
+ * @param value The value to set.
+ */
+void lpp_set_start_value(lpp_t *lpp, int var_idx, double value);
+
+/**
+ * @return The solution values of the variables from index begin to index end.
+ */
+lpp_sol_state_t lpp_get_solution(lpp_t *lpp, double *values, int begin, int end);
+
+/**
+ * Dumps the lpp into a file with name @p filename in MPS-format
+ */
+void lpp_dump(lpp_t *lpp, const char *filename);
+
+/**
+ * Set the log file, where the solver should write to.
+ * @param lpp The problem.
+ * @param log The logfile. NULL for no logging.
+ */
+void lpp_set_log(lpp_t *lpp, FILE *log);
+
+/**
+ * Check the start values and list conflicting constraints.
+ */
+void lpp_check_startvals(lpp_t *lpp);
+
+/**
+ * Dump problem into a text file.
+ * @param lpp The problem.
+ * @param f   The file.
+ */
+void lpp_dump_plain(lpp_t *lpp, FILE *f);
+
+#define lpp_get_iter_cnt(lpp)         ((lpp)->iterations)
+#define lpp_get_sol_time(lpp)         ((lpp)->sol_time)
+#define lpp_get_sol_state(lpp)        ((lpp)->sol_state)
+#define lpp_get_var_count(lpp)        ((lpp)->var_next-1)
+#define lpp_get_cst_count(lpp)        ((lpp)->cst_next-1)
+#define lpp_get_sol_state(lpp)        ((lpp)->sol_state)
+#define lpp_get_var_sol(lpp,idx)      ((lpp)->vars[idx]->value)
+#define lpp_is_sol_valid(lpp)         (lpp_get_sol_state(lpp) >= lpp_feasible)
+
+#define lpp_set_time_limit(lpp,secs)  ((lpp)->time_limit_secs = secs)
+
+/**
+ * Set a bound for the objective function.
+ * @param lpp The problem.
+ * @param bound A bound for the objective function.
+ *              If the problem is a minimization problem, the bound
+ *              is a lower bound. If it is a maximization problem,
+ *              the bound is an upper bound.
+ */
+#define lpp_set_bound(lpp,bnd)        ((lpp)->set_bound = 1, (lpp)->bound = (bnd))
+
+/**
+ * Clear a set bound.
+ * @param lpp The problem.
+ */
+#define lpp_unset_bound(lpp)          ((lpp)->set_bound = 0)
+
+/**
+ * Solve an ILP.
+ * @param lpp    The problem.
+ * @param host   The host to solve on.
+ * @param solver The solver to use.
+ */
+void lpp_solve(lpp_t *lpp, const char* host, const char* solver);
+
+#endif /* _LPP_H */
diff --git a/ir/lpp/lpp_comm.c b/ir/lpp/lpp_comm.c
new file mode 100644 (file)
index 0000000..21ce281
--- /dev/null
@@ -0,0 +1,417 @@
+/**
+ * @file   lpp_comm.c
+ * @date   21.07.2005
+ * @author Sebastian Hack
+ *
+ * Protocol stuff for lpp server
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winsock2.h>
+
+#define vsnprintf _vsnprintf
+
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#endif
+
+#include "irtools.h"
+#include "debug.h"
+
+#include "lpp_comm.h"
+
+/* undef to disable debugging */
+#undef  ENABLE_DEBUGGING
+
+struct _lpp_comm_t {
+       int fd;
+       size_t buf_size;
+       char *w_pos;
+       char *r_pos;
+       char *r_max;
+       char *w_buf;
+       char *r_buf;
+};
+
+static inline firm_dbg_module_t *get_dbg_module(void)
+{
+       static firm_dbg_module_t *dbg = NULL;
+       if(!dbg) {
+               dbg = firm_dbg_register("lpp.comm");
+       }
+
+       return dbg;
+}
+
+#define dbg get_dbg_module()
+
+/**
+ * Try to read some bytes but block until a certain amount is read.
+ * @param fd The file descriptor.
+ * @param buf The buffer to read into.
+ * @param try The amount of bytes to try to read.
+ * @param at_least block until this many bytes are read.
+ * @return The number of bytes read or -1 on error.
+ */
+static ssize_t secure_recv(int fd, void *buf, size_t try, size_t at_least)
+{
+       ssize_t res;
+       size_t bytes_read = 0;
+       char *data = buf;
+
+       do {
+               res = recv(fd, &data[bytes_read], try - bytes_read, 0);
+               if(res <= 0) {
+                       if(res == 0 || errno != EAGAIN)
+                               return -1;
+                       continue;
+               }
+
+               bytes_read += res;
+
+       } while(bytes_read < at_least);
+
+       return bytes_read;
+}
+
+static ssize_t secure_send(int fd, const void *buf, size_t n)
+{
+       ssize_t res;
+       size_t bytes_written = 0;
+       const char *data = buf;
+
+       do {
+               res = send(fd, &data[bytes_written], n - bytes_written, 0);
+               if(res < 0) {
+                       if(errno != EAGAIN)
+                               return -1;
+                       continue;
+               }
+
+               bytes_written += res;
+
+       } while(bytes_written < n);
+
+       return n;
+}
+
+ssize_t lpp_flush(lpp_comm_t *comm)
+{
+       ssize_t res = 0;
+       if(comm->w_pos - comm->w_buf > 0) {
+               DBG((dbg, LEVEL_1, "flushing %d bytes\n", comm->w_pos - comm->w_buf));
+               res = secure_send(comm->fd, comm->w_buf, comm->w_pos - comm->w_buf);
+               if(res < 0)
+                       return res;
+
+               comm->w_pos = comm->w_buf;
+       }
+       return res;
+}
+
+static ssize_t lpp_write(lpp_comm_t *comm, const void *buf, size_t len)
+{
+       assert(comm->w_pos - comm->w_buf >= 0);
+
+       DBG((dbg, LEVEL_1, "write of length %d\n", len));
+       if(len > 0) {
+               size_t free = (comm->w_buf + comm->buf_size) - comm->w_pos;
+               size_t copy = MIN(free, len);
+               size_t rest = len - copy;
+               const char *pos   = buf;
+
+               DBG((dbg, LEVEL_1, "\tfree = %d, copy = %d, rest = %d\n", free, copy, rest));
+               if(copy > 0) {
+                       memcpy(comm->w_pos, pos, copy);
+                       comm->w_pos += copy;
+                       pos         += copy;
+               }
+
+               /*
+                * Not everything in buf fits into the buffer,
+                * so flush the buffer and write the rest.
+                */
+               if(rest > 0) {
+                       size_t i;
+                       size_t n_direct = rest / comm->buf_size;
+                       size_t last_rest;
+
+                       if(lpp_flush(comm) < 0)
+                               return -1;
+
+                       for(i = 0; i < n_direct; ++i) {
+                               if(secure_send(comm->fd, pos, comm->buf_size) < 0)
+                                       return -1;
+
+                               pos += comm->buf_size;
+                       }
+
+                       last_rest = ((const char *) buf + len) - pos;
+
+                       if(last_rest > 0) {
+                               assert(last_rest < comm->buf_size);
+                               assert(comm->w_pos == comm->w_buf);
+                               memcpy(comm->w_pos, pos, last_rest);
+                               comm->w_pos += last_rest;
+                       }
+               }
+       }
+
+       return len;
+}
+
+static ssize_t lpp_read(lpp_comm_t *comm, void *buf, size_t len)
+{
+       DBG((dbg, LEVEL_1, "read of length %d\n", len));
+       if(len > 0) {
+               size_t left = comm->r_max - comm->r_pos;
+               size_t copy = MIN(left, len);
+               size_t rest = len - copy;
+               char *pos   = buf;
+
+               DBG((dbg, LEVEL_1, "\tleft = %d, copy = %d, rest = %d\n", left, copy, rest));
+               if(copy > 0) {
+                       memcpy(pos, comm->r_pos, copy);
+                       pos         += copy;
+                       comm->r_pos += copy;
+               }
+
+               /* We want to read more than the buffer can provide. */
+               if(rest > 0) {
+                       size_t bs = comm->buf_size;
+                       size_t n_direct = rest / comm->buf_size;
+                       size_t i;
+                       size_t last_rest;
+
+                       /*
+                        * The buffer is now completely read, so
+                        * reset the pointers.
+                        */
+                       comm->r_pos = comm->r_buf;
+                       comm->r_max = comm->r_buf;
+
+                       for(i = 0; i < n_direct; ++i) {
+                               if(secure_recv(comm->fd, pos, bs, bs) < 0)
+                                       return -1;
+
+                               pos += comm->buf_size;
+                       }
+
+                       last_rest = ((const char *) buf + len) - pos;
+
+                       if(last_rest > 0) {
+                               ssize_t bytes_read = 0;
+
+                               assert(last_rest < comm->buf_size);
+                               assert(comm->r_pos == comm->r_buf);
+
+                               bytes_read = secure_recv(comm->fd, comm->r_buf, bs, last_rest);
+                               if(bytes_read < 0)
+                                       return -1;
+
+                               memcpy(pos, comm->r_buf, last_rest);
+                               comm->r_pos = comm->r_buf + last_rest;
+                               comm->r_max = comm->r_buf + bytes_read;
+                       }
+               }
+       }
+
+       return len;
+}
+
+lpp_comm_t *lpp_comm_new(int fd, size_t buf_size)
+{
+       lpp_comm_t *res = malloc(sizeof(res[0]));
+
+       res->fd       = fd;
+       res->w_buf    = malloc(buf_size);
+       res->w_pos    = res->w_buf;
+       res->r_buf    = malloc(buf_size);
+       res->r_pos    = res->r_buf;
+       res->r_max    = res->r_buf;
+       res->buf_size = buf_size;
+
+       return res;
+}
+
+int lpp_comm_fileno(const lpp_comm_t *comm)
+{
+       return comm->fd;
+}
+
+void lpp_comm_free(lpp_comm_t *comm)
+{
+       free(comm->w_buf);
+       free(comm->r_buf);
+       free(comm);
+}
+
+void lpp_print_err(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       vfprintf(stderr, fmt, args);
+       va_end(args);
+}
+
+void lpp_writel(lpp_comm_t *comm, uint32_t x)
+{
+       x = htonl(x);
+       ERRNO_CHECK(lpp_write(comm, &x, sizeof(x)), !=, (ssize_t)sizeof(x));
+}
+
+void lpp_writed(lpp_comm_t *comm, double dbl)
+{
+       ERRNO_CHECK(lpp_write(comm, &dbl, sizeof(dbl)), !=, (ssize_t)sizeof(dbl));
+}
+
+void lpp_writes(lpp_comm_t *comm, const char *str)
+{
+       size_t n = strlen(str);
+       lpp_writel(comm, n);
+       ERRNO_CHECK(lpp_write(comm, str, n), !=, (ssize_t) n);
+}
+
+uint32_t lpp_readl(lpp_comm_t *comm)
+{
+       uint32_t res;
+
+       ERRNO_CHECK(lpp_read(comm, &res, sizeof(res)), !=, (ssize_t)sizeof(res));
+       return ntohl(res);
+}
+
+int lpp_read_cmd(lpp_comm_t *comm)
+{
+       uint32_t res = 0;
+       int retval;
+
+       for(;;) {
+               retval = recv(comm->fd, (char *)&res, sizeof(res), 0);
+               if(retval < 0) {
+                       if(errno != EAGAIN)
+                               return -1;
+               }
+
+               else
+                       break;
+       }
+
+       return (int) ntohl(res);
+}
+
+double lpp_readd(lpp_comm_t *comm)
+{
+       double res;
+       ERRNO_CHECK(lpp_read(comm, &res, sizeof(res)), !=, (ssize_t)sizeof(res));
+       return res;
+}
+
+char *lpp_reads(lpp_comm_t *comm)
+{
+       size_t len = lpp_readl(comm);
+       char *res = malloc(sizeof(char) * (len + 1));
+
+       ERRNO_CHECK(lpp_read(comm, res, len), !=, (ssize_t) len);
+       res[len] = '\0';
+       return res;
+}
+
+char *lpp_readbuf(lpp_comm_t *comm, char *buf, size_t buflen)
+{
+       char dummy[1024];
+       size_t i;
+       size_t n         = buflen - 1;
+       size_t len       = lpp_readl(comm);
+       size_t max_read  = n < len ? n : len;
+       size_t rest      = len - max_read;
+
+       if(buflen > 0 && buf != NULL) {
+               ERRNO_CHECK(lpp_read(comm, buf, max_read), !=, (ssize_t) max_read);
+               buf[max_read] = '\0';
+       }
+       else
+               rest = len;
+
+       /* eat up data that didnt fit into the string */
+       for(i = 0, n = rest / sizeof(dummy); i < n; ++i)
+               ERRNO_CHECK(lpp_read(comm, dummy, sizeof(dummy)), !=, (ssize_t)sizeof(dummy));
+
+       if(rest % sizeof(dummy) > 0)
+               ERRNO_CHECK(lpp_read(comm, dummy, rest % sizeof(dummy)), !=,
+                                       (ssize_t) (rest % sizeof(dummy)) );
+
+       return buf;
+}
+
+int lpp_ack(lpp_comm_t *comm, char *buf, size_t buflen)
+{
+       int res = 0;
+       int cmd = lpp_readl(comm);
+
+       switch(cmd) {
+       case LPP_CMD_OK:
+               res = 1;
+               break;
+       case LPP_CMD_BAD:
+               lpp_readbuf(comm, buf, buflen);
+       default:
+               res = 0;
+       }
+
+       return res;
+}
+
+void lpp_send_res(lpp_comm_t *comm, int ok, const char *fmt, ...)
+{
+       if(!ok) {
+               char buf[1024];
+               va_list args;
+
+               va_start(args, fmt);
+               vsnprintf(buf, sizeof(buf), fmt, args);
+               va_end(args);
+
+               lpp_writel(comm, LPP_CMD_BAD);
+               lpp_writes(comm, buf);
+       } else {
+               lpp_writel(comm, LPP_CMD_OK);
+       }
+}
+
+void lpp_send_ack(lpp_comm_t *comm)
+{
+       lpp_send_res(comm, 1, "");
+}
+
+const char *lpp_get_cmd_name(int cmd)
+{
+       switch(cmd) {
+       case LPP_CMD_BAD:       return "BAD";
+       case LPP_CMD_OK:        return "OK";
+       case LPP_CMD_PROBLEM:   return "PROBLEM";
+       case LPP_CMD_SOLUTION:  return "SOLUTION";
+       case LPP_CMD_SOLVER:    return "SOLVER";
+       case LPP_CMD_BYE:       return "BYE";
+       case LPP_CMD_SOLVERS:   return "SOLVERS";
+       case LPP_CMD_SET_DEBUG: return "SET_DEBUG";
+       case LPP_CMD_INFO:      return "INFO";
+       case LPP_CMD_LAST:
+               break;
+       }
+
+       return "<unknown>";
+}
diff --git a/ir/lpp/lpp_comm.h b/ir/lpp/lpp_comm.h
new file mode 100644 (file)
index 0000000..4c425d7
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ * @file   lpp_server.h
+ * @date   19.07.2005
+ * @author Sebastian Hack
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+
+#ifndef _LPP_COMM_H
+#define _LPP_COMM_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#define LPP_PORT    2175
+#define LPP_BUFSIZE (1 << 20)
+
+enum {
+       LPP_CMD_BAD,
+       LPP_CMD_OK,
+       LPP_CMD_PROBLEM,
+       LPP_CMD_SOLUTION,
+       LPP_CMD_SOLVER,
+       LPP_CMD_BYE,
+       LPP_CMD_SOLVERS,
+       LPP_CMD_SET_DEBUG,
+       LPP_CMD_INFO,
+       LPP_CMD_LAST
+};
+
+#define BASIC_ERR_CHECK(expr,op,cond,fmt,last) \
+do { \
+  int err_check_res; \
+  if((err_check_res = (expr)) op cond) { \
+    fprintf(stderr, "%s(%u): %d = %s(%d): ", \
+        __FILE__, (unsigned) __LINE__, err_check_res, #expr, cond); \
+    lpp_print_err fmt; \
+    fprintf(stderr, "\n"); \
+    last; \
+  } \
+} while(0)
+
+#define BASIC_ERRNO_CHECK(expr,op,cond,last) \
+do { \
+  int _basic_errno_check_res = (expr); \
+  if(_basic_errno_check_res op cond) { \
+    fprintf(stderr, "%s(%u): %d = %s(%d): %s\n", \
+        __FILE__, (unsigned) __LINE__, _basic_errno_check_res, #expr, (int) cond, strerror(errno)); \
+    last; \
+  } \
+} while(0)
+
+#define ERR_CHECK_RETURN(expr, op, cond, fmt, retval) \
+  BASIC_ERR_CHECK(expr, op, cond, fmt, return retval)
+
+#define ERRNO_CHECK_RETURN(expr, op, cond, retval) \
+  BASIC_ERRNO_CHECK(expr, op, cond, return retval)
+
+#define ERR_CHECK_RETURN_VOID(expr, op, cond, fmt) \
+  BASIC_ERR_CHECK(expr, op, cond, fmt, return)
+
+#define ERRNO_CHECK_RETURN_VOID(expr, op, cond) \
+  BASIC_ERRNO_CHECK(expr, op, cond, return)
+
+#define ERR_CHECK(expr, op, cond, fmt) \
+  BASIC_ERR_CHECK(expr, op, cond, fmt, (void) 0)
+
+#define ERRNO_CHECK(expr, op, cond) \
+  BASIC_ERRNO_CHECK(expr, op, cond, (void) 0)
+
+typedef struct _lpp_comm_t lpp_comm_t;
+
+lpp_comm_t *lpp_comm_new(int fd, size_t buf_size);
+
+int lpp_comm_fileno(const lpp_comm_t *comm);
+
+ssize_t lpp_flush(lpp_comm_t *comm);
+
+void lpp_comm_free(lpp_comm_t *comm);
+
+void lpp_print_err(const char *fmt, ...);
+
+void lpp_writel(lpp_comm_t *comm, uint32_t x);
+
+void lpp_writed(lpp_comm_t *comm, double dbl);
+
+void lpp_writes(lpp_comm_t *comm, const char *str);
+
+uint32_t lpp_readl(lpp_comm_t *comm);
+
+int lpp_read_cmd(lpp_comm_t *comm);
+
+double lpp_readd(lpp_comm_t *comm);
+
+char *lpp_reads(lpp_comm_t *comm);
+
+char *lpp_readbuf(lpp_comm_t *comm, char *buf, size_t buflen);
+
+int lpp_ack(lpp_comm_t *comm, char *buf, size_t buflen);
+
+void lpp_send_res(lpp_comm_t *comm, int ok, const char *fmt, ...);
+
+void lpp_send_ack(lpp_comm_t *comm);
+
+const char *lpp_get_cmd_name(int cmd);
+
+#endif
diff --git a/ir/lpp/lpp_cplex.c b/ir/lpp/lpp_cplex.c
new file mode 100644 (file)
index 0000000..544e5f8
--- /dev/null
@@ -0,0 +1,264 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        02.06.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#include "config.h"
+
+#ifdef WITH_CPLEX
+
+#include "lpp_cplex.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ilcplex/cplex.h>
+
+#include "obst.h"
+#include "stat_timing.h"
+#include "sp_matrix.h"
+
+static char cpx_cst_encoding[4] = "?ELG";
+static char cpx_var_encoding[4] = "??CB";
+
+typedef struct _cpx_t {
+       lpp_t *lpp;
+       CPXENVptr env;
+       CPXLPptr prob;
+       int status;
+       char buf[1024];
+} cpx_t;
+
+static void chk_cpx_err(cpx_t *cpx)
+{
+       if (cpx->status) {
+               if (CPXgeterrorstring(cpx->env, cpx->status, cpx->buf))
+                       printf("%s", cpx->buf);
+               else
+                       printf("Unknown CPLEX error\n");
+               assert(0);
+       }
+}
+
+static cpx_t *new_cpx(lpp_t *lpp)
+{
+       cpx_t *cpx = XMALLOCZ(cpx_t);
+       cpx->lpp = lpp;
+       cpx->env = CPXopenCPLEX(&cpx->status);
+       chk_cpx_err(cpx);
+       cpx->prob = CPXcreateprob(cpx->env, &cpx->status, lpp->name);
+       chk_cpx_err(cpx);
+       CPXchgobjsen(cpx->env, cpx->prob, (lpp->opt_type == lpp_minimize)?1:-1);
+       chk_cpx_err(cpx);
+       if (lpp->log && CPXsetlogfile(cpx->env, lpp->log))
+               lpp->log = NULL;
+       return cpx;
+}
+
+static void free_cpx(cpx_t *cpx)
+{
+       CPXfreeprob(cpx->env, &cpx->prob);
+       CPXcloseCPLEX(&cpx->env);
+       free(cpx);
+}
+
+/**
+ * Build CPLEX data structure from LPP matrix.
+ * @note: The LPP matrix is freed after this step, to save memory.
+ */
+static void cpx_construct(cpx_t *cpx)
+{
+       const matrix_elem_t *elem;
+       int                  i, o, sv_cnt;
+       int                  numcols, numrows, numentries;
+       int                  objsen, *matbeg, *matcnt, *matind, *indices;
+       double               *obj, *rhs, *matval, *lb, *ub, *startv;
+       char                 *sense, *vartype;
+       char                 **colname, **rowname;
+       struct obstack       obst;
+       lpp_t                *lpp = cpx->lpp;
+
+       numcols    = lpp->var_next-1;
+       numrows    = lpp->cst_next-1;
+       numentries = matrix_get_entries(lpp->m);
+       objsen     = lpp->opt_type == lpp_minimize ? 1 : -1;
+       obstack_init(&obst);
+
+       obj     = obstack_alloc(&obst, numcols * sizeof(*obj));
+       lb      = obstack_alloc(&obst, numcols * sizeof(*lb));
+       ub      = obstack_alloc(&obst, numcols * sizeof(*ub));
+       colname = obstack_alloc(&obst, numcols * sizeof(*colname));
+       rowname = obstack_alloc(&obst, numrows * sizeof(*rowname));
+       vartype = obstack_alloc(&obst, numcols * sizeof(*vartype));
+       indices = obstack_alloc(&obst, numcols * sizeof(*indices));
+       startv  = obstack_alloc(&obst, numcols * sizeof(*startv));
+       matbeg  = obstack_alloc(&obst, numcols * sizeof(*matbeg));
+       matcnt  = obstack_alloc(&obst, numcols * sizeof(*matcnt));
+       matind  = obstack_alloc(&obst, numentries * sizeof(*matind));
+       matval  = obstack_alloc(&obst, numentries * sizeof(*matval));
+       rhs     = obstack_alloc(&obst, numrows * sizeof(*rhs));
+       sense   = obstack_alloc(&obst, numrows * sizeof(*sense));
+
+       o      = 0;
+       sv_cnt = 0;
+       /* fill the CPLEX matrix*/
+       for (i = 0; i < numcols; ++i) {
+               lpp_name_t *curr_var = lpp->vars[1+i];
+
+               obj[i] = matrix_get(lpp->m, 0, 1+i);
+               lb[i]  = 0.0;
+               ub[i]  = CPX_INFBOUND;
+
+               colname[i] = (char*) curr_var->name;
+               vartype[i] = cpx_var_encoding[curr_var->type.var_type];
+
+               if (curr_var->value_kind == lpp_value_start) {
+                       indices[sv_cnt]  = i;
+                       startv[sv_cnt++] = curr_var->value;
+               }
+
+               matbeg[i] = o;
+               matcnt[i] = 0;
+               matrix_foreach_in_col(lpp->m, 1 + i, elem) {
+                       if (elem->row == 0)
+                               continue;
+                       matind[o] = elem->row-1;
+                       matval[o] = elem->val;
+                       matcnt[i]++;
+                       o++;
+               }
+       }
+
+       /* get constraint stuff (right hand side, type, name) */
+       for (i = 0; i < numrows; ++i) {
+               lpp_name_t *curr_cst = lpp->csts[1 + i];
+
+               rhs[i]     = matrix_get(lpp->m, 1 + i, 0);
+               sense[i]   = cpx_cst_encoding[curr_cst->type.cst_type];
+               rowname[i] = (char*) curr_cst->name;
+       }
+
+       cpx->status = CPXcopylpwnames(cpx->env, cpx->prob,
+                                               numcols, numrows, objsen,
+                                               obj, rhs, sense,
+                                               matbeg, matcnt, matind, matval,
+                                               lb, ub, NULL,
+                                               colname, rowname);
+       chk_cpx_err(cpx);
+
+       cpx->status = CPXcopyctype(cpx->env, cpx->prob, vartype);
+       chk_cpx_err(cpx);
+       cpx->status = CPXcopymipstart(cpx->env, cpx->prob, sv_cnt, indices, startv);
+       chk_cpx_err(cpx);
+
+       obstack_free(&obst, NULL);
+       free_lpp_matrix(lpp);
+}
+
+static void cpx_solve(cpx_t *cpx)
+{
+       int i, CPX_state, numcols;
+       double *values;
+       timing_ticks_t tvb;
+       timing_ticks_t tva;
+
+       lpp_t *lpp = cpx->lpp;
+       numcols = CPXgetnumcols(cpx->env, cpx->prob);
+       chk_cpx_err(cpx);
+
+       /* set performance parameters */
+       // CPXsetintparam(cpx->env, CPX_PARAM_MIPSTART, CPX_ON);
+       CPXsetintparam(cpx->env, CPX_PARAM_MIPORDTYPE, CPX_MIPORDER_COST);
+       /* output every search tree node */
+       // CPXsetintparam(cpx->env, CPX_PARAM_MIPINTERVAL, 1);
+
+       /* experimental switches */
+       // CPXsetintparam(cpx->env, CPX_PARAM_VARSEL, CPX_VARSEL_STRONG);
+       // CPXsetdblparam(cpx->env, CPX_PARAM_BTTOL, 1.0);
+       // CPXsetintparam(cpx->env, CPX_PARAM_BRDIR, CPX_BRDIR_UP);
+
+
+       /* Set the time limit appropriately */
+       if(lpp->time_limit_secs > 0.0)
+               CPXsetdblparam(cpx->env, CPX_PARAM_TILIM, lpp->time_limit_secs);
+
+       /*
+        * If we have enough time, we instruct cplex to imply some
+        * of its higher order magic to pursue the best solution
+        */
+       if(lpp->emphasis) {
+         CPXsetintparam(cpx->env, CPX_PARAM_MIPEMPHASIS, lpp->emphasis);
+       }
+
+       /*
+        * If a bound of the objective function is supplied,
+        * set it accordingly, dependign on minimization or maximization.
+        */
+       if(lpp->set_bound) {
+               CPXsetdblparam(cpx->env, (lpp->opt_type == lpp_minimize
+                                       ? CPX_PARAM_OBJLLIM : CPX_PARAM_OBJULIM), lpp->bound);
+       }
+
+       /* turn on the fancy messages :) */
+       // CPXsetintparam (cpx->env, CPX_PARAM_SCRIND, CPX_ON);
+
+       /* solve */
+       timing_ticks(&tvb);
+       cpx->status = CPXmipopt(cpx->env, cpx->prob);
+       timing_ticks(&tva);
+       chk_cpx_err(cpx);
+
+       /* get solution status */
+       CPX_state = CPXgetstat(cpx->env, cpx->prob);
+       {
+         char buf[512];
+         CPXgetstatstring(cpx->env, CPX_state, buf);
+         fprintf(stderr, "%s\n", buf);
+       }
+       switch (CPX_state) {
+               case CPXMIP_INFEASIBLE:
+               case CPX_STAT_INFEASIBLE:   lpp->sol_state = lpp_infeasible; break;
+               case CPXMIP_INForUNBD:
+               case CPX_STAT_INForUNBD:    lpp->sol_state = lpp_inforunb; break;
+               case CPXMIP_UNBOUNDED:
+               case CPX_STAT_UNBOUNDED:    lpp->sol_state = lpp_unbounded; break;
+               case CPXMIP_ABORT_FEAS:
+               case CPXMIP_FAIL_FEAS:
+               case CPXMIP_MEM_LIM_FEAS:
+               case CPXMIP_NODE_LIM_FEAS:
+               case CPXMIP_TIME_LIM_FEAS:  lpp->sol_state = lpp_feasible; break;
+               case CPXMIP_OPTIMAL:
+               case CPXMIP_OPTIMAL_TOL:    /* TODO: Is this ok? Read the docu more closely */
+               case CPX_STAT_OPTIMAL:      lpp->sol_state = lpp_optimal; break;
+               default:                    lpp->sol_state = lpp_unknown;
+       }
+
+       /* get variable solution values */
+       values = alloca(numcols * sizeof(*values));
+       CPXgetmipx(cpx->env, cpx->prob, values, 0, numcols-1);
+       chk_cpx_err(cpx);
+       for(i=0; i<numcols; ++i) {
+               lpp->vars[1+i]->value = values[i];
+               lpp->vars[1+i]->value_kind = lpp_value_solution;
+       }
+
+       /* Get the value of the objective function. */
+       CPXgetmipobjval(cpx->env, cpx->prob, &lpp->objval);
+       CPXgetbestobjval(cpx->env, cpx->prob, &lpp->best_bound);
+
+       /* get some statistics */
+       timing_ticks_sub(tva, tvb);
+       lpp->sol_time = timing_ticks_dbl(tva);
+       lpp->iterations = CPXgetmipitcnt(cpx->env, cpx->prob);
+}
+
+void lpp_solve_cplex(lpp_t *lpp)
+{
+       cpx_t *cpx = new_cpx(lpp);
+       cpx_construct(cpx);
+       cpx_solve(cpx);
+       free_cpx(cpx);
+}
+
+#endif
diff --git a/ir/lpp/lpp_cplex.h b/ir/lpp/lpp_cplex.h
new file mode 100644 (file)
index 0000000..4249477
--- /dev/null
@@ -0,0 +1,16 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        02.06.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#ifndef LPP_CPLEX_H
+#define LPP_CPLEX_H
+
+#include "lpp.h"
+
+#ifdef WITH_CPLEX
+void lpp_solve_cplex(lpp_t *lpp);
+#endif
+
+#endif
diff --git a/ir/lpp/lpp_gurobi.c b/ir/lpp/lpp_gurobi.c
new file mode 100644 (file)
index 0000000..7ec41a0
--- /dev/null
@@ -0,0 +1,240 @@
+/**
+ * Author:      Matthias Braun
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#include "config.h"
+
+#ifdef WITH_GUROBI
+#include "lpp_gurobi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "obst.h"
+
+#include <gurobi_c.h>
+
+#include "error.h"
+#include "sp_matrix.h"
+
+static char gurobi_cst_encoding[4] = { 0, GRB_EQUAL, GRB_LESS_EQUAL, GRB_GREATER_EQUAL };
+static char gurobi_var_encoding[4] = { 0, 0, GRB_CONTINUOUS, GRB_BINARY };
+
+typedef struct _gurobi_t {
+       lpp_t *lpp;
+       GRBenv *env;
+       GRBmodel *model;
+} gurobi_t;
+
+static void check_gurobi_error(gurobi_t *grb, int error)
+{
+       if (error != 0) {
+               panic("gurobi error: %s", GRBgeterrormsg(grb->env));
+       }
+}
+
+static gurobi_t *new_gurobi(lpp_t *lpp)
+{
+       int error;
+
+       gurobi_t *grb = XMALLOCZ(gurobi_t);
+       grb->lpp = lpp;
+       error = GRBloadenv(&grb->env, NULL);
+       check_gurobi_error(grb, error);
+       error = GRBsetlogfile(grb->env, lpp->log);
+       check_gurobi_error(grb, error);
+
+       return grb;
+}
+
+static void free_gurobi(gurobi_t *grb)
+{
+       GRBfreeenv(grb->env);
+       free(grb);
+}
+
+/**
+ * Build CPLEX data structure from LPP matrix.
+ * @note: The LPP matrix is freed after this step, to save memory.
+ */
+static void gurobi_construct(gurobi_t *grb)
+{
+       const matrix_elem_t *elem;
+       int                  i, o;
+       //int                  sv_cnt;
+       //int                 *indices;
+       //double              *startv;
+       int                  numcols, numrows, numentries;
+       int                  objsen, *matbeg, *matcnt, *matind;
+       double               *obj, *rhs, *matval, *lb;
+       char                 *sense, *vartype;
+       char                 **colname, **rowname;
+       struct obstack       obst;
+       lpp_t                *lpp = grb->lpp;
+       int                  error;
+
+       numcols    = lpp->var_next-1;
+       numrows    = lpp->cst_next-1;
+       numentries = matrix_get_entries(lpp->m);
+       objsen     = lpp->opt_type == lpp_minimize ? 1 : -1;
+       obstack_init(&obst);
+
+       obj     = obstack_alloc(&obst, numcols * sizeof(*obj));
+       lb      = obstack_alloc(&obst, numcols * sizeof(*lb));
+       colname = obstack_alloc(&obst, numcols * sizeof(*colname));
+       rowname = obstack_alloc(&obst, numrows * sizeof(*rowname));
+       vartype = obstack_alloc(&obst, numcols * sizeof(*vartype));
+       //indices = obstack_alloc(&obst, numcols * sizeof(*indices));
+       //startv  = obstack_alloc(&obst, numcols * sizeof(*startv));
+       matbeg  = obstack_alloc(&obst, numcols * sizeof(*matbeg));
+       matcnt  = obstack_alloc(&obst, numcols * sizeof(*matcnt));
+       matind  = obstack_alloc(&obst, numentries * sizeof(*matind));
+       matval  = obstack_alloc(&obst, numentries * sizeof(*matval));
+       rhs     = obstack_alloc(&obst, numrows * sizeof(*rhs));
+       sense   = obstack_alloc(&obst, numrows * sizeof(*sense));
+
+       o      = 0;
+       //sv_cnt = 0;
+       /* fill the CPLEX matrix*/
+       for (i = 0; i < numcols; ++i) {
+               lpp_name_t *curr_var = lpp->vars[1+i];
+
+               obj[i] = matrix_get(lpp->m, 0, 1+i);
+               lb[i]  = 0.0;
+
+               colname[i] = (char*) curr_var->name;
+               vartype[i] = gurobi_var_encoding[curr_var->type.var_type];
+
+#if 0
+               if (curr_var->value_kind == lpp_value_start) {
+                       panic("start values not supported in gurobi yet");
+                       indices[sv_cnt]  = i;
+                       startv[sv_cnt++] = curr_var->value;
+               }
+#endif
+
+               matbeg[i] = o;
+               matcnt[i] = 0;
+               matrix_foreach_in_col(lpp->m, 1 + i, elem) {
+                       if (elem->row == 0)
+                               continue;
+                       matind[o] = elem->row-1;
+                       matval[o] = elem->val;
+                       matcnt[i]++;
+                       o++;
+               }
+       }
+
+       /* get constraint stuff (right hand side, type, name) */
+       for (i = 0; i < numrows; ++i) {
+               lpp_name_t *curr_cst = lpp->csts[1 + i];
+
+               rhs[i]     = matrix_get(lpp->m, 1 + i, 0);
+               sense[i]   = gurobi_cst_encoding[curr_cst->type.cst_type];
+               rowname[i] = (char*) curr_cst->name;
+       }
+
+       error = GRBloadmodel(grb->env, &grb->model, lpp->name, numcols, numrows,
+                            objsen, 0, obj, sense, rhs, matbeg, matcnt, matind,
+                            matval, lb, NULL, vartype, colname, rowname);
+       check_gurobi_error(grb, error);
+
+       obstack_free(&obst, NULL);
+       free_lpp_matrix(lpp);
+}
+
+static void gurobi_solve(gurobi_t *grb)
+{
+       lpp_t *lpp = grb->lpp;
+       int i;
+       int optimstatus;
+       int error;
+       int numcols = lpp->var_next-1;
+       double *values;
+       double  iterations;
+
+       /* set performance parameters */
+       // CPXsetintparam(grb->env, CPX_PARAM_MIPSTART, CPX_ON);
+       //CPXsetintparam(grb->env, CPX_PARAM_MIPORDTYPE, CPX_MIPORDER_COST);
+       /* output every search tree node */
+       // CPXsetintparam(grb->env, CPX_PARAM_MIPINTERVAL, 1);
+
+       /* experimental switches */
+       // CPXsetintparam(grb->env, CPX_PARAM_VARSEL, CPX_VARSEL_STRONG);
+       // CPXsetdblparam(grb->env, CPX_PARAM_BTTOL, 1.0);
+       // CPXsetintparam(grb->env, CPX_PARAM_BRDIR, CPX_BRDIR_UP);
+
+       /* Set the time limit appropriately */
+       if(lpp->time_limit_secs > 0.0) {
+               error = GRBsetdblparam(grb->env, GRB_DBL_PAR_TIMELIMIT, lpp->time_limit_secs);
+               check_gurobi_error(grb, error);
+       }
+
+       /*
+        * If we have enough time, we instruct cplex to imply some
+        * of its higher order magic to pursue the best solution
+        */
+       if(lpp->emphasis) {
+               /* not implemented */
+       }
+
+       /*
+        * If a bound of the objective function is supplied,
+        * set it accordingly, dependign on minimization or maximization.
+        */
+       if(lpp->set_bound) {
+               //panic("bound not implemented yet");
+               fprintf(stderr, "Warning: gurobi bound not implemented yet\n");
+       }
+
+       /* solve */
+       error = GRBoptimize(grb->model);
+       check_gurobi_error(grb, error);
+
+       /* get solution status */
+       error = GRBgetintattr(grb->model, GRB_INT_ATTR_STATUS, &optimstatus);
+       check_gurobi_error(grb, error);
+
+       switch (optimstatus) {
+       case GRB_OPTIMAL:           lpp->sol_state = lpp_optimal; break;
+       case GRB_INFEASIBLE:        lpp->sol_state = lpp_infeasible; break;
+       case GRB_INF_OR_UNBD:       lpp->sol_state = lpp_inforunb; break;
+       case GRB_UNBOUNDED:         lpp->sol_state = lpp_unbounded; break;
+       /* TODO: is this correct? */
+       default:                    lpp->sol_state = lpp_feasible; break;
+       }
+
+       /* get variable solution values */
+       values = alloca(numcols * sizeof(*values));
+       error = GRBgetdblattrarray(grb->model, GRB_DBL_ATTR_X, 0, numcols, values);
+       check_gurobi_error(grb, error);
+       for(i=0; i<numcols; ++i) {
+               lpp->vars[1+i]->value      = values[i];
+               lpp->vars[1+i]->value_kind = lpp_value_solution;
+       }
+
+       /* Get the value of the objective function. */
+       error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_OBJVAL, &lpp->objval);
+       check_gurobi_error(grb, error);
+       error = GRBgetdblattr(grb->model , GRB_DBL_ATTR_OBJBOUND, &lpp->best_bound);
+       check_gurobi_error(grb, error);
+
+       /* get some statistics */
+       error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_ITERCOUNT, &iterations);
+       check_gurobi_error(grb, error);
+       lpp->iterations = (unsigned) iterations;
+
+       error = GRBgetdblattr(grb->model, GRB_DBL_ATTR_RUNTIME, &lpp->sol_time);
+       check_gurobi_error(grb, error);
+}
+
+void lpp_solve_gurobi(lpp_t *lpp)
+{
+       gurobi_t *grb = new_gurobi(lpp);
+       gurobi_construct(grb);
+       gurobi_solve(grb);
+       free_gurobi(grb);
+}
+
+#endif
diff --git a/ir/lpp/lpp_gurobi.h b/ir/lpp/lpp_gurobi.h
new file mode 100644 (file)
index 0000000..782e7ca
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ * Author:      Matthias Braun
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#ifndef LPP_GUROBI_H
+#define LPP_GUROBI_H
+
+#include "lpp.h"
+
+#ifdef WITH_GUROBI
+void lpp_solve_gurobi(lpp_t *lpp);
+#endif
+
+#endif
diff --git a/ir/lpp/lpp_net.c b/ir/lpp/lpp_net.c
new file mode 100644 (file)
index 0000000..f0ae59a
--- /dev/null
@@ -0,0 +1,234 @@
+/**
+ * @file   lpp_net.c
+ * @date   19.07.2005
+ * @author Sebastian Hack
+ *
+ * A client for an lpp solving server.
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+
+#ifdef _WIN32
+#include <winsock.h>
+#include <io.h>
+
+#else
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+
+/* solaris fix */
+#ifndef INADDR_NONE
+#define INADDR_NONE (in_addr_t)(-1)
+#endif
+
+#endif
+
+
+#include <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "timing.h"
+
+#include "lpp_net.h"
+#include "lpp_t.h"
+#include "lpp_comm.h"
+
+#ifdef _WIN32
+static int winsock_init(void)
+{
+       WORD wVersionRequested;
+       WSADATA wsaData;
+       int err;
+
+       wVersionRequested = MAKEWORD( 2, 2 );
+
+       err = WSAStartup( wVersionRequested, &wsaData );
+       if ( err != 0 ) {
+               /* Tell the user that we could not find a usable */
+               /* WinSock DLL.                                  */
+               return 0;
+       }
+
+       /* Confirm that the WinSock DLL supports 2.2.*/
+       /* Note that if the DLL supports versions greater    */
+       /* than 2.2 in addition to 2.2, it will still return */
+       /* 2.2 in wVersion since that is the version we      */
+       /* requested.                                        */
+
+       if ( LOBYTE( wsaData.wVersion ) != 2 ||
+                       HIBYTE( wsaData.wVersion ) != 2 ) {
+               /* Tell the user that we could not find a usable */
+               /* WinSock DLL.                                  */
+               WSACleanup( );
+               return 0;
+       }
+       return 1;
+}
+#endif
+
+static int connect_tcp(const char *host, uint16_t port)
+{
+       struct hostent     *phe;
+       struct protoent    *ppe;
+       struct sockaddr_in sin;
+       int s;
+
+#ifdef _WIN32
+       winsock_init();
+#endif
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port   = htons(port);
+
+       if ((phe = gethostbyname(host)))
+               memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
+       else if((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
+               lpp_print_err("cannot get host entry for %s", host);
+               return -1;
+       }
+
+       ppe = getprotobyname("tcp");
+       ERRNO_CHECK_RETURN(s = socket(PF_INET, SOCK_STREAM, ppe->p_proto), <, 0, -1);
+       ERRNO_CHECK_RETURN(connect(s, (struct sockaddr *) &sin, sizeof(sin)), <, 0, -1);
+
+       return s;
+}
+
+char **lpp_get_solvers(const char *host)
+{
+       int fd, n;
+       char **res = NULL;
+       lpp_comm_t *comm;
+
+       ERR_CHECK_RETURN(fd = connect_tcp(host, LPP_PORT), <, 0,
+                       ("could not connect to %s", host), NULL);
+
+       comm = lpp_comm_new(fd, LPP_BUFSIZE);
+
+       lpp_writel(comm, LPP_CMD_SOLVERS);
+       lpp_flush(comm);
+       n = lpp_readl(comm);
+       res = malloc((n + 1) * sizeof(res[0]));
+       res[n] = NULL;
+
+       if(n > 0) {
+               int i;
+               for(i = 0; i < n; ++i)
+                       res[i] = lpp_reads(comm);
+       }
+
+       lpp_writel(comm, LPP_CMD_BYE);
+       lpp_flush(comm);
+       lpp_comm_free(comm);
+       close(fd);
+       return res;
+}
+
+void lpp_set_dbg(const char *host, int mask)
+{
+       int fd;
+       lpp_comm_t *comm;
+
+       ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0, ("could not connect to %s", host));
+
+       comm = lpp_comm_new(fd, LPP_BUFSIZE);
+
+       lpp_writel(comm, LPP_CMD_SET_DEBUG);
+       lpp_writel(comm, mask);
+       lpp_flush(comm);
+       lpp_writel(comm, LPP_CMD_BYE);
+       lpp_flush(comm);
+       lpp_comm_free(comm);
+       close(fd);
+}
+
+void lpp_solve_net(lpp_t *lpp, const char *host, const char *solver)
+{
+       char buf[1024];
+       int n, fd, ready;
+       lpp_comm_t *comm;
+       ir_timer_t *t_send, *t_recv;
+
+       ERR_CHECK_RETURN_VOID(fd = connect_tcp(host, LPP_PORT), <, 0,
+               ("could not connect to %s", host));
+
+       comm = lpp_comm_new(fd, LPP_BUFSIZE);
+
+       /* Set the solver */
+       lpp_writel(comm, LPP_CMD_SOLVER);
+       lpp_writes(comm, solver);
+       lpp_flush(comm);
+
+#if 0
+       ERR_CHECK_RETURN_VOID(lpp_ack(fd, sizeof(buf), buf), == 0,
+               ("could not set solver: %s", solver));
+#endif
+
+       t_send = ir_timer_new();
+       t_recv = ir_timer_new();
+
+       ir_timer_push(t_send);
+       lpp_writel(comm, LPP_CMD_PROBLEM);
+       lpp_serialize(comm, lpp, 1);
+       lpp_serialize_values(comm, lpp, lpp_value_start);
+       lpp_flush(comm);
+       ir_timer_pop();
+       lpp->send_time = ir_timer_elapsed_usec(t_send);
+
+       ready = 0;
+       while (! ready) {
+               int cmd = lpp_readl(comm);
+               switch(cmd) {
+                       case LPP_CMD_SOLUTION:
+                               ir_timer_push(t_recv);
+                               lpp_deserialize_stats(comm, lpp);
+                               lpp_deserialize_values(comm, lpp, lpp_value_solution);
+                               ir_timer_pop();
+                               lpp->recv_time = ir_timer_elapsed_usec(t_recv);
+                               ready = 1;
+                               break;
+                       case LPP_CMD_INFO:
+                               lpp_readbuf(comm, buf, sizeof(buf));
+                               buf[sizeof(buf) - 1] = '\0';
+
+                               if(lpp->log != NULL) {
+                                       fputs(buf, lpp->log);
+                                       n = strlen(buf);
+                                       if(buf[n - 1] != '\n')
+                                               putc('\n', lpp->log);
+                                       fflush(lpp->log);
+                               }
+                               break;
+                       case LPP_CMD_BAD:
+                               fprintf(stderr, "solver process died unexpectedly\n");
+                               goto end;
+                       default:
+                               fprintf(stderr, "invalid command: %s(%d)\n", lpp_get_cmd_name(cmd), cmd);
+                               return;
+               }
+       }
+
+       lpp_writel(comm, LPP_CMD_BYE);
+       lpp_flush(comm);
+
+end:
+       lpp_comm_free(comm);
+#ifdef _WIN32
+       closesocket(fd);
+#else
+       close(fd);
+#endif
+}
diff --git a/ir/lpp/lpp_net.h b/ir/lpp/lpp_net.h
new file mode 100644 (file)
index 0000000..3e56656
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * @file   lpp_net.h
+ * @date   20.07.2005
+ * @author Sebastian Hack
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+#ifndef LPP_NET_H
+#define LPP_NET_H
+
+#include "lpp.h"
+
+char **lpp_get_solvers(const char *host);
+
+void lpp_set_dbg(const char *host, int mask);
+
+void lpp_solve_net(lpp_t *lpp, const char *host, const char *solver);
+
+#endif
diff --git a/ir/lpp/lpp_remote.c b/ir/lpp/lpp_remote.c
new file mode 100644 (file)
index 0000000..b7644c9
--- /dev/null
@@ -0,0 +1,192 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        02.06.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "lpp_remote.h"
+#include "assert.h"
+#include "mps.h"
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <io.h>
+
+#define snprintf      _snprintf
+#define chmod(a, b)   _chmod(a, b)
+
+/* disable warning: 'foo' was declared deprecated, use 'bla' instead */
+/* of course MS had to make 'bla' incompatible to 'foo', so a simple */
+/* define will not work :-((( */
+#pragma warning( disable : 4996 )
+
+#endif
+
+/* CPLEX-account related stuff */
+#define DELETE_FILES    /**< deletes all dumped files after use. Files on server are always deleted. */
+#define SSH_USER_HOST   "kb61@sp-smp.rz.uni-karlsruhe.de"
+#define SSH_PASSWD_FILE "/ben/daniel/.smppw"
+#define EXPECT_FILENAME "runme" /* name of the expect-script */
+
+static FILE *ffopen(const char *base, const char *ext, const char *mode)
+{
+       FILE *out;
+       char buf[1024];
+
+       snprintf(buf, sizeof(buf), "%s.%s", base, ext);
+       if (! (out = fopen(buf, mode))) {
+               fprintf(stderr, "Cannot open file %s in mode %s\n", buf, mode);
+               return NULL;
+       }
+       return out;
+}
+
+static void lpp_write_cmd(lpp_t *lpp)
+{
+       FILE *out = ffopen(lpp->name, "cmd", "wt");
+       fprintf(out, "set logfile %s.sol\n", lpp->name);
+       fprintf(out, "set mip strategy mipstart 1\n");
+       // fprintf(out, "set mip emphasis 3\n"); /* moving best bound */
+       fprintf(out, "set mip emphasis 0\n"); /* balance optimality and feasability */
+       fprintf(out, "set mip strategy variableselect 3\n"); /* strong branching */
+       fprintf(out, "read %s.mps\n", lpp->name);
+       fprintf(out, "read %s.mst\n", lpp->name);
+       fprintf(out, "optimize\n");
+       fprintf(out, "display solution variables -\n");
+       fprintf(out, "quit\n");
+       fclose(out);
+}
+
+static void lpp_write_exp(lpp_t *lpp)
+{
+       FILE *pwfile, *out;
+       char passwd[128];
+
+       pwfile = fopen(SSH_PASSWD_FILE, "rt");
+       fgets(passwd, sizeof(passwd), pwfile);
+       fclose(pwfile);
+
+       out = ffopen(EXPECT_FILENAME, "exp", "wt");
+       fprintf(out, "#! /usr/bin/expect\n");
+       fprintf(out, "spawn scp %s.mps %s.mst %s.cmd %s:\n", lpp->name, lpp->name, lpp->name, SSH_USER_HOST); /* copy problem files */
+       fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
+
+       fprintf(out, "spawn ssh %s \"./cplex90 < %s.cmd\"\n", SSH_USER_HOST, lpp->name); /* solve */
+       fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
+
+       fprintf(out, "spawn scp %s:%s.sol .\n", SSH_USER_HOST, lpp->name); /*copy back solution */
+       fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
+
+       fprintf(out, "spawn ssh %s ./dell\n", SSH_USER_HOST); /* clean files on server */
+       fprintf(out, "expect \"word:\"\nsend \"%s\\n\"\ninteract\n", passwd);
+       fclose(out);
+}
+
+static void lpp_read_solution(lpp_t *lpp)
+{
+       FILE *in;
+       double sol_time;
+       unsigned iter;
+       int vars_section = 0;
+       char var_name[128];
+       double var_value;
+
+       if (!(in = ffopen(lpp->name, "sol", "rt"))) {
+               lpp->sol_state = lpp_unknown;
+               return;
+       }
+       while (!feof(in)) {
+               char buf[1024];
+               fgets(buf, sizeof(buf), in);
+
+               /* error and solution state */
+               if (!strncmp(buf, "CPLEX Error", 11))
+                       lpp->error = strdup(buf);
+               else if (!strncmp(buf, "Warning:", 8))
+                       lpp->error = strdup(buf);
+               else if (!strncmp(buf, "Integer optimal solution:", 25))
+                       lpp->sol_state = lpp_optimal;
+               else if (!strcmp(buf, "No integer feasible solution exists."))
+                       lpp->sol_state = lpp_infeasible;
+               else if (!strcmp(buf, "Error termination, integer feasible:"))
+                       lpp->sol_state = lpp_feasible;
+               /* stats */
+               else if (sscanf(buf, "Solution time = %lg sec. Iterations = %u", &sol_time, &iter) == 2) {
+                       lpp->sol_time = sol_time;
+                       lpp->iterations = iter;
+               }
+               /* variable values */
+               else if(!strcmp(buf, "Variable Name           Solution Value")) {
+                       int i;
+                       vars_section = 1;
+                       for(i=0; i<lpp->var_next; ++i) {
+                               lpp_name_t *var = lpp->vars[i];
+                               var->value = 0;
+                               var->value_kind = lpp_value_solution;
+                       }
+               }
+               else if(!strncmp(buf, "All other var", 13))
+                       vars_section = 0;
+               else if (vars_section) {
+                       if (sscanf(buf, "%s %lg", var_name, &var_value) == 2)
+                               lpp->vars[lpp_get_var_idx(lpp, var_name)]->value = var_value;
+                       else
+                               assert(0 && "There should be variables to read in!");
+               }
+       }
+       fclose(in);
+       if (lpp->error) {
+               printf("\n%s\n", lpp->error);
+               assert(0);
+       }
+}
+
+#ifdef DELETE_FILES
+static void lpp_delete_files(lpp_t *lpp)
+{
+       char buf[1024];
+       int end = snprintf(buf, sizeof(buf), "%s", lpp->name);
+
+       snprintf(buf+end, sizeof(buf)-end, ".mps");
+       remove(buf);
+       snprintf(buf+end, sizeof(buf)-end, ".mst");
+       remove(buf);
+       snprintf(buf+end, sizeof(buf)-end, ".cmd");
+       remove(buf);
+       snprintf(buf+end, sizeof(buf)-end, ".sol");
+       remove(buf);
+       remove(EXPECT_FILENAME ".exp");
+}
+#endif
+
+void lpp_solve_remote(lpp_t *lpp)
+{
+       FILE *out;
+       out = ffopen(lpp->name, "mps", "wt");
+       mps_write_mps(lpp, s_mps_free, out);
+       fclose(out);
+
+       out = ffopen(lpp->name, "mst", "wt");
+       mps_write_mst(lpp, s_mps_free, out);
+       fclose(out);
+
+       lpp_write_cmd(lpp);
+       lpp_write_exp(lpp);
+
+       /* call the expect script */
+       chmod(EXPECT_FILENAME ".exp", 0700);
+       system(EXPECT_FILENAME ".exp");
+
+       lpp_read_solution(lpp);
+#ifdef DELETE_FILES
+       lpp_delete_files(lpp);
+#endif
+}
diff --git a/ir/lpp/lpp_remote.h b/ir/lpp/lpp_remote.h
new file mode 100644 (file)
index 0000000..c382a18
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        02.06.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+
+#ifndef _LPP_REMOTE_H_
+#define _LPP_REMOTE_H_
+
+#include "lpp.h"
+
+void lpp_solve_remote(lpp_t *lpp);
+
+#endif /*_LPP_REMOTE_H_*/
diff --git a/ir/lpp/lpp_solvers.c b/ir/lpp/lpp_solvers.c
new file mode 100644 (file)
index 0000000..1feb44b
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * @file   lpp_solvers.c
+ * @date   16.06.2011
+ * @author Sebastian Hack
+ *
+ * Copyright (C) 2011 Saarland University
+ * Released under the LGPL
+ */
+#include "config.h"
+
+#include "lpp_cplex.h"
+#include "lpp_solvers.h"
+#include "lpp_gurobi.h"
+
+lpp_solver_t lpp_solvers[] = {
+#ifdef WITH_CPLEX
+       { lpp_solve_cplex,   "cplex",   1 },
+#endif
+#ifdef WITH_GUROBI
+       { lpp_solve_gurobi,  "gurobi",  1 },
+#endif
+       { NULL,              NULL,      0 }
+};
+
+lpp_solver_func_t *lpp_find_solver(const char *name)
+{
+       int i;
+
+       for(i = 0; lpp_solvers[i].solver != NULL; i++)
+               if(strcmp(lpp_solvers[i].name, name) == 0)
+                       return lpp_solvers[i].solver;
+
+       return NULL;
+}
diff --git a/ir/lpp/lpp_solvers.h b/ir/lpp/lpp_solvers.h
new file mode 100644 (file)
index 0000000..c6b1e73
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * @file   lpp_solvers.h
+ * @date   16.06.2011
+ * @author Sebastian Hack
+ *
+ * Copyright (C) 2011 Saarland University
+ * Released under the LGPL
+ */
+#ifndef LPP_SOLVER_H
+#define LPP_SOLVER_H
+
+#include "lpp.h"
+
+typedef void (lpp_solver_func_t)(lpp_t *lpp);
+
+typedef struct {
+       lpp_solver_func_t *solver;
+       const char        *name;
+       int                n_instances;
+} lpp_solver_t;
+
+extern lpp_solver_t lpp_solvers[];
+
+/**
+ * Find a solver for a given name.
+ */
+lpp_solver_func_t *lpp_find_solver(const char *name);
+
+#endif
diff --git a/ir/lpp/lpp_t.h b/ir/lpp/lpp_t.h
new file mode 100644 (file)
index 0000000..7d95183
--- /dev/null
@@ -0,0 +1,52 @@
+
+/**
+ * @file   lpp_t.h
+ * @date   30.07.2005
+ * @author Sebastian Hack
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+#ifndef LPP_T_H
+#define LPP_T_H
+
+#include "lpp.h"
+#include "lpp_comm.h"
+
+/**
+ * Serialize a lpp to a file descriptor.
+ * @param comm The file descriptor.
+ * @param lpp The lpp.
+ * @param with_names Also send the names of constraints/variables.
+ */
+void lpp_serialize(lpp_comm_t *comm, const lpp_t *lpp, int with_names);
+
+/**
+ * Deserialize an lpp from a file descriptor.
+ * @param comm The file descriptor.
+ * @param with_names Also receive names of constraints/variables.
+ * @return The Problem.
+ */
+lpp_t *lpp_deserialize(lpp_comm_t *comm);
+
+/**
+ * Serialize values of the lpps for a given value kind.
+ * This function only serializes values of the given kind.
+ * @param fd   The file descriptor to serialize to.
+ * @param lpp  The problem.
+ * @param kind The value kind.
+ */
+void lpp_serialize_values(lpp_comm_t *comm, const lpp_t *lpp, lpp_value_kind_t kind);
+
+/**
+ * Desrialize values from a stream.
+ * @param fd   The file descriptor to read from.
+ * @param lpp  The problem to set the values.
+ * @param kind The value kind the values shall be assigned.
+ */
+void lpp_deserialize_values(lpp_comm_t *comm, lpp_t *lpp, lpp_value_kind_t kind);
+
+void lpp_serialize_stats(lpp_comm_t *comm, const lpp_t *lpp);
+void lpp_deserialize_stats(lpp_comm_t *comm, lpp_t *lpp);
+
+#endif
diff --git a/ir/lpp/mps.c b/ir/lpp/mps.c
new file mode 100644 (file)
index 0000000..e886594
--- /dev/null
@@ -0,0 +1,164 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        02.06.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#include "config.h"
+#include <stdarg.h>
+#include <assert.h>
+#include "mps.h"
+
+/**
+ * These must comply to the enum cst_t in lpp.h
+ */
+static const char *mps_cst_encoding[4] = {"N", "E", "L", "G"};
+
+/**
+ * Diffferent line styles which can be used in a mps file
+ */
+typedef enum _mps_line_t {l_raw,
+                                                 l_ind_name, l_ind_objs, l_ind_rows, l_ind_cols, l_ind_rhs, l_ind_end,
+                                                 l_data_row, l_data_col1, l_data_col2, l_data_mst, l_marker} mps_line_t;
+
+static void mps_write_line(FILE *out, style_t style, mps_line_t line_type, ...) {
+       va_list args;
+       const char *fmt = "";
+
+       assert(style == s_mps_fixed || style == s_mps_free);
+       va_start(args, line_type);
+
+       if (style == s_mps_fixed) {
+               /* white spaces are important! */
+               switch (line_type) {
+                       case l_raw:       fmt = "%s\n"; break;
+                       case l_ind_name:  fmt = "NAME          %s\n"; break;
+                       case l_ind_objs:  fmt = "OBJSENSE\n"; break;
+                       case l_ind_rows:  fmt = "ROWS\n"; break;
+                       case l_ind_cols:  fmt = "COLUMNS\n"; break;
+                       case l_ind_rhs:   fmt = "RHS\n"; break;
+                       case l_ind_end:   fmt = "ENDATA\n"; break;
+                       case l_data_row:  fmt = " %-2s %-8s\n"; break; /* Field 1-2 */
+                       case l_data_col1: fmt = "    %-8s  %-8s  %12g\n"; break; /* Field 2-4 */
+                       case l_data_col2: fmt = "    %-8s  %-8s  %12g   %-8s  %12g\n"; break; /* Field 2-6 */
+                       case l_data_mst:  fmt = "    %-8s            %12g\n"; break; /* Field 3-4 */
+                       case l_marker:    fmt = "    M%-7d  'MARKER'                 '%s'\n"; break; /* Field 2,3,5 */
+                       default: assert(0);
+               }
+       } else {
+               switch (line_type) {
+                       case l_raw:       fmt = "%s\n"; break;
+                       case l_ind_name:  fmt = "NAME %s\n"; break;
+                       case l_ind_objs:  fmt = "OBJSENSE\n"; break;
+                       case l_ind_rows:  fmt = "ROWS\n"; break;
+                       case l_ind_cols:  fmt = "COLUMNS\n"; break;
+                       case l_ind_rhs:   fmt = "RHS\n"; break;
+                       case l_ind_end:   fmt = "ENDATA\n"; break;
+                       case l_data_row:  fmt = " %s\t%s\n"; break;
+                       case l_data_col1: fmt = " %s\t%s\t%g\n"; break;
+                       case l_data_col2: fmt = " %s\t%s\t%g\t%s\t%g\n"; break;
+                       case l_data_mst:  fmt = " %s\t%g\n"; break;
+                       case l_marker:    fmt = " M%d\t'MARKER'\t'%s'\n"; break;
+                       default: assert(0);
+               }
+       }
+
+       vfprintf(out, fmt, args);
+       va_end(args);
+}
+
+static int mps_insert_markers(FILE *out, style_t style, lpp_var_t curr, lpp_var_t last, int marker_nr)
+{
+       assert(style == s_mps_fixed || style == s_mps_free);
+       if (last != curr) {
+               /* print end-marker for last */
+               if (last == lpp_binary)
+                       mps_write_line(out, style, l_marker, marker_nr++, "INTEND");
+
+               /* print begin-marker for curr */
+               if (curr == lpp_binary)
+                       mps_write_line(out, style, l_marker, marker_nr++, "INTORG");
+       }
+       return marker_nr;
+}
+
+void mps_write_mps(lpp_t *lpp, style_t style, FILE *out)
+{
+       int i, count, marker_nr = 0;
+       const lpp_name_t *curr;
+       const matrix_elem_t *elem, *before = NULL;
+       lpp_var_t last_type;
+       assert(style == s_mps_fixed || style == s_mps_free);
+
+       /* NAME */
+       mps_write_line(out, style, l_ind_name, lpp->name);
+
+       /* OBJSENSE */
+       if (lpp->opt_type == lpp_maximize) {
+               mps_write_line(out, style, l_ind_objs);
+               mps_write_line(out, style, l_raw, " MAX");
+       }
+
+       /* ROWS */
+       mps_write_line(out, style, l_ind_rows);
+       for(i=0; i<lpp->cst_next; ++i) {
+               curr = lpp->csts[i];
+               mps_write_line(out, style, l_data_row, mps_cst_encoding[curr->type.cst_type], curr->name);
+       }
+
+       /* COLUMNS */
+       mps_write_line(out, style, l_ind_cols);
+       last_type = lpp_invalid;
+       for(i=1; i<lpp->var_next; ++i) { /* column 0 is rhs */
+               curr = lpp->vars[i];
+
+               /* markers */
+               marker_nr = mps_insert_markers(out, style, curr->type.var_type, last_type, marker_nr);
+               last_type = curr->type.var_type;
+
+               /* participation in constraints */
+               count = 0;
+               matrix_foreach_in_col(lpp->m, curr->nr, elem) {
+                       if (count == 0) {
+                               before = elem;
+                               count = 1;
+                       } else {
+                               mps_write_line(out, style, l_data_col2, curr->name, lpp->csts[before->row]->name, (double)before->val, lpp->csts[elem->row]->name, (double)elem->val);
+                               count = 0;
+                       }
+               }
+               if (count == 1)
+                       mps_write_line(out, style, l_data_col1, curr->name, lpp->csts[before->row]->name, (double)before->val);
+       }
+       mps_insert_markers(out, style, lpp_invalid, last_type, marker_nr); /* potential end-marker */
+
+       /* RHS */
+       mps_write_line(out, style, l_ind_rhs);
+       count = 0;
+       matrix_foreach_in_col(lpp->m, 0, elem) {
+               if (count == 0) {
+                       before = elem;
+                       count = 1;
+               } else {
+                       mps_write_line(out, style, l_data_col2, "rhs", lpp->csts[before->row]->name, (double)before->val, lpp->csts[elem->row]->name, (double)elem->val);
+                       count = 0;
+               }
+       }
+       if (count == 1)
+               mps_write_line(out, style, l_data_col1, "rhs", lpp->csts[before->row]->name, (double)before->val);
+
+       /* ENDATA */
+       mps_write_line(out, style, l_ind_end);
+}
+
+void mps_write_mst(lpp_t *lpp, style_t style, FILE *out)
+{
+       int i;
+       mps_write_line(out, style, l_ind_name, "");
+       for (i=0; i<lpp->var_next; ++i) {
+               const lpp_name_t *var = lpp->vars[i];
+               if (var->value_kind == lpp_value_start)
+                       mps_write_line(out, style, l_data_mst, var->name, (double)var->value);
+       }
+       mps_write_line(out, style, l_ind_end);
+}
diff --git a/ir/lpp/mps.h b/ir/lpp/mps.h
new file mode 100644 (file)
index 0000000..a2c07ad
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        02.06.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#ifndef MPS_H
+#define MPS_H
+
+#include <stdio.h>
+#include "lpp.h"
+
+/**
+ * Two styles of mps files
+ *
+ * s_mps_fixed: mps where spaces are allowed in identifiers
+ *              and all things have a fixed column... :-0
+ * s_mps_free:  mps where whitespace is a seperator :-)
+ */
+typedef enum _style_t {s_mps_fixed, s_mps_free} style_t;
+
+/**
+ * Writes the description of a lp problem object (lpp)
+ * to the stream out, using the specified style.
+ */
+void mps_write_mps(lpp_t *lpp, style_t style, FILE *out);
+
+/**
+ * Writes the start values of a lp problem object (lpp)
+ * to the stream out, using the specified style.
+ */
+void mps_write_mst(lpp_t *lpp, style_t style, FILE *out);
+
+#endif
diff --git a/ir/lpp/sp_matrix.c b/ir/lpp/sp_matrix.c
new file mode 100644 (file)
index 0000000..7a598a1
--- /dev/null
@@ -0,0 +1,749 @@
+/**
+ * Author:      Daniel Grund, Christian Wuerdig
+ * Date:        07.04.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * CVS-Id:      $Id: sp_matrix.c 24123 2008-11-28 15:08:27Z mallon $
+ *
+ * Sparse matrix storage with linked lists for rows and cols.
+ * Matrix is optimized for left-to-right and top-to-bottom access.
+ * Complexity is O(1) then.
+ * Random access or right-to-left and bottom-to-top is O(m*n).
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <math.h>
+
+#include "sp_matrix.h"
+
+#include "irtools.h"
+#include "bitset.h"
+#include "xmalloc.h"
+
+typedef enum iter_direction_t {
+       down, right, all
+} iter_direction_t;
+
+/**
+ * Embedded list pointer.
+ */
+typedef struct sp_matrix_list_head_t {
+       struct sp_matrix_list_head_t *next;
+} sp_matrix_list_head_t;
+
+/**
+ * A matrix entry.
+ */
+typedef struct entry_t {
+       sp_matrix_list_head_t col_chain; /**< points to next element in same column */
+       sp_matrix_list_head_t row_chain; /**< points to next element in same row */
+       matrix_elem_t         e;         /**< The actual element */
+} entry_t;
+
+struct sp_matrix_t {
+       /* These specify the dimensions of the matrix.
+        * They equal the largest values ever used in matrix_set */
+       int maxrow, maxcol;
+       /* These are the dimensions of allocated arrays below.
+        * rowc >= maxrow and colc >= maxcol hold. */
+       int rowc, colc;
+       /* number of entries */
+       int entries;
+       /* arrays of sp_matrix_list_head* as entry-points to rows and cols */
+       sp_matrix_list_head_t **rows, **cols;
+       /* for iteration: first is to remember start-point;
+        *                last was returned just before
+        *                next is used in case last was removed from list */
+       iter_direction_t dir;
+       sp_matrix_list_head_t *first, *last, *next;
+       int iter_row; /* used for iteration over all elements */
+       /* for each column the last inserted element in col list */
+       sp_matrix_list_head_t **last_col_el;
+       /* for each row the last inserted element in row list */
+       sp_matrix_list_head_t **last_row_el;
+};
+
+#define SP_MATRIX_INIT_LIST_HEAD(ptr) do { (ptr)->next = NULL; } while (0)
+
+#define _offsetof(type,member) ((char *) &(((type *) 0)->member) - (char *) 0)
+#define _container_of(ptr,type,member) ((type *) ((char *) (ptr) - _offsetof(type, member)))
+
+#define is_empty_row(row) (row > m->maxrow || (m->rows[row])->next == NULL)
+#define is_empty_col(col) (col > m->maxcol || (m->cols[col])->next == NULL)
+
+#define list_entry_by_col(h) (&_container_of(h, entry_t, col_chain)->e)
+#define list_entry_by_row(h) (&_container_of(h, entry_t, row_chain)->e)
+
+/**
+ * Returns the size of a single matrix element.
+ */
+unsigned matrix_get_elem_size(void)
+{
+       return sizeof(entry_t);
+}
+
+/**
+ * Returns the new size for an array of size old_size,
+ *  which must at least store an entry at position min.
+ */
+static inline int m_new_size(int old_size, int min)
+{
+       unsigned bits = 0;
+       assert(min >= old_size);
+       while (min > 0) {
+               min >>= 1;
+               bits++;
+       }
+       assert(bits < sizeof(min) * 8 - 1);
+       return 1 << bits;
+}
+
+/**
+ * Allocates space for @p count entries in the rows array and
+ * initializes all entries from @p start to the end.
+ */
+static inline void m_alloc_row(sp_matrix_t *m, int start, int count)
+{
+       int p;
+
+       m->rowc        = count;
+       m->rows        = XREALLOC(m->rows, sp_matrix_list_head_t *, m->rowc);
+       m->last_row_el = XREALLOC(m->last_row_el, sp_matrix_list_head_t *, m->rowc);
+
+       for (p = start; p < m->rowc; ++p) {
+               m->rows[p] = XMALLOC(sp_matrix_list_head_t);
+               SP_MATRIX_INIT_LIST_HEAD(m->rows[p]);
+               m->last_row_el[p] = m->rows[p];
+       }
+}
+
+/**
+ * Allocates space for @p count entries in the cols array and
+ * initializes all entries from @p start to the end.
+ */
+static inline void m_alloc_col(sp_matrix_t *m, int start, int count)
+{
+       int p;
+
+       m->colc        = count;
+       m->cols        = XREALLOC(m->cols, sp_matrix_list_head_t*, m->colc);
+       m->last_col_el = XREALLOC(m->last_col_el, sp_matrix_list_head_t*, m->colc);
+
+       for (p = start; p < m->colc; ++p) {
+               m->cols[p] = XMALLOC(sp_matrix_list_head_t);
+               SP_MATRIX_INIT_LIST_HEAD(m->cols[p]);
+               m->last_col_el[p] = m->cols[p];
+       }
+}
+
+/**
+ * Searches in row @p row for the matrix element m[row, col], starting at element @p start.
+ * @return If the element exists:
+ *            Element m[row, col] and @p prev points to the sp_matrix_list_head in the entry_t holding the element.
+ *         Else: NULL and @p prev points to the sp_matrix_list_head after which the element would be inserted.
+ *         @p prev_prev always points to the previous element of @p prev
+ */
+static inline matrix_elem_t *m_search_in_row_from(const sp_matrix_t *m,
+                       int row, int col, sp_matrix_list_head_t *start, sp_matrix_list_head_t **prev, sp_matrix_list_head_t **prev_prev)
+{
+       sp_matrix_list_head_t *row_start;
+       matrix_elem_t         *res = NULL;
+
+       row_start = m->rows[row];
+       *prev     = start;
+
+       while ((*prev)->next != NULL && list_entry_by_row((*prev)->next)->col <= col) {
+               (*prev_prev) = (*prev);
+               *prev        = (*prev)->next;
+       }
+
+       if (*prev != row_start) {
+               matrix_elem_t *me = list_entry_by_row(*prev);
+
+               if (me->row == row && me->col == col)
+                       res = me;
+       }
+
+       if (res) {
+               m->last_row_el[row] = *prev;
+       }
+
+       return res;
+}
+
+/**
+ * Searches in row @p row for the matrix element m[row, col].
+ * @return If the element exists:
+ *            Element m[row, col] and @p prev points to the sp_matrix_list_head in the entry_t holding the element.
+ *         Else: NULL and @p prev points to the sp_matrix_list_head after which the element would be inserted.
+ *         @p prev_prev always points to the previous element of @p prev
+ */
+static inline matrix_elem_t *m_search_in_row(const sp_matrix_t *m,
+                       int row, int col, sp_matrix_list_head_t **prev, sp_matrix_list_head_t **prev_prev)
+{
+       sp_matrix_list_head_t *start = m->rows[row];
+
+       *prev_prev = NULL;
+
+       if (m->last_row_el[row] != start) {
+               matrix_elem_t *el = list_entry_by_row(m->last_row_el[row]);
+               if (el->col < col) {
+                       *prev_prev = start = m->last_row_el[row];
+               }
+       }
+
+       return m_search_in_row_from(m, row, col, start, prev, prev_prev);
+}
+
+/**
+ * Searches in col @p col for the matrix element m[row, col], starting at @p start.
+ * @return If the element exists:
+ *            Element m[row, col] and @p prev points to the sp_matrix_list_head in the entry_t holding the element.
+ *         Else: NULL and @p prev points to the sp_matrix_list_head after which the element would be inserted.
+ *         @p prev_prev always points to the previous element of @p prev
+ */
+static inline matrix_elem_t *m_search_in_col_from(const sp_matrix_t *m,
+                       int row, int col, sp_matrix_list_head_t *start, sp_matrix_list_head_t **prev, sp_matrix_list_head_t **prev_prev)
+{
+       sp_matrix_list_head_t *col_start;
+       matrix_elem_t         *res = NULL;
+
+       col_start = m->cols[col];
+       *prev     = start;
+
+       while ((*prev)->next != NULL && list_entry_by_col((*prev)->next)->row <= row) {
+               *prev_prev = (*prev);
+               *prev      = (*prev)->next;
+       }
+
+       if (*prev != col_start) {
+               matrix_elem_t *me = list_entry_by_col(*prev);
+
+               if (me->row == row && me->col == col)
+                       res = me;
+       }
+
+       if (res) {
+               m->last_col_el[col] = *prev;
+       }
+
+       return res;
+}
+
+/**
+ * Searches in col @p col for the matrix element m[row, col].
+ * @return If the element exists:
+ *            Element m[row, col] and @p prev points to the sp_matrix_list_head in the entry_t holding the element.
+ *         Else: NULL and @p prev points to the sp_matrix_list_head after which the element would be inserted.
+ *         @p prev_prev always points to the previous element of @p prev
+ */
+static inline matrix_elem_t *m_search_in_col(const sp_matrix_t *m,
+                       int row, int col, sp_matrix_list_head_t **prev, sp_matrix_list_head_t **prev_prev)
+{
+       sp_matrix_list_head_t *start = m->cols[col];
+
+       *prev_prev = NULL;
+
+       if (m->last_col_el[col] != start) {
+               matrix_elem_t *el = list_entry_by_col(m->last_col_el[col]);
+               if (el->row < row) {
+                       *prev_prev = start = m->last_col_el[col];
+               }
+       }
+
+       return m_search_in_col_from(m, row, col, start, prev, prev_prev);
+}
+
+sp_matrix_t *new_matrix(int row_init, int col_init)
+{
+       sp_matrix_t *res = XMALLOCZ(sp_matrix_t);
+       res->maxrow = -1;
+       res->maxcol = -1;
+       m_alloc_row(res, 0, MAX(0, row_init));
+       m_alloc_col(res, 0, MAX(0, col_init));
+       return res;
+}
+
+void del_matrix(sp_matrix_t *m)
+{
+       int i;
+
+       for (i = 0; i < m->rowc; ++i) {
+               if (! is_empty_row(i)) {
+                       entry_t *e;
+                       sp_matrix_list_head_t *n;
+
+                       n = m->rows[i]->next;
+                       do {
+                               /* get current matrix element */
+                               e = _container_of(n, entry_t, row_chain);
+                               n = n->next;
+                               xfree(e);
+                       } while (n != NULL);
+
+               }
+               xfree(m->rows[i]);
+       }
+       for (i = 0; i < m->colc; ++i)
+               xfree(m->cols[i]);
+       xfree(m->last_col_el);
+       xfree(m->last_row_el);
+       xfree(m->rows);
+       xfree(m->cols);
+       xfree(m);
+}
+
+void matrix_set(sp_matrix_t *m, int row, int col, double val)
+{
+       matrix_elem_t *me = NULL;
+       entry_t       *entr;
+       sp_matrix_list_head_t *leftof, *above;
+       sp_matrix_list_head_t *prev_leftof, *prev_above;
+
+       /* if necessary enlarge the matrix */
+       if (row > m->maxrow) {
+               m->maxrow = row;
+               if (row >= m->rowc)
+                       m_alloc_row(m, m->rowc, m_new_size(m->rowc, row));
+       }
+       if (col > m->maxcol) {
+               m->maxcol = col;
+               if (col >= m->colc)
+                       m_alloc_col(m, m->colc, m_new_size(m->colc, col));
+       }
+
+       /* search for existing entry */
+       if (m->maxrow < m->maxcol)
+               me = m_search_in_col(m, row, col, &above, &prev_above);
+       else
+               me = m_search_in_row(m, row, col, &leftof, &prev_leftof);
+
+       /* if it exists, set the value and return */
+       if (me) {
+               if (val != 0) {
+                       me->val = (float)val;
+               } else {
+                       entr = _container_of(me, entry_t, e);
+
+                       /* remove row_chain entry */
+                       if (prev_leftof)
+                               prev_leftof->next = entr->row_chain.next;
+                       else
+                               m->rows[row]->next = entr->row_chain.next;
+
+                       /* remove col_chain entry */
+                       if (prev_above)
+                               prev_above->next = entr->col_chain.next;
+                       else
+                               m->cols[col]->next = entr->col_chain.next;
+
+                       entr->row_chain.next = NULL;
+                       entr->col_chain.next = NULL;
+
+                       /* set the last pointer to the "previous" element */
+                       if (m->last_col_el[col] == &entr->col_chain ||
+                               m->last_row_el[row] == &entr->row_chain)
+                       {
+                               m->last_col_el[col] = prev_above  ? prev_above  : m->cols[col];
+                               m->last_row_el[row] = prev_leftof ? prev_leftof : m->rows[row];
+                       }
+
+                       free(entr);
+                       m->entries--;
+               }
+               return;
+       }
+
+       /* if it does not exist and 0 should be set just quit */
+       if (val == 0)
+               return;
+
+       /* if it does not exist and val != 0 search the other direction */
+       if (m->maxrow >= m->maxcol)
+               m_search_in_col(m, row, col, &above, &prev_above);
+       else
+               m_search_in_row(m, row, col, &leftof, &prev_leftof);
+       /* now leftof and above are the entry_t's prior the new one in each direction */
+
+       /* insert new entry */
+       entr        = XMALLOC(entry_t);
+       entr->e.row = row;
+       entr->e.col = col;
+       entr->e.val = (float)val;
+
+       /* add row_chain entry */
+       entr->row_chain.next = leftof->next;
+       leftof->next = &entr->row_chain;
+
+       /* add col_chain entry */
+       entr->col_chain.next = above->next;
+       above->next = &entr->col_chain;
+
+       m->last_col_el[col] = &entr->col_chain;
+       m->last_row_el[row] = &entr->row_chain;
+
+       m->entries++;
+}
+
+void matrix_set_row_bulk(sp_matrix_t *m, int row, int *cols, int num_cols, double val)
+{
+       matrix_elem_t *me = NULL;
+       entry_t       *entr;
+       int           i;
+       sp_matrix_list_head_t *leftof, *above;
+       sp_matrix_list_head_t *prev_leftof, *prev_above;
+
+       /* if necessary enlarge the matrix */
+       if (row > m->maxrow) {
+               m->maxrow = row;
+               if (row >= m->rowc)
+                       m_alloc_row(m, m->rowc, m_new_size(m->rowc, row));
+       }
+       if (cols[num_cols - 1] > m->maxcol) {
+               m->maxcol = cols[num_cols - 1];
+               if (cols[num_cols - 1] >= m->colc)
+                       m_alloc_col(m, m->colc, m_new_size(m->colc, cols[num_cols - 1]));
+       }
+
+    /* set start values */
+       prev_above  = NULL;
+       prev_leftof = NULL;
+
+       for (i = 0; i < num_cols; ++i) {
+               /* search for existing entry */
+               me = m_search_in_row(m, row, cols[i], &leftof, &prev_leftof);
+
+               /* if it exists, set the value and return */
+               if (me) {
+                       if (val != 0) {
+                               me->val = (float)val;
+                       } else {
+                               entr = _container_of(me, entry_t, e);
+
+                               /* remove row_chain entry */
+                               if (prev_leftof)
+                                       prev_leftof->next = entr->row_chain.next;
+                               else
+                                       m->rows[row]->next = entr->row_chain.next;
+
+                               /* remove col_chain entry */
+                               if (prev_above)
+                                       prev_above->next = entr->col_chain.next;
+                               else
+                                       m->cols[cols[i]]->next = entr->col_chain.next;
+
+                               entr->row_chain.next = NULL;
+                               entr->col_chain.next = NULL;
+
+                               /* set the last pointer to the "previous" element */
+                               if (m->last_col_el[cols[i]] == &entr->col_chain ||
+                                       m->last_row_el[row]     == &entr->row_chain)
+                               {
+                                       m->last_col_el[cols[i]] = prev_above  ? prev_above  : m->cols[cols[i]];
+                                       m->last_row_el[row]     = prev_leftof ? prev_leftof : m->rows[row];
+                               }
+
+                               free(entr);
+                               m->entries--;
+                       }
+
+                       continue;
+               }
+
+               /* if it does not exist and 0 should be set just quit */
+               if (val == 0)
+                       continue;
+
+               /* we have to search the col list as well, to get the above pointer */
+               m_search_in_col(m, row, cols[i], &above, &prev_above);
+
+               /* now leftof and above are the entry_t's prior the new one in each direction */
+
+               /* insert new entry */
+               entr        = XMALLOC(entry_t);
+               entr->e.row = row;
+               entr->e.col = cols[i];
+               entr->e.val = (float)val;
+
+               m->last_col_el[cols[i]] = &entr->col_chain;
+               m->last_row_el[row]     = &entr->row_chain;
+
+               /* add row_chain entry */
+               entr->row_chain.next = leftof->next;
+               leftof->next = &entr->row_chain;
+
+               /* add col_chain entry */
+               entr->col_chain.next = above->next;
+               above->next = &entr->col_chain;
+
+               m->entries++;
+       }
+}
+
+double matrix_get(const sp_matrix_t *m, int row, int col)
+{
+       sp_matrix_list_head_t *dummy, *dummy2;
+       matrix_elem_t *me;
+
+       if (is_empty_row(row) || is_empty_col(col))
+               return 0.0;
+
+       if (m->maxrow < m->maxcol)
+               me = m_search_in_col(m, row, col, &dummy, &dummy2);
+       else
+               me = m_search_in_row(m, row, col, &dummy, &dummy2);
+
+       if (me)
+               assert(me->col == col && me->row == row);
+
+       return me ? me->val : 0.0;
+}
+
+int matrix_get_entries(const sp_matrix_t *m)
+{
+       return m->entries;
+}
+
+int matrix_get_rowcount(const sp_matrix_t *m)
+{
+       return m->maxrow + 1;
+}
+
+int matrix_get_colcount(const sp_matrix_t *m)
+{
+       return m->maxcol + 1;
+}
+
+const matrix_elem_t *matrix_row_first(sp_matrix_t *m, int row)
+{
+       if (is_empty_row(row))
+               return NULL;
+
+       m->dir   = right;
+       m->first = m->rows[row];
+       m->last  = m->first->next;
+       m->next  = m->last ? m->last->next : NULL;
+
+       assert (list_entry_by_row(m->last)->row == row);
+
+       return list_entry_by_row(m->last);
+}
+
+const matrix_elem_t *matrix_col_first(sp_matrix_t *m, int col)
+{
+       if (is_empty_col(col))
+               return NULL;
+
+       m->dir   = down;
+       m->first = m->cols[col];
+       m->last  = m->first->next;
+       m->next  = m->last ? m->last->next : NULL;
+
+       assert (list_entry_by_col(m->last)->col == col);
+
+       return list_entry_by_col(m->last);
+}
+
+static inline const matrix_elem_t *matrix_first_from(sp_matrix_t *m, int startrow)
+{
+       const matrix_elem_t *res;
+       int i;
+
+       for (i = startrow; i <= m->maxrow; ++i) {
+               res = matrix_row_first(m, i);
+               if (res) {
+                       m->iter_row = i;
+                       m->dir      = all;
+                       return res;
+               }
+       }
+
+       return NULL;
+}
+
+const matrix_elem_t *matrix_first(sp_matrix_t *m)
+{
+       return matrix_first_from(m, 0);
+}
+
+const matrix_elem_t *matrix_next(sp_matrix_t *m)
+{
+       assert(m->first && "Start iteration with matrix_???_first, before calling me!");
+
+       if (m->next == NULL) {
+               if (m->dir == all)
+                       return matrix_first_from(m, ++m->iter_row);
+               else
+                       return NULL;
+       }
+
+       m->last = m->next;
+       m->next = m->next->next;
+
+       if (m->dir == down)
+               return list_entry_by_col(m->last);
+       else /* right or all */
+               return list_entry_by_row(m->last);
+}
+
+static int cmp_count(const void *e1, const void *e2)
+{
+       return (int *)e2 - (int *)e1;
+}
+
+static inline void matrix_fill_row(sp_matrix_t *m, int row, bitset_t *fullrow)
+{
+       const matrix_elem_t *e;
+       bitset_set(fullrow, row);
+       matrix_foreach_in_col(m, row, e) {
+               if (! bitset_is_set(fullrow, e->row)) {
+                       assert(0.0 == matrix_get(m, e->col, e->row));
+                       matrix_set(m, e->col, e->row, e->val);
+                       matrix_set(m, e->row, e->col, 0.0);
+               }
+       }
+}
+
+void matrix_optimize(sp_matrix_t *m)
+{
+       int i, size, redo;
+       int *c;
+       const matrix_elem_t *e;
+       bitset_t *fullrow;
+
+       size = MAX(m->maxcol, m->maxrow)+1;
+
+       /* kill all double-entries (Mij and Mji are set) */
+       matrix_foreach(m, e) {
+               double t_val;
+
+               assert(e->row != e->col && "Root has itself as arg. Ok. But the arg (=root) will always have the same color as root");
+               t_val = matrix_get(m, e->col, e->row);
+               if (fabs(t_val) > 1e-10) {
+                       matrix_set(m, e->col, e->row, 0);
+                       matrix_set(m, e->row, e->col, e->val + t_val);
+               }
+       }
+
+       c       = alloca(size * sizeof(*c));
+       redo    = 1;
+       fullrow = bitset_alloca(size);
+
+       /* kill 'all' rows containing only 1 entry */
+       while (redo) {
+               redo = 0;
+               /* count elements in rows */
+               memset(c, 0, size * sizeof(*c));
+
+               matrix_foreach(m, e)
+                       c[e->row]++;
+
+               for (i = 0; i<size; ++i)
+                       if (c[i] == 1 && ! bitset_is_set(fullrow, i)) {
+                               redo = 1;
+                               /* if the other row isn't empty move the e in there, else fill e's row */
+                               if (e = matrix_row_first(m, i), e) {
+                                       if (c[e->col] > 0)
+                                               matrix_fill_row(m, e->col, fullrow);
+                                       else
+                                               matrix_fill_row(m, e->row, fullrow);
+                               }
+                       }
+       }
+
+
+       memset(c, 0, size * sizeof(*c));
+       matrix_foreach(m, e)
+               c[e->row]++;
+
+       qsort(c, size, sizeof(*c), cmp_count);
+
+       for (i = 0; i < size; ++i) {
+               if (! bitset_is_set(fullrow, i))
+                       matrix_fill_row(m, i, fullrow);
+       }
+}
+
+void matrix_dump(sp_matrix_t *m, FILE *out, int factor)
+{
+       int i, o, last_idx;
+       const matrix_elem_t *e;
+
+       for (i = 0; i <= m->maxrow; ++i) {
+               last_idx = -1;
+               matrix_foreach_in_row(m, i, e) {
+                       for (o = last_idx + 1; o < e->col; ++o)
+                               fprintf(out, " %4.1f" , 0.0);
+
+                       fprintf(out, " %4.1f", factor * e->val);
+                       last_idx = e->col;
+               }
+
+               for (o = last_idx + 1; o <= m->maxcol; ++o)
+                       fprintf(out, " %4.1f" , 0.0);
+
+               fprintf(out, "\n");
+       }
+}
+
+void matrix_self_test(int d)
+{
+       int i, o;
+       const matrix_elem_t *e;
+       sp_matrix_t *m = new_matrix(10, 10);
+
+       for (i = 0; i < d; ++i)
+               for (o = 0; o < d; ++o)
+                       matrix_set(m, i, o, i*o);
+
+       for (i = 0; i < d; ++i)
+               for (o = 0; o<d; ++o)
+                       assert(matrix_get(m, i, o) == i*o);
+
+       i = 1;
+       matrix_foreach_in_row(m,1,e) {
+               assert(e->val == i);
+               i++;
+       }
+       assert(!matrix_next(m)); /*iter must finish */
+
+       i = d-1;
+       matrix_foreach_in_col(m,d-1,e) {
+               assert(e->val == i);
+               i += d-1;
+       }
+       assert(!matrix_next(m));
+       del_matrix(m);
+       m = new_matrix(16,16);
+       matrix_set(m, 1,1,9);
+       matrix_set(m, 1,2,8);
+       matrix_set(m, 1,3,7);
+
+       matrix_set(m, 1,3,6);
+       matrix_set(m, 1,2,5);
+       matrix_set(m, 1,1,4);
+       i = 1;
+       matrix_foreach_in_row(m, 1, e) {
+               assert(e->row == 1 && e->col == i && e->val == i+3);
+               i++;
+       }
+       assert(i == 4);
+       del_matrix(m);
+
+       m = new_matrix(5,5);
+       matrix_set(m, 1,1,1);
+       matrix_set(m, 2,2,2);
+       matrix_set(m, 3,3,3);
+       matrix_set(m, 3,5,4);
+       matrix_set(m, 4,4,5);
+       matrix_set(m, 5,5,6);
+       for (i=1, e = matrix_first(m); e; ++i, e=matrix_next(m))
+               assert(e->val == i);
+       assert(i == 7);
+       matrix_set(m, 1,1,0);
+       assert(5 == matrix_get_entries(m));
+       del_matrix(m);
+}
diff --git a/ir/lpp/sp_matrix.h b/ir/lpp/sp_matrix.h
new file mode 100644 (file)
index 0000000..20ed293
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * Author:      Daniel Grund
+ * Date:        07.04.2005
+ * Copyright:   (c) Universitaet Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * CVS-Id:      $Id: sp_matrix.h 16112 2007-10-07 15:50:49Z mallon $
+ *
+ * Sparse matrix storage with linked lists for rows and cols.
+ */
+
+#ifndef _SP_MATRIX_H
+#define _SP_MATRIX_H
+
+#include <stdio.h>
+
+/**
+ * A matrix element.
+ */
+typedef struct matrix_elem_t {
+       int   row;  /* row index */
+       int   col;  /* column index */
+       float val;  /* the actual value of the entry */
+} matrix_elem_t;
+
+typedef struct sp_matrix_t sp_matrix_t;
+
+/**
+ * Allocate a new matrix and init internal data for a matrix of size
+ * row_init X col_init. Matrix cannot grow beyond these init values.
+ * All elements are initially (implicit) set to 0.
+ */
+sp_matrix_t *new_matrix(int rows, int cols);
+
+/**
+ * Free space used by matrix m
+ */
+void del_matrix(sp_matrix_t *m);
+
+/**
+ * Sets m[row, col] to val
+ */
+void matrix_set(sp_matrix_t *m, int row, int col, double val);
+
+/**
+ * Sets m[row, cols[0,...,i]] to val for i in (0, ..., num_cols - 1)
+ * Following assumptions are done here:
+ * - the current row inserted is the last inserted row so far
+ * - cols[] is sorted ascending by col number
+ */
+void matrix_set_row_bulk(sp_matrix_t *m, int row, int *cols, int num_cols, double val);
+
+/**
+ * Returns the value stored in m[row, col].
+ */
+double matrix_get(const sp_matrix_t *m, int row, int col);
+
+/**
+ * Returns the number of (not-0-)entries.
+ */
+int matrix_get_entries(const sp_matrix_t *m);
+
+/**
+ * Returns the number of rows in this matrix; the height; the first dimension
+ */
+int matrix_get_rowcount(const sp_matrix_t *m);
+
+/**
+ * Returns the number of cols in this matrix; the width; the second dimension
+ */
+int matrix_get_colcount(const sp_matrix_t *m);
+
+/**
+ * Start iteration over all matrix elements. Row by row, from top to bottom.
+ * @return NULL if the matrix is empty, else the first element.
+ */
+const matrix_elem_t *matrix_first(sp_matrix_t *m);
+
+/**
+ * Start iteration over a row. Elements are returned from left to right.
+ * @return NULL if row is empty, else the first element.
+ */
+const matrix_elem_t *matrix_row_first(sp_matrix_t *m, int row);
+
+/**
+ * Start iteration over a column. Elements are returned from top to bottom.
+ * @return NULL if column is empty, else the first element.
+ */
+const matrix_elem_t *matrix_col_first(sp_matrix_t *m, int col);
+
+/**
+ * @return the next element in iteration order or NULL if iteration is done.
+ */
+const matrix_elem_t *matrix_next(sp_matrix_t *m);
+
+/**
+ * @return the size for a single matrix element
+ */
+unsigned matrix_get_elem_size(void);
+
+/**
+ * m    The matrix
+ * curr The variable to assign all elements to during iteration
+ * Save against removal of curr
+ */
+#define matrix_foreach(m,curr) \
+               for (curr = matrix_first(m); curr; curr = matrix_next(m))
+
+/**
+ * m    The matrix
+ * r    The row
+ * curr The variable to assign all elements to during iteration
+ * Save against removal of curr
+ */
+#define matrix_foreach_in_row(m,r,curr) \
+               for (curr = matrix_row_first(m, r); curr; curr = matrix_next(m))
+
+/**
+ * m    The matrix
+ * c    The col
+ * curr The variable to assign all elements to during iteration
+ * Save against removal of curr
+ */
+#define matrix_foreach_in_col(m,c,curr) \
+               for (curr = matrix_col_first(m, c); curr; curr = matrix_next(m))
+
+/**
+ * Changes the matrix into an equivalent one with maximal number zero-rows.
+ * The only equivalence transformation is:
+ * Adding a constant to Qij and subtracting it from Qji
+ */
+void matrix_optimize(sp_matrix_t *m);
+
+/**
+ * Dumps the matrix factor*m to the stream @p out.
+ * Remark: I dont need spaces between the elements. So feel free to add
+ *         char *seperator to the arguments.
+ */
+void matrix_dump(sp_matrix_t *m, FILE *out, int factor);
+
+/**
+ * Perform a self test with a square matrix of dimensions d.
+ */
+void matrix_self_test(int d);
+
+#endif
index 99b9116..d6f3c0e 100644 (file)
@@ -79,7 +79,8 @@ static bool is_Block_removable(ir_node *block)
 }
 
 /** checks if a given Cond node is a switch Cond. */
-static bool is_switch_Cond(ir_node *cond) {
+static bool is_switch_Cond(ir_node *cond)
+{
        ir_node *sel = get_Cond_selector(cond);
        return get_irn_mode(sel) != mode_b;
 }
@@ -602,33 +603,46 @@ typedef enum block_flags_t {
        BF_IS_UNKNOWN_JUMP_TARGET = 1 << 2,
 } block_flags_t;
 
-static bool get_phase_flag(ir_phase *block_info, ir_node *block, int flag) {
-       return ((int)phase_get_irn_data(block_info, block)) & flag;
+static bool get_phase_flag(ir_phase *block_info, ir_node *block, int flag)
+{
+       return PTR_TO_INT(phase_get_irn_data(block_info, block)) & flag;
 }
-static void set_phase_flag(ir_phase *block_info, ir_node *block, block_flags_t flag) {
-       int data = (int)phase_get_irn_data(block_info, block);
+
+static void set_phase_flag(ir_phase *block_info, ir_node *block,
+                           block_flags_t flag)
+{
+       int data = PTR_TO_INT(phase_get_irn_data(block_info, block));
        data |= flag;
-       phase_set_irn_data(block_info, block, (void*)data);
+       phase_set_irn_data(block_info, block, INT_TO_PTR(data));
 }
 
-static bool has_operations(ir_phase *block_info, ir_node *block) {
+static bool has_operations(ir_phase *block_info, ir_node *block)
+{
        return get_phase_flag(block_info, block, BF_HAS_OPERATIONS);
 }
-static void set_has_operations(ir_phase *block_info, ir_node *block) {
+
+static void set_has_operations(ir_phase *block_info, ir_node *block)
+{
        set_phase_flag(block_info, block, BF_HAS_OPERATIONS);
 }
 
-static bool has_phis(ir_phase *block_info, ir_node *block) {
+static bool has_phis(ir_phase *block_info, ir_node *block)
+{
        return get_phase_flag(block_info, block, BF_HAS_PHIS);
 }
-static void set_has_phis(ir_phase *block_info, ir_node *block) {
+
+static void set_has_phis(ir_phase *block_info, ir_node *block)
+{
        set_phase_flag(block_info, block, BF_HAS_PHIS);
 }
 
-static bool is_unknown_jump_target(ir_phase *block_info, ir_node *block) {
+static bool is_unknown_jump_target(ir_phase *block_info, ir_node *block)
+{
        return get_phase_flag(block_info, block, BF_IS_UNKNOWN_JUMP_TARGET);
 }
-static void set_is_unknown_jump_target(ir_phase *block_info, ir_node *block) {
+
+static void set_is_unknown_jump_target(ir_phase *block_info, ir_node *block)
+{
        set_phase_flag(block_info, block, BF_IS_UNKNOWN_JUMP_TARGET);
 }
 
@@ -723,7 +737,8 @@ static void remove_empty_blocks(ir_node *block, void *x)
 /*
  * Some cfg optimizations, which do not touch Phi nodes
  */
-static void cfgopt_ignoring_phis(ir_graph *irg) {
+static void cfgopt_ignoring_phis(ir_graph *irg)
+{
        ir_phase *block_info = new_phase(irg, NULL);
        skip_env env = { false, block_info };
 
index 901ac42..50bf3a9 100644 (file)
@@ -66,7 +66,7 @@ typedef struct walk_env {
 } walk_env_t;
 
 /** debug handle */
-DEBUG_ONLY(firm_dbg_module_t *dbgHandle;)
+DEBUG_ONLY(static firm_dbg_module_t *dbgHandle;)
 
 /**
  * checks whether a Raise leaves a method
index 7561ded..39de745 100644 (file)
@@ -60,7 +60,7 @@ static void add_pred(ir_node* node, ir_node* x)
        int n;
        int i;
 
-       assert(is_Block(node) || is_Phi(node));
+       assert(is_Block(node));
 
        n = get_irn_arity(node);
        NEW_ARR_A(ir_node*, ins, n + 1);
@@ -194,6 +194,16 @@ static void construct_ssa(ir_node *orig_block, ir_node *orig_val,
        }
 }
 
+/**
+ * jumpthreading produces critical edges, e.g. B-C:
+ *     A         A
+ *  \ /       \  |
+ *   B    =>   B |
+ *  / \       / \|
+ *     C         C
+ *
+ * By splitting this critical edge more threadings might be possible.
+ */
 static void split_critical_edge(ir_node *block, int pos)
 {
        ir_graph *irg = get_irn_irg(block);
@@ -634,6 +644,7 @@ static void thread_jumps(ir_node* block, void* data)
        ir_node *badX;
        int      cnst_pos;
 
+       /* we do not deal with Phis, so restrict this to exactly one cfgpred */
        if (get_Block_n_cfgpreds(block) != 1)
                return;
 
index aaf784f..156293d 100644 (file)
@@ -1678,7 +1678,7 @@ static void do_load_store_optimize(ir_node *n, void *env)
                break;
 
        default:
-               ;
+               break;
        }
 }  /* do_load_store_optimize */
 
@@ -2196,15 +2196,15 @@ static void do_dfs(ir_graph *irg, loop_env *env)
                ir_node *pred = get_Block_cfgpred(endblk, i);
 
                pred = skip_Proj(pred);
-               if (is_Return(pred))
+               if (is_Return(pred)) {
                        dfs(get_Return_mem(pred), env);
-               else if (is_Raise(pred))
+               } else if (is_Raise(pred)) {
                        dfs(get_Raise_mem(pred), env);
-               else if (is_fragile_op(pred))
+               } else if (is_fragile_op(pred)) {
                        dfs(get_fragile_op_mem(pred), env);
-               else if (is_Bad(pred))
-                       /* ignore non-optimized block predecessor */;
-               else {
+               } else if (is_Bad(pred)) {
+                       /* ignore non-optimized block predecessor */
+               else {
                        assert(0 && "Unknown EndBlock predecessor");
                }
        }
index 8bc39fa..4f5a1e1 100644 (file)
@@ -26,6 +26,8 @@
  */
 #include "config.h"
 
+#include <stdbool.h>
+
 #include "iroptimize.h"
 #include "opt_init.h"
 #include "irnode.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg);
 
-/* DBG print stats for every procedure.  */
-#define LOOP_OPT_STATS 1
-
-/* DBG: Ignore node limits and process every possible loop. */
-#define LOOP_IGNORE_NODE_LIMITS 0
-
 /**
  * Convenience macro for iterating over every phi node of the given block.
  * Requires phi list per block.
@@ -79,7 +75,7 @@ typedef enum {
 } unrolling_kind_flag;
 
 /* Condition for performing visiting a node during copy_walk. */
-typedef unsigned walker_condition(ir_node *);
+typedef bool walker_condition(const ir_node *);
 
 /* Node and position of a predecessor. */
 typedef struct entry_edge {
@@ -97,18 +93,12 @@ typedef struct unrolling_node_info {
 static entry_edge *cur_head_outs;
 
 /* Information about the loop head */
-static ir_node *loop_head = NULL;
-static unsigned loop_head_valid = 1;
+static ir_node *loop_head       = NULL;
+static bool     loop_head_valid = true;
 
 /* List of all inner loops, that are processed. */
 static ir_loop **loops;
 
-#if LOOP_OPT_STATS
-
-#define count_stats(val) (++val)
-#define print_stats() (do_print_stats())
-#define reset_stats() (do_reset_stats())
-
 /* Stats */
 typedef struct loop_stats_t {
        unsigned loops;
@@ -128,13 +118,13 @@ typedef struct loop_stats_t {
 static loop_stats_t stats;
 
 /* Set stats to sero */
-static void do_reset_stats(void)
+static void reset_stats(void)
 {
        memset(&stats, 0, sizeof(loop_stats_t));
 }
 
 /* Print stats */
-static void do_print_stats(void)
+static void print_stats(void)
 {
        DB((dbg, LEVEL_2, "---------------------------------------\n"));
        DB((dbg, LEVEL_2, "loops             :   %d\n",stats.loops));
@@ -148,28 +138,21 @@ static void do_print_stats(void)
        DB((dbg, LEVEL_2, "invariant_unroll  :   %d\n",stats.invariant_unroll));
        DB((dbg, LEVEL_2, "=======================================\n"));
 }
-#else
-/* No stats */
-#define count_stats(val) ((void)0)
-#define print_stats() ((void)0)
-#define reset_stats() ((void)0)
-
-#endif
 
 /* Commandline parameters */
 typedef struct loop_opt_params_t {
 unsigned max_loop_size;     /* Maximum number of nodes  [nodes]*/
 int      depth_adaption;    /* Loop nest depth adaption [percent] */
 unsigned allowed_calls;     /* Number of calls allowed [number] */
-unsigned count_phi:1;       /* Count phi nodes */
-unsigned count_proj:1;      /* Count projections */
+bool     count_phi;         /* Count phi nodes */
+bool     count_proj;        /* Count projections */
 
 unsigned max_cc_size;       /* Maximum condition chain size [nodes] */
 unsigned max_branches;
 
 unsigned max_unrolled_loop_size;    /* [nodes] */
-unsigned allow_const_unrolling:1;
-unsigned allow_invar_unrolling:1;
+bool     allow_const_unrolling;
+bool     allow_invar_unrolling;
 unsigned invar_unrolling_min_size;  /* [nodes] */
 
 } loop_opt_params_t;
@@ -257,34 +240,47 @@ static void reset_link(ir_node *node, void *env)
 }
 
 /* Returns 0 if the node or block is not in cur_loop. */
-static unsigned is_in_loop(ir_node *node)
+static bool is_in_loop(const ir_node *node)
 {
-       return (get_irn_loop(get_block(node)) == cur_loop);
+       return get_irn_loop(get_block_const(node)) == cur_loop;
 }
 
 /* Returns 0 if the given edge is not a backedge
  * with its pred in the cur_loop. */
-static unsigned is_own_backedge(ir_node *n, int pos)
+static bool is_own_backedge(const ir_node *n, int pos)
 {
-       return (is_backedge(n, pos) && is_in_loop(get_irn_n(n, pos)));
+       return is_backedge(n, pos) && is_in_loop(get_irn_n(n, pos));
 }
 
 /* Finds loop head and some loop_info as calls or else if necessary. */
 static void get_loop_info(ir_node *node, void *env)
 {
-       unsigned node_in_loop, pred_in_loop;
+       bool node_in_loop = is_in_loop(node);
        int i, arity;
        (void)env;
 
+       /* collect some loop information */
+       if (node_in_loop) {
+               if (is_Phi(node) && opt_params.count_phi)
+                       ++loop_info.nodes;
+               else if (is_Proj(node) && opt_params.count_proj)
+                       ++loop_info.nodes;
+               else if (!is_Confirm(node) && !is_Const(node) && !is_SymConst(node))
+                       ++loop_info.nodes;
+
+               if (is_Load(node) || is_Store(node))
+                       ++loop_info.ld_st;
+
+               if (is_Call(node))
+                       ++loop_info.calls;
+       }
+
        arity = get_irn_arity(node);
        for (i = 0; i < arity; i++) {
-               ir_node *pred = get_irn_n(node, i);
+               ir_node *pred         = get_irn_n(node, i);
+               bool     pred_in_loop = is_in_loop(pred);
 
-               pred_in_loop = is_in_loop(pred);
-               node_in_loop = is_in_loop(node);
-
-               if (!node_in_loop && pred_in_loop && is_Block(node))
-               {
+               if (is_Block(node) && !node_in_loop && pred_in_loop) {
                        entry_edge entry;
                        entry.node = node;
                        entry.pos = i;
@@ -294,31 +290,15 @@ static void get_loop_info(ir_node *node, void *env)
                        loop_info.cf_out = entry;
                }
 
-               /* collect some loop information */
-               if (node_in_loop) {
-                       if (is_Phi(node) && opt_params.count_phi)
-                               ++loop_info.nodes;
-                       else if (is_Proj(node) && opt_params.count_proj)
-                               ++loop_info.nodes;
-                       else if (!is_Confirm(node) && !is_Const(node) && !is_SymConst(node))
-                               ++loop_info.nodes;
-
-                       if (is_Load(node) || is_Store(node))
-                               ++loop_info.ld_st;
-
-                       if (is_Call(node))
-                               ++loop_info.calls;
-
-               }
-
                /* Find the loops head/the blocks with cfpred outside of the loop */
                if (is_Block(node)) {
                        const ir_edge_t *edge;
                        unsigned outs_n = 0;
 
                        /* Count innerloop branches */
-                       foreach_out_edge_kind(node, edge, EDGE_KIND_NORMAL) {
-                               if (is_Block(get_edge_src_irn(edge)) && is_in_loop(get_edge_src_irn(edge)))
+                       foreach_out_edge_kind(node, edge, EDGE_KIND_BLOCK) {
+                               ir_node *succ = get_edge_src_irn(edge);
+                               if (is_Block(succ) && is_in_loop(succ))
                                        ++outs_n;
                        }
                        if (outs_n > 1)
@@ -332,7 +312,7 @@ static void get_loop_info(ir_node *node, void *env)
                                                                node, pred));
                                        /* another head? We do not touch this. */
                                        if (loop_head && loop_head != node) {
-                                               loop_head_valid = 0;
+                                               loop_head_valid = false;
                                        } else {
                                                loop_head = node;
                                        }
@@ -571,26 +551,20 @@ static void reset_block_mark(ir_node *node, void * env)
 
 /* Returns mark of node, or its block if node is not a block.
  * Used in this context to determine if node is in the condition chain. */
-static unsigned is_nodes_block_marked(ir_node* node)
+static bool is_nodes_block_marked(const ir_node* node)
 {
-       if (is_Block(node))
-               return get_Block_mark(node);
-       else
-               return get_Block_mark(get_block(node));
+       return get_Block_mark(get_block_const(node));
 }
 
 /* Extends a nodes ins by node new.
  * NOTE: This is slow if a node n needs to be extended more than once. */
-static void extend_irn(ir_node *n, ir_node *newnode, int new_is_backedge)
+static void extend_irn(ir_node *n, ir_node *newnode, bool new_is_backedge)
 {
-       ir_node **ins;
        int i;
        int arity = get_irn_arity(n);
        int new_arity = arity + 1;
-       int *bes;
-
-       NEW_ARR_A(int, bes, new_arity);
-       NEW_ARR_A(ir_node *, ins, new_arity);
+       ir_node **ins = XMALLOCN(ir_node*, new_arity);
+       bool     *bes = XMALLOCN(bool, new_arity);
 
        /* save bes */
        /* Bes are important!
@@ -633,7 +607,7 @@ static void extend_ins_by_copy(ir_node *block, int pos)
        pred = get_irn_n(block, pos);
        new_in = get_inversion_copy(pred);
        DB((dbg, LEVEL_5, "Extend block %N by %N cp of %N\n", block, new_in, pred));
-       extend_irn(block, new_in, 0);
+       extend_irn(block, new_in, false);
 
        /* Extend block phis by copy of definition at pos */
        for_each_phi(block, phi) {
@@ -649,12 +623,12 @@ static void extend_ins_by_copy(ir_node *block, int pos)
                        new_in = cp;
 
                DB((dbg, LEVEL_5, "Extend phi %N by %N cp of %N\n", phi, new_in, pred));
-               extend_irn(phi, new_in, 0);
+               extend_irn(phi, new_in, false);
        }
 }
 
 /* Returns the number of blocks backedges. With or without alien bes. */
-static int get_backedge_n(ir_node *block, unsigned with_alien)
+static int get_backedge_n(ir_node *block, bool with_alien)
 {
        int i;
        int be_n = 0;
@@ -958,10 +932,10 @@ static void get_head_outs(ir_node *node, void *env)
 static void find_condition_chain(ir_node *block)
 {
        const    ir_edge_t *edge;
-       unsigned mark = 0;
-       unsigned has_be = 0;
-       unsigned jmp_only;
-       unsigned nodes_n = 0;
+       bool     mark     = false;
+       bool     has_be   = false;
+       bool     jmp_only = true;
+       unsigned nodes_n  = 0;
 
        mark_irn_visited(block);
 
@@ -982,12 +956,11 @@ static void find_condition_chain(ir_node *block)
        }
 
        /* Check if block only has a jmp instruction. */
-       jmp_only = 1;
        foreach_out_edge(block, edge) {
                ir_node *src = get_edge_src_irn(edge);
 
-               if (! is_Block(src) && ! is_Jmp(src)) {
-                       jmp_only = 0;
+               if (!is_Block(src) && !is_Jmp(src)) {
+                       jmp_only = false;
                }
        }
 
@@ -997,8 +970,8 @@ static void find_condition_chain(ir_node *block)
                ir_node *src = get_edge_src_irn(edge);
                int pos = get_edge_src_pos(edge);
 
-               if (! is_in_loop(src))
-                       mark = 1;
+               if (!is_in_loop(src))
+                       mark = true;
 
                /* Inverting blocks with backedge outs leads to a cf edge
                 * from the inverted head, into the inverted head (skipping the body).
@@ -1006,7 +979,7 @@ static void find_condition_chain(ir_node *block)
                 * this would introduce another loop in the existing loop.
                 * This loop inversion cannot cope with this case. */
                if (is_backedge(src, pos)) {
-                       has_be = 1;
+                       has_be = true;
                        break;
                }
        }
@@ -1025,7 +998,7 @@ static void find_condition_chain(ir_node *block)
         */
        /* Collect blocks containing only a Jmp.
         * Do not collect blocks with backedge outs. */
-       if ((jmp_only == 1 || mark == 1) && has_be == 0) {
+       if ((jmp_only || mark) && !has_be) {
                set_Block_mark(block, 1);
                ++inversion_blocks_in_cc;
                loop_info.cc_size += nodes_n;
@@ -1058,7 +1031,7 @@ static void fix_copy_inversion(void)
        ir_node *head_cp = get_inversion_copy(loop_head);
        ir_graph *irg    = get_irn_irg(head_cp);
        int arity        = get_irn_arity(head_cp);
-       int backedges    = get_backedge_n(head_cp, 0);
+       int backedges    = get_backedge_n(head_cp, false);
        int new_arity    = arity - backedges;
        int pos;
        int i;
@@ -1113,7 +1086,7 @@ static void fix_head_inversion(void)
        ir_node **phis;
        ir_graph *irg = get_irn_irg(loop_head);
        int arity     = get_irn_arity(loop_head);
-       int backedges = get_backedge_n(loop_head, 0);
+       int backedges = get_backedge_n(loop_head, false);
        int new_arity = backedges;
        int pos;
        int i;
@@ -1176,7 +1149,7 @@ static void fix_head_inversion(void)
 }
 
 /* Does the loop inversion.  */
-static void inversion_walk(entry_edge *head_entries)
+static void inversion_walk(ir_graph *irg, entry_edge *head_entries)
 {
        size_t i;
 
@@ -1185,10 +1158,10 @@ static void inversion_walk(entry_edge *head_entries)
         * Any change of the order leads to lost information that would be needed later.
         */
 
-       ir_reserve_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
+       ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
 
        /* 1. clone condition chain */
-       inc_irg_visited(current_ir_graph);
+       inc_irg_visited(irg);
 
        for (i = 0; i < ARR_LEN(head_entries); ++i) {
                entry_edge entry = head_entries[i];
@@ -1199,7 +1172,7 @@ static void inversion_walk(entry_edge *head_entries)
                copy_walk(pred, is_nodes_block_marked, cur_loop);
        }
 
-       ir_free_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
+       ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
 
        /* 2. Extends the head control flow successors ins
         *    with the definitions of the copied head node. */
@@ -1276,14 +1249,14 @@ static void inversion_walk(entry_edge *head_entries)
 }
 
 /* Performs loop inversion of cur_loop if possible and reasonable. */
-static void loop_inversion(void)
+static void loop_inversion(ir_graph *irg)
 {
        int      loop_depth;
        unsigned max_loop_nodes = opt_params.max_loop_size;
        unsigned max_loop_nodes_adapted;
        int      depth_adaption = opt_params.depth_adaption;
 
-       unsigned do_inversion = 1;
+       bool do_inversion = true;
 
        /* Depth of 0 is the procedure and 1 a topmost loop. */
        loop_depth = get_loop_depth(cur_loop) - 1;
@@ -1294,17 +1267,14 @@ static void loop_inversion(void)
        DB((dbg, LEVEL_1, "max_nodes: %d\nmax_nodes_adapted %d at depth of %d (adaption %d)\n",
                        max_loop_nodes, max_loop_nodes_adapted, loop_depth, depth_adaption));
 
-       if (! (loop_info.nodes > 0))
+       if (loop_info.nodes == 0)
                return;
 
-#if LOOP_IGNORE_NODE_LIMITS
-       DB((dbg, LEVEL_1, "WARNING: Loop node limitations ignored."));
-#else
        if (loop_info.nodes > max_loop_nodes) {
                /* Only for stats */
                DB((dbg, LEVEL_1, "Nodes %d > allowed nodes %d\n",
                        loop_info.nodes, loop_depth, max_loop_nodes));
-               count_stats(stats.too_large);
+               ++stats.too_large;
                /* no RETURN */
                /* Adaption might change it */
        }
@@ -1313,24 +1283,23 @@ static void loop_inversion(void)
        if (loop_info.nodes > max_loop_nodes_adapted) {
                DB((dbg, LEVEL_1, "Nodes %d > allowed nodes (depth %d adapted) %d\n",
                        loop_info.nodes, loop_depth, max_loop_nodes_adapted));
-               count_stats(stats.too_large_adapted);
+               ++stats.too_large_adapted;
                return;
        }
 
        if (loop_info.calls > opt_params.allowed_calls) {
                DB((dbg, LEVEL_1, "Calls %d > allowed calls %d\n",
                        loop_info.calls, opt_params.allowed_calls));
-               count_stats(stats.calls_limit);
+               ++stats.calls_limit;
                return;
        }
-#endif
 
        /*inversion_head_node_limit = INT_MAX;*/
-       ir_reserve_resources(current_ir_graph, IR_RESOURCE_BLOCK_MARK);
+       ir_reserve_resources(irg, IR_RESOURCE_BLOCK_MARK);
 
        /* Reset block marks.
         * We use block marks to flag blocks of the original condition chain. */
-       irg_walk_graph(current_ir_graph, reset_block_mark, NULL, NULL);
+       irg_walk_graph(irg, reset_block_mark, NULL, NULL);
 
        /*loop_info.blocks = get_loop_n_blocks(cur_loop);*/
        cond_chain_entries = NEW_ARR_F(entry_edge, 0);
@@ -1340,39 +1309,34 @@ static void loop_inversion(void)
        inversion_blocks_in_cc = 0;
 
        /* Use phase to keep copy of nodes from the condition chain. */
-       phase = new_phase(current_ir_graph, phase_irn_init_default);
+       phase = new_phase(irg, phase_irn_init_default);
 
        /* Search for condition chains and temporarily save the blocks in an array. */
        cc_blocks = NEW_ARR_F(ir_node *, 0);
-       inc_irg_visited(current_ir_graph);
+       inc_irg_visited(irg);
        find_condition_chain(loop_head);
 
        unmark_not_allowed_cc_blocks();
        DEL_ARR_F(cc_blocks);
 
-#if LOOP_IGNORE_NODE_LIMITS
-       (void) unmark_cc_blocks;
-#else
        /* Condition chain too large.
         * Loop should better be small enough to fit into the cache. */
        /* TODO Of course, we should take a small enough cc in the first place,
         * which is not that simple. (bin packing)  */
        if (loop_info.cc_size > opt_params.max_cc_size) {
-               count_stats(stats.cc_limit_reached);
+               ++stats.cc_limit_reached;
 
-               do_inversion = 0;
+               do_inversion = false;
 
                /* Unmark cc blocks except the head.
                 * Invert head only for possible unrolling. */
                unmark_cc_blocks();
-
        }
-#endif
 
        /* We also catch endless loops here,
         * because they do not have a condition chain. */
        if (inversion_blocks_in_cc < 1) {
-               do_inversion = 0;
+               do_inversion = false;
                DB((dbg, LEVEL_3,
                        "Loop contains %d (less than 1) invertible blocks => No Inversion done.\n",
                        inversion_blocks_in_cc));
@@ -1382,17 +1346,18 @@ static void loop_inversion(void)
                cur_head_outs = NEW_ARR_F(entry_edge, 0);
 
                /* Get all edges pointing into the condition chain. */
-               irg_walk_graph(current_ir_graph, get_head_outs, NULL, NULL);
+               irg_walk_graph(irg, get_head_outs, NULL, NULL);
 
                /* Do the inversion */
-               inversion_walk(cur_head_outs);
+               inversion_walk(irg, cur_head_outs);
 
                DEL_ARR_F(cur_head_outs);
 
                /* Duplicated blocks changed doms */
-               set_irg_doms_inconsistent(current_ir_graph);
+               set_irg_doms_inconsistent(irg);
+               set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
 
-               count_stats(stats.inverted);
+               ++stats.inverted;
        }
 
        /* free */
@@ -1400,7 +1365,7 @@ static void loop_inversion(void)
        DEL_ARR_F(cond_chain_entries);
        DEL_ARR_F(head_df_loop);
 
-       ir_free_resources(current_ir_graph, IR_RESOURCE_BLOCK_MARK);
+       ir_free_resources(irg, IR_RESOURCE_BLOCK_MARK);
 }
 
 /* Fix the original loop_heads ins for invariant unrolling case. */
@@ -1627,9 +1592,9 @@ static ir_node *clone_phis_sans_bes(ir_node *phi, ir_node *be_block, ir_node *de
  * using be_block as supplier of backedge informations. */
 static ir_node *clone_block_sans_bes(ir_node *node, ir_node *be_block)
 {
-       ir_node **ins;
        int arity = get_irn_arity(node);
        int i, c = 0;
+       ir_node **ins;
 
        assert(get_irn_arity(node) == get_irn_arity(be_block));
        assert(is_Block(node));
@@ -2049,18 +2014,12 @@ static ir_node *is_simple_loop(void)
 
        DB((dbg, LEVEL_4, "1 loop exit\n"));
 
-#if LOOP_IGNORE_NODE_LIMITS
-       /* Ignore loop size. Probably not wise in other than testcases. */
-       loop_info.max_unroll = 40;
-#else
        /* Calculate maximum unroll_nr keeping node count below limit. */
        loop_info.max_unroll = (int)((double)opt_params.max_unrolled_loop_size / (double)loop_info.nodes);
        if (loop_info.max_unroll < 2) {
-               count_stats(stats.too_large);
+               ++stats.too_large;
                return NULL;
        }
-#endif
-
 
        DB((dbg, LEVEL_4, "maximum unroll factor %u, to not exceed node limit \n",
                opt_params.max_unrolled_loop_size));
@@ -2476,7 +2435,7 @@ static unsigned get_unroll_decision_constant(void)
                return 0;
        }
 
-       count_stats(stats.u_simple_counting_loop);
+       ++stats.u_simple_counting_loop;
 
        loop_info.latest_value = is_latest_val;
 
@@ -2543,23 +2502,19 @@ static void unroll_loop(void)
        if (! (loop_info.nodes > 0))
                return;
 
-#if LOOP_IGNORE_NODE_LIMITS
-       DB((dbg, LEVEL_1, "WARNING: Loop node limitations ignored."));
-#else
        if (loop_info.nodes > opt_params.max_unrolled_loop_size) {
                DB((dbg, LEVEL_2, "Nodes %d > allowed nodes %d\n",
                        loop_info.nodes, opt_params.max_unrolled_loop_size));
-               count_stats(stats.too_large);
+               ++stats.too_large;
                return;
        }
 
        if (loop_info.calls > 0) {
                DB((dbg, LEVEL_2, "Calls %d > allowed calls 0\n",
                        loop_info.calls));
-               count_stats(stats.calls_limit);
+               ++stats.calls_limit;
                return;
        }
-#endif
 
        unroll_nr = 0;
 
@@ -2614,9 +2569,9 @@ static void unroll_loop(void)
                irg_walk_graph(current_ir_graph, correct_phis, NULL, NULL);
 
                if (loop_info.unroll_kind == constant)
-                       count_stats(stats.constant_unroll);
+                       ++stats.constant_unroll;
                else
-                       count_stats(stats.invariant_unroll);
+                       ++stats.invariant_unroll;
 
                set_irg_doms_inconsistent(current_ir_graph);
 
@@ -2627,12 +2582,12 @@ static void unroll_loop(void)
 
 /* Analyzes the loop, and checks if size is within allowed range.
  * Decides if loop will be processed. */
-static void init_analyze(ir_loop *loop)
+static void init_analyze(ir_graph *irg, ir_loop *loop)
 {
        cur_loop = loop;
 
-       loop_head = NULL;
-       loop_head_valid = 1;
+       loop_head       = NULL;
+       loop_head_valid = true;
 
        /* Reset loop info */
        memset(&loop_info, 0, sizeof(loop_info_t));
@@ -2641,7 +2596,7 @@ static void init_analyze(ir_loop *loop)
                get_loop_node(loop, 0)));
 
        /* Collect loop informations: head, node counts. */
-       irg_walk_graph(current_ir_graph, get_loop_info, NULL, NULL);
+       irg_walk_graph(irg, get_loop_info, NULL, NULL);
 
        /* RETURN if there is no valid head */
        if (!loop_head || !loop_head_valid) {
@@ -2654,13 +2609,13 @@ static void init_analyze(ir_loop *loop)
        if (loop_info.branches > opt_params.max_branches) {
                DB((dbg, LEVEL_1, "Branches %d > allowed branches %d\n",
                        loop_info.branches, opt_params.max_branches));
-               count_stats(stats.calls_limit);
+               ++stats.calls_limit;
                return;
        }
 
        switch (loop_op) {
                case loop_op_inversion:
-                       loop_inversion();
+                       loop_inversion(irg);
                        break;
 
                case loop_op_unrolling:
@@ -2694,15 +2649,15 @@ static void set_loop_params(void)
 {
     opt_params.max_loop_size = 100;
     opt_params.depth_adaption = -50;
-    opt_params.count_phi = 1;
-    opt_params.count_proj = 0;
+    opt_params.count_phi = true;
+    opt_params.count_proj = false;
     opt_params.allowed_calls = 0;
 
     opt_params.max_cc_size = 5;
 
 
-    opt_params.allow_const_unrolling = 1;
-    opt_params.allow_invar_unrolling = 0;
+    opt_params.allow_const_unrolling = true;
+    opt_params.allow_invar_unrolling = false;
 
     opt_params.invar_unrolling_min_size = 20;
     opt_params.max_unrolled_loop_size = 400;
@@ -2726,14 +2681,10 @@ void loop_optimization(ir_graph *irg)
 
        edges_assure(irg);
        assure_irg_outs(irg);
-
-       /* NOTE: sets only the loop attribute of blocks, not nodes */
-       /* NOTE: Kills links */
        assure_cf_loop(irg);
 
        ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
        collect_phiprojs(irg);
-       ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
 
        loop = get_irg_loop(irg);
        sons = get_loop_n_sons(loop);
@@ -2744,73 +2695,47 @@ void loop_optimization(ir_graph *irg)
                find_innermost_loop(get_loop_son(loop, nr));
        }
 
-       ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
        /* Set all links to NULL */
-       irg_walk_graph(current_ir_graph, reset_link, NULL, NULL);
+       irg_walk_graph(irg, reset_link, NULL, NULL);
 
        for (i = 0; i < ARR_LEN(loops); ++i) {
                ir_loop *loop = loops[i];
 
-               count_stats(stats.loops);
+               ++stats.loops;
 
                /* Analyze and handle loop */
-               init_analyze(loop);
+               init_analyze(irg, loop);
 
                /* Copied blocks do not have their phi list yet */
                collect_phiprojs(irg);
 
                /* Set links to NULL
                 * TODO Still necessary? */
-               irg_walk_graph(current_ir_graph, reset_link, NULL, NULL);
+               irg_walk_graph(irg, reset_link, NULL, NULL);
        }
 
        print_stats();
 
        DEL_ARR_F(loops);
-       ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
-       ir_free_resources(irg, IR_RESOURCE_PHI_LIST);
+       ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
 }
 
 void do_loop_unrolling(ir_graph *irg)
 {
        loop_op = loop_op_unrolling;
-
-       DB((dbg, LEVEL_1, " >>> unrolling (Startnode %N) <<<\n",
-                               get_irg_start(irg)));
-
        loop_optimization(irg);
-
-       DB((dbg, LEVEL_1, " >>> unrolling done (Startnode %N) <<<\n",
-                               get_irg_start(irg)));
 }
 
 void do_loop_inversion(ir_graph *irg)
 {
        loop_op = loop_op_inversion;
-
-       DB((dbg, LEVEL_1, " >>> inversion (Startnode %N) <<<\n",
-                               get_irg_start(irg)));
-
        loop_optimization(irg);
-
-       assure_cf_loop(irg);
-
-       DB((dbg, LEVEL_1, " >>> inversion done (Startnode %N) <<<\n",
-                               get_irg_start(irg)));
 }
 
 void do_loop_peeling(ir_graph *irg)
 {
        loop_op = loop_op_peeling;
-
-       DB((dbg, LEVEL_1, " >>> peeling (Startnode %N) <<<\n",
-                               get_irg_start(irg)));
-
        loop_optimization(irg);
-
-       DB((dbg, LEVEL_1, " >>> peeling done (Startnode %N) <<<\n",
-                               get_irg_start(irg)));
-
 }
 
 ir_graph_pass_t *loop_inversion_pass(const char *name)
index 3735c14..6b66643 100644 (file)
@@ -735,7 +735,7 @@ static void apply(ir_graph *irg, partition_t *part)
        ir_node **ins, **phi_ins;
        phi_t   *repr_phi, *phi;
        pair_t  *repr_pair, *pair;
-       int     i, j, k, n, block_nr, n_phis;
+       int     i, j, k, n, n_phis;
 
        list_del(&repr->block_list);
 
@@ -769,10 +769,8 @@ static void apply(ir_graph *irg, partition_t *part)
 
        /* collect new in arrays */
        end = get_irg_end(irg);
-       block_nr = 0;
        list_for_each_entry(block_t, bl, &part->blocks, block_list) {
                block = bl->block;
-               ++block_nr;
 
                DB((dbg, LEVEL_1, "%+F, ", block));
 
index 2b33df9..8a0500a 100644 (file)
@@ -67,25 +67,25 @@ static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir
 #define DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, v) \
   ir_printf("In %e:\na %= %n && b %= %n  ==>  a %= b == %s\n", \
     get_irg_entity(current_ir_graph), \
-    l_relation, l_bound, r_relation, r_bound, relation, v);
+    l_relation, l_bound, r_relation, r_bound, relation, v)
 
 /* right side */
 #define DBG_OUT_R(r_relation, r_bound, left, relation, right, v) \
   ir_printf("In %e:\na %= %n ==>  %n %= %n == %s\n", \
     get_irg_entity(current_ir_graph), \
-    r_relation, r_bound, left, relation, right, v);
+    r_relation, r_bound, left, relation, right, v)
 
 /* left side */
 #define DBG_OUT_L(l_relation, l_bound, left, relation, right, v) \
   ir_printf("In %e:\na %= %n ==>  %n %= %n == %s\n", \
     get_irg_entity(current_ir_graph), \
-    l_relation, l_bound, left, relation, right, v);
+    l_relation, l_bound, left, relation, right, v)
 
 #else
 
-#define DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, v)
-#define DBG_OUT_R(r_relation, r_bound, left, relation, right, v)
-#define DBG_OUT_L(l_relation, l_bound, left, relation, right, v)
+#define DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, v)  (void)0
+#define DBG_OUT_R(r_relation, r_bound, left, relation, right, v)  (void)0
+#define DBG_OUT_L(l_relation, l_bound, left, relation, right, v)  (void)0
 
 #endif /* DEBUG_CONFIRM */
 
@@ -97,7 +97,7 @@ static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir
  */
 FIRM_API int value_not_zero(const ir_node *n, ir_node_cnst_ptr *confirm)
 {
-#define RET_ON(x)  if (x) { *confirm = n; return 1; }; break
+#define RET_ON(x)  if (x) { *confirm = n; return 1; } break
 
        ir_tarval *tv;
        ir_mode *mode = get_irn_mode(n);
index 773b89d..5a218e4 100644 (file)
@@ -91,7 +91,7 @@ static ir_type *get_dynamic_type(ir_node *ptr)
                        ptr = get_Confirm_value(ptr);
                        continue;
                default:
-                       ;
+                       break;
                }
                break;
        }
index cedf85b..c27125e 100644 (file)
@@ -941,7 +941,7 @@ int optimize_reassociation(ir_graph *irg)
 
        /*
         * Calculate loop info, so we could identify loop-invariant
-        * code and threat it like a constant.
+        * code and treat it like a constant.
         * We only need control flow loops here but can handle generic
         * INTRA info as well.
         */
@@ -994,7 +994,7 @@ ir_op_ops *firm_set_default_reassoc(unsigned code, ir_op_ops *ops)
        CASE(Eor);
        CASE(Shl);
        default:
-               /* leave NULL */;
+               break;
        }
 
        return ops;
index b3d1576..dabf76b 100644 (file)
@@ -596,7 +596,7 @@ static ir_op *stat_get_irn_op(ir_node *node)
                }  /* if */
                break;
        default:
-               ;
+               break;
        }  /* switch */
 
        return op;
@@ -946,7 +946,7 @@ end_parameter: ;
                        }  /* if */
                }  /* if */
        default:
-               ;
+               break;
        }  /* switch */
 }  /* stat_update_address */
 
@@ -1001,7 +1001,7 @@ static void update_node_stat(ir_node *node, void *env)
                        }
                }
        default:
-               ;
+               break;
        }  /* switch */
 
        /* we want to count the constant IN nodes, not the CSE'ed constant's itself */
index 098413e..833ef69 100644 (file)
 
 #ifdef DISABLE_STATEV
 
-#define stat_ev_do(expr)
-#define stat_ev_enabled             0
-#define stat_ev_if                  if (0)
-#define stat_ev_dbl(name, val)
-#define stat_ev_int(name, val)
-#define stat_ev(name)
-#define stat_ev_emit(name, value)
-
-#define stat_ev_cnt_decl(var)
-#define stat_ev_cnt_inc(var)
-#define stat_ev_cnt_done(name, var)
-#define stat_ev_tim_push()
-#define stat_ev_tim_pop(name)
-
-#define stat_ev_ctx_push(key)
-#define stat_ev_ctx_push_str(key, str)
-#define stat_ev_ctx_push_fmt(key, fmt, value)
-#define stat_ev_ctx_push_fobj(key, firm_object)
-#define stat_ev_ctx_pop(key)
-#define stat_ev_flush()
+#define stat_ev_enabled                          0
+#define stat_ev_dbl(name, val)                   ((void)0)
+#define stat_ev_int(name, val)                   ((void)0)
+#define stat_ev(name)                            ((void)0)
+#define stat_ev_emit(name, value)                ((void)0)
+
+#define stat_ev_cnt_decl(var)                    ((void)0)
+#define stat_ev_cnt_inc(var)                     ((void)0)
+#define stat_ev_cnt_done(name, var)              ((void)0)
+#define stat_ev_tim_push()                       ((void)0)
+#define stat_ev_tim_pop(name)                    ((void)0)
+
+#define stat_ev_ctx_push(key)                    ((void)0)
+#define stat_ev_ctx_push_str(key, str)           ((void)0)
+#define stat_ev_ctx_push_fmt(key, fmt, value)    ((void)0)
+#define stat_ev_ctx_push_fobj(key, firm_object)  ((void)0)
+#define stat_ev_ctx_pop(key)                     ((void)0)
+#define stat_ev_flush()                          ((void)0)
 
 #else
 
@@ -132,9 +130,6 @@ static inline void stat_ev_tim_pop(const char *name) {
 #define stat_ev_cnt_inc(var)        do { ++stat_ev_cnt_var_ ## var; } while(0)
 #define stat_ev_cnt_done(var, name) stat_ev_emit((name), stat_ev_cnt_var_ ## var)
 
-#define stat_ev_do(expr)            (stat_ev_enabled ? ((expr), 1) : 0)
-#define stat_ev_if                  if (stat_ev_enabled)
-
 /**
  * Initialize the stat ev machinery.
  * @param filename_prefix  The prefix of the filename (.ev or .ev.gz will be appended).
index 2bca584..191656d 100644 (file)
@@ -670,7 +670,6 @@ static void verify_irn_class_cast_state(ir_node *n, void *env)
        ccs_env             *ccs = (ccs_env *)env;
        ir_class_cast_state this_state = ir_class_casts_any;
        ir_type             *fromtype, *totype;
-       int                 ref_depth = 0;
 
        if (!is_Cast(n)) return;
 
@@ -680,7 +679,6 @@ static void verify_irn_class_cast_state(ir_node *n, void *env)
        while (is_Pointer_type(totype) && is_Pointer_type(fromtype)) {
                totype   = get_pointer_points_to_type(totype);
                fromtype = get_pointer_points_to_type(fromtype);
-               ref_depth++;
        }
 
        if (!is_Class_type(totype)) return;
index 8993ae7..23c806a 100644 (file)
@@ -78,6 +78,7 @@ do { \
 
 static const char *firm_verify_failure_msg;
 
+#if 0
 /**
  * Show diagnostic if an entity overwrites another one not
  * in direct superclasses.
@@ -98,6 +99,7 @@ static void show_ent_not_supertp(ir_entity *ent, ir_entity *ovw)
                ir_fprintf(stderr, " %+F:\n", super);
        }
 }
+#endif
 
 /**
  * Show diagnostic if an entity overwrites a wrong number of things.
@@ -178,7 +180,8 @@ static int check_class(ir_type *tp)
                        show_ent_overwrite_cnt(mem)
                );
 
-               if (false) {
+#if 0
+               {
                        size_t j, m;
                        /* check if the overwrite relation is flat, i.e. every overwrite
                         * is visible in every direct superclass. */
@@ -201,6 +204,7 @@ static int check_class(ir_type *tp)
                                }
                        }
                }
+#endif
        }
        return 0;
 }
index f5db17b..2a11023 100644 (file)
@@ -325,7 +325,7 @@ void set_type_alignment_bytes(ir_type *tp, unsigned align)
 
 const char *get_type_state_name(ir_type_state s)
 {
-#define X(a)    case a: return #a;
+#define X(a)    case a: return #a
        switch (s) {
                X(layout_undefined);
                X(layout_fixed);
index 673f5f1..2858449 100644 (file)
@@ -775,7 +775,7 @@ static void _trunc(const fp_value *a, fp_value *result)
                return;
        }
 
-       if (exp_val > a->desc.mantissa_size) {
+       if (exp_val > (long)a->desc.mantissa_size) {
                if (a != result)
                        memcpy(result, a, calc_buffer_size);
 
@@ -936,7 +936,7 @@ long double fc_val_to_ieee754(const fp_value *val)
        fp_value *value;
        fp_value *temp = NULL;
 
-       int byte_offset;
+       unsigned byte_offset;
 
        uint32_t sign;
        uint32_t exponent;
@@ -1338,7 +1338,7 @@ int fc_can_lossless_conv_to(const fp_value *value, const ieee_descriptor_t *desc
        if (0 < v && v < (1 << desc->exponent_size) - 1) {
                /* exponent can be encoded, now check the mantissa */
                v = value->desc.mantissa_size + ROUNDING_BITS - sc_get_lowest_set_bit(_mant(value));
-               return v <= desc->mantissa_size;
+               return v <= (int)desc->mantissa_size;
        }
        return 0;
 }
index 933c55f..ac2d4f6 100644 (file)
@@ -64,7 +64,9 @@ typedef enum float_to_int_mode {
 
 static float_to_int_mode current_float_to_int_mode = TRUNCATE;
 
+/* set this to true if infinity should be clipped to +/- MAX_FLOAT */
 #define SWITCH_NOINFINITY 0
+/* set this to true if denormals should be clipped to zero */
 #define SWITCH_NODENORMALS 0
 
 /****************************************************************************
@@ -124,11 +126,12 @@ static void _fail_verify(ir_tarval *tv, const char* file, int line)
        else
                panic("%s:%d: Invalid tarval (null)", file, line);
 }
+
+inline static
 #ifdef __GNUC__
-inline static void tarval_verify(ir_tarval *tv) __attribute__ ((unused));
+       __attribute__((unused))
 #endif
-
-inline static void tarval_verify(ir_tarval *tv)
+void tarval_verify(ir_tarval *tv)
 {
        assert(tv);
        assert(tv->mode);
@@ -252,7 +255,7 @@ static ir_tarval *get_tarval_overflow(const void *value, size_t length, ir_mode
                        case TV_OVERFLOW_SATURATE:
                                return get_mode_min(mode);
                        case TV_OVERFLOW_WRAP: {
-                               char *temp = (char*) alloca(sc_get_buffer_length());
+                               temp = (char*) alloca(sc_get_buffer_length());
                                memcpy(temp, value, sc_get_buffer_length());
                                sc_truncate(get_mode_size_bits(mode), temp);
                                return get_tarval(temp, length, mode);
@@ -266,14 +269,13 @@ static ir_tarval *get_tarval_overflow(const void *value, size_t length, ir_mode
                break;
 
        case irms_float_number:
-#ifdef SWITCH_NOINFINITY
+#if SWITCH_NOINFINITY
                if (fc_is_inf((const fp_value*) value)) {
                        /* clip infinity to maximum value */
                        return fc_is_negative((const fp_value*) value) ? get_mode_min(mode) : get_mode_max(mode);
                }
 #endif
-
-#ifdef SWITCH_NODENORMALS
+#if SWITCH_NODENORMALS
                if (fc_is_subnormal((const fp_value*) value)) {
                        /* clip denormals to zero */
                        return get_mode_null(mode);
@@ -315,6 +317,7 @@ static const ieee_descriptor_t *get_descriptor(const ir_mode *mode)
                                                                                real payload */
        /* case 128: return &quad_desc; */
        default:
+               (void) quad_desc;
                panic("Unsupported mode in get_descriptor()");
        }
 }
@@ -962,10 +965,10 @@ ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode)
                        return get_tarval(buffer, sc_get_buffer_length(), dst_mode);
 
                default:
-                       /* the rest can't be converted */
-                       return tarval_bad;
+                       break;
                }
-               break;
+               /* the rest can't be converted */
+               return tarval_bad;
 
        /* cast int/characters to something */
        case irms_int_number:
@@ -1598,7 +1601,6 @@ int tarval_snprintf(char *buf, size_t len, ir_tarval *tv)
                default:
                        return snprintf(buf, len, "%s%s%s", prefix, fc_print((const fp_value*) tv->value, tv_buf, sizeof(tv_buf), FC_DEC), suffix);
                }
-               break;
 
        case irms_internal_boolean:
                switch (mode_info->mode_output) {
index 3696854..b982d69 100755 (executable)
@@ -329,8 +329,8 @@ ir_node *new_rd_{{node.name}}(
        res->attr.{{node.attrs_name}}{{attr["fqname"]}} = {{ attr["init"] -}};
        {%- endfor %}
        {{- node.init }}
-       res = optimize_node(res);
        irn_verify_irg(res, irg);
+       res = optimize_node(res);
        {{- node.init_after_opt }}
        return res;
 }
@@ -484,6 +484,8 @@ nodeops_h_template = env.from_string(
 
 #include "firm_types.h"
 
+#include "begin.h"
+
 /**
  * @addtogroup ir_node
  * @{
@@ -568,7 +570,7 @@ FIRM_API ir_node *new_{{node.name}}(
 {% endfor %}
 
 {% for node in nodes %}
-/** Return true of the node is a {{node.name}} node. */
+/** Return true if the node is a {{node.name}} node. */
 FIRM_API int is_{{node.name}}(const ir_node *node);
 {%- endfor %}
 
@@ -585,6 +587,8 @@ FIRM_API void set_{{node.name}}_{{attr.name}}(ir_node *node, {{attr.type}} {{att
 
 /** @} */
 
+#include "end.h"
+
 #endif
 
 ''')
index 424c1cd..40ea285 100644 (file)
@@ -756,7 +756,7 @@ class InternalName(Expr):
     yourself but the parser provides a
     :meth:`~jinja2.parser.Parser.free_identifier` method that creates
     a new identifier for you.  This identifier is not available from the
-    template and is not threated specially by the compiler.
+    template and is not treated specially by the compiler.
     """
     fields = ('name',)
 
diff --git a/support/lpp_server/lpp_server.c b/support/lpp_server/lpp_server.c
new file mode 100644 (file)
index 0000000..9c36f2d
--- /dev/null
@@ -0,0 +1,528 @@
+/**
+ * @file   lpp_server.c
+ * @date   19.07.2005
+ * @author Sebastian Hack
+ *
+ * lpp_solving server.
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+
+#ifdef _WIN32
+#error Sorry, lpp_server is for UNIX only.
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <unistd.h>
+#include <pthread.h>
+
+#include <time.h>
+#include <time.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "debug.h"
+#include "list.h"
+#include "irtools.h"
+#include "util.h"
+
+#include "lpp_t.h"
+#include "lpp_comm.h"
+#include "lpp_solvers.h"
+
+#define MAX_JOBS 128
+
+/* stack size of the solver thread. */
+static size_t solver_stack_size = PTHREAD_STACK_MIN;
+
+/* master listening socket. */
+static int msock;
+
+/* master semaphore */
+static int sem;
+
+/* title of the current process */
+static char *title;
+static int title_length;
+
+static int n_children = 0;
+
+extern char** environ;
+
+typedef struct _job_t {
+       struct list_head list;
+       int id;
+       pthread_t solver;
+       pthread_t session;
+       lpp_comm_t *comm;
+       lpp_t *lpp;
+       lpp_solver_func_t *solver_func;
+       time_t received;
+       int csock;
+} job_t;
+
+#define set_solver_stack_size(size) solver_stack_size = MAX(PTHREAD_STACK_MIN, (size))
+
+#define setproctitle(name, args...) snprintf(title,title_length,(name),##args)
+
+static void initproctitle(int argc, char **argv) {
+       int i;
+       char **envp = environ;
+
+       /*
+        * Move the environment so we can reuse the memory.
+        * (Code borrowed from sendmail.)
+        * WARNING: ugly assumptions on memory layout here;
+        *          if this ever causes problems, #undef DO_PS_FIDDLING
+        */
+       for (i = 0; envp[i] != NULL; i++)
+               continue;
+       environ = (char **) malloc(sizeof(char *) * (i + 1));
+       if (environ == NULL)
+               return;
+       for (i = 0; envp[i] != NULL; i++)
+               if ((environ[i] = strdup(envp[i])) == NULL)
+                       return;
+       environ[i] = NULL;
+
+       title = argv[0];
+       if (i > 0)
+               title_length = envp[i-1] + strlen(envp[i-1]) - argv[0];
+       else
+               title_length = argv[argc-1] + strlen(argv[argc-1]) - argv[0];
+
+       argv[1] = NULL;
+       memset(title, 0, title_length);
+       --title_length;
+}
+
+static void job_init(job_t *job, lpp_comm_t *comm, lpp_t *lpp, lpp_solver_func_t *solver_func)
+{
+  /* TODO MAXJOBS */
+  memset(job, 0, sizeof(job[0]));
+  job->lpp         = lpp;
+  job->solver_func = solver_func;
+  job->comm        = comm;
+  job->csock       = lpp_comm_fileno(comm);
+  job->received    = time(NULL);
+  job->session     = pthread_self();
+  job->id          = getpid();
+}
+
+static firm_dbg_module_t *dbg = NULL;
+
+/**
+ * Set up a socket.
+ */
+static int passive_tcp(uint16_t port, int queue_len)
+{
+       int s;
+       int one = 1;
+       struct protoent    *ppe;
+       struct sockaddr_in sin;
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family       = AF_INET;
+       sin.sin_addr.s_addr  = INADDR_ANY;
+       sin.sin_port         = htons(port);
+
+       ppe = getprotobyname("tcp");
+       s = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
+       setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+
+       if(bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+               perror("bind server socket");
+               exit(1);
+       }
+
+       if(listen(s, queue_len) < 0) {
+               perror("listen server socket");
+               exit(1);
+       }
+
+       return s;
+}
+
+static void *solver_thread(void * data)
+{
+       job_t *job = data;
+       DBG((dbg, LEVEL_1, "starting solver thread pid %d tid %d\n", getpid(), pthread_self()));
+       setproctitle("lpp_server [problem solving: %s]", job->lpp->name);
+
+       /* I may be cancelled at every time. */
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+       /* solve */
+       job->solver_func(job->lpp);
+
+       /* notify the session thread that we are finished. */
+       fclose(job->lpp->log);
+
+       return NULL;
+}
+
+static int solve(lpp_comm_t *comm, job_t *job)
+{
+       char buf[1024];
+       struct timeval tv;
+       fd_set rfds;
+       int fds[2];
+       FILE *rd, *log;
+       int res = 0;
+       int retval, fd_rd, fd_comm;
+       pthread_attr_t solver_thr_attr;
+
+       struct sembuf semops;
+       /* try to acquire a lock for the solver resource. */
+       semops.sem_num = 0;
+       semops.sem_op = -1;
+       semops.sem_flg = SEM_UNDO;
+       retval = semop(sem, &semops, 1);
+       if(retval < 0) {
+               perror("free semaphore");
+       }
+       DBG((dbg, LEVEL_1, "job %d: solving problem %s\n", job->id, job->lpp->name));
+
+       /* set the log file of the lpp to the pipe. */
+       pipe(fds);
+       DBG((dbg, LEVEL_4, "pipe read %d write %d\n", fds[0], fds[1]));
+
+       fd_comm = lpp_comm_fileno(comm);
+       fd_rd   = fds[0];
+       rd      = fdopen(fd_rd, "r");
+       log     = fdopen(fds[1], "w");
+
+       lpp_set_log(job->lpp, log);
+
+       /* also set the stack size of the solver thread to a considerable amount */
+       pthread_attr_init(&solver_thr_attr);
+       pthread_attr_setstacksize(&solver_thr_attr, solver_stack_size);
+       pthread_create(&job->solver, &solver_thr_attr, solver_thread, job);
+
+       while(1) {
+               /* set select timeout to 10 seconds */
+               tv.tv_sec  = 10;
+               tv.tv_usec = 0;
+
+               /* set the file descriptors. */
+               FD_ZERO(&rfds);
+               FD_SET(fd_rd, &rfds);
+               FD_SET(fd_comm, &rfds);
+               DBG((dbg, LEVEL_4, "select %d %d\n", fd_rd, fd_comm));
+               retval = select(MAX(fd_rd, fd_comm) + 1, &rfds, NULL, NULL, &tv);
+               DBG((dbg, LEVEL_4, "retval %d\n", retval));
+
+               /* an event on one of the descriptors arrived. */
+               if(retval > 0) {
+                       /* A log message arrived. */
+                       if(FD_ISSET(fd_rd, &rfds)) {
+
+                               /* if there is nothing more to read, the child died; we go home now. */
+                               if(feof(rd))
+                                       break;
+
+                               if(fgets(buf, sizeof(buf), rd)) {
+                                       DBG((dbg, LEVEL_4, "receiving log message %s\n", buf));
+                                       /* send the message over the net. */
+                                       lpp_writel(comm, LPP_CMD_INFO);
+                                       lpp_writes(comm, buf);
+                                       lpp_flush(comm);
+                               }
+                       }
+
+                       /* A network message arrived. */
+                       if(FD_ISSET(fd_comm, &rfds)) {
+                               int cmd;
+
+                               retval = read(fd_comm, &cmd, sizeof(cmd));
+                               if(retval == 0) {
+                                       DBG((dbg, LEVEL_2, "cancelling solver thread tid %d\n", job->solver));
+                                       //pthread_cancel(job->solver);
+                                       exit(1);
+                                       //res = 1;
+                                       //break;
+                               }
+
+                               switch(cmd) {
+                                       /* eat senseless data. */
+                                       default:
+                                               while(read(fd_comm, &cmd, sizeof(cmd)) > 0) {
+                                               }
+                               }
+                               res = 1;
+                       }
+               }
+       }
+
+       pthread_join(job->solver, NULL);
+       semops.sem_num = 0;
+       semops.sem_op = 1;
+       semops.sem_flg = SEM_UNDO;
+       retval = semop(sem, &semops, 1);
+       if(retval < 0) {
+               perror("free semaphore");
+       }
+
+       fclose(rd);
+       return res;
+}
+
+static void *session(int fd)
+{
+       lpp_solver_func_t *solver = lpp_find_solver("dummy");
+       lpp_comm_t *comm          = lpp_comm_new(fd, LPP_BUFSIZE);
+
+       DBG((dbg, LEVEL_1, "starting session thread pid %d tid %d\n", getpid(), pthread_self()));
+       setproctitle("lpp_server [child]");
+
+       /* install the signal handler which gets triggered when the child dies. */
+       DBG((dbg, LEVEL_1, "new thread\n"));
+       for(;;) {
+               char buf[64];
+               int cmd = lpp_readl(comm);
+
+               DBG((dbg, LEVEL_2, "command: %s(%d)\n", lpp_get_cmd_name(cmd), cmd));
+               setproctitle("lpp_server [command %s(%d)]", lpp_get_cmd_name(cmd), cmd);
+               switch(cmd) {
+                       /* we could not read from the socket, so the connection died. bail out. */
+                       case -1:
+                       case LPP_CMD_BAD:
+                               goto end;
+
+                       case LPP_CMD_PROBLEM:
+                               {
+                                       job_t job;
+                                       lpp_t *lpp;
+
+                                       lpp = lpp_deserialize(comm);
+                                       lpp_deserialize_values(comm, lpp, lpp_value_start);
+                                       DBG((dbg, LEVEL_3, "problem %s received\n", lpp->name));
+                                       job_init(&job, comm, lpp, solver);
+
+                                       DBG((dbg, LEVEL_3, "starting job for problem %s\n", lpp->name));
+                                       setproctitle("lpp_server [problem waiting: %s]", lpp->name);
+
+                                       solve(comm, &job);
+                                       lpp_writel(comm, LPP_CMD_SOLUTION);
+                                       lpp_serialize_stats(comm, lpp);
+                                       lpp_serialize_values(comm, lpp, lpp_value_solution);
+                                       lpp_flush(comm);
+                                       DBG((dbg, LEVEL_1, "job %d: finished with problem %s\n", job.id, lpp->name));
+                                       setproctitle("lpp_server [problem finished: %s]", lpp->name);
+
+                                       free_lpp(lpp);
+                               }
+
+                               break;
+
+                       case LPP_CMD_SOLVER:
+                               lpp_readbuf(comm, buf, sizeof(buf));
+                               solver = lpp_find_solver(buf);
+                               DBG((dbg, LEVEL_2, "setting solver to: %s\n", buf));
+                               //lpp_send_res(comm, solver != NULL, "could not find solver: %s", buf);
+                               break;
+
+                       case LPP_CMD_SOLVERS: {
+                               int i;
+
+                               for(i = 0; lpp_solvers[i].solver != NULL; i++) {
+                               }
+                               lpp_writel(comm, i);
+
+                               for(i = 0; lpp_solvers[i].solver != NULL; i++)
+                                       lpp_writes(comm, lpp_solvers[i].name);
+                               lpp_flush(comm);
+                               break;
+                       }
+
+                       case LPP_CMD_SET_DEBUG:
+                               {
+                                       int mask = lpp_readl(comm);
+                                       firm_dbg_set_mask(dbg, mask);
+                               }
+                               break;
+
+                       case LPP_CMD_BYE:
+                               goto end;
+
+                       default:
+                               fprintf(stderr, "illegal command %d. exiting\n", cmd);
+                               goto end;
+               }
+       }
+
+end:
+       /* signal the queue, bail out and we are free now. */
+       lpp_comm_free(comm);
+       close(fd);
+
+       exit(0);
+}
+
+static void child_handler(int sig)
+{
+       pid_t pid;
+       int status;
+
+       (void) sig;
+
+       pid = waitpid(-1, &status, WNOHANG);
+       do {
+               if(WIFEXITED(status)) {
+                       DBG((dbg, LEVEL_1, "child %d died normally with return value %d\n", pid, WEXITSTATUS(status)));
+                       --n_children;
+                       if(n_children != 0)
+                               setproctitle("lpp_server [main (%d %s)]", n_children, (n_children>1)?"children":"child");
+                       else
+                               setproctitle("lpp_server [main]");
+               } else if(WIFSIGNALED(status)) {
+                       DBG((dbg, LEVEL_1, "child %d died by signal %d\n", pid, WTERMSIG(status)));
+                       --n_children;
+                       if(n_children != 0)
+                               setproctitle("lpp_server [main (%d %s)]", n_children, (n_children>1)?"children":"child");
+                       else
+                               setproctitle("lpp_server [main]");
+               } else
+                       DBG((dbg, LEVEL_1, "child %d did something unexpected\n", pid));
+
+               pid = waitpid(-1, &status, WNOHANG);
+       } while(pid > 0);
+}
+
+static void main_loop(void)
+{
+       int csock;
+
+       DBG((dbg, LEVEL_1, "master pid %d\n", getpid()));
+
+       msock = passive_tcp(LPP_PORT, 10);
+
+       for(;;) {
+               struct sockaddr_in fsin;
+               socklen_t len = sizeof(fsin);
+               pid_t child;
+
+               csock = accept(msock, (struct sockaddr *) &fsin, &len);
+               if(csock < 0) {
+                       if(errno == EINTR)
+                               continue;
+                       else
+                               fprintf(stderr, "could not accept: %s\n", strerror(errno));
+               }
+
+               child = fork();
+               switch(child) {
+                       case 0: /* we're in the new child, start the session handler */
+                               close(msock);
+                               session(csock);
+                               break;
+                       case -1: /* error, die! */
+                               perror("fork");
+                               exit(1);
+                       default: /* if we're in the parent just continue */
+                               ++n_children;
+                               setproctitle("lpp_server [main (%d %s)]", n_children, (n_children>1)?"children":"child");
+                               close(csock);
+                               break;
+               }
+       }
+}
+
+static void toggle_dbg(int num)
+{
+       static int mask = 0;
+       (void) num;
+       mask = ~mask;
+       firm_dbg_set_mask(dbg, mask);
+}
+
+#define SEMKEYPATH "/tmp/lppkey"
+#define SEMKEYID 42
+
+static void print_syntax(void) {
+       fprintf(stderr, "lpp_server [-g <dbg level>] [-s <thread stack size>]\n");
+}
+
+int main(int argc, char *argv[])
+{
+       key_t semkey;
+       int ret;
+       int c;
+       struct sigaction sigact1, sigact2;
+
+       dbg = firm_dbg_register("lpp.server");
+       firm_dbg_set_mask(dbg, 1);
+
+       set_solver_stack_size(128 * 1024 * 1024);
+
+       /* parse options. */
+       while((c = getopt(argc, argv, "s:g:")) != -1) {
+               switch(c) {
+                       case 's':
+                               set_solver_stack_size(atoi(optarg));
+                               break;
+                       case 'g':
+                               firm_dbg_set_mask(dbg, atoi(optarg));
+                               break;
+                       default:
+                               print_syntax();
+                               exit(1);
+               }
+       }
+
+       initproctitle(argc, argv);
+       setproctitle("lpp_server [main]");
+
+       memset(&sigact1, 0, sizeof(sigact1));
+       sigact1.sa_handler = toggle_dbg;
+       sigaction(SIGUSR1, &sigact1, NULL);
+
+       memset(&sigact2, 0, sizeof(sigact2));
+       sigact2.sa_handler = child_handler;
+       sigact2.sa_flags = SA_NOCLDSTOP;
+       sigaction(SIGCHLD, &sigact2, NULL);
+
+       /* set up semaphore */
+       semkey = ftok(SEMKEYPATH,SEMKEYID);
+       if ( semkey == (key_t)-1 ) {
+               perror("ftok() for sem failed");
+               return 1;
+       }
+
+       sem = semget( semkey, 1, 0666 | IPC_CREAT);// | IPC_EXCL );
+       if ( sem == -1 ) {
+               perror("semget() failed");
+               return -1;
+       }
+
+       ret = semctl(sem, 0, SETVAL, 1);
+       if ( ret < 0 ) {
+               perror("semctl() failed");
+               return -1;
+       }
+
+       main_loop();
+
+       ret = semctl( sem, 0, IPC_RMID );
+       if (ret < 0) {
+               printf("semctl() remove id failed\n");
+               return -1;
+       }
+       return 0;
+}
diff --git a/support/lpp_server/lpp_server.h b/support/lpp_server/lpp_server.h
new file mode 100644 (file)
index 0000000..8d6eb71
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * @file   lpp_server.h
+ * @date   19.07.2005
+ * @author Sebastian Hack
+ *
+ * Copyright (C) 2005 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+
+#ifndef LPP_SERVER_H
+#define LPP_SERVER_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+enum {
+#define LPP_CMD(x) x,
+#include "lpp_cmd.def"
+#undef LPP_CMD
+  LPP_CMD_LAST
+};
+
+#define BASIC_ERR_CHECK(expr,cond,fmt,last) \
+  if((expr) cond) { \
+    fprintf(stderr, "%s(%d): %s %s: ", __FILE__, __LINE__, #expr, #cond); \
+    print_err fmt; \
+    fprintf(stderr, "\n"); \
+    last; \
+  }
+
+#define BASIC_ERRNO_CHECK(expr,cond,last) \
+  if((expr) cond) { \
+    fprintf(stderr, "%s(%d): %s %s: %s\n", \
+        __FILE__, __LINE__, #expr, #cond, strerror(errno)); \
+    last; \
+  }
+
+#define ERR_CHECK_RETURN(expr, cond, fmt, retval) \
+  BASIC_ERR_CHECK(expr, cond, fmt, return retval)
+
+#define ERRNO_CHECK_RETURN(expr, cond, retval) \
+  BASIC_ERRNO_CHECK(expr, cond, return retval)
+
+#define ERR_CHECK_RETURN_VOID(expr, cond, fmt) \
+  BASIC_ERR_CHECK(expr, cond, fmt, return)
+
+#define ERRNO_CHECK_RETURN_VOID(expr, cond) \
+  BASIC_ERRNO_CHECK(expr, cond, return)
+
+#define ERR_CHECK(expr, cond, fmt) \
+  BASIC_ERR_CHECK(expr, cond, fmt, (void) 0)
+
+#define ERRNO_CHECK(expr, cond) \
+  BASIC_ERRNO_CHECK(expr, cond, (void) 0)
+
+static void print_err(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       vfprintf(stderr, fmt, args);
+       va_end(args);
+}
+
+static  void writel(int fd, uint32_t x)
+{
+       x = htonl(x);
+       ERRNO_CHECK(write(fd, &x, sizeof(x)), == -1);
+}
+
+static  void writed(int fd, double dbl)
+{
+       ERRNO_CHECK(write(fd, &dbl, sizeof(dbl)), == -1);
+}
+
+static  void writes(int fd, const char *str)
+{
+       size_t n = strlen(str);
+       writel(fd, n);
+       ERRNO_CHECK(write(fd, str, n), == -1);
+}
+
+static  uint32_t readl(int fd)
+{
+       uint32_t res;
+
+       ERRNO_CHECK(read(fd, &res, sizeof(res)), == -1);
+       return ntohl(res);
+}
+
+static  double readd(int fd)
+{
+       double res;
+       ERRNO_CHECK(read(fd, &res, sizeof(res)), == -1);
+       return res;
+}
+
+static  char *reads(int fd)
+{
+       size_t len = readl(fd);
+       char *res = malloc(sizeof(char) * (len + 1));
+
+       ERRNO_CHECK(read(fd, res, len), == -1);
+       res[len] = '\0';
+       return res;
+}
+
+static char *readbuf(int fd, size_t buflen, char *buf)
+{
+       char dummy[1024];
+       size_t i;
+       size_t n         = buflen - 1;
+       size_t len       = readl(fd);
+       size_t max_read  = n < len ? n : len;
+       size_t rest      = len - max_read;
+
+       if(buflen > 0 && buf != NULL) {
+               ERRNO_CHECK(read(fd, buf, max_read), == -1);
+               buf[max_read] = '\0';
+       }
+
+       /* eat up data that didnt fit into the string */
+       for(i = 0, n = rest / sizeof(dummy); i < n; ++i)
+               read(fd, dummy, sizeof(dummy));
+
+       if(rest % sizeof(dummy) > 0)
+               read(fd, dummy, rest % sizeof(dummy));
+
+       return buf;
+}
+
+static int ack(int fd, size_t buflen, char *buf)
+{
+       int res = 0;
+       int cmd = readl(fd);
+
+       switch(cmd) {
+               case LPP_CMD_OK:
+                       res = 1;
+                       break;
+               case LPP_CMD_BAD:
+                       readbuf(fd, buflen, buf);
+               default:
+                       res = 0;
+       }
+
+       return res;
+}
+
+static void send_res(int fd, int ok, const char *fmt, ...)
+{
+       if(!ok) {
+               char buf[1024];
+               va_list args;
+
+               va_start(args, fmt);
+               vsnprintf(buf, sizeof(buf), fmt, args);
+               va_end(args);
+
+               writel(fd, LPP_CMD_BAD);
+               writes(fd, buf);
+       }
+
+       else
+               writel(fd, LPP_CMD_OK);
+}
+
+static void send_ack(int fd)
+{
+       send_res(fd, 1, "");
+}
+
+#endif