Commit 8dfa8a66 authored by Matthias Braun's avatar Matthias Braun
Browse files

a normalisation which shrinks values on the right shift operand because of...

a normalisation which shrinks values on the right shift operand because of modulo_shift behaviour. As a nice side-effect this simplifies the Rotl matcher

[r27954]
parent 6f37b3f5
......@@ -1771,39 +1771,14 @@ static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2)
*/
static ir_node *gen_Rotl(ir_node *node)
{
ir_node *rotate = NULL;
ir_node *op1 = get_Rotl_left(node);
ir_node *op2 = get_Rotl_right(node);
/* Firm has only RotL, so we are looking for a right (op2)
operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
that means we can create a RotR instead of an Add and a RotL */
if (is_Add(op2)) {
ir_node *add = op2;
ir_node *left = get_Add_left(add);
ir_node *right = get_Add_right(add);
if (is_Const(right)) {
tarval *tv = get_Const_tarval(right);
ir_mode *mode = get_irn_mode(node);
long bits = get_mode_size_bits(mode);
if (is_Minus(left) &&
tarval_is_long(tv) &&
get_tarval_long(tv) == bits &&
bits == 32)
{
DB((dbg, LEVEL_1, "RotL into RotR ... "));
rotate = gen_Ror(node, op1, get_Minus_op(left));
}
}
}
if (rotate == NULL) {
rotate = gen_Rol(node, op1, op2);
if (is_Minus(op2)) {
return gen_Ror(node, op1, get_Minus_op(op2));
}
return rotate;
return gen_Rol(node, op1, op2);
}
......
......@@ -50,6 +50,7 @@
#include "array_t.h"
#include "vrp.h"
#include "firm_types.h"
#include "bitfiddle.h"
#include "be.h"
/* Make types visible to allow most efficient access */
......@@ -5126,9 +5127,13 @@ static ir_node *transform_node_Or_Rotl(ir_node *or)
{
ir_mode *mode = get_irn_mode(or);
ir_node *shl, *shr, *block;
ir_node *irn, *x, *c1, *c2, *v, *sub, *n, *rotval;
ir_node *irn, *x, *c1, *c2, *n;
tarval *tv1, *tv2;
/* some backends can't handle rotl */
if (!be_get_backend_param()->support_rotl)
return or;
if (! mode_is_int(mode))
return or;
......@@ -5166,10 +5171,6 @@ static ir_node *transform_node_Or_Rotl(ir_node *or)
!= (int) get_mode_size_bits(mode))
return or;
/* some backends can't handle rotl */
if (!be_get_backend_param()->support_rotl)
return or;
/* yet, condition met */
block = get_nodes_block(or);
......@@ -5179,41 +5180,15 @@ static ir_node *transform_node_Or_Rotl(ir_node *or)
return n;
}
if (is_Sub(c1)) {
v = c2;
sub = c1;
rotval = sub; /* a Rot right is not supported, so use a rot left */
} else if (is_Sub(c2)) {
v = c1;
sub = c2;
rotval = v;
} else {
/* Note: the obvious rot formulation (a << x) | (a >> (32-x)) gets
* transformed to (a << x) | (a >> -x) by transform_node_shift_modulo() */
if (!is_negated_value(c1, c2)) {
return or;
}
if (get_Sub_right(sub) != v)
return or;
c1 = get_Sub_left(sub);
if (!is_Const(c1))
return or;
tv1 = get_Const_tarval(c1);
if (! tarval_is_long(tv1))
return or;
if (get_tarval_long(tv1) != (int) get_mode_size_bits(mode))
return or;
/* some backends can't handle rotl */
if (!be_get_backend_param()->support_rotl)
return or;
/* yet, condition met */
block = get_nodes_block(or);
n = new_r_Rotl(block, x, rotval, mode);
n = new_r_Rotl(block, x, c1, mode);
DBG_OPT_ALGSIM0(or, n, FS_OPT_OR_SHFT_TO_ROTL);
return n;
} /* transform_node_Or_Rotl */
......@@ -5526,6 +5501,91 @@ static ir_node *transform_node_shl_shr(ir_node *n)
return new_and;
}
static tarval *get_modulo_tv_value(tarval *tv, int modulo_val)
{
ir_mode *mode = get_tarval_mode(tv);
tarval *modulo_tv = new_tarval_from_long(modulo_val, mode);
return tarval_mod(tv, modulo_tv);
}
typedef ir_node*(*new_shift_func)(dbg_info *dbgi, ir_node *block,
ir_node *left, ir_node *right, ir_mode *mode);
/**
* Normalisation: if we have a shl/shr with modulo_shift behaviour
* then we can use that to minimize the value of Add(x, const) or
* Sub(Const, x). In particular this often avoids 1 instruction in some
* backends for the Shift(x, Sub(Const, y)) case because it can be replaced
* by Shift(x, Minus(y)) which doesnt't need an explicit Const constructed.
*/
static ir_node *transform_node_shift_modulo(ir_node *n,
new_shift_func new_shift)
{
ir_mode *mode = get_irn_mode(n);
int modulo = get_mode_modulo_shift(mode);
ir_node *newop = NULL;
ir_mode *mode_right;
ir_node *block;
ir_node *right;
ir_graph *irg;
if (modulo == 0)
return n;
if (get_mode_arithmetic(mode) != irma_twos_complement)
return n;
if (!is_po2(modulo))
return n;
irg = get_irn_irg(n);
block = get_nodes_block(n);
right = get_binop_right(n);
mode_right = get_irn_mode(right);
if (is_Const(right)) {
tarval *tv = get_Const_tarval(right);
tarval *tv_mod = get_modulo_tv_value(tv, modulo);
if (tv_mod == tv)
return n;
newop = new_r_Const(irg, tv_mod);
} else if (is_Add(right)) {
ir_node *add_right = get_Add_right(right);
if (is_Const(add_right)) {
tarval *tv = get_Const_tarval(add_right);
tarval *tv_mod = get_modulo_tv_value(tv, modulo);
ir_node *newconst;
if (tv_mod == tv)
return n;
newconst = new_r_Const(irg, tv_mod);
newop = new_r_Add(block, get_Add_left(right), newconst,
mode_right);
}
} else if (is_Sub(right)) {
ir_node *sub_left = get_Sub_left(right);
if (is_Const(sub_left)) {
tarval *tv = get_Const_tarval(sub_left);
tarval *tv_mod = get_modulo_tv_value(tv, modulo);
ir_node *newconst;
if (tv_mod == tv)
return n;
newconst = new_r_Const(irg, tv_mod);
newop = new_r_Sub(block, newconst, get_Sub_right(right),
mode_right);
}
} else {
return n;
}
if (newop != NULL) {
dbg_info *dbgi = get_irn_dbg_info(n);
ir_node *left = get_binop_left(n);
return new_shift(dbgi, block, left, newop, mode);
}
return n;
}
/**
* Transform a Shr.
*/
......@@ -5539,6 +5599,8 @@ static ir_node *transform_node_Shr(ir_node *n)
HANDLE_BINOP_PHI((eval_func) tarval_shr, left, right, c, mode);
n = transform_node_shift(n);
if (is_Shr(n))
n = transform_node_shift_modulo(n, new_rd_Shr);
if (is_Shr(n))
n = transform_node_shl_shr(n);
if (is_Shr(n))
......@@ -5560,6 +5622,8 @@ static ir_node *transform_node_Shrs(ir_node *n)
HANDLE_BINOP_PHI((eval_func) tarval_shrs, a, b, c, mode);
n = transform_node_shift(n);
if (is_Shrs(n))
n = transform_node_shift_modulo(n, new_rd_Shrs);
if (is_Shrs(n))
n = transform_node_bitop_shift(n);
......@@ -5579,6 +5643,8 @@ static ir_node *transform_node_Shl(ir_node *n)
HANDLE_BINOP_PHI((eval_func) tarval_shl, a, b, c, mode);
n = transform_node_shift(n);
if (is_Shl(n))
n = transform_node_shift_modulo(n, new_rd_Shl);
if (is_Shl(n))
n = transform_node_shl_shr(n);
if (is_Shl(n))
......
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