Commit 5ae1785f authored by Michael Beck's avatar Michael Beck
Browse files

Add an DivRL for remainderless div nodes (we don't have to generate correction

code than ...

[r17833]
parent 5cfae452
......@@ -1515,6 +1515,20 @@ ir_node *new_rd_DivMod (dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *new_rd_Div (dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a remainderless Div node.
*
* @param *db A pointer for debug information.
* @param *irg The IR graph the node belongs to.
* @param *block The IR block the node belongs to.
* @param *memop The store needed to model exceptions
* @param *op1 The first operand.
* @param *op2 The second operand.
* @param *mode The mode of the result.
* @param state The pinned state.
*/
ir_node *new_rd_DivRL (dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a Mod node.
*
* @param *db A pointer for debug information.
......@@ -2349,6 +2363,19 @@ ir_node *new_r_DivMod (ir_graph *irg, ir_node *block,
ir_node *new_r_Div (ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a remainderless Div node.
*
* @param *irg The IR graph the node belongs to.
* @param *block The IR block the node belongs to.
* @param *memop The store needed to model exceptions
* @param *op1 The first operand.
* @param *op2 The second operand.
* @param *mode The mode of the result.
* @param state The pinned state.
*/
ir_node *new_r_DivRL (ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a Mod node.
*
* @param *irg The IR graph the node belongs to.
......@@ -3167,6 +3194,19 @@ ir_node *new_d_DivMod (dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2,
*/
ir_node *new_d_Div (dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a remainderless Div node.
*
* Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *memop The store needed to model exceptions
* @param *op1 The first operand.
* @param *op2 The second operand.
* @param *mode The mode of the result.
* @param state The pinned state.
*/
ir_node *new_d_DivRL (dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a Mod node.
*
* Adds the node to the block in current_ir_block.
......@@ -3989,6 +4029,18 @@ ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode,
*/
ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a remainderless Div node.
*
* Adds the node to the block in current_ir_block.
*
* @param *memop The store needed to model exceptions
* @param *op1 The first operand.
* @param *op2 The second operand.
* @param *mode The mode of the result.
* @param state The pinned state.
*/
ir_node *new_DivRL (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
/** Constructor for a Mod node.
*
* Adds the node to the block in current_ir_block.
......
......@@ -763,6 +763,7 @@ ir_node *get_Div_mem(const ir_node *node);
void set_Div_mem(ir_node *node, ir_node *mem);
ir_mode *get_Div_resmode(const ir_node *node);
void set_Div_resmode(ir_node *node, ir_mode *mode);
int is_Div_remainderless(const ir_node *node);
/**
* Projection numbers for Div: use for Proj nodes!
......
......@@ -930,16 +930,20 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn) {
ir_node *k_node;
ir_node *curr = left;
if (k != 1) {
k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
curr = new_rd_Shrs(dbg, current_ir_graph, block, left, k_node, mode);
if (! is_Div_remainderless(irn)) {
if (k != 1) {
k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
curr = new_rd_Shrs(dbg, current_ir_graph, block, left, k_node, mode);
}
k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, bits - k);
curr = new_rd_Shr(dbg, current_ir_graph, block, curr, k_node, mode);
curr = new_rd_Add(dbg, current_ir_graph, block, left, curr, mode);
} else {
k_node = left;
}
k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, bits - k);
curr = new_rd_Shr(dbg, current_ir_graph, block, curr, k_node, mode);
curr = new_rd_Add(dbg, current_ir_graph, block, left, curr, mode);
k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
res = new_rd_Shrs(dbg, current_ir_graph, block, curr, k_node, mode);
......
......@@ -115,6 +115,7 @@ new_bd_##instr(dbg_info *db, ir_node *block, \
res = new_ir_node(db, irg, block, op_##instr, mode_T, 3, in); \
res->attr.divmod.exc.pin_state = state; \
res->attr.divmod.res_mode = mode; \
res->attr.divmod.no_remainder = 0; \
res = optimize_node(res); \
IRN_VRFY_IRG(res, irg); \
return res; \
......@@ -399,6 +400,25 @@ NEW_BD_UNOP(Abs)
NEW_BD_BINOP(Carry)
NEW_BD_BINOP(Borrow)
/** Creates a remainderless Div node. */
static ir_node *new_bd_DivRL(dbg_info *db, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
{
ir_node *in[3];
ir_node *res;
ir_graph *irg = current_ir_graph;
in[0] = memop;
in[1] = op1;
in[2] = op2;
res = new_ir_node(db, irg, block, op_Div, mode_T, 3, in);
res->attr.divmod.exc.pin_state = state;
res->attr.divmod.res_mode = mode;
res->attr.divmod.no_remainder = 1;
res = optimize_node(res);
IRN_VRFY_IRG(res, irg);
return res;
}
static ir_node *
new_bd_Cmp(dbg_info *db, ir_node *block, ir_node *op1, ir_node *op2) {
ir_node *in[2];
......@@ -1035,6 +1055,18 @@ NEW_RD_UNOP(Abs)
NEW_RD_BINOP(Carry)
NEW_RD_BINOP(Borrow)
/* creates a rd constructor for an divRL */
ir_node *new_rd_DivRL(dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
{
ir_node *res;
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
res = new_bd_DivRL(db, block, memop, op1, op2, mode, state);
current_ir_graph = rem;
return res;
}
ir_node *
new_rd_Cmp(dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *op1, ir_node *op2) {
......@@ -1535,6 +1567,10 @@ ir_node *new_r_Div(ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
return new_rd_Div(NULL, irg, block, memop, op1, op2, mode, state);
}
ir_node *new_r_DivRL(ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
return new_rd_DivRL(NULL, irg, block, memop, op1, op2, mode, state);
}
ir_node *new_r_Mod(ir_graph *irg, ir_node *block,
ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
return new_rd_Mod(NULL, irg, block, memop, op1, op2, mode, state);
......@@ -2391,7 +2427,18 @@ new_d_Div(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mod
#endif
return res;
}
} /* new_d_Div */
ir_node *
new_d_DivRL(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
ir_node *res;
res = new_bd_DivRL(db, current_ir_graph->current_block, memop, op1, op2, mode, state);
#if PRECISE_EXC_CONTEXT
allocate_frag_arr(res, op_Div, &res->attr.except.frag_arr); /* Could be optimized away. */
#endif
return res;
} /* new_d_DivRL */
ir_node *
new_d_Mod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
......@@ -2931,6 +2978,9 @@ ir_node *new_DivMod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, o
ir_node *new_Div(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
return new_d_Div(NULL, memop, op1, op2, mode, state);
}
ir_node *new_DivRL(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
return new_d_DivRL(NULL, memop, op1, op2, mode, state);
}
ir_node *new_Mod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
return new_d_Mod(NULL, memop, op1, op2, mode, state);
}
......
......@@ -827,7 +827,10 @@ int dump_node_opcode(FILE *F, ir_node *n)
fprintf(F, "%s", get_irn_opname(n));
break;
case iro_Div:
fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Div_resmode(n), &bad));
fprintf(F, "%s", get_irn_opname(n));
if (is_Div_remainderless(n))
fprintf(F, "RL");
fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), &bad));
break;
case iro_Mod:
fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
......
......@@ -571,10 +571,16 @@ store_attr *get_irn_store_attr(ir_node *node) {
except_attr *get_irn_except_attr(ir_node *node) {
assert(node->op == op_Div || node->op == op_Quot ||
node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc);
node->op == op_DivMod || node->op == op_Mod || node->op == op_Call || node->op == op_Alloc || node->op == op_Bound);
return &node->attr.except;
}
divmod_attr *get_irn_divmod_attr(ir_node *node) {
assert(node->op == op_Div || node->op == op_Quot ||
node->op == op_DivMod || node->op == op_Mod);
return &node->attr.divmod;
}
void *(get_irn_generic_attr)(ir_node *node) {
assert(is_ir_node(node));
return _get_irn_generic_attr(node);
......@@ -1456,6 +1462,11 @@ BINOP(Cmp)
UNOP(Conv)
UNOP(Cast)
int is_Div_remainderless(const ir_node *node) {
assert(node->op == op_Div);
return node->attr.divmod.no_remainder;
}
int get_Conv_strict(const ir_node *node) {
assert(node->op == op_Conv);
return node->attr.conv.strict;
......
......@@ -58,6 +58,7 @@ block_attr *get_irn_block_attr (ir_node *node);
load_attr *get_irn_load_attr (ir_node *node);
store_attr *get_irn_store_attr (ir_node *node);
except_attr *get_irn_except_attr (ir_node *node);
divmod_attr *get_irn_divmod_attr (ir_node *node);
/** @} */
/**
......
......@@ -4997,7 +4997,7 @@ static int node_cmp_attr_SymConst(ir_node *a, ir_node *b) {
/** Compares the attributes of two Call nodes. */
static int node_cmp_attr_Call(ir_node *a, ir_node *b) {
return (get_irn_call_attr(a) != get_irn_call_attr(b));
return get_irn_call_attr(a) != get_irn_call_attr(b);
} /* node_cmp_attr_Call */
/** Compares the attributes of two Sel nodes. */
......@@ -5057,6 +5057,49 @@ static int node_cmp_attr_Store(ir_node *a, ir_node *b) {
get_Store_volatility(b) == volatility_is_volatile);
} /* node_cmp_attr_Store */
/** Compares two exception attributes */
static int node_cmp_exception(ir_node *a, ir_node *b) {
const except_attr *ea = get_irn_except_attr(a);
const except_attr *eb = get_irn_except_attr(b);
return ea->pin_state != eb->pin_state;
}
#define node_cmp_attr_Bound node_cmp_exception
/** Compares the attributes of two Div nodes. */
static int node_cmp_attr_Div(ir_node *a, ir_node *b) {
const divmod_attr *ma = get_irn_divmod_attr(a);
const divmod_attr *mb = get_irn_divmod_attr(b);
return ma->exc.pin_state != mb->exc.pin_state ||
ma->res_mode != mb->res_mode ||
ma->no_remainder != mb->no_remainder;
} /* node_cmp_attr_Div */
/** Compares the attributes of two DivMod nodes. */
static int node_cmp_attr_DivMod(ir_node *a, ir_node *b) {
const divmod_attr *ma = get_irn_divmod_attr(a);
const divmod_attr *mb = get_irn_divmod_attr(b);
return ma->exc.pin_state != mb->exc.pin_state ||
ma->res_mode != mb->res_mode;
} /* node_cmp_attr_DivMod */
/** Compares the attributes of two Mod nodes. */
static int node_cmp_attr_Mod(ir_node *a, ir_node *b) {
const divmod_attr *ma = get_irn_divmod_attr(a);
const divmod_attr *mb = get_irn_divmod_attr(b);
return ma->exc.pin_state != mb->exc.pin_state ||
ma->res_mode != mb->res_mode;
} /* node_cmp_attr_Mod */
/** Compares the attributes of two Quot nodes. */
static int node_cmp_attr_Quot(ir_node *a, ir_node *b) {
const divmod_attr *ma = get_irn_divmod_attr(a);
const divmod_attr *mb = get_irn_divmod_attr(b);
return ma->exc.pin_state != mb->exc.pin_state ||
ma->res_mode != mb->res_mode;
} /* node_cmp_attr_Quot */
/** Compares the attributes of two Confirm nodes. */
static int node_cmp_attr_Confirm(ir_node *a, ir_node *b) {
return (get_Confirm_cmp(a) != get_Confirm_cmp(b));
......@@ -5140,6 +5183,12 @@ static ir_op_ops *firm_set_default_node_cmp_attr(ir_opcode code, ir_op_ops *ops)
CASE(Store);
CASE(Confirm);
CASE(ASM);
CASE(Div);
CASE(DivMod);
CASE(Mod);
CASE(Quot);
CASE(Bound);
/* FIXME CopyB */
default:
/* leave NULL */;
}
......
......@@ -280,6 +280,7 @@ typedef struct {
typedef struct {
except_attr exc; /**< The exception attribute. MUST be the first one. */
ir_mode *res_mode; /**< Result mode for the division. */
char no_remainder; /**< Set, if known that a division can be done without a remainder. */
} divmod_attr;
/** Inline Assembler support attribute. */
......
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