Commit 26bffd78 authored by Michael Beck's avatar Michael Beck
Browse files

Add an cse_neutral opcode property. Nodes with this property are

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]
parent 73ed3cd4
......@@ -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.
*/
......
......@@ -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. */
......
......@@ -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 => "",
......
......@@ -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;
......
......@@ -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,... */
......
......@@ -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)
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment