From 74d06db969867d5a97ee0da20d5a6256853fbcd0 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Wed, 19 Oct 2011 11:05:10 +0200 Subject: [PATCH] ia32: change ShrD/ShlD patterns to match Add instead of Or --- ir/be/ia32/ia32_transform.c | 227 ++++++++++++++++++------------------ 1 file changed, 116 insertions(+), 111 deletions(-) diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 9db14b2ef..5f2099626 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1239,6 +1239,118 @@ static int am_has_immediates(const ia32_address_t *addr) || addr->frame_entity || addr->use_frame; } +typedef ir_node* (*new_shiftd_func)(dbg_info *dbgi, ir_node *block, + ir_node *high, ir_node *low, + ir_node *count); + +/** + * Transforms a l_ShlD/l_ShrD into a ShlD/ShrD. Those nodes have 3 data inputs: + * op1 - target to be shifted + * op2 - contains bits to be shifted into target + * op3 - shift count + * Only op3 can be an immediate. + */ +static ir_node *gen_64bit_shifts(dbg_info *dbgi, ir_node *block, + ir_node *high, ir_node *low, ir_node *count, + new_shiftd_func func) +{ + ir_node *new_block = be_transform_node(block); + ir_node *new_high = be_transform_node(high); + ir_node *new_low = be_transform_node(low); + ir_node *new_count; + ir_node *new_node; + + /* the shift amount can be any mode that is bigger than 5 bits, since all + * other bits are ignored anyway */ + while (is_Conv(count) && + get_irn_n_edges(count) == 1 && + mode_is_int(get_irn_mode(count))) { + assert(get_mode_size_bits(get_irn_mode(count)) >= 5); + count = get_Conv_op(count); + } + new_count = create_immediate_or_transform(count, 0); + + new_node = func(dbgi, new_block, new_high, new_low, new_count); + return new_node; +} + +/** + * test wether 2 values result in 'x' and '32-x' when interpreted as a shift + * value. + */ +static bool is_complementary_shifts(ir_node *value1, ir_node *value2) +{ + if (is_Const(value1) && is_Const(value2)) { + ir_tarval *tv1 = get_Const_tarval(value1); + ir_tarval *tv2 = get_Const_tarval(value2); + if (tarval_is_long(tv1) && tarval_is_long(tv2)) { + long v1 = get_tarval_long(tv1); + long v2 = get_tarval_long(tv2); + return v1 <= v2 && v2 == 32-v1; + } + } + return false; +} + +static ir_node *match_64bit_shift(ir_node *node) +{ + ir_node *op1 = get_binop_left(node); + ir_node *op2 = get_binop_right(node); + assert(is_Or(node) || is_Add(node)); + + if (is_Shr(op1)) { + ir_node *tmp = op1; + op1 = op2; + op2 = tmp; + } + + /* match ShlD operation */ + if (is_Shl(op1) && is_Shr(op2)) { + ir_node *shl_right = get_Shl_right(op1); + ir_node *shl_left = get_Shl_left(op1); + ir_node *shr_right = get_Shr_right(op2); + ir_node *shr_left = get_Shr_left(op2); + /* constant ShlD operation */ + if (is_complementary_shifts(shl_right, shr_right)) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + return gen_64bit_shifts(dbgi, block, shl_left, shr_left, shl_right, + new_bd_ia32_ShlD); + } + /* constant ShrD operation */ + if (is_complementary_shifts(shr_right, shl_right)) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + return gen_64bit_shifts(dbgi, block, shr_left, shl_left, shr_right, + new_bd_ia32_ShrD); + } + /* lower_dw produces the following for ShlD: + * Or(Shr(Shr(high,1),Not(c)),Shl(low,c)) */ + if (is_Shr(shr_left) && is_Not(shr_right) + && is_Const_1(get_Shr_right(shr_left)) + && get_Not_op(shr_right) == shl_right) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *val_h = get_Shr_left(shr_left); + return gen_64bit_shifts(dbgi, block, shl_left, val_h, shl_right, + new_bd_ia32_ShlD); + } + /* lower_dw produces the following for ShrD: + * Or(Shl(Shl(high,1),Not(c)), Shr(low,c)) */ + if (is_Shl(shl_left) && is_Not(shl_right) + && is_Const_1(get_Shl_right(shl_left)) + && get_Not_op(shl_right) == shr_right) { + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *block = get_nodes_block(node); + ir_node *val_h = get_Shl_left(shl_left); + return gen_64bit_shifts(dbgi, block, shr_left, val_h, shr_right, + new_bd_ia32_ShrD); + } + } + + return NULL; +} + /** * Creates an ia32 Add. * @@ -1254,6 +1366,10 @@ static ir_node *gen_Add(ir_node *node) ia32_address_t addr; ia32_address_mode_t am; + new_node = match_64bit_shift(node); + if (new_node != NULL) + return new_node; + if (mode_is_float(mode)) { if (ia32_cg_config.use_sse2) return gen_binop(node, op1, op2, new_bd_ia32_xAdd, @@ -1424,117 +1540,6 @@ static ir_node *gen_And(ir_node *node) match_commutative | match_mode_neutral | match_am | match_immediate); } -/** - * test wether 2 values result in 'x' and '32-x' when interpreted as a shift - * value. - */ -static bool is_complementary_shifts(ir_node *value1, ir_node *value2) -{ - if (is_Const(value1) && is_Const(value2)) { - ir_tarval *tv1 = get_Const_tarval(value1); - ir_tarval *tv2 = get_Const_tarval(value2); - if (tarval_is_long(tv1) && tarval_is_long(tv2)) { - long v1 = get_tarval_long(tv1); - long v2 = get_tarval_long(tv2); - return v1 <= v2 && v2 == 32-v1; - } - } - return false; -} - -typedef ir_node* (*new_shiftd_func)(dbg_info *dbgi, ir_node *block, - ir_node *high, ir_node *low, - ir_node *count); - -/** - * Transforms a l_ShlD/l_ShrD into a ShlD/ShrD. Those nodes have 3 data inputs: - * op1 - target to be shifted - * op2 - contains bits to be shifted into target - * op3 - shift count - * Only op3 can be an immediate. - */ -static ir_node *gen_64bit_shifts(dbg_info *dbgi, ir_node *block, - ir_node *high, ir_node *low, ir_node *count, - new_shiftd_func func) -{ - ir_node *new_block = be_transform_node(block); - ir_node *new_high = be_transform_node(high); - ir_node *new_low = be_transform_node(low); - ir_node *new_count; - ir_node *new_node; - - /* the shift amount can be any mode that is bigger than 5 bits, since all - * other bits are ignored anyway */ - while (is_Conv(count) && - get_irn_n_edges(count) == 1 && - mode_is_int(get_irn_mode(count))) { - assert(get_mode_size_bits(get_irn_mode(count)) >= 5); - count = get_Conv_op(count); - } - new_count = create_immediate_or_transform(count, 0); - - new_node = func(dbgi, new_block, new_high, new_low, new_count); - return new_node; -} - -static ir_node *match_64bit_shift(ir_node *node) -{ - ir_node *op1 = get_Or_left(node); - ir_node *op2 = get_Or_right(node); - - if (is_Shr(op1)) { - ir_node *tmp = op1; - op1 = op2; - op2 = tmp; - } - - /* match ShlD operation */ - if (is_Shl(op1) && is_Shr(op2)) { - ir_node *shl_right = get_Shl_right(op1); - ir_node *shl_left = get_Shl_left(op1); - ir_node *shr_right = get_Shr_right(op2); - ir_node *shr_left = get_Shr_left(op2); - /* constant ShlD operation */ - if (is_complementary_shifts(shl_right, shr_right)) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - return gen_64bit_shifts(dbgi, block, shl_left, shr_left, shl_right, - new_bd_ia32_ShlD); - } - /* constant ShrD operation */ - if (is_complementary_shifts(shr_right, shl_right)) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - return gen_64bit_shifts(dbgi, block, shr_left, shl_left, shr_right, - new_bd_ia32_ShrD); - } - /* lower_dw produces the following for ShlD: - * Or(Shr(Shr(high,1),Not(c)),Shl(low,c)) */ - if (is_Shr(shr_left) && is_Not(shr_right) - && is_Const_1(get_Shr_right(shr_left)) - && get_Not_op(shr_right) == shl_right) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *val_h = get_Shr_left(shr_left); - return gen_64bit_shifts(dbgi, block, shl_left, val_h, shl_right, - new_bd_ia32_ShlD); - } - /* lower_dw produces the following for ShrD: - * Or(Shl(Shl(high,1),Not(c)), Shr(low,c)) */ - if (is_Shl(shl_left) && is_Not(shl_right) - && is_Const_1(get_Shl_right(shl_left)) - && get_Not_op(shl_right) == shr_right) { - dbg_info *dbgi = get_irn_dbg_info(node); - ir_node *block = get_nodes_block(node); - ir_node *val_h = get_Shl_left(shl_left); - return gen_64bit_shifts(dbgi, block, shr_left, val_h, shr_right, - new_bd_ia32_ShrD); - } - } - - return NULL; -} - /** * Creates an ia32 Or. * -- 2.20.1