Commit 3a448bc0 authored by Matthias Braun's avatar Matthias Braun
Browse files

implement some localopt rules for And(Cmp(a,0), Cmp(b,0))

parent e3a4bae9
......@@ -103,6 +103,13 @@ FIRM_API int ir_is_negated_value(const ir_node *a, const ir_node *b);
FIRM_API ir_relation ir_get_possible_cmp_relations(const ir_node *left,
const ir_node *right);
/**
* tests wether a given Cmp node is an equal/not-equal test with 0
* (this is a bit tricky because it has to catch x!=0 for the signed case and
* x>0 for the unsigned case)
*/
FIRM_API int ir_is_equality_cmp_0(const ir_node *node);
#include "end.h"
#endif
......@@ -3107,6 +3107,38 @@ static ir_node *transform_bitwise_distributive(ir_node *n,
return n;
}
int ir_is_equality_cmp_0(const ir_node *node)
{
ir_relation relation = get_Cmp_relation(node);
ir_node *left = get_Cmp_left(node);
ir_node *right = get_Cmp_right(node);
ir_mode *mode = get_irn_mode(left);
/* this probably makes no sense if unordered is involved */
assert(!mode_is_float(mode));
if (!is_Const(right) || !is_Const_null(right))
return false;
if (relation == ir_relation_equal)
return true;
if (mode_is_signed(mode) && relation == ir_relation_less_greater)
return true;
if (relation == ir_relation_greater)
return true;
return false;
}
/**
* Create a 0 constant of given mode.
*/
static ir_node *create_zero_const(ir_graph *irg, ir_mode *mode)
{
ir_tarval *tv = get_mode_null(mode);
ir_node *cnst = new_r_Const(irg, tv);
return cnst;
}
/**
* Transform an And.
*/
......@@ -3118,12 +3150,13 @@ static ir_node *transform_node_And(ir_node *n)
ir_mode *mode;
vrp_attr *a_vrp, *b_vrp;
/* we can combine the relations of two compares with the same operands */
if (is_Cmp(a) && is_Cmp(b)) {
ir_node *a_left = get_Cmp_left(a);
ir_node *a_right = get_Cmp_left(a);
ir_node *b_left = get_Cmp_left(b);
ir_node *b_right = get_Cmp_right(b);
/* we can combine the relations of two compares with the same
* operands */
if (a_left == b_left && b_left == b_right) {
dbg_info *dbgi = get_irn_dbg_info(n);
ir_node *block = get_nodes_block(n);
......@@ -3132,6 +3165,22 @@ static ir_node *transform_node_And(ir_node *n)
ir_relation new_relation = a_relation & b_relation;
return new_rd_Cmp(dbgi, block, a_left, a_right, new_relation);
}
/* Cmp(a, 0) and Cmp(b,0) can be optimized to Cmp(a|b, 0) */
if (ir_is_equality_cmp_0(a) && ir_is_equality_cmp_0(b)
&& (get_Cmp_relation(a) & ir_relation_equal) == (get_Cmp_relation(b) & ir_relation_equal)) {
dbg_info *dbgi = get_irn_dbg_info(n);
ir_node *block = get_nodes_block(n);
ir_relation relation = get_Cmp_relation(a);
ir_mode *mode = get_irn_mode(a_left);
ir_node *n_b_left = b_left;
if (get_irn_mode(n_b_left) != mode) {
n_b_left = new_rd_Conv(dbgi, block, b_left, mode);
}
ir_node *or = new_rd_Or(dbgi, block, a_left, b_left, mode);
ir_graph *irg = get_irn_irg(n);
ir_node *zero = create_zero_const(irg, mode);
return new_rd_Cmp(dbgi, block, or, zero, relation);
}
}
mode = get_irn_mode(n);
......@@ -3777,17 +3826,6 @@ static bool is_single_bit(const ir_node *node)
return false;
}
/**
* Create a 0 constant of given mode.
*/
static ir_node *create_zero_const(ir_graph *irg, ir_mode *mode)
{
ir_tarval *tv = get_mode_null(mode);
ir_node *cnst = new_r_Const(irg, tv);
return cnst;
}
/**
* Normalizes and optimizes Cmp nodes.
*/
......
......@@ -982,25 +982,6 @@ static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env)
set_lowered(env, node, res_low, res_high);
}
static bool is_cmp_0_equality(ir_node *cmp)
{
ir_relation relation = get_Cmp_relation(cmp);
ir_node *right = get_Cmp_right(cmp);
ir_node *left = get_Cmp_right(cmp);
ir_mode *mode = get_irn_mode(left);
/* assume constants are normalized to the right side */
if (!is_Const(right) || !is_Const_null(right))
return false;
/* assume unordered bites have been optimized away */
if (relation == ir_relation_equal)
return true;
if (mode_is_signed(mode) && relation == ir_relation_less_greater)
return true;
if (relation == ir_relation_greater)
return true;
return false;
}
/**
* Translate a Cond.
*/
......@@ -1071,7 +1052,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env)
dbg = get_irn_dbg_info(sel);
relation = get_Cmp_relation(sel);
if (is_cmp_0_equality(sel)) {
if (ir_is_equality_cmp_0(sel)) {
/* x ==/!= 0 ==> or(low,high) ==/!= 0 */
ir_mode *mode = env->low_unsigned;
ir_node *low = new_r_Conv(block, lentry->low_word, mode);
......
Supports Markdown
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