Commit b772ac48 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

be: Factorise code to skip down converions while transforming.

parent be10d142
......@@ -317,30 +317,6 @@ static inline bool mode_needs_gp_reg(ir_mode *mode)
&& mode != amd64_mode_xmm; /* mode_xmm is 128bit int at the moment */
}
static bool is_downconv(const ir_node *node)
{
if (!is_Conv(node))
return false;
ir_mode *dest_mode = get_irn_mode(node);
if (!mode_needs_gp_reg(dest_mode))
return false;
ir_mode *src_mode = get_irn_mode(get_Conv_op(node));
if (!mode_needs_gp_reg(src_mode))
return false;
return get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}
static ir_node *skip_downconv(ir_node *node)
{
while (is_downconv(node)) {
if (get_irn_n_edges(node) > 1)
break;
node = get_Conv_op(node);
}
return node;
}
static bool is_sameconv(const ir_node *node)
{
if (!is_Conv(node))
......@@ -763,8 +739,8 @@ static void match_binop(amd64_args_t *args, ir_node *block,
/* TODO: legalize phase */
if (mode_neutral) {
op1 = skip_downconv(op1);
op2 = skip_downconv(op2);
op1 = be_skip_downconv(op1, true);
op2 = be_skip_downconv(op2, true);
} else {
/* TODO: extend inputs? */
(void)needs_extension;
......@@ -852,8 +828,8 @@ static ir_node *gen_binop_rax(ir_node *node, ir_node *op1, ir_node *op2,
/* TODO: legalize phase */
if (mode_neutral) {
op1 = skip_downconv(op1);
op2 = skip_downconv(op2);
op1 = be_skip_downconv(op1, true);
op2 = be_skip_downconv(op2, true);
} else {
/* TODO: extend inputs? */
(void)needs_extension;
......@@ -977,7 +953,7 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
ir_node *in[3];
int arity = 0;
if (flags & match_mode_neutral) {
op1 = skip_downconv(op1);
op1 = be_skip_downconv(op1, true);
in[arity++] = be_transform_node(op1);
mode = get_mode_size_bits(mode) > 32 ? mode_gp : mode_Iu;
} else {
......
......@@ -344,30 +344,6 @@ static bool try_encode_as_immediate(const ir_node *node, arm_immediate_t *res)
return false;
}
static bool is_downconv(const ir_node *node)
{
if (!is_Conv(node))
return false;
/* we only want to skip the conv when we're the only user
* (not optimal but for now...) */
if (get_irn_n_edges(node) > 1)
return false;
ir_mode *src_mode = get_irn_mode(get_Conv_op(node));
ir_mode *dest_mode = get_irn_mode(node);
return get_mode_arithmetic(src_mode) == irma_twos_complement
&& get_mode_arithmetic(dest_mode) == irma_twos_complement
&& get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}
static ir_node *arm_skip_downconv(ir_node *node)
{
while (is_downconv(node))
node = get_Conv_op(node);
return node;
}
static bool is_sameconv(const ir_node *node)
{
if (!is_Conv(node))
......@@ -418,8 +394,8 @@ static ir_node *gen_int_binop_ops(ir_node *node, ir_node *op1, ir_node *op2,
dbg_info *dbgi = get_irn_dbg_info(node);
if (flags & MATCH_SIZE_NEUTRAL) {
op1 = arm_skip_downconv(op1);
op2 = arm_skip_downconv(op2);
op1 = be_skip_downconv(op1, true);
op2 = be_skip_downconv(op2, true);
} else {
assert(get_mode_size_bits(get_irn_mode(node)) == 32);
op1 = arm_skip_sameconv(op1);
......@@ -1016,8 +992,8 @@ static ir_node *make_shift(ir_node *node, match_flags_t flags,
panic("modulo shift!=256 not supported");
if (flags & MATCH_SIZE_NEUTRAL) {
op1 = arm_skip_downconv(op1);
op2 = arm_skip_downconv(op2);
op1 = be_skip_downconv(op1, true);
op2 = be_skip_downconv(op2, true);
}
ir_node *new_op1 = be_transform_node(op1);
......
......@@ -823,3 +823,30 @@ uint32_t be_get_tv_bits32(ir_tarval *const tv, unsigned const offset)
val |= (uint32_t)get_tarval_sub_bits(tv, offset + 3) << 24;
return val;
}
static bool mode_needs_gp_reg(ir_mode *const mode)
{
return get_mode_arithmetic(mode) == irma_twos_complement;
}
ir_node *be_skip_downconv(ir_node *node, bool const single_user)
{
assert(mode_needs_gp_reg(get_irn_mode(node)));
for (;;) {
if (single_user && get_irn_n_edges(node) > 1) {
/* we only want to skip the conv when we're the only user
* (because this test is used in the context of address-mode selection
* and we don't want to use address mode for multiple users) */
break;
} else if (is_Conv(node)) {
ir_node *const op = get_Conv_op(node);
ir_mode *const src_mode = get_irn_mode(op);
if (!mode_needs_gp_reg(src_mode) || get_mode_size_bits(get_irn_mode(node)) > get_mode_size_bits(src_mode))
break;
node = op;
} else {
break;
}
}
return node;
}
......@@ -145,4 +145,13 @@ void be_add_parameter_entity_stores(ir_graph *irg);
uint32_t be_get_tv_bits32(ir_tarval *tv, unsigned offset);
/**
* Skip integer truncations.
*
* @param node the node
* @param single_user only skip, if a down-conv has a single user
* @return the node after skipping down-convs
*/
ir_node *be_skip_downconv(ir_node *node, bool single_user);
#endif
......@@ -855,32 +855,6 @@ static void set_am_attributes(ir_node *node, const ia32_address_mode_t *am)
set_ia32_commutative(node);
}
/**
* Skip integer truncations.
*
* @param node the node
* @param single_user only skip, if a down-conv has a single user
* @return the node after skipping down-convs
*/
static ir_node *skip_downconv(ir_node *node, bool const single_user)
{
for (;;) {
if (single_user && get_irn_n_edges(node) > 1) {
break;
} else if (is_Conv(node)) {
ir_node *const op = get_Conv_op(node);
ir_mode *const src_mode = get_irn_mode(op);
ir_mode *const dest_mode = get_irn_mode(node);
if (!mode_needs_gp_reg(src_mode) || !mode_needs_gp_reg(dest_mode) || get_mode_size_bits(dest_mode) > get_mode_size_bits(src_mode))
break;
node = op;
} else {
break;
}
}
return node;
}
static bool is_float_downconv(const ir_node *node)
{
if (!is_Conv(node))
......@@ -1018,9 +992,9 @@ static void match_arguments(ia32_address_mode_t *am, ir_node *block,
/* we can simply skip downconvs for mode neutral nodes: the upper bits
* can be random for these operations */
if (flags & match_mode_neutral) {
op2 = skip_downconv(op2, true);
op2 = be_skip_downconv(op2, true);
if (op1 != NULL) {
op1 = skip_downconv(op1, true);
op1 = be_skip_downconv(op1, true);
}
} else {
op2 = ia32_skip_sameconv(op2);
......@@ -1339,7 +1313,7 @@ static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
ir_node *new_op1;
if (flags & match_mode_neutral) {
op1 = skip_downconv(op1, true);
op1 = be_skip_downconv(op1, true);
new_op1 = be_transform_node(op1);
} else {
op1 = ia32_skip_sameconv(op1);
......@@ -1382,7 +1356,7 @@ static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func,
{
assert(flags == 0 || flags == match_mode_neutral);
if (flags & match_mode_neutral) {
op = skip_downconv(op, true);
op = be_skip_downconv(op, true);
}
ir_node *new_op = be_transform_node(op);
......@@ -2853,7 +2827,7 @@ static ir_node *create_store(dbg_info *dbgi, ir_node *new_block,
addr->mem, new_op, op_mode);
mode = op_mode;
} else {
value = skip_downconv(value, false);
value = be_skip_downconv(value, false);
ir_node *new_val = create_immediate_or_transform(value, 'i');
assert(mode != mode_b);
......@@ -3970,7 +3944,7 @@ static ir_node *create_I2I_Conv(ir_mode *const src_mode, dbg_info *const dbgi, i
}
#endif
op = skip_downconv(op, false);
op = be_skip_downconv(op, false);
if (be_upper_bits_clean(op, src_mode)) {
return be_transform_node(op);
......
......@@ -11,6 +11,7 @@
*/
#include "beirg.h"
#include "beutil.h"
#include "betranshlp.h"
#include "x86_address_mode.h"
#include "irtypes.h"
......@@ -187,30 +188,6 @@ static bool eat_shl(x86_address_t *addr, ir_node *node)
return true;
}
static bool is_downconv(const ir_node *node)
{
if (!is_Conv(node))
return false;
ir_mode *dest_mode = get_irn_mode(node);
if (get_mode_arithmetic(dest_mode) != irma_twos_complement)
return false;
ir_mode *src_mode = get_irn_mode(get_Conv_op(node));
if (get_mode_arithmetic(src_mode) != irma_twos_complement)
return false;
return get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}
static ir_node *skip_downconv(ir_node *node)
{
while (is_downconv(node)) {
if (get_irn_n_edges(node) > 1)
break;
node = get_Conv_op(node);
}
return node;
}
void x86_create_address_mode(x86_address_t *addr, ir_node *node,
x86_create_am_flags_t flags)
{
......@@ -227,7 +204,7 @@ void x86_create_address_mode(x86_address_t *addr, ir_node *node,
ir_node *eat_imms = eat_immediates(addr, node, flags);
if (eat_imms != node) {
if (flags & x86_create_am_force) {
eat_imms = skip_downconv(eat_imms);
eat_imms = be_skip_downconv(eat_imms, true);
}
node = eat_imms;
......@@ -251,8 +228,8 @@ void x86_create_address_mode(x86_address_t *addr, ir_node *node,
ir_node *right = get_Add_right(node);
if (flags & x86_create_am_force) {
left = skip_downconv(left);
right = skip_downconv(right);
left = be_skip_downconv(left, true);
right = be_skip_downconv(right, true);
}
left = eat_immediates(addr, left, flags);
right = eat_immediates(addr, right, flags);
......
......@@ -185,35 +185,6 @@ static bool needs_extension(ir_node *op)
return !be_upper_bits_clean(op, mode);
}
/**
* Check, if a given node is a Down-Conv, i.e. a integer Conv
* from a mode with a mode with more bits to a mode with fewer bits.
* Moreover, we return only true if the node has not more than 1 user.
*
* @param node the node
* @return non-zero if node is a Down-Conv
*/
static bool is_downconv(const ir_node *node)
{
if (!is_Conv(node))
return false;
ir_mode *src_mode = get_irn_mode(get_Conv_op(node));
ir_mode *dest_mode = get_irn_mode(node);
return
mode_needs_gp_reg(src_mode) &&
mode_needs_gp_reg(dest_mode) &&
get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}
static ir_node *skip_downconv(ir_node *node)
{
while (is_downconv(node)) {
node = get_Conv_op(node);
}
return node;
}
/**
* An assembler constraint.
*/
......@@ -612,8 +583,8 @@ static ir_node *gen_helper_binop_args(ir_node *node,
ir_node *block = be_transform_nodes_block(node);
if (flags & MATCH_MODE_NEUTRAL) {
op1 = skip_downconv(op1);
op2 = skip_downconv(op2);
op1 = be_skip_downconv(op1, false);
op2 = be_skip_downconv(op2, false);
}
ir_mode *mode2 = get_irn_mode(op2);
/* we should not see 64bit code */
......@@ -1074,14 +1045,10 @@ static ir_node *gen_Store(ir_node *node)
new_store = create_stf(dbgi, block, new_val, address.ptr, new_mem,
mode, address.entity, address.offset, false);
} else {
unsigned dest_bits = get_mode_size_bits(mode);
while (is_downconv(node)
&& get_mode_size_bits(get_irn_mode(node)) >= dest_bits) {
val = get_Conv_op(val);
}
val = be_skip_downconv(val, false);
ir_node *new_val = be_transform_node(val);
assert(dest_bits <= 32);
assert(get_mode_size_bits(mode) <= 32);
address_t address;
match_address(ptr, &address, true);
if (address.ptr2 != NULL) {
......
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