BugFix: ensure that two ASM nodes are never congruent in combo.
[libfirm] / ir / opt / combo.c
index 47c216a..3b71669 100644 (file)
@@ -114,7 +114,7 @@ struct opcode_key_t {
                ir_entity *ent;   /**< For Sel Nodes, its entity */
                int       intVal; /**< For Conv/Div Nodes: strict/remainderless */
                unsigned  uintVal;/**< for Builtin: the kind */
-               ir_node   *block; /**< for Block: itself */
+               ir_node   *irn;   /**< for nodes that never be construent: the node itself */
                void      *ptr;   /**< generic pointer for hash/cmp */
        } u;
 };
@@ -260,6 +260,23 @@ static void check_partition(const partition_t *T)
        }
 }  /* check_partition */
 
+/**
+ * return the result mode of a node (part of combo's opcode).
+ */
+static ir_mode *get_irn_resmode(const ir_node *irn)
+{
+       switch (get_irn_opcode(irn)) {
+       case iro_Load:
+               return get_Load_mode(irn);
+       case iro_Div:
+               return get_Div_resmode(irn);
+       case iro_Mod:
+               return get_Mod_resmode(irn);
+       default:
+               return get_irn_mode(irn);
+       }
+}  /* get_irn_resmode */
+
 /**
  * check that all leader nodes in the partition have the same opcode.
  */
@@ -274,7 +291,7 @@ static void check_opcode(const partition_t *Z)
 
                if (first) {
                        key.code   = get_irn_opcode(irn);
-                       key.mode   = get_irn_mode(irn);
+                       key.mode   = get_irn_resmode(irn);
                        key.arity  = get_irn_arity(irn);
                        key.u.proj = 0;
                        key.u.ent  = NULL;
@@ -293,10 +310,8 @@ static void check_opcode(const partition_t *Z)
                                key.u.intVal = get_Div_no_remainder(irn);
                                break;
                        case iro_Block:
-                               key.u.block = irn;
-                               break;
-                       case iro_Load:
-                               key.mode = get_Load_mode(irn);
+                       case iro_ASM:
+                               key.u.irn = irn;
                                break;
                        case iro_Builtin:
                                key.u.intVal = get_Builtin_kind(irn);
@@ -306,8 +321,8 @@ static void check_opcode(const partition_t *Z)
                        }
                        first = 0;
                } else {
-                       assert((unsigned)key.code  == get_irn_opcode(irn));
-                       assert(key.mode  == get_irn_mode(irn));
+                       assert((unsigned)key.code == get_irn_opcode(irn));
+                       assert(key.mode  == get_irn_resmode(irn));
                        assert(key.arity == get_irn_arity(irn));
 
                        switch (get_irn_opcode(irn)) {
@@ -324,13 +339,11 @@ static void check_opcode(const partition_t *Z)
                                assert(key.u.intVal == get_Div_no_remainder(irn));
                                break;
                        case iro_Block:
-                               assert(key.u.block == irn);
-                               break;
-                       case iro_Load:
-                               assert(key.mode == get_Load_mode(irn));
+                       case iro_ASM:
+                               assert(key.u.irn == irn);
                                break;
                        case iro_Builtin:
-                               assert(key.u.intVal == (int) get_Builtin_kind(irn));
+                               assert(key.u.intVal == (int)get_Builtin_kind(irn));
                                break;
                        default:
                                break;
@@ -1727,7 +1740,7 @@ static void *lambda_opcode(const node_t *node, environment_t *env)
        ir_node      *irn = node->node;
 
        key.code   = get_irn_opcode(irn);
-       key.mode   = get_irn_mode(irn);
+       key.mode   = get_irn_resmode(irn);
        key.arity  = get_irn_arity(irn);
        key.u.proj = 0;
        key.u.ent  = NULL;
@@ -1752,10 +1765,17 @@ static void *lambda_opcode(const node_t *node, environment_t *env)
                 * We fix it by never letting blocks be congruent
                 * which cannot be detected by combo either.
                 */
-               key.u.block = irn;
+               key.u.irn = irn;
                break;
-       case iro_Load:
-               key.mode = get_Load_mode(irn);
+       case iro_ASM:
+               /*
+                * If is difficult to detect when two ASM nodes are congruent: even
+                * if the assembler "text" is identical, the instruction might
+                * have a side effect like flag toggle or function call.
+                * So, do not even try it.
+                *
+                */
+               key.u.irn = irn;
                break;
        case iro_Builtin:
                key.u.intVal = get_Builtin_kind(irn);