BugFix for a rare case:
[libfirm] / ir / opt / combo.c
index 67fcd41..9d4584e 100644 (file)
@@ -34,9 +34,7 @@
  * in some cases from Firm terminology.  Especially, Click's type is a
  * Firm tarval/entity, nevertheless we call it type here for "maximum compatibility".
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <assert.h>
 
@@ -323,7 +321,7 @@ static void check_list(const node_t *list, const partition_t *Z) {
 #endif /* CHECK_PARTITIONS */
 
 #ifdef DEBUG_libfirm
-static INLINE lattice_elem_t get_partition_type(const partition_t *X);
+static inline lattice_elem_t get_partition_type(const partition_t *X);
 
 /**
  * Dump partition to output.
@@ -550,7 +548,7 @@ static void sort_irn_outs(node_t *node) {
  *
  * @return the associated type of this node
  */
-static INLINE lattice_elem_t get_node_type(const ir_node *irn) {
+static inline lattice_elem_t get_node_type(const ir_node *irn) {
        return get_irn_node(irn)->type;
 }  /* get_node_type */
 
@@ -561,7 +559,7 @@ static INLINE lattice_elem_t get_node_type(const ir_node *irn) {
  *
  * @return the associated type of this node
  */
-static INLINE tarval *get_node_tarval(const ir_node *irn) {
+static inline tarval *get_node_tarval(const ir_node *irn) {
        lattice_elem_t type = get_node_type(irn);
 
        if (is_tarval(type.tv))
@@ -572,7 +570,7 @@ static INLINE tarval *get_node_tarval(const ir_node *irn) {
 /**
  * Add a partition to the worklist.
  */
-static INLINE void add_to_worklist(partition_t *X, environment_t *env) {
+static inline void add_to_worklist(partition_t *X, environment_t *env) {
        assert(X->on_worklist == 0);
        DB((dbg, LEVEL_2, "Adding part%d to worklist\n", X->nr));
        X->wl_next     = env->worklist;
@@ -587,7 +585,7 @@ static INLINE void add_to_worklist(partition_t *X, environment_t *env) {
  *
  * @return a newly allocated partition
  */
-static INLINE partition_t *new_partition(environment_t *env) {
+static inline partition_t *new_partition(environment_t *env) {
        partition_t *part = obstack_alloc(&env->obst, sizeof(*part));
 
        INIT_LIST_HEAD(&part->Leader);
@@ -617,7 +615,7 @@ static INLINE partition_t *new_partition(environment_t *env) {
 /**
  * Get the first node from a partition.
  */
-static INLINE node_t *get_first_node(const partition_t *X) {
+static inline node_t *get_first_node(const partition_t *X) {
        return list_entry(X->Leader.next, node_t, node_list);
 }  /* get_first_node */
 
@@ -629,7 +627,7 @@ static INLINE node_t *get_first_node(const partition_t *X) {
  *
  * @return the type of the first element of the partition
  */
-static INLINE lattice_elem_t get_partition_type(const partition_t *X) {
+static inline lattice_elem_t get_partition_type(const partition_t *X) {
        const node_t *first = get_first_node(X);
        return first->type;
 }  /* get_partition_type */
@@ -713,7 +711,7 @@ static void create_initial_partitions(ir_node *irn, void *ctx) {
  * @param y    a node
  * @param env  the environment
  */
-static INLINE void add_to_touched(node_t *y, environment_t *env) {
+static inline void add_to_touched(node_t *y, environment_t *env) {
        if (y->on_touched == 0) {
                partition_t *part = y->part;
 
@@ -1083,9 +1081,9 @@ static partition_t *split(partition_t **pX, node_t *gg, environment_t *env) {
        partition_t *X = *pX;
        partition_t *X_prime;
        list_head   tmp;
-       step_env    env1, env2, *winner;
+       step_env    senv[2];
        node_t      *g, *h, *node, *t;
-       int         max_input, transitions;
+       int         max_input, transitions, winner, shf;
        unsigned    n;
        DEBUG_ONLY(static int run = 0;)
 
@@ -1122,44 +1120,46 @@ static partition_t *split(partition_t **pX, node_t *gg, environment_t *env) {
        /* restore X.Leader */
        list_splice(&tmp, &X->Leader);
 
-       env1.initial       = g;
-       env1.unwalked      = NULL;
-       env1.walked        = NULL;
-       env1.index         = 0;
-       env1.side          = 1;
+       senv[0].initial   = g;
+       senv[0].unwalked  = NULL;
+       senv[0].walked    = NULL;
+       senv[0].index     = 0;
+       senv[0].side      = 1;
 
-       env2.initial       = h;
-       env2.unwalked      = NULL;
-       env2.walked        = NULL;
-       env2.index         = 0;
-       env2.side          = 2;
+       senv[1].initial   = h;
+       senv[1].unwalked  = NULL;
+       senv[1].walked    = NULL;
+       senv[1].index     = 0;
+       senv[1].side      = 2;
 
        for (;;) {
-               if (step(&env1)) {
-                       winner = &env1;
+               if (step(&senv[0])) {
+                       winner = 0;
                        break;
                }
-               if (step(&env2)) {
-                       winner = &env2;
+               if (step(&senv[1])) {
+                       winner = 1;
                        break;
                }
        }
-       assert(winner->initial == NULL);
-       assert(winner->unwalked == NULL);
+       assert(senv[winner].initial == NULL);
+       assert(senv[winner].unwalked == NULL);
 
        /* clear flags from walked/unwalked */
-       transitions  = clear_flags(env1.unwalked);
-       transitions |= clear_flags(env1.walked);
-       transitions |= clear_flags(env2.unwalked);
-       transitions |= clear_flags(env2.walked);
+       shf = winner;
+       transitions  = clear_flags(senv[0].unwalked) << shf;
+       transitions |= clear_flags(senv[0].walked)   << shf;
+       shf ^= 1;
+       transitions |= clear_flags(senv[1].unwalked) << shf;
+       transitions |= clear_flags(senv[1].walked)   << shf;
 
-       dump_race_list("winner ", winner->walked);
+       dump_race_list("winner ", senv[winner].walked);
 
        /* Move walked_{winner} to a new partition, X'. */
        X_prime   = new_partition(env);
        max_input = 0;
        n         = 0;
-       for (node = winner->walked; node != NULL; node = node->race_next) {
+       for (node = senv[winner].walked; node != NULL; node = node->race_next) {
                list_del(&node->node_list);
                node->part = X_prime;
                if (node->is_follower) {
@@ -1185,7 +1185,7 @@ static partition_t *split(partition_t **pX, node_t *gg, environment_t *env) {
        list_for_each_entry_safe(node_t, node, t, &X_prime->Follower, node_list) {
                if (identity(node) == node) {
                        follower_to_leader(node);
-                       transitions = 1;
+                       transitions |= 1;
                }
        }
 
@@ -1199,20 +1199,28 @@ static partition_t *split(partition_t **pX, node_t *gg, environment_t *env) {
         * If there where follower to leader transitions, ensure that the nodes
         * can be split out if necessary.
         */
-       if (transitions) {
-               /* place partitions on the cprop list */
+       if (transitions & 1) {
+               /* place winner partition on the cprop list */
                if (X_prime->on_cprop == 0) {
                        X_prime->cprop_next = env->cprop;
                        env->cprop          = X_prime;
                        X_prime->on_cprop   = 1;
                }
        }
+       if (transitions & 2) {
+               /* place other partition on the cprop list */
+               if (X->on_cprop == 0) {
+                       X->cprop_next = env->cprop;
+                       env->cprop    = X;
+                       X->on_cprop   = 1;
+               }
+       }
 
        dump_partition("Now ", X);
        dump_partition("Created new ", X_prime);
 
        /* we have to ensure that the partition containing g is returned */
-       if (winner == &env2) {
+       if (winner != 0) {
                *pX = X_prime;
                return X;
        }