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]
*/
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.
*/
/** 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. */
# %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",
# "allocates" a free register
ProduceVal => {
- op_flags => "c",
+ op_flags => "c|n",
irn_flags => "R",
reg_req => { out => [ "gp" ] },
emit => "",
#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;
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) {
/* 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,... */
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;
#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)
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);
}
/* 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