Add an cse_neutral opcode property. Nodes with this property are
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Mon, 18 Jan 2010 02:28:05 +0000 (02:28 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Mon, 18 Jan 2010 02:28:05 +0000 (02:28 +0000)
CSE neutral to its users, i.e. op(..., x, ...) ~ op(..., y, ...) if x and y are both neutral.
Setting this property to ia32_ProduceVal nodes allow to CSE nodes that differ in ProduceVals only (which themself NEVER are cse'd).
This "fixes" divmod.

[r26981]

include/libfirm/irnode.h
include/libfirm/irop.h
ir/be/ia32/ia32_spec.pl
ir/be/scripts/generate_new_opcodes.pl
ir/ir/irnode.c
ir/ir/irnode_t.h
ir/ir/irop_t.h
ir/ir/iropt.c

index 7d20903..a480cd3 100644 (file)
@@ -1367,6 +1367,11 @@ int is_irn_machine_operand(const ir_node *node);
  */
 int is_irn_machine_user(const ir_node *node, unsigned n);
 
+/**
+ * Returns non-zero for nodes that are CSE neutral to its users.
+ */
+int is_irn_cse_neutral(const ir_node *node);
+
 /**
  * A type to express conditional jump predictions.
  */
index 65cd166..dc07dcb 100644 (file)
@@ -55,27 +55,28 @@ typedef enum {
 
 /** The irop flags */
 typedef enum {
-       irop_flag_none        = 0x00000000, /**< Nothing. */
-       irop_flag_labeled     = 0x00000001, /**< If set, output edge labels on in-edges in vcg graph. */
-       irop_flag_commutative = 0x00000002, /**< This operation is commutative. */
-       irop_flag_cfopcode    = 0x00000004, /**< This operation is a control flow operation. */
-       irop_flag_ip_cfopcode = 0x00000008, /**< This operation manipulates the interprocedural control flow. */
-       irop_flag_fragile     = 0x00000010, /**< Set if the operation can change the control flow because
-                                                of an exception. */
-       irop_flag_forking     = 0x00000020, /**< Forking control flow at this operation. */
-       irop_flag_highlevel   = 0x00000040, /**< This operation is a pure high-level one and can be
-                                                skipped in low-level optimizations. */
-       irop_flag_constlike   = 0x00000080, /**< This operation has no arguments and is some
-                                                kind of a constant. */
-       irop_flag_always_opt  = 0x00000100, /**< This operation must always be optimized .*/
-       irop_flag_keep        = 0x00000200, /**< This operation can be kept in End's keep-alive list. */
-       irop_flag_start_block = 0x00000400, /**< This operation is always placed in the Start block. */
-       irop_flag_uses_memory = 0x00000800, /**< This operation has a memory input and may change the memory state. */
+       irop_flag_none         = 0x00000000, /**< Nothing. */
+       irop_flag_labeled      = 0x00000001, /**< If set, output edge labels on in-edges in vcg graph. */
+       irop_flag_commutative  = 0x00000002, /**< This operation is commutative. */
+       irop_flag_cfopcode     = 0x00000004, /**< This operation is a control flow operation. */
+       irop_flag_ip_cfopcode  = 0x00000008, /**< This operation manipulates the interprocedural control flow. */
+       irop_flag_fragile      = 0x00000010, /**< Set if the operation can change the control flow because
+                                                 of an exception. */
+       irop_flag_forking      = 0x00000020, /**< Forking control flow at this operation. */
+       irop_flag_highlevel    = 0x00000040, /**< This operation is a pure high-level one and can be
+                                                 skipped in low-level optimizations. */
+       irop_flag_constlike    = 0x00000080, /**< This operation has no arguments and is some
+                                                 kind of a constant. */
+       irop_flag_always_opt   = 0x00000100, /**< This operation must always be optimized .*/
+       irop_flag_keep         = 0x00000200, /**< This operation can be kept in End's keep-alive list. */
+       irop_flag_start_block  = 0x00000400, /**< This operation is always placed in the Start block. */
+       irop_flag_uses_memory  = 0x00000800, /**< This operation has a memory input and may change the memory state. */
        irop_flag_dump_noblock = 0x00001000, /**< node should be dumped outside any blocks */
        irop_flag_dump_noinput = 0x00002000, /**< node is a placeholder for "no input" */
-       irop_flag_machine     = 0x00010000, /**< This operation is a machine operation. */
-       irop_flag_machine_op  = 0x00020000, /**< This operation is a machine operand. */
-       irop_flag_user        = 0x00040000  /**< This flag and all higher ones are free for machine user. */
+       irop_flag_machine      = 0x00010000, /**< This operation is a machine operation. */
+       irop_flag_machine_op   = 0x00020000, /**< This operation is a machine operand. */
+       irop_flag_cse_neutral  = 0x00040000, /**< This operation is CSE neutral to its users. */
+       irop_flag_user         = 0x00080000  /**< This flag and all higher ones are free for machine user. */
 } irop_flags;
 
 /** The opcodes of the libFirm predefined operations. */
index 155f22f..0196a9f 100644 (file)
@@ -15,7 +15,7 @@ $arch = "ia32";
 # %nodes = (
 #
 # <op-name> => {
-#   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
+#   op_flags  => "N|L|C|X|I|F|Y|H|c|K|n",
 #   irn_flags => "R|N"
 #   arity     => "0|1|2|3 ... |variable|dynamic|any",
 #   state     => "floats|pinned|mem_pinned|exc_pinned",
@@ -339,7 +339,7 @@ Asm => {
 
 # "allocates" a free register
 ProduceVal => {
-       op_flags  => "c",
+       op_flags  => "c|n",
        irn_flags => "R",
        reg_req   => { out => [ "gp" ] },
        emit      => "",
index 7c1e4c9..683aed8 100755 (executable)
@@ -1048,6 +1048,7 @@ void $arch\_create_opcodes(const arch_irn_ops_t *be_ops) {
 #define O   irop_flag_machine_op
 #define NB  irop_flag_dump_noblock
 #define NI  irop_flag_dump_noinput
+#define n   irop_flag_cse_neutral
 #define R   (irop_flag_user << 0)
 
        ir_op_ops  ops;
index 6d0ffee..2ec8ff3 100644 (file)
@@ -2782,6 +2782,10 @@ int (is_irn_machine_user)(const ir_node *node, unsigned n) {
        return _is_irn_machine_user(node, n);
 }
 
+/* Returns non-zero for nodes that are CSE neutral to its users. */
+int (is_irn_cse_neutral)(const ir_node *node) {
+       return _is_irn_cse_neutral(node);
+}
 
 /* Gets the string representation of the jump prediction .*/
 const char *get_cond_jmp_predicate_name(cond_jmp_predicate pred) {
@@ -2922,7 +2926,11 @@ unsigned firm_default_hash(const ir_node *node) {
 
        /* consider all in nodes... except the block if not a control flow. */
        for (i = is_cfop(node) ? -1 : 0;  i < irn_arity;  ++i) {
-               h = 9*h + HASH_PTR(get_irn_intra_n(node, i));
+               ir_node *pred = get_irn_intra_n(node, i);
+               if (is_irn_cse_neutral(pred))
+                       h *= 9;
+               else
+                       h = 9*h + HASH_PTR(pred);
        }
 
        /* ...mode,... */
index 58e5ec5..3d6cfbf 100644 (file)
@@ -600,6 +600,10 @@ static inline int _is_irn_machine_user(const ir_node *node, unsigned n) {
        return is_op_machine_user(_get_irn_op(node), n);
 }
 
+static inline int _is_irn_cse_neutral(const ir_node *node) {
+       return is_op_cse_neutral(_get_irn_op(node));
+}
+
 static inline cond_jmp_predicate _get_Cond_jmp_pred(const ir_node *node) {
        assert(_get_irn_op(node) == op_Cond);
        return node->attr.cond.jmp_pred;
@@ -757,6 +761,7 @@ _is_arg_Proj(const ir_node *node) {
 #define is_irn_machine_op(node)               _is_irn_machine_op(node)
 #define is_irn_machine_operand(node)          _is_irn_machine_operand(node)
 #define is_irn_machine_user(node, n)          _is_irn_machine_user(node, n)
+#define is_irn_cse_neutral(node)              _is_irn_cse_neutral(node)
 #define get_Cond_jmp_pred(node)               _get_Cond_jmp_pred(node)
 #define set_Cond_jmp_pred(node, pred)         _set_Cond_jmp_pred(node, pred)
 #define get_irn_generic_attr(node)            _get_irn_generic_attr(node)
index cdb68fb..c0c3285 100644 (file)
@@ -128,6 +128,11 @@ static inline int is_op_machine_operand(const ir_op *op) {
        return op->flags & irop_flag_machine_op;
 }
 
+/** Returns non-zero if operation is CSE neutral */
+static inline int is_op_cse_neutral(const ir_op *op) {
+       return op->flags & irop_flag_cse_neutral;
+}
+
 /** Returns non-zero if operation is a machine user op number n */
 static inline int is_op_machine_user(const ir_op *op, unsigned n) {
   return op->flags & (irop_flag_user << n);
index 03c707b..9eba1a3 100644 (file)
@@ -6245,9 +6245,15 @@ int identities_cmp(const void *elt, const void *key) {
        }
 
        /* compare a->in[0..ins] with b->in[0..ins] */
-       for (i = 0; i < irn_arity_a; i++)
-               if (get_irn_intra_n(a, i) != get_irn_intra_n(b, i))
-                       return 1;
+       for (i = 0; i < irn_arity_a; ++i) {
+               ir_node *pred_a = get_irn_intra_n(a, i);
+               ir_node *pred_b = get_irn_intra_n(b, i);
+               if (pred_a != pred_b) {
+                       /* if both predecessors are CSE neutral they might be different */
+                       if (!is_irn_cse_neutral(pred_a) || !is_irn_cse_neutral(pred_b))
+                               return 1;
+               }
+       }
 
        /*
         * here, we already now that the nodes are identical except their