# define ENUM_COUNTABLE(type)
#endif
+/**
+ * Relations for comparing numbers
+ */
+typedef enum ir_relation {
+ ir_relation_false = 0, /**< always false */
+ ir_relation_equal = 1u << 0, /**< equal */
+ ir_relation_less = 1u << 1, /**< less */
+ ir_relation_greater = 1u << 2, /**< greater */
+ ir_relation_unordered = 1u << 3, /**< unordered */
+ ir_relation_less_equal = ir_relation_equal|ir_relation_less, /**< less or equal */
+ ir_relation_greater_equal = ir_relation_equal|ir_relation_greater, /**< greater or equal */
+ ir_relation_less_greater = ir_relation_less|ir_relation_greater, /** less or greater ('not equal' for integer numbers) */
+ ir_relation_less_equal_greater = ir_relation_equal|ir_relation_less|ir_relation_greater, /**< less equal or greater ('not unordered') */
+ ir_relation_unordered_equal = ir_relation_unordered|ir_relation_equal, /**< unordered or equal */
+ ir_relation_unordered_less = ir_relation_unordered|ir_relation_less, /**< unorderedor less */
+ ir_relation_unordered_less_equal = ir_relation_unordered|ir_relation_less|ir_relation_equal, /**< unordered, less or equal */
+ ir_relation_unordered_greater = ir_relation_unordered|ir_relation_greater, /**< unordered or greater */
+ ir_relation_unordered_greater_equal = ir_relation_unordered|ir_relation_greater|ir_relation_equal, /**< unordered, greater or equal */
+ ir_relation_unordered_less_greater = ir_relation_unordered|ir_relation_less|ir_relation_greater, /**< unordered, less or greater ('not equal' for floatingpoint numbers) */
+ ir_relation_true = ir_relation_equal|ir_relation_less|ir_relation_greater|ir_relation_unordered, /**< always true */
+} ir_relation;
+ENUM_BITSET(ir_relation)
+
/**
* constrained flags for memory operations.
*/
FIRM_API ir_node *get_binop_right(const ir_node *node);
FIRM_API void set_binop_right(ir_node *node, ir_node *right);
-/** returns the pnc name from an pnc constant */
-FIRM_API const char *get_pnc_string(int pnc);
+/** returns the name of an ir_relation */
+FIRM_API const char *get_relation_string(ir_relation relation);
-/** Calculates the negated (Complement(R)) pnc condition. */
-FIRM_API pn_Cmp get_negated_pnc(long pnc, ir_mode *mode);
+/** Calculates the negated (Complement(R)) relation, i.e. "<" --> ">=" */
+FIRM_API ir_relation get_negated_relation(ir_relation relation);
-/** Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
-FIRM_API pn_Cmp get_inversed_pnc(long pnc);
-
-/** An alternative name for get_inversed_pnc() that can be better memorized. */
-#define get_mirrored_pnc(pnc) get_inversed_pnc(pnc)
+/** Calculates the inversed (R^-1) relation, i.e., "<" --> ">" */
+FIRM_API ir_relation get_inversed_relation(ir_relation relation);
/** Checks for upcast.
*
/** Return the projection number of a Proj node. */
FIRM_API long get_Proj_proj(const ir_node *node);
FIRM_API void set_Proj_proj(ir_node *node, long proj);
-FIRM_API pn_Cmp get_Proj_pn_cmp(const ir_node*);
/**
* Returns non-zero if a node is a routine parameter.
* Return the value of a Cmp if one or both predecessors
* are Confirm nodes.
*
- * @param cmp the compare node that will be evaluated
- * @param left the left operand of the Cmp
- * @param right the right operand of the Cmp
- * @param pnc the compare relation
+ * @param cmp the compare node that will be evaluated
+ * @param left the left operand of the Cmp
+ * @param right the right operand of the Cmp
+ * @param relation the compare relation
*/
FIRM_API ir_tarval *computed_value_Cmp_Confirm(
- ir_node *cmp, ir_node *left, ir_node *right, pn_Cmp pnc);
+ const ir_node *cmp, ir_node *left, ir_node *right, ir_relation relation);
#include "end.h"
* @sa
* Techreport 1999-14
* irmode.h for the modes definitions
- * irnode.h for the pn_Cmp table
*/
#ifndef FIRM_TV_TV_H
#define FIRM_TV_TV_H
+#include <stddef.h>
#include "firm_types.h"
-#include "irnode.h"
#include "begin.h"
/**
* Compares two tarvals
*
- * Compare a with b and return a pn_Cmp describing the relation
- * between a and b. This is either pn_Cmp_Uo, pn_Cmp_Lt, pn_Cmp_Eq, pn_Cmp_Gt,
- * or pn_Cmp_False if a or b are symbolic pointers which can not be compared at all.
+ * Compare a with b and return their relation.
+ * This is either ir_rel_unordered, ir_rel_less, ir_rel_greater, ir_rel_equal
+ * or ir_rel_false if a or b are symbolic pointers which can not be compared at
+ * all.
*
* @param a the first tarval to be compared
* @param b the second tarval to be compared
- *
- * @return
- * The pn_Cmp best describing the relation between a and b is returned.
- * This means the mode with the least bits set is returned, e.g. if the
- * tarvals are equal the pn_Cmp 'pn_Cmp_Eq' is returned, not 'pn_Cmp_Ge' which
- * indicates 'greater or equal'
- *
- * @sa
- * irnode.h for the definition of pn_Cmp
*/
-FIRM_API pn_Cmp tarval_cmp(ir_tarval *a, ir_tarval *b);
+FIRM_API ir_relation tarval_cmp(ir_tarval *a, ir_tarval *b);
/**
* Converts a tarval to another mode.
*
* @param left: the left node
* @param right: the right node
- *
- * @return the pn_Cmp, if one can be derived
+ * @return all possible relations
*/
-FIRM_API pn_Cmp vrp_cmp(const ir_node *left, const ir_node *right);
+FIRM_API ir_relation vrp_cmp(const ir_node *left, const ir_node *right);
/*
* Return the vrp data for this node
*
* @param block the block which is entered by the branch
* @param cmp the Cmp node expressing the branch condition
- * @param pnc the Compare relation for taking this branch
+ * @param rel the Compare relation for taking this branch
* @param env statistical environment
*/
-static void handle_if(ir_node *block, ir_node *cmp, pn_Cmp pnc, env_t *env)
+static void handle_if(ir_node *block, ir_node *cmp, ir_relation rel, env_t *env)
{
ir_node *left = get_Cmp_left(cmp);
ir_node *right = get_Cmp_right(cmp);
left = right;
right = t;
- pnc = get_inversed_pnc(pnc);
+ rel = get_inversed_relation(rel);
}
/*
* First case: both values are identical.
* replace the left one by the right (potentially const) one.
*/
- if (pnc == pn_Cmp_Eq) {
+ if (rel == ir_relation_equal) {
cond_block = get_Block_cfgpred_block(block, 0);
for (edge = get_irn_out_edge_first(left); edge; edge = next) {
ir_node *user = get_edge_src_irn(edge);
}
}
}
- } else { /* not pn_Cmp_Eq cases */
+ } else { /* not ir_relation_equal cases */
ir_node *c = NULL;
foreach_out_edge_safe(left, edge, next) {
* We can replace the input with a Confirm(left, pnc, right).
*/
if (! c)
- c = new_r_Confirm(block, left, right, pnc);
+ c = new_r_Confirm(block, left, right, rel);
pos = get_edge_src_pos(edge);
set_irn_n(succ, pos, c);
/* also construct inverse Confirms */
ir_node *rc = NULL;
- pnc = get_inversed_pnc(pnc);
+ rel = get_inversed_relation(rel);
foreach_out_edge_safe(right, edge, next) {
ir_node *succ = get_edge_src_irn(edge);
int pos;
/*
* Ok, we found a usage of right in a block
* dominated by the branch block.
- * We can replace the input with a Confirm(right, pnc^-1, left).
+ * We can replace the input with a Confirm(right, rel^-1, left).
*/
if (! rc)
- rc = new_r_Confirm(block, right, left, pnc);
+ rc = new_r_Confirm(block, right, left, rel);
pos = get_edge_src_pos(edge);
set_irn_n(succ, pos, rc);
if (mode == mode_b) {
ir_node *cmp;
- pn_Cmp pnc;
+ ir_relation rel;
handle_modeb(block, selector, (pn_Cond) get_Proj_proj(proj), env);
if (! is_Cmp(cmp))
return;
- pnc = (pn_Cmp) get_Proj_proj(selector);
+ rel = get_Cmp_relation(cmp);
if (get_Proj_proj(proj) != pn_Cond_true) {
/* it's the false branch */
mode = get_irn_mode(get_Cmp_left(cmp));
- pnc = get_negated_pnc(pnc, mode);
+ rel = get_negated_relation(rel);
}
- DB((dbg, LEVEL_2, "At %+F using %+F Confirm %=\n", block, cmp, pnc));
+ DB((dbg, LEVEL_2, "At %+F using %+F Confirm %=\n", block, cmp, rel));
- handle_if(block, cmp, pnc, env);
+ handle_if(block, cmp, rel, env);
} else if (mode_is_int(mode)) {
long proj_nr = get_Proj_proj(proj);
for (;;) {
if (! is_Confirm(ptr))
break;
- if (get_Confirm_cmp(ptr) == pn_Cmp_Lg) {
+ if (get_Confirm_relation(ptr) == ir_relation_less_greater) {
ir_node *bound = get_Confirm_bound(ptr);
if (is_Const(bound) && is_Const_null(bound))
ir_mode *mode = get_irn_mode(ptr);
ir_graph *irg = get_irn_irg(block);
c = new_r_Const(irg, get_mode_null(mode));
- c = new_r_Confirm(block, ptr, c, pn_Cmp_Lg);
+ c = new_r_Confirm(block, ptr, c, ir_relation_less_greater);
}
set_irn_n(succ, pos, c);
if (size == 0)
return tarval_is_null(tv) ? ir_may_alias : ir_no_alias;
tv_size = new_tarval_from_long(size, get_tarval_mode(tv));
- return tarval_cmp(tv_size, tv) & (pn_Cmp_Eq|pn_Cmp_Lt) ? ir_no_alias : ir_may_alias;
+ return tarval_cmp(tv_size, tv) & (ir_relation_less_equal) ? ir_no_alias : ir_may_alias;
} /* check_const */
/**
} else {
tv_size = new_tarval_from_long(size, m2);
- if (tarval_cmp(tv2, tv_size) & (pn_Cmp_Eq|pn_Cmp_Gt)) {
+ if (tarval_cmp(tv2, tv_size) & (ir_relation_greater_equal)) {
/* tv1 is negative and tv2 >= tv_size, so the difference is bigger than size */
return ir_no_alias;
}
tv1 = tarval_convert_to(tv1, m2);
/* now we can compare without overflow */
- return tarval_cmp(tv1, tv2) & (pn_Cmp_Eq|pn_Cmp_Gt) ? ir_no_alias : ir_may_alias;
+ return tarval_cmp(tv1, tv2) & (ir_relation_greater_equal) ? ir_no_alias : ir_may_alias;
}
}
}
- if (tarval_cmp(tv1, tv2) == pn_Cmp_Gt) {
+ if (tarval_cmp(tv1, tv2) == ir_relation_greater) {
ir_tarval *t = tv1;
tv1 = tv2;
tv2 = t;
/* tv1 is now the "smaller" one */
tv = tarval_sub(tv2, tv1, NULL);
tv_size = new_tarval_from_long(size, get_tarval_mode(tv));
- return tarval_cmp(tv_size, tv) & (pn_Cmp_Eq|pn_Cmp_Lt) ? ir_no_alias : ir_may_alias;
+ return tarval_cmp(tv_size, tv) & (ir_relation_less_equal) ? ir_no_alias : ir_may_alias;
}
/* Note: we rely here on the fact that normalization puts constants on the RIGHT side */
new_bits_set = tarval_and(
new_bits_not_set, tarval_convert_to(vrp_pred->bits_set, new_mode));
- if (tarval_cmp(vrp_pred->range_top, get_mode_max(new_mode)) == pn_Cmp_Le) {
+ /* Matze: TODO, BUGGY, tarval_cmp never returns ir_relation_less_equal */
+ if (tarval_cmp(vrp_pred->range_top, get_mode_max(new_mode)) == ir_relation_less_equal) {
vrp->range_top = vrp_pred->range_top;
}
- if (tarval_cmp(vrp_pred->range_bottom, get_mode_min(new_mode)) == pn_Cmp_Ge) {
+ /* Matze: TODO, BUGGY, tarval_cmp never returns ir_relation_greater_equal */
+ if (tarval_cmp(vrp_pred->range_bottom, get_mode_min(new_mode)) == ir_relation_greater_equal) {
vrp->range_bottom = vrp_pred->range_bottom;
}
break;
}
case iro_Confirm: {
- const pn_Cmp cmp = get_Confirm_cmp(node);
- const ir_node *bound = get_Confirm_bound(node);
+ const ir_relation relation = get_Confirm_relation(node);
+ const ir_node *bound = get_Confirm_bound(node);
- if (cmp == pn_Cmp_Lg) {
+ if (relation == ir_relation_less_greater) {
/** @todo: Handle non-Const bounds */
if (is_Const(bound)) {
new_range_type = VRP_ANTIRANGE;
new_range_top = get_Const_tarval(bound);
new_range_bottom = get_Const_tarval(bound);
}
- } else if (cmp == pn_Cmp_Le) {
+ } else if (relation == ir_relation_less_equal) {
if (is_Const(bound)) {
new_range_type = VRP_RANGE;
new_range_top = get_Const_tarval(bound);
/* combine all ranges*/
int num = get_Phi_n_preds(node);
- pn_Cmp cmp;
+ ir_relation relation;
int i;
const ir_node *pred = get_Phi_pred(node,0);
vrp_pred = get_vrp_attr(pred);
if (new_range_type == VRP_RANGE && vrp_pred->range_type ==
VRP_RANGE) {
- cmp = tarval_cmp(new_range_top, vrp_pred->range_top);
- if (cmp == pn_Cmp_Lt) {
+ relation = tarval_cmp(new_range_top, vrp_pred->range_top);
+ if (relation == ir_relation_less) {
new_range_top = vrp_pred->range_top;
}
- cmp = tarval_cmp(new_range_bottom, vrp_pred->range_bottom);
- if (cmp == pn_Cmp_Gt) {
+ relation = tarval_cmp(new_range_bottom, vrp_pred->range_bottom);
+ if (relation == ir_relation_greater) {
new_range_bottom = vrp_pred->range_bottom;
}
} else {
/* Merge the newly calculated values with those that might already exist*/
if (new_bits_set != tarval_bad) {
new_bits_set = tarval_or(new_bits_set, vrp->bits_set);
- if (tarval_cmp(new_bits_set, vrp->bits_set) != pn_Cmp_Eq) {
+ if (tarval_cmp(new_bits_set, vrp->bits_set) != ir_relation_equal) {
something_changed = 1;
vrp->bits_set = new_bits_set;
}
if (new_bits_not_set != tarval_bad) {
new_bits_not_set = tarval_and(new_bits_not_set, vrp->bits_not_set);
- if (tarval_cmp(new_bits_not_set, vrp->bits_not_set) != pn_Cmp_Eq) {
+ if (tarval_cmp(new_bits_not_set, vrp->bits_not_set) != ir_relation_equal) {
something_changed = 1;
vrp->bits_not_set = new_bits_not_set;
}
} else if (vrp->range_type == VRP_RANGE) {
if (new_range_type == VRP_RANGE) {
- if (tarval_cmp(vrp->range_bottom, new_range_bottom) == pn_Cmp_Lt) {
+ if (tarval_cmp(vrp->range_bottom, new_range_bottom) == ir_relation_less) {
something_changed = 1;
vrp->range_bottom = new_range_bottom;
}
- if (tarval_cmp(vrp->range_top, new_range_top) == pn_Cmp_Gt) {
+ if (tarval_cmp(vrp->range_top, new_range_top) == ir_relation_greater) {
something_changed = 1;
vrp->range_top = new_range_top;
}
if (new_range_type == VRP_ANTIRANGE) {
/* if they are overlapping, cut the range.*/
/* TODO: Maybe we can preserve more information here*/
- if (tarval_cmp(vrp->range_bottom, new_range_top) == pn_Cmp_Gt &&
- tarval_cmp(vrp->range_bottom, new_range_bottom) == pn_Cmp_Gt) {
+ if (tarval_cmp(vrp->range_bottom, new_range_top) == ir_relation_greater &&
+ tarval_cmp(vrp->range_bottom, new_range_bottom) == ir_relation_greater) {
something_changed = 1;
vrp->range_bottom = new_range_top;
- } else if (tarval_cmp(vrp->range_top, new_range_bottom) == pn_Cmp_Gt &&
- tarval_cmp(vrp->range_top, new_range_top) == pn_Cmp_Lt) {
+ } else if (tarval_cmp(vrp->range_top, new_range_bottom) == ir_relation_greater &&
+ tarval_cmp(vrp->range_top, new_range_top) == ir_relation_less) {
something_changed = 1;
vrp->range_top = new_range_bottom;
}
}
} else if (vrp->range_type == VRP_ANTIRANGE) {
if (new_range_type == VRP_ANTIRANGE) {
- if (tarval_cmp(vrp->range_bottom, new_range_bottom) == pn_Cmp_Gt) {
+ if (tarval_cmp(vrp->range_bottom, new_range_bottom) == ir_relation_greater) {
something_changed = 1;
vrp->range_bottom = new_range_bottom;
}
- if (tarval_cmp(vrp->range_top, new_range_top) == pn_Cmp_Lt) {
+ if (tarval_cmp(vrp->range_top, new_range_top) == ir_relation_less) {
something_changed = 1;
vrp->range_top = new_range_top;
}
}
if (new_range_type == VRP_RANGE) {
- if (tarval_cmp(vrp->range_bottom, new_range_top) == pn_Cmp_Gt) {
+ if (tarval_cmp(vrp->range_bottom, new_range_top) == ir_relation_greater) {
something_changed = 1;
vrp->range_bottom = new_range_top;
}
- if (tarval_cmp(vrp->range_top, new_range_bottom) == pn_Cmp_Lt) {
+ if (tarval_cmp(vrp->range_top, new_range_bottom) == ir_relation_less) {
something_changed = 1;
vrp->range_top = new_range_bottom;
}
return def_graph_pass(name ? name : "set_vrp", set_vrp_data);
}
-pn_Cmp vrp_cmp(const ir_node *left, const ir_node *right)
+ir_relation vrp_cmp(const ir_node *left, const ir_node *right)
{
vrp_attr *vrp_left, *vrp_right;
vrp_left = vrp_get_info(left);
vrp_right = vrp_get_info(right);
- if (!vrp_left || !vrp_right) {
- return pn_Cmp_False;
- }
+ if (!vrp_left || !vrp_right)
+ return ir_relation_true;
if (vrp_left->range_type == VRP_RANGE && vrp_right->range_type == VRP_RANGE) {
- if (tarval_cmp(vrp_left->range_top, vrp_right->range_bottom) == pn_Cmp_Lt) {
- return pn_Cmp_Lt;
+ if (tarval_cmp(vrp_left->range_top, vrp_right->range_bottom) == ir_relation_less) {
+ return ir_relation_less;
}
- if (tarval_cmp(vrp_left->range_bottom, vrp_right->range_top) == pn_Cmp_Gt) {
- return pn_Cmp_Gt;
+ if (tarval_cmp(vrp_left->range_bottom, vrp_right->range_top) == ir_relation_greater) {
+ return ir_relation_greater;
}
}
if (!tarval_is_null(tarval_and(vrp_left->bits_set, tarval_not(vrp_right->bits_not_set))) ||
!tarval_is_null(tarval_and(tarval_not(vrp_left->bits_not_set), vrp_right->bits_set))) {
- return pn_Cmp_Lg;
+ return ir_relation_less_greater;
}
- /* TODO: We can get way more information here*/
- return pn_Cmp_False;
+ /* TODO: We can get way more information here*/
+ return ir_relation_true;
}
vrp_attr *vrp_get_info(const ir_node *node)
const ir_node *next_block;
const char *suffix;
const amd64_attr_t *attr = get_amd64_attr_const(irn);
- int proj_num = attr->ext.pnc;
+ ir_relation relation = attr->ext.relation;
ir_node *op1 = get_irn_n(irn, 0);
const amd64_attr_t *cmp_attr = get_amd64_attr_const(op1);
bool is_signed = !cmp_attr->data.cmp_unsigned;
}
if (cmp_attr->data.ins_permuted) {
- proj_num = get_mirrored_pnc(proj_num);
+ relation = get_inversed_relation(relation);
}
/* for now, the code works for scheduled and non-schedules blocks */
/* we have a block schedule */
next_block = sched_next_block(block);
- assert(proj_num != pn_Cmp_False);
- assert(proj_num != pn_Cmp_True);
+ assert(relation != ir_relation_false);
+ assert(relation != ir_relation_true);
if (get_cfop_target_block(proj_true) == next_block) {
/* exchange both proj's so the second one can be omitted */
proj_true = proj_false;
proj_false = t;
- proj_num = get_negated_pnc(proj_num, mode_Lu);
+ relation = get_negated_relation(relation);
}
- switch (proj_num) {
- case pn_Cmp_Eq: suffix = "e"; break;
- case pn_Cmp_Lt: suffix = is_signed ? "l" : "b"; break;
- case pn_Cmp_Le: suffix = is_signed ? "le" : "be"; break;
- case pn_Cmp_Gt: suffix = is_signed ? "g" : "a"; break;
- case pn_Cmp_Ge: suffix = is_signed ? "ge" : "ae"; break;
- case pn_Cmp_Lg: suffix = "ne"; break;
- case pn_Cmp_Leg: suffix = "mp"; break;
+ switch (relation) {
+ case ir_relation_equal: suffix = "e"; break;
+ case ir_relation_less: suffix = is_signed ? "l" : "b"; break;
+ case ir_relation_less_equal: suffix = is_signed ? "le" : "be"; break;
+ case ir_relation_greater: suffix = is_signed ? "g" : "a"; break;
+ case ir_relation_greater_equal: suffix = is_signed ? "ge" : "ae"; break;
+ case ir_relation_less_greater: suffix = "ne"; break;
+ case ir_relation_less_equal_greater: suffix = "mp"; break;
default: panic("Cmp has unsupported pnc");
}
attr->data.ins_permuted = 0;
attr->data.cmp_unsigned = 0;
- attr->ext.pnc = (pn_Cmp)0;
+ attr->ext.relation = ir_relation_false;
attr->ext.imm_value = 0;
}
unsigned cmp_unsigned : 1; /**< compare should be unsigned */
} data;
struct amd64_attr_extended {
- pn_Cmp pnc; /**< type of compare operation >*/
- unsigned imm_value; /**< immediate value to use >*/
+ ir_relation relation; /**< type of compare operation >*/
+ unsigned imm_value; /**< immediate value to use >*/
} ext;
};
reg_req => { in => [ "eflags" ], out => [ "none", "none" ] },
ins => [ "eflags" ],
outs => [ "false", "true" ],
- attr => "pn_Cmp pnc",
- init_attr => "attr->ext.pnc = pnc;",
+ attr => "ir_relation relation",
+ init_attr => "attr->ext.relation = relation;",
mode => "mode_T",
},
Load => {
*/
static ir_node *gen_Cond(ir_node *node)
{
- ir_node *selector = get_Cond_selector(node);
- ir_mode *mode = get_irn_mode(selector);
- ir_node *block;
- ir_node *flag_node;
- dbg_info *dbgi;
+ ir_node *selector = get_Cond_selector(node);
+ ir_mode *mode = get_irn_mode(selector);
+ ir_node *block;
+ ir_node *flag_node;
+ ir_relation relation;
+ dbg_info *dbgi;
if (mode != mode_b) {
panic ("create_Switch not implemented yet!");
// return gen_SwitchJmp(node);
}
- assert(is_Proj(selector));
+ assert(is_Cmp(selector));
block = be_transform_node(get_nodes_block(node));
dbgi = get_irn_dbg_info(node);
- flag_node = be_transform_node(get_Proj_pred(selector));
+ flag_node = be_transform_node(selector);
+ relation = get_Cmp_relation(selector);
- return new_bd_amd64_Jcc(dbgi, block, flag_node, get_Proj_pn_cmp(selector));
+ return new_bd_amd64_Jcc(dbgi, block, flag_node, relation);
}
#if 0
const ir_node *next_block;
ir_node *op1 = get_irn_n(irn, 0);
const char *suffix;
- pn_Cmp pnc = get_arm_CondJmp_pnc(irn);
+ ir_relation relation = get_arm_CondJmp_relation(irn);
const arm_cmp_attr_t *cmp_attr = get_arm_cmp_attr_const(op1);
bool is_signed = !cmp_attr->is_unsigned;
}
if (cmp_attr->ins_permuted) {
- pnc = get_mirrored_pnc(pnc);
+ relation = get_inversed_relation(relation);
}
/* for now, the code works for scheduled and non-schedules blocks */
/* we have a block schedule */
next_block = sched_next_block(block);
- assert(pnc != pn_Cmp_False);
- assert(pnc != pn_Cmp_True);
+ assert(relation != ir_relation_false);
+ assert(relation != ir_relation_true);
if (get_cfop_target_block(proj_true) == next_block) {
/* exchange both proj's so the second one can be omitted */
proj_true = proj_false;
proj_false = t;
- pnc = get_negated_pnc(pnc, mode_Iu);
+ relation = get_negated_relation(relation);
}
- switch (pnc) {
- case pn_Cmp_Eq: suffix = "eq"; break;
- case pn_Cmp_Lt: suffix = is_signed ? "lt" : "lo"; break;
- case pn_Cmp_Le: suffix = is_signed ? "le" : "ls"; break;
- case pn_Cmp_Gt: suffix = is_signed ? "gt" : "hi"; break;
- case pn_Cmp_Ge: suffix = is_signed ? "ge" : "hs"; break;
- case pn_Cmp_Lg: suffix = "ne"; break;
- case pn_Cmp_Leg: suffix = "al"; break;
- default: panic("Cmp has unsupported pnc");
+ switch (relation & (ir_relation_less_equal_greater)) {
+ case ir_relation_equal: suffix = "eq"; break;
+ case ir_relation_less: suffix = is_signed ? "lt" : "lo"; break;
+ case ir_relation_less_equal: suffix = is_signed ? "le" : "ls"; break;
+ case ir_relation_greater: suffix = is_signed ? "gt" : "hi"; break;
+ case ir_relation_greater_equal: suffix = is_signed ? "ge" : "hs"; break;
+ case ir_relation_less_greater: suffix = "ne"; break;
+ case ir_relation_less_equal_greater: suffix = "al"; break;
+ default: panic("Cmp has unsupported relation");
}
/* emit the true proj */
attr->tv = tv;
}
-pn_Cmp get_arm_CondJmp_pnc(const ir_node *node)
+ir_relation get_arm_CondJmp_relation(const ir_node *node)
{
const arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr_const(node);
- return attr->pnc;
+ return attr->relation;
}
-void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc)
+void set_arm_CondJmp_relation(ir_node *node, ir_relation relation)
{
arm_CondJmp_attr_t *attr = get_arm_CondJmp_attr(node);
- attr->pnc = pnc;
+ attr->relation = relation;
}
int get_arm_SwitchJmp_n_projs(const ir_node *node)
/**
* Returns the compare kind
*/
-pn_Cmp get_arm_CondJmp_pnc(const ir_node *node);
+ir_relation get_arm_CondJmp_relation(const ir_node *node);
/**
* Set compare type
*/
-void set_arm_CondJmp_pnc(ir_node *node, pn_Cmp pnc);
+void set_arm_CondJmp_relation(ir_node *node, ir_relation relation);
ir_node *new_r_arm_StoreStackMInc(ir_graph *irg, ir_node *block, ir_node *mem, ir_node *sp,
int n_regs, ir_node **regs, ir_mode *mode);
/** Attributes for a CondJmp */
typedef struct arm_CondJmp_attr_t {
arm_attr_t base;
- pn_Cmp pnc;
+ ir_relation relation;
} arm_CondJmp_attr_t;
/** Attributes for a SwitchJmp */
state => "pinned",
mode => "mode_T",
reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
- attr => "pn_Cmp pnc",
+ attr => "ir_relation relation",
attr_type => "arm_CondJmp_attr_t",
- init_attr => "\tset_arm_CondJmp_pnc(res, pnc);",
+ init_attr => "\tset_arm_CondJmp_relation(res, relation);",
},
Jmp => {
static ir_node *gen_Cond(ir_node *node)
{
- ir_node *selector = get_Cond_selector(node);
- ir_mode *mode = get_irn_mode(selector);
- ir_node *block;
- ir_node *flag_node;
- dbg_info *dbgi;
+ ir_node *selector = get_Cond_selector(node);
+ ir_mode *mode = get_irn_mode(selector);
+ ir_relation relation;
+ ir_node *block;
+ ir_node *flag_node;
+ dbg_info *dbgi;
if (mode != mode_b) {
return gen_SwitchJmp(node);
}
- assert(is_Proj(selector));
+ assert(is_Cmp(selector));
block = be_transform_node(get_nodes_block(node));
dbgi = get_irn_dbg_info(node);
- flag_node = be_transform_node(get_Proj_pred(selector));
+ flag_node = be_transform_node(selector);
+ relation = get_Cmp_relation(selector);
- return new_bd_arm_B(dbgi, block, flag_node, get_Proj_pn_cmp(selector));
+ return new_bd_arm_B(dbgi, block, flag_node, relation);
}
enum fpa_imm_mode {
#include "config.h"
#include "beemitter.h"
+#include "irnode_t.h"
#include "irprintf.h"
#include "ident.h"
#include "tv.h"
int be_mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false)
{
- ir_node *cmp_left;
- ir_node *cmp_right;
- ir_node *cmp;
- ir_mode *mode;
- pn_Cmp pnc;
+ ir_node *cmp_left;
+ ir_node *cmp_right;
+ ir_mode *mode;
+ ir_relation relation;
- if (!is_Proj(sel))
- return 0;
- cmp = get_Proj_pred(sel);
- if (!is_Cmp(cmp))
+ if (!is_Cmp(sel))
return 0;
/**
return 0;
/* must be <, <=, >=, > */
- pnc = get_Proj_pn_cmp(sel);
- switch (pnc) {
- case pn_Cmp_Ge:
- case pn_Cmp_Gt:
- case pn_Cmp_Le:
- case pn_Cmp_Lt:
- case pn_Cmp_Uge:
- case pn_Cmp_Ug:
- case pn_Cmp_Ul:
- case pn_Cmp_Ule:
- break;
- default:
+ relation = get_Cmp_relation(sel);
+ if ((relation & ir_relation_less_greater) == 0)
return 0;
- }
if (!is_negated_value(mux_true, mux_false))
return 0;
/* must be x cmp 0 */
- cmp_right = get_Cmp_right(cmp);
+ cmp_right = get_Cmp_right(sel);
if (!is_Const(cmp_right) || !is_Const_null(cmp_right))
return 0;
- cmp_left = get_Cmp_left(cmp);
+ cmp_left = get_Cmp_left(sel);
if (cmp_left == mux_false) {
- if (pnc & pn_Cmp_Lt) {
+ if (relation & ir_relation_less) {
return 1;
} else {
- assert(pnc & pn_Cmp_Gt);
+ assert(relation & ir_relation_greater);
return -1;
}
} else if (cmp_left == mux_true) {
- if (pnc & pn_Cmp_Lt) {
+ if (relation & ir_relation_less) {
return -1;
} else {
- assert(pnc & pn_Cmp_Gt);
+ assert(relation & ir_relation_greater);
return 1;
}
}
ir_node *be_get_abs_op(ir_node *sel)
{
- ir_node *cmp = get_Proj_pred(sel);
- ir_node *cmp_left = get_Cmp_left(cmp);
+ ir_node *cmp_left = get_Cmp_left(sel);
return cmp_left;
}
static bool mux_is_float_min_max(ir_node *sel, ir_node *mux_true,
ir_node *mux_false)
{
- ir_node *cmp_l;
- ir_node *cmp_r;
- ir_node *cmp;
- pn_Cmp pnc;
+ ir_node *cmp_l;
+ ir_node *cmp_r;
+ ir_relation relation;
- if (!is_Proj(sel))
- return false;
- cmp = get_Proj_pred(sel);
- if (!is_Cmp(cmp))
+ if (!is_Cmp(sel))
return false;
- cmp_l = get_Cmp_left(cmp);
- cmp_r = get_Cmp_right(cmp);
+ cmp_l = get_Cmp_left(sel);
+ cmp_r = get_Cmp_right(sel);
if (!mode_is_float(get_irn_mode(cmp_l)))
return false;
* or max(a, b) = a >= b ? a : b
* (Note we only handle float min/max here)
*/
- pnc = get_Proj_pn_cmp(sel);
- switch (pnc) {
- case pn_Cmp_Ge:
- case pn_Cmp_Gt:
+ relation = get_Cmp_relation(sel);
+ switch (relation) {
+ case ir_relation_greater_equal:
+ case ir_relation_greater:
/* this is a max */
if (cmp_l == mux_true && cmp_r == mux_false)
return true;
break;
- case pn_Cmp_Le:
- case pn_Cmp_Lt:
+ case ir_relation_less_equal:
+ case ir_relation_less:
/* this is a min */
if (cmp_l == mux_true && cmp_r == mux_false)
return true;
break;
- case pn_Cmp_Uge:
- case pn_Cmp_Ug:
+ case ir_relation_unordered_greater_equal:
+ case ir_relation_unordered_greater:
/* this is a min */
if (cmp_l == mux_false && cmp_r == mux_true)
return true;
break;
- case pn_Cmp_Ule:
- case pn_Cmp_Ul:
+ case ir_relation_unordered_less_equal:
+ case ir_relation_unordered_less:
/* this is a max */
if (cmp_l == mux_false && cmp_r == mux_true)
return true;
return false;
if (is_Const(mux_true) && is_Const(mux_false)) {
- /* we can create a set plus up two 3 instructions for any combination of constants */
+ /* we can create a set plus up two 3 instructions for any combination
+ * of constants */
return true;
}
static bool mux_is_doz(ir_node *sel, ir_node *mux_true, ir_node *mux_false)
{
- ir_node *cmp;
- ir_node *cmp_left;
- ir_node *cmp_right;
- ir_node *sub_left;
- ir_node *sub_right;
- ir_mode *mode;
- long pn;
-
- if (!is_Proj(sel))
- return false;
+ ir_node *cmp_left;
+ ir_node *cmp_right;
+ ir_node *sub_left;
+ ir_node *sub_right;
+ ir_mode *mode;
+ ir_relation relation;
- cmp = get_Proj_pred(sel);
- if (!is_Cmp(cmp))
+ if (!is_Cmp(sel))
return false;
mode = get_irn_mode(mux_true);
if (mode_is_signed(mode) || mode_is_float(mode))
return false;
- pn = get_Proj_proj(sel);
- cmp_left = get_Cmp_left(cmp);
- cmp_right = get_Cmp_right(cmp);
+ relation = get_Cmp_relation(sel);
+ cmp_left = get_Cmp_left(sel);
+ cmp_right = get_Cmp_right(sel);
/* "move" zero constant to false input */
if (is_Const(mux_true) && is_Const_null(mux_true)) {
ir_node *tmp = mux_false;
mux_false = mux_true;
mux_true = tmp;
- pn = get_negated_pnc(pn, mode);
+ relation = get_negated_relation(relation);
}
if (!is_Const(mux_false) || !is_Const_null(mux_false))
return false;
sub_right = get_Sub_right(mux_true);
/* Mux(a >=u b, 0, a-b) */
- if ((pn == pn_Cmp_Gt || pn == pn_Cmp_Ge)
+ if ((relation & ir_relation_greater)
&& sub_left == cmp_left && sub_right == cmp_right)
return true;
/* Mux(a <=u b, 0, b-a) */
- if ((pn == pn_Cmp_Lt || pn == pn_Cmp_Le)
+ if ((relation & ir_relation_less)
&& sub_left == cmp_right && sub_right == cmp_left)
return true;
/* the shift count is a const, create better code */
ir_tarval *tv = get_Const_tarval(cnt);
- if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
+ if (tarval_cmp(tv, new_tarval_from_long(32, l_mode))
+ & (ir_relation_greater_equal)) {
/* simplest case: shift only the lower bits. Note that there is no
need to reduce the constant here, this is done by the hardware. */
ir_node *conv = new_rd_Conv(dbg, block, a_l, h_mode);
c_mode = get_irn_mode(cnt);
irn = new_r_Const_long(irg, c_mode, 32);
irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
- irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
- irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
+ irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
cond = new_rd_Cond(dbg, upper, irn);
in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
/* the shift count is a const, create better code */
ir_tarval *tv = get_Const_tarval(cnt);
- if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
+ if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (ir_relation_greater_equal)) {
/* simplest case: shift only the higher bits. Note that there is no
need to reduce the constant here, this is done by the hardware. */
ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
c_mode = get_irn_mode(cnt);
irn = new_r_Const_long(irg, c_mode, 32);
irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
- irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
- irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
+ irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
cond = new_rd_Cond(dbg, upper, irn);
in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
/* the shift count is a const, create better code */
ir_tarval *tv = get_Const_tarval(cnt);
- if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
+ if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (ir_relation_greater_equal)) {
/* simplest case: shift only the higher bits. Note that there is no
need to reduce the constant here, this is done by the hardware. */
ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
c_mode = get_irn_mode(cnt);
irn = new_r_Const_long(irg, c_mode, 32);
irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
- irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
- irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
+ irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
cond = new_rd_Cond(dbg, upper, irn);
in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
part_block(call);
upper_blk = get_nodes_block(call);
- cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr);
- proj = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
- cond = new_rd_Cond(dbg, upper_blk, proj);
+ cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr, ir_relation_less);
+ cond = new_rd_Cond(dbg, upper_blk, cmp);
in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
blk = new_r_Block(irg, 1, &in[1]);
return new_bd_ia32_Bt(dbgi, new_block, op1, op2);
}
-static ia32_condition_code_t pnc_to_condition_code(pn_Cmp pnc, ir_mode *mode)
+static ia32_condition_code_t relation_to_condition_code(ir_relation relation,
+ ir_mode *mode)
{
if (mode_is_float(mode)) {
- switch (pnc) {
- case pn_Cmp_Eq: return ia32_cc_float_equal;
- case pn_Cmp_Lt: return ia32_cc_float_below;
- case pn_Cmp_Le: return ia32_cc_float_below_equal;
- case pn_Cmp_Gt: return ia32_cc_float_above;
- case pn_Cmp_Ge: return ia32_cc_float_above_equal;
- case pn_Cmp_Lg: return ia32_cc_not_equal;
- case pn_Cmp_Leg: return ia32_cc_not_parity;
- case pn_Cmp_Uo: return ia32_cc_parity;
- case pn_Cmp_Ue: return ia32_cc_equal;
- case pn_Cmp_Ul: return ia32_cc_float_unordered_below;
- case pn_Cmp_Ule: return ia32_cc_float_unordered_below_equal;
- case pn_Cmp_Ug: return ia32_cc_float_unordered_above;
- case pn_Cmp_Uge: return ia32_cc_float_unordered_above_equal;
- case pn_Cmp_Ne: return ia32_cc_float_not_equal;
- case pn_Cmp_False:
- case pn_Cmp_True:
- case pn_Cmp_max:
+ switch (relation) {
+ case ir_relation_equal: return ia32_cc_float_equal;
+ case ir_relation_less: return ia32_cc_float_below;
+ case ir_relation_less_equal: return ia32_cc_float_below_equal;
+ case ir_relation_greater: return ia32_cc_float_above;
+ case ir_relation_greater_equal: return ia32_cc_float_above_equal;
+ case ir_relation_less_greater: return ia32_cc_not_equal;
+ case ir_relation_less_equal_greater: return ia32_cc_not_parity;
+ case ir_relation_unordered: return ia32_cc_parity;
+ case ir_relation_unordered_equal: return ia32_cc_equal;
+ case ir_relation_unordered_less: return ia32_cc_float_unordered_below;
+ case ir_relation_unordered_less_equal:
+ return ia32_cc_float_unordered_below_equal;
+ case ir_relation_unordered_greater:
+ return ia32_cc_float_unordered_above;
+ case ir_relation_unordered_greater_equal:
+ return ia32_cc_float_unordered_above_equal;
+ case ir_relation_unordered_less_greater:
+ return ia32_cc_float_not_equal;
+ case ir_relation_false:
+ case ir_relation_true:
/* should we introduce a jump always/jump never? */
break;
}
panic("Unexpected float pnc");
} else if (mode_is_signed(mode)) {
- switch (pnc) {
- case pn_Cmp_Ue:
- case pn_Cmp_Eq: return ia32_cc_equal;
- case pn_Cmp_Ul:
- case pn_Cmp_Lt: return ia32_cc_less;
- case pn_Cmp_Ule:
- case pn_Cmp_Le: return ia32_cc_less_equal;
- case pn_Cmp_Ug:
- case pn_Cmp_Gt: return ia32_cc_greater;
- case pn_Cmp_Uge:
- case pn_Cmp_Ge: return ia32_cc_greater_equal;
- case pn_Cmp_Lg:
- case pn_Cmp_Ne: return ia32_cc_not_equal;
- case pn_Cmp_Leg:
- case pn_Cmp_Uo:
- case pn_Cmp_False:
- case pn_Cmp_True:
- case pn_Cmp_max:
+ switch (relation) {
+ case ir_relation_unordered_equal:
+ case ir_relation_equal: return ia32_cc_equal;
+ case ir_relation_unordered_less:
+ case ir_relation_less: return ia32_cc_less;
+ case ir_relation_unordered_less_equal:
+ case ir_relation_less_equal: return ia32_cc_less_equal;
+ case ir_relation_unordered_greater:
+ case ir_relation_greater: return ia32_cc_greater;
+ case ir_relation_unordered_greater_equal:
+ case ir_relation_greater_equal: return ia32_cc_greater_equal;
+ case ir_relation_unordered_less_greater:
+ case ir_relation_less_greater: return ia32_cc_not_equal;
+ case ir_relation_less_equal_greater:
+ case ir_relation_unordered:
+ case ir_relation_false:
+ case ir_relation_true:
/* introduce jump always/jump never? */
break;
}
panic("Unexpected pnc");
} else {
- switch (pnc) {
- case pn_Cmp_Ue:
- case pn_Cmp_Eq: return ia32_cc_equal;
- case pn_Cmp_Ul:
- case pn_Cmp_Lt: return ia32_cc_below;
- case pn_Cmp_Ule:
- case pn_Cmp_Le: return ia32_cc_below_equal;
- case pn_Cmp_Ug:
- case pn_Cmp_Gt: return ia32_cc_above;
- case pn_Cmp_Uge:
- case pn_Cmp_Ge: return ia32_cc_above_equal;
- case pn_Cmp_Lg:
- case pn_Cmp_Ne: return ia32_cc_not_equal;
- case pn_Cmp_Leg:
- case pn_Cmp_Uo:
- case pn_Cmp_False:
- case pn_Cmp_True:
- case pn_Cmp_max:
+ switch (relation) {
+ case ir_relation_unordered_equal:
+ case ir_relation_equal: return ia32_cc_equal;
+ case ir_relation_unordered_less:
+ case ir_relation_less: return ia32_cc_below;
+ case ir_relation_unordered_less_equal:
+ case ir_relation_less_equal: return ia32_cc_below_equal;
+ case ir_relation_unordered_greater:
+ case ir_relation_greater: return ia32_cc_above;
+ case ir_relation_unordered_greater_equal:
+ case ir_relation_greater_equal: return ia32_cc_above_equal;
+ case ir_relation_unordered_less_greater:
+ case ir_relation_less_greater: return ia32_cc_not_equal;
+ case ir_relation_less_equal_greater:
+ case ir_relation_unordered:
+ case ir_relation_false:
+ case ir_relation_true:
/* introduce jump always/jump never? */
break;
}
return flags;
}
-static ir_node *get_flags_node_cmp(ir_node *node, ia32_condition_code_t *cc_out)
+static ir_node *get_flags_node_cmp(ir_node *cmp, ia32_condition_code_t *cc_out)
{
- /* must have a Proj(Cmp) as input */
- ir_node *cmp = get_Proj_pred(node);
- int pnc = get_Proj_pn_cmp(node);
- ir_node *l = get_Cmp_left(cmp);
- ir_mode *mode = get_irn_mode(l);
- ir_node *flags;
+ /* must have a Cmp as input */
+ ir_relation relation = get_Cmp_relation(cmp);
+ ir_node *l = get_Cmp_left(cmp);
+ ir_mode *mode = get_irn_mode(l);
+ ir_node *flags;
/* check for bit-test */
- if (ia32_cg_config.use_bt
- && (pnc == pn_Cmp_Eq
- || (mode_is_signed(mode) && pnc == pn_Cmp_Lg)
- || (!mode_is_signed(mode) && (pnc & pn_Cmp_Ge) == pn_Cmp_Gt))) {
+ if (ia32_cg_config.use_bt && (relation == ir_relation_equal
+ || (mode_is_signed(mode) && relation == ir_relation_less_greater)
+ || (!mode_is_signed(mode) && ((relation & ir_relation_greater_equal) == ir_relation_greater)))) {
ir_node *l = get_Cmp_left(cmp);
ir_node *r = get_Cmp_right(cmp);
if (is_And(l)) {
ir_node *n = get_Shl_right(la);
flags = gen_bt(cmp, ra, n);
/* the bit is copied into the CF flag */
- if (pnc & pn_Cmp_Eq)
+ if (relation & ir_relation_equal)
*cc_out = ia32_cc_above_equal; /* test for CF=0 */
else
*cc_out = ia32_cc_below; /* test for CF=1 */
}
/* just do a normal transformation of the Cmp */
- *cc_out = pnc_to_condition_code(pnc, mode);
+ *cc_out = relation_to_condition_code(relation, mode);
flags = be_transform_node(cmp);
return flags;
}
*/
static ir_node *get_flags_node(ir_node *node, ia32_condition_code_t *cc_out)
{
- if (is_Proj(node) && is_Cmp(get_Proj_pred(node)))
+ if (is_Cmp(node))
return get_flags_node_cmp(node, cc_out);
assert(get_irn_mode(node) == mode_b);
return get_flags_mode_b(node, cc_out);
static ir_node *gen_Load(ir_node *node)
{
ir_node *old_block = get_nodes_block(node);
- ir_node *block = be_transform_node(old_block);
- ir_node *ptr = get_Load_ptr(node);
- ir_node *mem = get_Load_mem(node);
- ir_node *new_mem = be_transform_node(mem);
+ ir_node *block = be_transform_node(old_block);
+ ir_node *ptr = get_Load_ptr(node);
+ ir_node *mem = get_Load_mem(node);
+ ir_node *new_mem = be_transform_node(mem);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_mode *mode = get_Load_mode(node);
ir_node *base;
ir_node *index;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_Load_mode(node);
ir_node *new_node;
ia32_address_t addr;
return new_node;
}
-/**
- * helper function: checks whether all Cmp projs are Lg or Eq which is needed
- * to fold an and into a test node
- */
-static bool can_fold_test_and(ir_node *node)
-{
- const ir_edge_t *edge;
-
- /** we can only have eq and lg projs */
- foreach_out_edge(node, edge) {
- ir_node *proj = get_edge_src_irn(edge);
- pn_Cmp pnc = get_Proj_pn_cmp(proj);
- if (pnc != pn_Cmp_Eq && pnc != pn_Cmp_Lg)
- return false;
- }
-
- return true;
-}
-
/**
* returns true if it is assured, that the upper bits of a node are "clean"
* which means for a 16 or 8 bit value, that the upper bits in the register
/* Prefer the Test instruction, when encountering (x & y) ==/!= 0 */
if (is_Const_0(right) &&
is_And(left) &&
- get_irn_n_edges(left) == 1 &&
- can_fold_test_and(node)) {
+ get_irn_n_edges(left) == 1) {
/* Test(and_left, and_right) */
ir_node *and_left = get_And_left(left);
ir_node *and_right = get_And_right(left);
if (is_Proj(new_node)) {
sub = get_Proj_pred(new_node);
- assert(is_ia32_Sub(sub));
} else {
sub = new_node;
set_irn_mode(sub, mode_T);
new_node = new_rd_Proj(NULL, sub, mode, pn_ia32_res);
}
+ assert(is_ia32_Sub(sub));
eflags = new_rd_Proj(NULL, sub, mode_Iu, pn_ia32_Sub_flags);
dbgi = get_irn_dbg_info(psi);
t = f;
f = tmp;
cc = ia32_negate_condition_code(cc);
- } else if (tarval_cmp(t, f) == pn_Cmp_Lt) {
+ } else if (tarval_cmp(t, f) == ir_relation_less) {
// now, t is the bigger one
ir_tarval *tmp = t;
t = f;
ir_node *new_block = be_transform_node(block);
ir_node *mux_true = get_Mux_true(node);
ir_node *mux_false = get_Mux_false(node);
- ir_node *cond = get_Mux_sel(node);
+ ir_node *sel = get_Mux_sel(node);
ir_mode *mode = get_irn_mode(node);
ir_node *flags;
ir_node *new_node;
int is_abs;
ia32_condition_code_t cc;
- assert(get_irn_mode(cond) == mode_b);
+ assert(get_irn_mode(sel) == mode_b);
- is_abs = be_mux_is_abs(cond, mux_true, mux_false);
+ is_abs = be_mux_is_abs(sel, mux_true, mux_false);
if (is_abs != 0) {
- return create_abs(dbgi, block, be_get_abs_op(cond), is_abs < 0, node);
+ return create_abs(dbgi, block, be_get_abs_op(sel), is_abs < 0, node);
}
/* Note: a Mux node uses a Load two times IFF it's used in the compare AND in the result */
if (mode_is_float(mode)) {
- ir_node *cmp = get_Proj_pred(cond);
- ir_node *cmp_left = get_Cmp_left(cmp);
- ir_node *cmp_right = get_Cmp_right(cmp);
- int pnc = get_Proj_proj(cond);
+ ir_node *cmp_left = get_Cmp_left(sel);
+ ir_node *cmp_right = get_Cmp_right(sel);
+ ir_relation relation = get_Cmp_relation(sel);
if (ia32_cg_config.use_sse2) {
- if (pnc == pn_Cmp_Lt || pnc == pn_Cmp_Le) {
+ if (relation == ir_relation_less || relation == ir_relation_less_equal) {
if (cmp_left == mux_true && cmp_right == mux_false) {
/* Mux(a <= b, a, b) => MIN */
return gen_binop(node, cmp_left, cmp_right, new_bd_ia32_xMin,
return gen_binop(node, cmp_left, cmp_right, new_bd_ia32_xMax,
match_commutative | match_am | match_two_users);
}
- } else if (pnc == pn_Cmp_Gt || pnc == pn_Cmp_Ge) {
+ } else if (relation == ir_relation_greater || relation == ir_relation_greater_equal) {
if (cmp_left == mux_true && cmp_right == mux_false) {
/* Mux(a >= b, a, b) => MAX */
return gen_binop(node, cmp_left, cmp_right, new_bd_ia32_xMax,
ir_mode *new_mode;
unsigned scale;
- flags = get_flags_node(cond, &cc);
+ flags = get_flags_node(sel, &cc);
new_node = create_set_32bit(dbgi, new_block, flags, cc, node);
if (ia32_cg_config.use_sse2) {
} else {
assert(ia32_mode_needs_gp_reg(mode));
- if (is_Proj(cond)) {
- ir_node *cmp = get_Proj_pred(cond);
- if (is_Cmp(cmp)) {
- ir_node *cmp_left = get_Cmp_left(cmp);
- ir_node *cmp_right = get_Cmp_right(cmp);
- ir_node *val_true = mux_true;
- ir_node *val_false = mux_false;
- int pnc = get_Proj_proj(cond);
-
- if (is_Const(val_true) && is_Const_null(val_true)) {
- ir_node *tmp = val_false;
- val_false = val_true;
- val_true = tmp;
- pnc = get_negated_pnc(pnc, get_irn_mode(cmp_left));
+ if (is_Cmp(sel)) {
+ ir_node *cmp_left = get_Cmp_left(sel);
+ ir_node *cmp_right = get_Cmp_right(sel);
+ ir_relation relation = get_Cmp_relation(sel);
+ ir_node *val_true = mux_true;
+ ir_node *val_false = mux_false;
+
+ if (is_Const(val_true) && is_Const_null(val_true)) {
+ ir_node *tmp = val_false;
+ val_false = val_true;
+ val_true = tmp;
+ relation = get_negated_relation(relation);
+ }
+ if (is_Const_0(val_false) && is_Sub(val_true)) {
+ if ((relation & ir_relation_greater)
+ && get_Sub_left(val_true) == cmp_left
+ && get_Sub_right(val_true) == cmp_right) {
+ return create_doz(node, cmp_left, cmp_right);
}
- if (is_Const_0(val_false) && is_Sub(val_true)) {
- if ((pnc == pn_Cmp_Gt || pnc == pn_Cmp_Ge)
- && get_Sub_left(val_true) == cmp_left
- && get_Sub_right(val_true) == cmp_right) {
- return create_doz(node, cmp_left, cmp_right);
- }
- if ((pnc == pn_Cmp_Lt || pnc == pn_Cmp_Le)
- && get_Sub_left(val_true) == cmp_right
- && get_Sub_right(val_true) == cmp_left) {
- return create_doz(node, cmp_right, cmp_left);
- }
+ if ((relation & ir_relation_less)
+ && get_Sub_left(val_true) == cmp_right
+ && get_Sub_right(val_true) == cmp_left) {
+ return create_doz(node, cmp_right, cmp_left);
}
}
}
- flags = get_flags_node(cond, &cc);
+ flags = get_flags_node(sel, &cc);
if (is_Const(mux_true) && is_Const(mux_false)) {
/* both are const, good */
}
}
} else {
- new_node = create_CMov(node, cond, flags, cc);
+ new_node = create_CMov(node, sel, flags, cc);
}
return new_node;
}
ir_node *signed_x = new_rd_Conv(dbgi, block, unsigned_x, mode_s);
ir_node *res = new_rd_Conv(dbgi, block, signed_x, mode_d);
ir_node *zero = new_r_Const(irg, get_mode_null(mode_s));
- ir_node *cmp = new_rd_Cmp(dbgi, block, signed_x, zero);
- ir_node *proj_lt = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
- ir_node *cond = new_rd_Cond(dbgi, block, proj_lt);
+ ir_node *cmp = new_rd_Cmp(dbgi, block, signed_x, zero,
+ ir_relation_less);
+ ir_node *cond = new_rd_Cond(dbgi, block, cmp);
ir_node *proj_true = new_r_Proj(cond, mode_X, pn_Cond_true);
ir_node *proj_false = new_r_Proj(cond, mode_X, pn_Cond_false);
ir_node *in_true[1] = { proj_true };
be_emit_finish_line_gas(node);
}
-static const char *get_icc_unsigned(pn_Cmp pnc)
+static const char *get_icc_unsigned(ir_relation relation)
{
- switch (pnc) {
- case pn_Cmp_False: return "bn";
- case pn_Cmp_Eq: return "be";
- case pn_Cmp_Lt: return "blu";
- case pn_Cmp_Le: return "bleu";
- case pn_Cmp_Gt: return "bgu";
- case pn_Cmp_Ge: return "bgeu";
- case pn_Cmp_Lg: return "bne";
- case pn_Cmp_Leg: return "ba";
- default: panic("Cmp has unsupported pnc");
+ switch (relation & (ir_relation_less_equal_greater)) {
+ case ir_relation_false: return "bn";
+ case ir_relation_equal: return "be";
+ case ir_relation_less: return "blu";
+ case ir_relation_less_equal: return "bleu";
+ case ir_relation_greater: return "bgu";
+ case ir_relation_greater_equal: return "bgeu";
+ case ir_relation_less_greater: return "bne";
+ case ir_relation_less_equal_greater: return "ba";
+ default: panic("Cmp has unsupported relation");
}
}
-static const char *get_icc_signed(pn_Cmp pnc)
+static const char *get_icc_signed(ir_relation relation)
{
- switch (pnc) {
- case pn_Cmp_False: return "bn";
- case pn_Cmp_Eq: return "be";
- case pn_Cmp_Lt: return "bl";
- case pn_Cmp_Le: return "ble";
- case pn_Cmp_Gt: return "bg";
- case pn_Cmp_Ge: return "bge";
- case pn_Cmp_Lg: return "bne";
- case pn_Cmp_Leg: return "ba";
- default: panic("Cmp has unsupported pnc");
+ switch (relation & (ir_relation_less_equal_greater)) {
+ case ir_relation_false: return "bn";
+ case ir_relation_equal: return "be";
+ case ir_relation_less: return "bl";
+ case ir_relation_less_equal: return "ble";
+ case ir_relation_greater: return "bg";
+ case ir_relation_greater_equal: return "bge";
+ case ir_relation_less_greater: return "bne";
+ case ir_relation_less_equal_greater: return "ba";
+ default: panic("Cmp has unsupported relation");
}
}
-static const char *get_fcc(pn_Cmp pnc)
+static const char *get_fcc(ir_relation relation)
{
- switch (pnc) {
- case pn_Cmp_False: return "fbn";
- case pn_Cmp_Eq: return "fbe";
- case pn_Cmp_Lt: return "fbl";
- case pn_Cmp_Le: return "fble";
- case pn_Cmp_Gt: return "fbg";
- case pn_Cmp_Ge: return "fbge";
- case pn_Cmp_Lg: return "fblg";
- case pn_Cmp_Leg: return "fbo";
- case pn_Cmp_Uo: return "fbu";
- case pn_Cmp_Ue: return "fbue";
- case pn_Cmp_Ul: return "fbul";
- case pn_Cmp_Ule: return "fbule";
- case pn_Cmp_Ug: return "fbug";
- case pn_Cmp_Uge: return "fbuge";
- case pn_Cmp_Ne: return "fbne";
- case pn_Cmp_True: return "fba";
- case pn_Cmp_max:
- break;
+ switch (relation) {
+ case ir_relation_false: return "fbn";
+ case ir_relation_equal: return "fbe";
+ case ir_relation_less: return "fbl";
+ case ir_relation_less_equal: return "fble";
+ case ir_relation_greater: return "fbg";
+ case ir_relation_greater_equal: return "fbge";
+ case ir_relation_less_greater: return "fblg";
+ case ir_relation_less_equal_greater: return "fbo";
+ case ir_relation_unordered: return "fbu";
+ case ir_relation_unordered_equal: return "fbue";
+ case ir_relation_unordered_less: return "fbul";
+ case ir_relation_unordered_less_equal: return "fbule";
+ case ir_relation_unordered_greater: return "fbug";
+ case ir_relation_unordered_greater_equal: return "fbuge";
+ case ir_relation_unordered_less_greater: return "fbne";
+ case ir_relation_true: return "fba";
}
- panic("invalid pnc");
+ panic("invalid relation");
}
-typedef const char* (*get_cc_func)(pn_Cmp pnc);
+typedef const char* (*get_cc_func)(ir_relation relation);
static void emit_sparc_branch(const ir_node *node, get_cc_func get_cc)
{
const sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr_const(node);
- pn_Cmp pnc = attr->pnc;
+ ir_relation relation = attr->relation;
const ir_node *proj_true = NULL;
const ir_node *proj_false = NULL;
const ir_edge_t *edge;
proj_true = proj_false;
proj_false = t;
- if (is_sparc_fbfcc(node)) {
- pnc = get_negated_pnc(pnc, mode_F);
- } else {
- pnc = get_negated_pnc(pnc, mode_Iu);
- }
+ relation = get_negated_relation(relation);
}
/* emit the true proj */
be_emit_cstring("\t");
- be_emit_string(get_cc(pnc));
+ be_emit_string(get_cc(relation));
be_emit_char(' ');
sparc_emit_cfop_target(proj_true);
be_emit_finish_line_gas(proj_true);
if (has_jmp_cond_attr(n)) {
const sparc_jmp_cond_attr_t *attr
= get_sparc_jmp_cond_attr_const(n);
- fprintf(F, "pnc: %d (%s)\n", attr->pnc, get_pnc_string(attr->pnc));
+ fprintf(F, "relation: %d (%s)\n", attr->relation,
+ get_relation_string(attr->relation));
fprintf(F, "unsigned: %s\n", attr->is_unsigned ? "true" : "false");
}
if (has_switch_jmp_attr(n)) {
attr->immediate_value = immediate_value;
}
-static void init_sparc_jmp_cond_attr(ir_node *node, pn_Cmp pnc, bool is_unsigned)
+static void init_sparc_jmp_cond_attr(ir_node *node, ir_relation relation,
+ bool is_unsigned)
{
sparc_jmp_cond_attr_t *attr = get_sparc_jmp_cond_attr(node);
- attr->pnc = pnc;
+ attr->relation = relation;
attr->is_unsigned = is_unsigned;
}
if (cmp_attr_sparc(a, b))
return 1;
- return attr_a->pnc != attr_b->pnc
+ return attr_a->relation != attr_b->relation
|| attr_a->is_unsigned != attr_b->is_unsigned;
}
typedef struct sparc_jmp_cond_attr_t sparc_jmp_cond_attr_t;
struct sparc_jmp_cond_attr_t {
sparc_attr_t base; /**< generic attribute */
- pn_Cmp pnc;
+ ir_relation relation;
bool is_unsigned : 1;
};
state => "pinned",
mode => "mode_T",
attr_type => "sparc_jmp_cond_attr_t",
- attr => "pn_Cmp pnc, bool is_unsigned",
- init_attr => "\tinit_sparc_jmp_cond_attr(res, pnc, is_unsigned);",
+ attr => "ir_relation relation, bool is_unsigned",
+ init_attr => "\tinit_sparc_jmp_cond_attr(res, relation, is_unsigned);",
reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
},
state => "pinned",
mode => "mode_T",
attr_type => "sparc_jmp_cond_attr_t",
- attr => "pn_Cmp pnc",
- init_attr => "\tinit_sparc_jmp_cond_attr(res, pnc, false);",
+ attr => "ir_relation relation",
+ init_attr => "\tinit_sparc_jmp_cond_attr(res, relation, false);",
reg_req => { in => [ "fpflags" ], out => [ "none", "none" ] },
},
static ir_mode *get_cmp_mode(ir_node *b_value)
{
- ir_node *pred;
ir_node *op;
- if (!is_Proj(b_value))
- panic("can't determine cond signednes");
- pred = get_Proj_pred(b_value);
- if (!is_Cmp(pred))
+ if (!is_Cmp(b_value))
panic("can't determine cond signednes (no cmp)");
- op = get_Cmp_left(pred);
+ op = get_Cmp_left(b_value);
return get_irn_mode(op);
}
static ir_node *gen_Cond(ir_node *node)
{
- ir_node *selector = get_Cond_selector(node);
- ir_mode *mode = get_irn_mode(selector);
- ir_mode *cmp_mode;
- ir_node *block;
- ir_node *flag_node;
- bool is_unsigned;
- pn_Cmp pnc;
- dbg_info *dbgi;
+ ir_node *selector = get_Cond_selector(node);
+ ir_mode *mode = get_irn_mode(selector);
+ ir_mode *cmp_mode;
+ ir_node *block;
+ ir_node *flag_node;
+ bool is_unsigned;
+ ir_relation relation;
+ dbg_info *dbgi;
// switch/case jumps
if (mode != mode_b) {
}
// regular if/else jumps
- assert(is_Proj(selector));
- assert(is_Cmp(get_Proj_pred(selector)));
+ assert(is_Cmp(selector));
cmp_mode = get_cmp_mode(selector);
block = be_transform_node(get_nodes_block(node));
dbgi = get_irn_dbg_info(node);
flag_node = be_transform_node(get_Proj_pred(selector));
- pnc = get_Proj_pn_cmp(selector);
+ relation = get_Cmp_relation(selector);
is_unsigned = !mode_is_signed(cmp_mode);
if (mode_is_float(cmp_mode)) {
assert(!is_unsigned);
- return new_bd_sparc_fbfcc(dbgi, block, flag_node, pnc);
+ return new_bd_sparc_fbfcc(dbgi, block, flag_node, relation);
} else {
- return new_bd_sparc_Bicc(dbgi, block, flag_node, pnc, is_unsigned);
+ return new_bd_sparc_Bicc(dbgi, block, flag_node, relation, is_unsigned);
}
}
int bits = get_mode_size_bits(u_mode);
int p;
ir_tarval *ad, *anc, *delta, *q1, *r1, *q2, *r2, *t; /* unsigned */
- pn_Cmp d_cmp, M_cmp;
+ ir_relation d_cmp, M_cmp;
ir_tarval *bits_minus_1, *two_bits_1;
q1 = ADD(q1, q1); /* Update q1 = 2^p/|nc| */
r1 = ADD(r1, r1); /* Update r1 = rem(2^p, |nc|) */
- if (CMP(r1, anc) & pn_Cmp_Ge) {
+ if (CMP(r1, anc) & ir_relation_greater_equal) {
q1 = ADD(q1, ONE(u_mode));
r1 = SUB(r1, anc);
}
q2 = ADD(q2, q2); /* Update q2 = 2^p/|d| */
r2 = ADD(r2, r2); /* Update r2 = rem(2^p, |d|) */
- if (CMP(r2, ad) & pn_Cmp_Ge) {
+ if (CMP(r2, ad) & ir_relation_greater_equal) {
q2 = ADD(q2, ONE(u_mode));
r2 = SUB(r2, ad);
}
delta = SUB(ad, r2);
- } while (CMP(q1, delta) & pn_Cmp_Lt || (CMP(q1, delta) & pn_Cmp_Eq && CMP(r1, ZERO(u_mode)) & pn_Cmp_Eq));
+ } while (CMP(q1, delta) & ir_relation_less || (CMP(q1, delta) & ir_relation_equal && CMP(r1, ZERO(u_mode)) & ir_relation_equal));
d_cmp = CMP(d, ZERO(mode));
- if (d_cmp & pn_Cmp_Ge)
+ if (d_cmp & ir_relation_greater_equal)
mag.M = ADD(CNV(q2, mode), ONE(mode));
else
mag.M = SUB(ZERO(mode), ADD(CNV(q2, mode), ONE(mode)));
mag.s = p - bits;
/* need an add if d > 0 && M < 0 */
- mag.need_add = d_cmp & pn_Cmp_Gt && M_cmp & pn_Cmp_Lt;
+ mag.need_add = d_cmp & ir_relation_greater && M_cmp & ir_relation_less;
/* need a sub if d < 0 && M > 0 */
- mag.need_sub = d_cmp & pn_Cmp_Lt && M_cmp & pn_Cmp_Gt;
+ mag.need_sub = d_cmp & ir_relation_less && M_cmp & ir_relation_greater;
tarval_set_integer_overflow_mode(rem);
do {
++p;
- if (CMP(r1, SUB(nc, r1)) & pn_Cmp_Ge) {
+ if (CMP(r1, SUB(nc, r1)) & ir_relation_greater_equal) {
q1 = ADD(ADD(q1, q1), ONE(mode));
r1 = SUB(ADD(r1, r1), nc);
}
r1 = ADD(r1, r1);
}
- if (CMP(ADD(r2, ONE(mode)), SUB(d, r2)) & pn_Cmp_Ge) {
- if (CMP(q2, seven_ff) & pn_Cmp_Ge)
+ if (CMP(ADD(r2, ONE(mode)), SUB(d, r2)) & ir_relation_greater_equal) {
+ if (CMP(q2, seven_ff) & ir_relation_greater_equal)
magu.need_add = 1;
q2 = ADD(ADD(q2, q2), ONE(mode));
r2 = SUB(ADD(ADD(r2, r2), ONE(mode)), d);
}
else {
- if (CMP(q2, two_bits_1) & pn_Cmp_Ge)
+ if (CMP(q2, two_bits_1) & ir_relation_greater_equal)
magu.need_add = 1;
q2 = ADD(q2, q2);
}
delta = SUB(SUB(d, ONE(mode)), r2);
} while (p < 2*bits &&
- (CMP(q1, delta) & pn_Cmp_Lt || (CMP(q1, delta) & pn_Cmp_Eq && CMP(r1, ZERO(mode)) & pn_Cmp_Eq)));
+ (CMP(q1, delta) & ir_relation_less || (CMP(q1, delta) & ir_relation_equal && CMP(r1, ZERO(mode)) & ir_relation_equal)));
magu.M = ADD(q2, ONE(mode)); /* Magic number */
magu.s = p - bits; /* and shift amount */
} else if (is_Sel(node)) {
snprintf(buf, sizeof(buf), "%s%s %s[%s]", A("irn"), get_irn_opname(node),
get_mode_name(get_irn_mode(node)), get_entity_name(get_Sel_entity(node)));
+ } else if (is_Cmp(node)) {
+ ir_relation relation = get_Cmp_relation(node);
+ snprintf(buf, sizeof(buf), "%s%s %s", A("irn"), get_irn_opname(node), get_relation_string(relation));
} else {
snprintf(buf, sizeof(buf), "%s%s %s", A("irn"), get_irn_opname(node),
get_mode_name(get_irn_mode(node)));
const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
{
int value = arg->v_int;
- const char *p = get_pnc_string(value);
+ const char *p = get_relation_string(value);
return lc_arg_append(app, occ, p, strlen(p));
}
proj_nr = get_Proj_proj(n);
code = get_irn_opcode(pred);
- if (code == iro_Cmp)
- fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
- else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
+ if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
fprintf(F, "Arg %ld ", proj_nr);
else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
fprintf(F, "%ld ", proj_nr);
case iro_Cast:
ir_fprintf(F, "(%+F)", get_Cast_type(n));
break;
+ case iro_Cmp:
+ fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
+ break;
case iro_Confirm:
- fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
+ fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
break;
case iro_CopyB:
ir_fprintf(F, "(%+F)", get_CopyB_type(n));
case iro_Cast: {
ir_fprintf(F, " cast to type: %+F\n", get_Cast_type(n));
} break;
+ case iro_Cmp: {
+ ir_relation relation = get_Cmp_relation(n);
+ ir_fprintf(F, " relation: %s\n", get_relation_string(relation));
+ } break;
case iro_Return: {
size_t i;
ir_type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
fprintf(F, " align: %s\n", get_align_name(get_Store_align(n)));
break;
case iro_Confirm:
- fprintf(F, " compare operation: %s\n", get_pnc_string(get_Confirm_cmp(n)));
+ fprintf(F, " compare operation: %s\n", get_relation_string(get_Confirm_relation(n)));
break;
case iro_ASM: {
const ir_asm_constraint *cons;
#include "irhooks.h"
#include "irtools.h"
+#include "util.h"
#include "beinfo.h"
#define RETURN_RESULT_OFFSET 1 /* mem is not a result */
#define END_KEEPALIVE_OFFSET 0
-static const char *pnc_name_arr [] = {
- "pn_Cmp_False", "pn_Cmp_Eq", "pn_Cmp_Lt", "pn_Cmp_Le",
- "pn_Cmp_Gt", "pn_Cmp_Ge", "pn_Cmp_Lg", "pn_Cmp_Leg",
- "pn_Cmp_Uo", "pn_Cmp_Ue", "pn_Cmp_Ul", "pn_Cmp_Ule",
- "pn_Cmp_Ug", "pn_Cmp_Uge", "pn_Cmp_Ne", "pn_Cmp_True"
+static const char *relation_names [] = {
+ "false",
+ "equal",
+ "less",
+ "less_equal",
+ "greater",
+ "greater_equal",
+ "less_greater",
+ "less_equal_greater",
+ "unordered",
+ "unordered_equal",
+ "unordered_less",
+ "unordered_less_equal",
+ "unordered_greater",
+ "unordered_greater_equal",
+ "not_equal",
+ "true"
};
-/**
- * returns the pnc name from an pnc constant
- */
-const char *get_pnc_string(int pnc)
+const char *get_relation_string(ir_relation relation)
{
- assert(pnc >= 0 && pnc <
- (int) (sizeof(pnc_name_arr)/sizeof(pnc_name_arr[0])));
- return pnc_name_arr[pnc];
+ assert(relation < (ir_relation)ARRAY_SIZE(relation_names));
+ return relation_names[relation];
}
-/*
- * Calculates the negated (Complement(R)) pnc condition.
- */
-pn_Cmp get_negated_pnc(long pnc, ir_mode *mode)
+ir_relation get_negated_relation(ir_relation relation)
{
- pnc ^= pn_Cmp_True;
-
- /* do NOT add the Uo bit for non-floating point values */
- if (! mode_is_float(mode))
- pnc &= ~pn_Cmp_Uo;
-
- return (pn_Cmp) pnc;
+ return relation ^ ir_relation_true;
}
-/* Calculates the inversed (R^-1) pnc condition, i.e., "<" --> ">" */
-pn_Cmp get_inversed_pnc(long pnc)
+ir_relation get_inversed_relation(ir_relation relation)
{
- long code = pnc & ~(pn_Cmp_Lt|pn_Cmp_Gt);
- long lesser = pnc & pn_Cmp_Lt;
- long greater = pnc & pn_Cmp_Gt;
-
- code |= (lesser ? pn_Cmp_Gt : 0) | (greater ? pn_Cmp_Lt : 0);
-
- return (pn_Cmp) code;
+ ir_relation code = relation & ~(ir_relation_less|ir_relation_greater);
+ bool less = relation & ir_relation_less;
+ bool greater = relation & ir_relation_greater;
+ code |= (less ? ir_relation_greater : 0) | (greater ? ir_relation_less : 0);
+ return code;
}
/**
return _is_arg_Proj(node);
}
-pn_Cmp (get_Proj_pn_cmp)(const ir_node *node)
-{
- return _get_Proj_pn_cmp(node);
-}
-
ir_node **get_Tuple_preds_arr(ir_node *node)
{
assert(is_Tuple(node));
return pn_Start_T_args == get_Proj_proj(node) && is_Start(get_Proj_pred(node));
}
-static inline pn_Cmp _get_Proj_pn_cmp(const ir_node *node)
-{
- assert(is_Cmp(get_Proj_pred(node)));
- return (pn_Cmp)get_Proj_proj(node);
-}
-
/** initialize ir_node module */
void init_irnode(void);
#define is_arg_Proj(node) _is_arg_Proj(node)
-#define get_Proj_pn_cmp(node) _get_Proj_pn_cmp(node)
-
#endif
ir_tarval *tb = value_of(b);
if ((ta != tarval_bad) && (tb != tarval_bad)) {
- return tarval_cmp(ta, tb) == pn_Cmp_Lt ? get_mode_one(m) : get_mode_null(m);
+ return tarval_cmp(ta, tb) == ir_relation_less ? get_mode_one(m) : get_mode_null(m);
} else if (tarval_is_null(ta)) {
return get_mode_null(m);
}
*/
static ir_tarval *computed_value_Confirm(const ir_node *n)
{
- if (get_Confirm_cmp(n) == pn_Cmp_Eq) {
+ if (get_Confirm_relation(n) == ir_relation_equal) {
ir_tarval *tv = value_of(get_Confirm_bound(n));
if (tv != tarval_bad)
return tv;
} /* computed_value_Confirm */
/**
- * Return the value of a Proj(Cmp).
- *
- * This performs a first step of unreachable code elimination.
- * Proj can not be computed, but folding a Cmp above the Proj here is
- * not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
- * only 1 is used.
- * There are several case where we can evaluate a Cmp node, see later.
+ * gives a (conservative) estimation of possible relation when comparing
+ * left+right
*/
-static ir_tarval *computed_value_Proj_Cmp(const ir_node *n)
+static ir_relation determine_possible_cmp_relations(const ir_node *left,
+ const ir_node *right)
{
- ir_node *cmp = get_Proj_pred(n);
- ir_node *left = get_Cmp_left(cmp);
- ir_node *right = get_Cmp_right(cmp);
- pn_Cmp pn_cmp = get_Proj_pn_cmp(n);
- ir_mode *mode = get_irn_mode(left);
- ir_tarval *tv_l, *tv_r;
-
- /*
- * BEWARE: a == a is NOT always True for floating Point values, as
- * NaN != NaN is defined, so we must check this here.
- */
- if (left == right && (!mode_is_float(mode) || pn_cmp == pn_Cmp_Lt || pn_cmp == pn_Cmp_Gt)) {
- /* This is a trick with the bits used for encoding the Cmp
- Proj numbers, the following statement is not the same:
- return new_tarval_from_long(pn_cmp == pn_Cmp_Eq, mode_b) */
- return new_tarval_from_long(pn_cmp & pn_Cmp_Eq, mode_b);
- }
- tv_l = value_of(left);
- tv_r = value_of(right);
+ ir_relation possible = ir_relation_true;
+ ir_tarval *tv_l = value_of(left);
+ ir_tarval *tv_r = value_of(right);
+ ir_mode *mode = get_irn_mode(left);
+ ir_tarval *min = mode == mode_b ? tarval_b_false : get_mode_min(mode);
+ ir_tarval *max = mode == mode_b ? tarval_b_true : get_mode_max(mode);
+ /* both values known - evaluate them */
if ((tv_l != tarval_bad) && (tv_r != tarval_bad)) {
- /*
- * The predecessors of Cmp are target values. We can evaluate
- * the Cmp.
- */
- pn_Cmp flags = tarval_cmp(tv_l, tv_r);
- if (flags != pn_Cmp_False) {
- return new_tarval_from_long (pn_cmp & flags, mode_b);
- }
- } else if (mode_is_int(mode)) {
- /* for integer values, we can check against MIN/MAX */
- pn_Cmp cmp_result;
-
- if (tv_l == get_mode_min(mode)) {
- /* MIN <=/> x. This results in true/false. */
- if (pn_cmp == pn_Cmp_Le)
- return tarval_b_true;
- else if (pn_cmp == pn_Cmp_Gt)
- return tarval_b_false;
- } else if (tv_r == get_mode_min(mode)) {
- /* x >=/< MIN. This results in true/false. */
- if (pn_cmp == pn_Cmp_Ge)
- return tarval_b_true;
- else if (pn_cmp == pn_Cmp_Lt)
- return tarval_b_false;
- } else if (tv_l == get_mode_max(mode)) {
- /* MAX >=/< x. This results in true/false. */
- if (pn_cmp == pn_Cmp_Ge)
- return tarval_b_true;
- else if (pn_cmp == pn_Cmp_Lt)
- return tarval_b_false;
- } else if (tv_r == get_mode_max(mode)) {
- /* x <=/> MAX. This results in true/false. */
- if (pn_cmp == pn_Cmp_Le)
- return tarval_b_true;
- else if (pn_cmp == pn_Cmp_Gt)
- return tarval_b_false;
- }
-
- cmp_result = vrp_cmp(left, right);
- if (cmp_result != pn_Cmp_False) {
- if (cmp_result == pn_Cmp_Lg) {
- if (pn_cmp == pn_Cmp_Eq) {
- return tarval_b_false;
- } else if (pn_cmp == pn_Cmp_Lg) {
- return tarval_b_true;
- }
- } else {
- return new_tarval_from_long(cmp_result & pn_cmp, mode_b);
- }
- }
- } else if (mode_is_reference(mode)) {
- /* pointer compare */
- ir_node *s_l = skip_Proj(left);
- ir_node *s_r = skip_Proj(right);
+ possible = tarval_cmp(tv_l, tv_r);
+ /* we can return now, won't get any better */
+ return possible;
+ }
+ /* a == a is never less or greater (but might be equal or unordered) */
+ if (left == right)
+ possible &= ~ir_relation_less_greater;
+ /* unordered results only happen for float compares */
+ if (!mode_is_float(mode))
+ possible &= ~ir_relation_unordered;
+ /* values can never be less than the least representable number or
+ * greater than the greatest representable number */
+ if (tv_l == min)
+ possible &= ~ir_relation_greater;
+ if (tv_l == max)
+ possible &= ~ir_relation_less;
+ if (tv_r == max)
+ possible &= ~ir_relation_greater;
+ if (tv_r == min)
+ possible &= ~ir_relation_less;
+ /* maybe vrp can tell us more */
+ possible &= vrp_cmp(left, right);
+ /* Alloc nodes never return null (but throw an exception) */
+ if (is_Alloc(left) && tarval_is_null(tv_r))
+ possible &= ~ir_relation_equal;
+
+ return possible;
+}
- if ((is_Alloc(s_l) && tarval_is_null(tv_r)) ||
- (tarval_is_null(tv_l) && is_Alloc(s_r))) {
- /*
- * The predecessors are Allocs and (void*)(0) constants. In Firm Allocs never
- * return NULL, they raise an exception. Therefore we can predict
- * the Cmp result.
- */
- return new_tarval_from_long(pn_cmp & pn_Cmp_Lg, mode_b);
- }
- }
- return computed_value_Cmp_Confirm(cmp, left, right, pn_cmp);
-} /* computed_value_Proj_Cmp */
+/**
+ * Return the value of a Cmp.
+ *
+ * The basic idea here is to determine which relations are possible and which
+ * one are definitely impossible.
+ */
+static ir_tarval *computed_value_Cmp(const ir_node *cmp)
+{
+ ir_node *left = get_Cmp_left(cmp);
+ ir_node *right = get_Cmp_right(cmp);
+ ir_relation possible = determine_possible_cmp_relations(left, right);
+ ir_relation relation = get_Cmp_relation(cmp);
+
+ /* if none of the requested relations is possible, return false */
+ if ((possible & relation) == ir_relation_false)
+ return tarval_b_false;
+ /* if possible relations are a subset of the requested ones return true */
+ if ((possible & ~relation) == ir_relation_false)
+ return tarval_b_true;
+
+ return computed_value_Cmp_Confirm(cmp, left, right, relation);
+}
/**
* Calculate the value of an integer Div.
ir_tarval *computed_value(const ir_node *n)
{
vrp_attr *vrp = vrp_get_info(n);
- if (vrp && vrp->valid && tarval_cmp(vrp->bits_set, vrp->bits_not_set) == pn_Cmp_Eq) {
+ if (vrp && vrp->valid && tarval_cmp(vrp->bits_set, vrp->bits_not_set) == ir_relation_equal) {
return vrp->bits_set;
}
if (n->op->ops.computed_value)
break
switch (code) {
- CASE(Const);
- CASE(SymConst);
CASE(Add);
- CASE(Sub);
- CASE(Carry);
+ CASE(And);
CASE(Borrow);
+ CASE(Carry);
+ CASE(Cmp);
+ CASE(Confirm);
+ CASE(Const);
+ CASE(Conv);
+ CASE(Eor);
CASE(Minus);
CASE(Mul);
- CASE(And);
- CASE(Or);
- CASE(Eor);
+ CASE(Mux);
CASE(Not);
+ CASE(Or);
+ CASE(Proj);
+ CASE(Rotl);
CASE(Shl);
CASE(Shr);
CASE(Shrs);
- CASE(Rotl);
- CASE(Conv);
- CASE(Mux);
- CASE(Confirm);
- CASE_PROJ(Cmp);
+ CASE(Sub);
+ CASE(SymConst);
CASE_PROJ(Div);
CASE_PROJ(Mod);
- CASE(Proj);
default:
/* leave NULL */
break;
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_EQ);
return n;
}
- if (is_Proj(sel) && !mode_honor_signed_zeros(get_irn_mode(n))) {
- ir_node *cmp = get_Proj_pred(sel);
- long proj_nr = get_Proj_proj(sel);
- ir_node *f = get_Mux_false(n);
- ir_node *t = get_Mux_true(n);
+ if (is_Cmp(sel) && !mode_honor_signed_zeros(get_irn_mode(n))) {
+ ir_relation relation = get_Cmp_relation(sel);
+ ir_node *f = get_Mux_false(n);
+ ir_node *t = get_Mux_true(n);
/*
* Note further that these optimization work even for floating point
* with NaN's because -NaN == NaN.
* However, if +0 and -0 is handled differently, we cannot use the first one.
*/
- if (is_Cmp(cmp)) {
- ir_node *const cmp_l = get_Cmp_left(cmp);
- ir_node *const cmp_r = get_Cmp_right(cmp);
-
- switch (proj_nr) {
- case pn_Cmp_Eq:
- if ((cmp_l == t && cmp_r == f) || /* Mux(t == f, t, f) -> f */
- (cmp_l == f && cmp_r == t)) { /* Mux(f == t, t, f) -> f */
- n = f;
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
- return n;
- }
- break;
+ ir_node *const cmp_l = get_Cmp_left(sel);
+ ir_node *const cmp_r = get_Cmp_right(sel);
+
+ switch (relation) {
+ case ir_relation_equal:
+ if ((cmp_l == t && cmp_r == f) || /* Mux(t == f, t, f) -> f */
+ (cmp_l == f && cmp_r == t)) { /* Mux(f == t, t, f) -> f */
+ n = f;
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
+ return n;
+ }
+ break;
- case pn_Cmp_Lg:
- case pn_Cmp_Ne:
- if ((cmp_l == t && cmp_r == f) || /* Mux(t != f, t, f) -> t */
- (cmp_l == f && cmp_r == t)) { /* Mux(f != t, t, f) -> t */
- n = t;
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
- return n;
- }
- break;
+ case ir_relation_less_greater:
+ case ir_relation_unordered_less_greater:
+ if ((cmp_l == t && cmp_r == f) || /* Mux(t != f, t, f) -> t */
+ (cmp_l == f && cmp_r == t)) { /* Mux(f != t, t, f) -> t */
+ n = t;
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
+ return n;
}
+ break;
+ default:
+ break;
+ }
- /*
- * Note: normalization puts the constant on the right side,
- * so we check only one case.
- */
- if (cmp_l == t && tarval_is_null(value_of(cmp_r))) {
- /* Mux(t CMP 0, X, t) */
- if (is_Minus(f) && get_Minus_op(f) == t) {
- /* Mux(t CMP 0, -t, t) */
- if (proj_nr == pn_Cmp_Eq) {
- /* Mux(t == 0, -t, t) ==> -t */
- n = f;
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
- } else if (proj_nr == pn_Cmp_Lg || proj_nr == pn_Cmp_Ne) {
- /* Mux(t != 0, -t, t) ==> t */
- n = t;
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
- }
+ /*
+ * Note: normalization puts the constant on the right side,
+ * so we check only one case.
+ */
+ if (cmp_l == t && tarval_is_null(value_of(cmp_r))) {
+ /* Mux(t CMP 0, X, t) */
+ if (is_Minus(f) && get_Minus_op(f) == t) {
+ /* Mux(t CMP 0, -t, t) */
+ if (relation == ir_relation_equal) {
+ /* Mux(t == 0, -t, t) ==> -t */
+ n = f;
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
+ } else if (relation == ir_relation_less_greater || relation == ir_relation_unordered_less_greater) {
+ /* Mux(t != 0, -t, t) ==> t */
+ n = t;
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_MUX_TRANSFORM);
}
}
}
}
+
return n;
-} /* equivalent_node_Mux */
+}
/**
* Remove Confirm nodes if setting is on.
*/
static ir_node *equivalent_node_Confirm(ir_node *n)
{
- ir_node *pred = get_Confirm_value(n);
- pn_Cmp pnc = get_Confirm_cmp(n);
+ ir_node *pred = get_Confirm_value(n);
+ ir_relation relation = get_Confirm_relation(n);
- while (is_Confirm(pred) && pnc == get_Confirm_cmp(pred)) {
+ while (is_Confirm(pred) && relation == get_Confirm_relation(pred)) {
/*
* rare case: two identical Confirms one after another,
* replace the second one with the first.
*/
n = pred;
pred = get_Confirm_value(n);
- pnc = get_Confirm_cmp(n);
}
return n;
}
return n;
} /* transform_node_Mod */
-/**
- * Optimize -a CMP -b into b CMP a.
- * This works only for for modes where unary Minus
- * cannot Overflow.
- * Note that two-complement integers can Overflow
- * so it will NOT work.
- *
- * For == and != can be handled in Proj(Cmp)
- */
-static ir_node *transform_node_Cmp(ir_node *n)
-{
- ir_node *oldn = n;
- ir_node *left = get_Cmp_left(n);
- ir_node *right = get_Cmp_right(n);
-
- if (is_Minus(left) && is_Minus(right) &&
- !mode_overflow_on_unary_Minus(get_irn_mode(left))) {
- ir_node *const new_left = get_Minus_op(right);
- ir_node *const new_right = get_Minus_op(left);
- n = new_rd_Cmp(get_irn_dbg_info(n), get_nodes_block(n), new_left, new_right);
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_CMP_OP_OP);
- }
- return n;
-} /* transform_node_Cmp */
-
-
/**
* Transform a Cond node.
*
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);
+ if (a_left == b_left && b_left == b_right) {
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+ ir_relation a_relation = get_Cmp_relation(a);
+ ir_relation b_relation = get_Cmp_relation(b);
+ ir_relation new_relation = a_relation & b_relation;
+ return new_rd_Cmp(dbgi, block, a_left, a_right, new_relation);
+ }
+ }
+
mode = get_irn_mode(n);
HANDLE_BINOP_PHI((eval_func) tarval_and, a, b, c, mode);
- /* we can evaluate 2 Projs of the same Cmp */
- if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
- ir_node *pred_a = get_Proj_pred(a);
- ir_node *pred_b = get_Proj_pred(b);
- if (pred_a == pred_b) {
- dbg_info *dbgi = get_irn_dbg_info(n);
- pn_Cmp pn_a = get_Proj_pn_cmp(a);
- pn_Cmp pn_b = get_Proj_pn_cmp(b);
- /* yes, we can simply calculate with pncs */
- pn_Cmp new_pnc = pn_a & pn_b;
-
- return new_rd_Proj(dbgi, pred_a, mode_b, new_pnc);
- }
- }
if (is_Or(a)) {
if (is_Not(b)) {
ir_node *op = get_Not_op(b);
b_vrp = vrp_get_info(b);
if (is_Const(a) && b_vrp && (tarval_cmp(tarval_or(get_Const_tarval(a),
- b_vrp->bits_not_set), get_Const_tarval(a)) == pn_Cmp_Eq)) {
+ b_vrp->bits_not_set), get_Const_tarval(a)) == ir_relation_equal)) {
return b;
a_vrp = vrp_get_info(a);
if (is_Const(b) && a_vrp && (tarval_cmp(tarval_or(get_Const_tarval(b),
- a_vrp->bits_not_set), get_Const_tarval(b)) == pn_Cmp_Eq)) {
+ a_vrp->bits_not_set), get_Const_tarval(b)) == ir_relation_equal)) {
return a;
}
ir_node *b = get_Eor_right(n);
ir_mode *mode = get_irn_mode(n);
- HANDLE_BINOP_PHI((eval_func) tarval_eor, a, b, c, mode);
-
- /* we can evaluate 2 Projs of the same Cmp */
- if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
- ir_node *pred_a = get_Proj_pred(a);
- ir_node *pred_b = get_Proj_pred(b);
- if (pred_a == pred_b) {
- dbg_info *dbgi = get_irn_dbg_info(n);
- pn_Cmp pn_a = get_Proj_pn_cmp(a);
- pn_Cmp pn_b = get_Proj_pn_cmp(b);
- /* yes, we can simply calculate with pncs */
- pn_Cmp new_pnc = pn_a ^ pn_b;
-
- return new_rd_Proj(dbgi, pred_a, mode_b, new_pnc);
+ /* 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);
+ if (a_left == b_left && b_left == b_right) {
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+ ir_relation a_relation = get_Cmp_relation(a);
+ ir_relation b_relation = get_Cmp_relation(b);
+ ir_relation new_relation = a_relation ^ b_relation;
+ return new_rd_Cmp(dbgi, block, a_left, a_right, new_relation);
}
}
+ HANDLE_BINOP_PHI((eval_func) tarval_eor, a, b, c, mode);
+
/* normalize not nodes... ~a ^ b <=> a ^ ~b */
if (is_Not(a) && operands_are_normalized(get_Not_op(a), b)) {
dbg_info *dbg = get_irn_dbg_info(n);
HANDLE_UNOP_PHI(tarval_not,a,c);
/* check for a boolean Not */
- if (mode == mode_b && is_Proj(a)) {
- ir_node *a_pred = get_Proj_pred(a);
- if (is_Cmp(a_pred)) {
- /* We negate a Cmp. The Cmp has the negated result anyways! */
- n = new_r_Proj(get_Proj_pred(a),
- mode_b, get_negated_pnc(get_Proj_proj(a), mode_b));
- DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_CMP);
- return n;
- }
+ if (is_Cmp(a)) {
+ dbg_info *dbgi = get_irn_dbg_info(a);
+ ir_node *block = get_nodes_block(a);
+ ir_relation relation = get_Cmp_relation(a);
+ relation = get_negated_relation(relation);
+ n = new_rd_Cmp(dbgi, block, get_Cmp_left(a), get_Cmp_right(a), relation);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_CMP);
+ return n;
}
/* normalize ~(a ^ b) => a ^ ~b */
}
}
return n;
-} /* transform_node_Not */
+}
/**
* Transform a Minus.
*/
static ir_node *transform_node_Proj_Cond(ir_node *proj)
{
- if (get_opt_unreachable_code()) {
- ir_node *n = get_Proj_pred(proj);
- ir_node *b = get_Cond_selector(n);
+ ir_node *n = get_Proj_pred(proj);
+ ir_node *b = get_Cond_selector(n);
- if (mode_is_int(get_irn_mode(b))) {
- ir_tarval *tb = value_of(b);
+ if (!get_opt_unreachable_code())
+ return n;
- if (tb != tarval_bad) {
- /* we have a constant switch */
- long num = get_Proj_proj(proj);
+ if (mode_is_int(get_irn_mode(b))) {
+ ir_tarval *tb = value_of(b);
- if (num != get_Cond_default_proj(n)) { /* we cannot optimize default Proj's yet */
- if (get_tarval_long(tb) == num) {
- /* Do NOT create a jump here, or we will have 2 control flow ops
- * in a block. This case is optimized away in optimize_cf(). */
- return proj;
- } else {
- ir_graph *irg = get_irn_irg(proj);
- /* this case will NEVER be taken, kill it */
- return get_irg_bad(irg);
- }
- }
- } else {
- long num = get_Proj_proj(proj);
- vrp_attr *b_vrp = vrp_get_info(b);
- if (num != get_Cond_default_proj(n) && b_vrp) {
- /* Try handling with vrp data. We only remove dead parts. */
- ir_tarval *tp = new_tarval_from_long(num, get_irn_mode(b));
-
- if (b_vrp->range_type == VRP_RANGE) {
- pn_Cmp cmp_result = tarval_cmp(b_vrp->range_bottom, tp);
- pn_Cmp cmp_result2 = tarval_cmp(b_vrp->range_top, tp);
-
- if ((cmp_result & pn_Cmp_Gt) == cmp_result && (cmp_result2
- & pn_Cmp_Lt) == cmp_result2) {
- ir_graph *irg = get_irn_irg(proj);
- return get_irg_bad(irg);
- }
- } else if (b_vrp->range_type == VRP_ANTIRANGE) {
- pn_Cmp cmp_result = tarval_cmp(b_vrp->range_bottom, tp);
- pn_Cmp cmp_result2 = tarval_cmp(b_vrp->range_top, tp);
-
- if ((cmp_result & pn_Cmp_Le) == cmp_result && (cmp_result2
- & pn_Cmp_Ge) == cmp_result2) {
- ir_graph *irg = get_irn_irg(proj);
- return get_irg_bad(irg);
- }
- }
+ if (tb != tarval_bad) {
+ /* we have a constant switch */
+ long num = get_Proj_proj(proj);
- if (!(tarval_cmp(
- tarval_and( b_vrp->bits_set, tp),
- b_vrp->bits_set
- ) == pn_Cmp_Eq)) {
+ if (num != get_Cond_default_proj(n)) { /* we cannot optimize default Proj's yet */
+ if (get_tarval_long(tb) == num) {
+ /* Do NOT create a jump here, or we will have 2 control flow ops
+ * in a block. This case is optimized away in optimize_cf(). */
+ return proj;
+ } else {
+ ir_graph *irg = get_irn_irg(proj);
+ /* this case will NEVER be taken, kill it */
+ return get_irg_bad(irg);
+ }
+ }
+ } else {
+ long num = get_Proj_proj(proj);
+ vrp_attr *b_vrp = vrp_get_info(b);
+ if (num != get_Cond_default_proj(n) && b_vrp) {
+ /* Try handling with vrp data. We only remove dead parts. */
+ ir_tarval *tp = new_tarval_from_long(num, get_irn_mode(b));
+
+ if (b_vrp->range_type == VRP_RANGE) {
+ ir_relation cmp_result = tarval_cmp(b_vrp->range_bottom, tp);
+ ir_relation cmp_result2 = tarval_cmp(b_vrp->range_top, tp);
+
+ if ((cmp_result & ir_relation_greater) == cmp_result && (cmp_result2
+ & ir_relation_less) == cmp_result2) {
ir_graph *irg = get_irn_irg(proj);
return get_irg_bad(irg);
}
+ } else if (b_vrp->range_type == VRP_ANTIRANGE) {
+ ir_relation cmp_result = tarval_cmp(b_vrp->range_bottom, tp);
+ ir_relation cmp_result2 = tarval_cmp(b_vrp->range_top, tp);
- if (!(tarval_cmp(
- tarval_and(
- tarval_not(tp),
- tarval_not(b_vrp->bits_not_set)),
- tarval_not(b_vrp->bits_not_set))
- == pn_Cmp_Eq)) {
+ if ((cmp_result & ir_relation_less_equal) == cmp_result && (cmp_result2
+ & ir_relation_greater_equal) == cmp_result2) {
ir_graph *irg = get_irn_irg(proj);
return get_irg_bad(irg);
}
+ }
+ if (!(tarval_cmp(
+ tarval_and( b_vrp->bits_set, tp),
+ b_vrp->bits_set
+ ) == ir_relation_equal)) {
+ ir_graph *irg = get_irn_irg(proj);
+ return get_irg_bad(irg);
+ }
+ if (!(tarval_cmp(
+ tarval_and(
+ tarval_not(tp),
+ tarval_not(b_vrp->bits_not_set)),
+ tarval_not(b_vrp->bits_not_set))
+ == ir_relation_equal)) {
+ ir_graph *irg = get_irn_irg(proj);
+ return get_irg_bad(irg);
}
+
+
}
}
}
return proj;
-} /* transform_node_Proj_Cond */
+}
/**
* return true if the operation returns a value with exactly 1 bit set
/**
* Normalizes and optimizes Cmp nodes.
*/
-static ir_node *transform_node_Proj_Cmp(ir_node *proj)
-{
- ir_node *n = get_Proj_pred(proj);
- ir_node *left = get_Cmp_left(n);
- ir_node *right = get_Cmp_right(n);
- ir_tarval *tv = NULL;
- int changed = 0;
- ir_mode *mode = get_irn_mode(left);
- long proj_nr = get_Proj_proj(proj);
-
- /* we can evaluate some cases directly */
- switch (proj_nr) {
- case pn_Cmp_False: {
- ir_graph *irg = get_irn_irg(proj);
- return new_r_Const(irg, get_tarval_b_false());
- }
- case pn_Cmp_True: {
- ir_graph *irg = get_irn_irg(proj);
- return new_r_Const(irg, get_tarval_b_true());
- }
- case pn_Cmp_Leg:
- if (!mode_is_float(mode)) {
- ir_graph *irg = get_irn_irg(proj);
- return new_r_Const(irg, get_tarval_b_true());
- }
- break;
- default:
- break;
- }
+static ir_node *transform_node_Cmp(ir_node *n)
+{
+ ir_node *left = get_Cmp_left(n);
+ ir_node *right = get_Cmp_right(n);
+ ir_mode *mode = get_irn_mode(left);
+ ir_tarval *tv = NULL;
+ bool changed = false;
+ bool changedc = false;
+ ir_relation relation = get_Cmp_relation(n);
+ ir_relation possible = determine_possible_cmp_relations(left, right);
- /* remove Casts of both sides */
- left = skip_Cast(left);
- right = skip_Cast(right);
+ /* mask out impossible relations */
+ ir_relation new_relation = relation & possible;
+ if (new_relation != relation) {
+ relation = new_relation;
+ changed = true;
+ }
/* Remove unnecessary conversions */
- /* TODO handle constants */
+ /* TODO handle conv+constant */
if (is_Conv(left) && is_Conv(right)) {
ir_node *op_left = get_Conv_op(left);
ir_node *op_right = get_Conv_op(right);
if (mode_left == mode_right) {
left = op_left;
right = op_right;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CONV_CONV);
} else if (smaller_mode(mode_left, mode_right)) {
left = new_r_Conv(block, op_left, mode_right);
right = op_right;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CONV);
} else if (smaller_mode(mode_right, mode_left)) {
left = op_left;
right = new_r_Conv(block, op_right, mode_left);
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CONV);
}
}
}
+ /*
+ * Optimize -a CMP -b into b CMP a.
+ * This works only for modes where unary Minus cannot Overflow.
+ * Note that two-complement integers can Overflow so it will NOT work.
+ */
+ if (!mode_overflow_on_unary_Minus(mode) &&
+ is_Minus(left) && is_Minus(right)) {
+ left = get_Minus_op(left);
+ right = get_Minus_op(right);
+ relation = get_inversed_relation(relation);
+ changed = true;
+ DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
+ }
+
/* remove operation on both sides if possible */
- if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
+ if (relation == ir_relation_equal || relation == ir_relation_less_greater) {
/*
* The following operations are NOT safe for floating point operations, for instance
* 1.0 + inf == 2.0 + inf, =/=> x == y
/* ~a CMP ~b => a CMP b, -a CMP -b ==> a CMP b */
left = get_unop_op(left);
right = get_unop_op(right);
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
break;
case iro_Add:
/* X + a CMP X + b ==> a CMP b */
left = lr;
right = rr;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
} else if (ll == rr) {
/* X + a CMP b + X ==> a CMP b */
left = lr;
right = rl;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
} else if (lr == rl) {
/* a + X CMP X + b ==> a CMP b */
left = ll;
right = rr;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
} else if (lr == rr) {
/* a + X CMP b + X ==> a CMP b */
left = ll;
right = rl;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
}
break;
/* X - a CMP X - b ==> a CMP b */
left = lr;
right = rr;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
} else if (lr == rr) {
/* a - X CMP b - X ==> a CMP b */
left = ll;
right = rl;
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
}
break;
/* a ROTL X CMP b ROTL X ==> a CMP b */
left = get_Rotl_left(left);
right = get_Rotl_left(right);
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
}
break;
if (ll == right) {
ir_graph *irg = get_irn_irg(n);
left = lr;
- right = create_zero_const(irg, mode);
- changed |= 1;
+ right = create_zero_const(irg, mode);
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
}
}
if (rl == left) {
ir_graph *irg = get_irn_irg(n);
left = rr;
- right = create_zero_const(irg, mode);
- changed |= 1;
+ right = create_zero_const(irg, mode);
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_OP);
}
}
left = new_rd_And(dbg, block, get_Shr_left(ll), new_r_Const(irg, mask), mode);
right = new_r_Const(irg, value);
- changed |= 1;
+ changed = true;
}
}
}
if (is_Const(right) && is_Const_null(right) && is_Eor(left)) {
right = get_Eor_right(left);
left = get_Eor_left(left);
- changed |= 1;
+ changed = true;
}
} /* mode_is_int(...) */
- } /* proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg */
+ }
/* Cmp(And(1bit, val), 1bit) "bit-testing" can be replaced
* by the simpler Cmp(And(1bit), val), 0) negated pnc */
- if (mode_is_int(mode) && is_And(left) && (proj_nr == pn_Cmp_Eq
- || (mode_is_signed(mode) && proj_nr == pn_Cmp_Lg)
- || (!mode_is_signed(mode) && (proj_nr & pn_Cmp_Le) == pn_Cmp_Lt))) {
+ if (mode_is_int(mode) && is_And(left)
+ && (relation == ir_relation_equal
+ || (mode_is_signed(mode) && relation == ir_relation_less_greater)
+ || (!mode_is_signed(mode) && (relation & ir_relation_less_equal) == ir_relation_less))) {
ir_node *and0 = get_And_left(left);
ir_node *and1 = get_And_right(left);
if (and1 == right) {
}
if (and0 == right && is_single_bit(and0)) {
ir_graph *irg = get_irn_irg(n);
- proj_nr = proj_nr == pn_Cmp_Eq ? pn_Cmp_Lg : pn_Cmp_Eq;
+ relation =
+ relation == ir_relation_equal ? ir_relation_less_greater : ir_relation_equal;
right = create_zero_const(irg, mode);
changed |= 1;
}
}
/* replace mode_b compares with ands/ors */
- if (get_irn_mode(left) == mode_b) {
+ if (mode == mode_b) {
ir_node *block = get_nodes_block(n);
ir_node *bres;
- switch (proj_nr) {
- case pn_Cmp_Le: bres = new_r_Or( block, new_r_Not(block, left, mode_b), right, mode_b); break;
- case pn_Cmp_Lt: bres = new_r_And(block, new_r_Not(block, left, mode_b), right, mode_b); break;
- case pn_Cmp_Ge: bres = new_r_Or( block, left, new_r_Not(block, right, mode_b), mode_b); break;
- case pn_Cmp_Gt: bres = new_r_And(block, left, new_r_Not(block, right, mode_b), mode_b); break;
- case pn_Cmp_Lg: bres = new_r_Eor(block, left, right, mode_b); break;
- case pn_Cmp_Eq: bres = new_r_Not(block, new_r_Eor(block, left, right, mode_b), mode_b); break;
- default: bres = NULL;
- }
- if (bres) {
+ switch (relation) {
+ case ir_relation_less_equal:
+ bres = new_r_Or(block, new_r_Not(block, left, mode_b), right, mode_b);
+ break;
+ case ir_relation_less:
+ bres = new_r_And(block, new_r_Not(block, left, mode_b), right, mode_b);
+ break;
+ case ir_relation_greater_equal:
+ bres = new_r_Or(block, left, new_r_Not(block, right, mode_b), mode_b);
+ break;
+ case ir_relation_greater:
+ bres = new_r_And(block, left, new_r_Not(block, right, mode_b), mode_b);
+ break;
+ case ir_relation_less_greater:
+ bres = new_r_Eor(block, left, right, mode_b);
+ break;
+ case ir_relation_equal:
+ bres = new_r_Not(block, new_r_Eor(block, left, right, mode_b), mode_b);
+ break;
+ default:
+#ifdef DEBUG_libfirm
+ ir_fprintf(stderr, "Optimisation warning, unexpected mode_b Cmp %+F\n", n);
+#endif
+ bres = NULL;
+ }
+ if (bres != NULL) {
DBG_OPT_ALGSIM0(n, bres, FS_OPT_CMP_TO_BOOL);
return bres;
}
*/
if (!operands_are_normalized(left, right)) {
ir_node *t = left;
-
left = right;
right = t;
- proj_nr = get_inversed_pnc(proj_nr);
- changed |= 1;
+ relation = get_inversed_relation(relation);
+ changed = true;
}
/*
*/
tv = value_of(right);
if (tv != tarval_bad) {
- mode = get_irn_mode(right);
+ ir_mode *mode = get_irn_mode(right);
/* TODO extend to arbitrary constants */
if (is_Conv(left) && tarval_is_null(tv)) {
* win. (on the other side it makes detection/creation of fabs hard)
*/
if (get_mode_size_bits(mode) > get_mode_size_bits(op_mode) &&
- ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) ||
+ ((relation == ir_relation_equal || relation == ir_relation_less_greater) ||
mode_is_signed(mode) || !mode_is_signed(op_mode)) &&
!mode_is_float(mode)) {
tv = get_mode_null(op_mode);
left = op;
mode = op_mode;
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CONV);
}
}
*/
if (is_Minus(left) &&
(!mode_overflow_on_unary_Minus(mode) ||
- (mode_is_int(mode) && (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg)))) {
+ (mode_is_int(mode) && (relation == ir_relation_equal || relation == ir_relation_less_greater)))) {
tv = tarval_neg(tv);
if (tv != tarval_bad) {
left = get_Minus_op(left);
- proj_nr = get_inversed_pnc(proj_nr);
- changed |= 2;
+ relation = get_inversed_relation(relation);
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_C);
}
- } else if (is_Not(left) && (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg)) {
+ } else if (is_Not(left) && (relation == ir_relation_equal || relation == ir_relation_less_greater)) {
/* Not(a) ==/!= c ==> a ==/!= Not(c) */
tv = tarval_not(tv);
if (tv != tarval_bad) {
left = get_Not_op(left);
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_C);
}
}
/* for integer modes, we have more */
if (mode_is_int(mode)) {
- /* Ne includes Unordered which is not possible on integers.
- * However, frontends often use this wrong, so fix it here */
- if (proj_nr & pn_Cmp_Uo) {
- proj_nr &= ~pn_Cmp_Uo;
- set_Proj_proj(proj, proj_nr);
- }
-
/* c > 0 : a < c ==> a <= (c-1) a >= c ==> a > (c-1) */
- if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Ge) &&
- tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Gt) {
+ if ((relation == ir_relation_less || relation == ir_relation_greater_equal) &&
+ tarval_cmp(tv, get_mode_null(mode)) == ir_relation_greater) {
tv = tarval_sub(tv, get_mode_one(mode), NULL);
if (tv != tarval_bad) {
- proj_nr ^= pn_Cmp_Eq;
- changed |= 2;
+ relation ^= ir_relation_equal;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CNST_MAGN);
}
}
/* c < 0 : a > c ==> a >= (c+1) a <= c ==> a < (c+1) */
- else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Le) &&
- tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Lt) {
+ else if ((relation == ir_relation_greater || relation == ir_relation_less_equal) &&
+ tarval_cmp(tv, get_mode_null(mode)) == ir_relation_less) {
tv = tarval_add(tv, get_mode_one(mode));
if (tv != tarval_bad) {
- proj_nr ^= pn_Cmp_Eq;
- changed |= 2;
+ relation ^= ir_relation_equal;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CNST_MAGN);
}
}
/* the following reassociations work only for == and != */
- if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
+ if (relation == ir_relation_equal || relation == ir_relation_less_greater) {
#if 0 /* Might be not that good in general */
/* a-b == 0 ==> a == b, a-b != 0 ==> a != b */
if (tv2 != tarval_bad) {
left = get_Sub_left(left);
tv = tv2;
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_C);
}
}
if (tv2 != tarval_bad) {
left = a;
tv = tv2;
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_C);
}
}
if (tv2 != tarval_bad) {
left = get_Minus_op(left);
tv = tv2;
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_OP_C);
}
}
} /* == or != */
} /* mode_is_int */
- if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
+ if (relation == ir_relation_equal || relation == ir_relation_less_greater) {
switch (get_irn_opcode(left)) {
ir_node *c1;
if (mask != tv) {
/* TODO: move to constant evaluation */
ir_graph *irg = get_irn_irg(n);
- tv = proj_nr == pn_Cmp_Eq ? get_tarval_b_false() : get_tarval_b_true();
+ tv = relation == ir_relation_equal ? get_tarval_b_false() : get_tarval_b_true();
c1 = new_r_Const(irg, tv);
- DBG_OPT_CSTEVAL(proj, c1);
+ DBG_OPT_CSTEVAL(n, c1);
return c1;
}
if (get_Const_tarval(c1) == tv) {
/* fine: do the transformation */
tv = get_mode_null(get_tarval_mode(tv));
- proj_nr ^= pn_Cmp_Leg;
- changed |= 2;
+ relation ^= ir_relation_less_equal_greater;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_CNST_MAGN);
}
}
if (! tarval_is_null(get_Const_tarval(c1))) {
/* TODO: move to constant evaluation */
ir_graph *irg = get_irn_irg(n);
- tv = proj_nr == pn_Cmp_Eq ? get_tarval_b_false() : get_tarval_b_true();
+ tv = relation == ir_relation_equal ? get_tarval_b_false() : get_tarval_b_true();
c1 = new_r_Const(irg, tv);
- DBG_OPT_CSTEVAL(proj, c1);
+ DBG_OPT_CSTEVAL(n, c1);
return c1;
}
}
if (tarval_and(tv, cmask) != tv) {
/* condition not met */
- tv = proj_nr == pn_Cmp_Eq ? get_tarval_b_false() : get_tarval_b_true();
+ tv = relation == ir_relation_equal ? get_tarval_b_false() : get_tarval_b_true();
c1 = new_r_Const(irg, tv);
- DBG_OPT_CSTEVAL(proj, c1);
+ DBG_OPT_CSTEVAL(n, c1);
return c1;
}
sl = get_Shl_left(left);
blk = get_nodes_block(n);
left = new_rd_And(get_irn_dbg_info(left), blk, sl, new_r_Const(irg, amask), mode);
tv = tarval_shr(tv, tv1);
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_SHF_TO_AND);
}
break;
if (tarval_and(tv, cmask) != tv) {
/* condition not met */
- tv = proj_nr == pn_Cmp_Eq ? get_tarval_b_false() : get_tarval_b_true();
+ tv = relation == ir_relation_equal ? get_tarval_b_false() : get_tarval_b_true();
c1 = new_r_Const(irg, tv);
- DBG_OPT_CSTEVAL(proj, c1);
+ DBG_OPT_CSTEVAL(n, c1);
return c1;
}
sl = get_Shr_left(left);
blk = get_nodes_block(n);
left = new_rd_And(get_irn_dbg_info(left), blk, sl, new_r_Const(irg, amask), mode);
tv = tarval_shl(tv, tv1);
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_SHF_TO_AND);
}
break;
if (!tarval_is_all_one(cond) && !tarval_is_null(cond)) {
/* condition not met */
- tv = proj_nr == pn_Cmp_Eq ? get_tarval_b_false() : get_tarval_b_true();
+ tv = relation == ir_relation_equal ? get_tarval_b_false() : get_tarval_b_true();
c1 = new_r_Const(irg, tv);
- DBG_OPT_CSTEVAL(proj, c1);
+ DBG_OPT_CSTEVAL(n, c1);
return c1;
}
sl = get_Shrs_left(left);
blk = get_nodes_block(n);
left = new_rd_And(get_irn_dbg_info(left), blk, sl, new_r_Const(irg, amask), mode);
tv = tarval_shl(tv, tv1);
- changed |= 2;
+ changedc = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_SHF_TO_AND);
}
break;
} /* tarval != bad */
}
- if (changed & 2) { /* need a new Const */
+ if (changedc) { /* need a new Const */
ir_graph *irg = get_irn_irg(n);
right = new_r_Const(irg, tv);
+ changed = true;
}
- if ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) && is_Const(right) && is_Const_null(right) && is_Proj(left)) {
+ if ((relation == ir_relation_equal || relation == ir_relation_less_greater) && is_Const(right) && is_Const_null(right) && is_Proj(left)) {
ir_node *op = get_Proj_pred(left);
if (is_Mod(op) && get_Proj_proj(left) == pn_Mod_res) {
tv = tarval_sub(tv, get_mode_one(mode), NULL);
left = new_rd_And(get_irn_dbg_info(op), blk, v, new_r_Const(irg, tv), mode);
- changed |= 1;
+ changed = true;
DBG_OPT_ALGSIM0(n, n, FS_OPT_CMP_MOD_TO_AND);
}
}
}
if (changed) {
- ir_node *block = get_nodes_block(n);
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
/* create a new compare */
- n = new_rd_Cmp(get_irn_dbg_info(n), block, left, right);
- proj = new_rd_Proj(get_irn_dbg_info(proj), n, get_irn_mode(proj), proj_nr);
+ n = new_rd_Cmp(dbgi, block, left, right, relation);
}
- return proj;
-} /* transform_node_Proj_Cmp */
+ return n;
+}
/**
* Optimize CopyB(mem, x, x) into a Nop.
/* Beware of Phi0 */
if (n > 0) {
- ir_node *pred = get_irn_n(phi, 0);
- ir_node *bound, *new_phi, *block, **in;
- pn_Cmp pnc;
+ ir_node *pred = get_irn_n(phi, 0);
+ ir_node *bound, *new_phi, *block, **in;
+ ir_relation relation;
if (! is_Confirm(pred))
return phi;
- bound = get_Confirm_bound(pred);
- pnc = get_Confirm_cmp(pred);
+ bound = get_Confirm_bound(pred);
+ relation = get_Confirm_relation(pred);
NEW_ARR_A(ir_node *, in, n);
in[0] = get_Confirm_value(pred);
if (! is_Confirm(pred) ||
get_Confirm_bound(pred) != bound ||
- get_Confirm_cmp(pred) != pnc)
+ get_Confirm_relation(pred) != relation)
return phi;
in[i] = get_Confirm_value(pred);
}
/* move the Confirm nodes "behind" the Phi */
block = get_irn_n(phi, -1);
new_phi = new_r_Phi(block, n, in, get_irn_mode(phi));
- return new_r_Confirm(block, new_phi, bound, pnc);
+ return new_r_Confirm(block, new_phi, bound, relation);
}
}
return phi;
-} /* transform_node_Phi */
+}
/**
* Returns the operands of a commutative bin-op, if one operand is
return n;
}
- /* we can evaluate 2 Projs of the same Cmp */
- if (get_irn_mode(n) == mode_b && is_Proj(a) && is_Proj(b)) {
- ir_node *pred_a = get_Proj_pred(a);
- ir_node *pred_b = get_Proj_pred(b);
- if (pred_a == pred_b) {
- dbg_info *dbgi = get_irn_dbg_info(n);
- pn_Cmp pn_a = get_Proj_pn_cmp(a);
- pn_Cmp pn_b = get_Proj_pn_cmp(b);
- /* yes, we can simply calculate with pncs */
- pn_Cmp new_pnc = pn_a | pn_b;
-
- return new_rd_Proj(dbgi, pred_a, mode_b, new_pnc);
+ /* 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);
+ if (a_left == b_left && b_left == b_right) {
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ ir_node *block = get_nodes_block(n);
+ ir_relation a_relation = get_Cmp_relation(a);
+ ir_relation b_relation = get_Cmp_relation(b);
+ ir_relation new_relation = a_relation | b_relation;
+ return new_rd_Cmp(dbgi, block, a_left, a_right, new_relation);
}
}
assert(modulo_shf >= (int) get_mode_size_bits(mode));
/* shifting too much */
- if (!(tarval_cmp(res, modulo) & pn_Cmp_Lt)) {
+ if (!(tarval_cmp(res, modulo) & ir_relation_less)) {
if (is_Shrs(n)) {
ir_node *block = get_nodes_block(n);
dbg_info *dbgi = get_irn_dbg_info(n);
ir_tarval *tv_shift;
ir_tarval *tv_mask;
ir_graph *irg;
- pn_Cmp pnc;
+ ir_relation relation;
int need_shrs = 0;
assert(is_Shl(n) || is_Shr(n) || is_Shrs(n));
if (is_Shrs(left)) {
/* shrs variant only allowed if c1 >= c2 */
- if (! (tarval_cmp(tv_shl, tv_shr) & pn_Cmp_Ge))
+ if (! (tarval_cmp(tv_shl, tv_shr) & ir_relation_greater_equal))
return n;
tv_mask = tarval_shrs(get_mode_all_one(mode), tv_shr);
irg = get_irn_irg(block);
dbgi = get_irn_dbg_info(n);
- pnc = tarval_cmp(tv_shl, tv_shr);
- if (pnc == pn_Cmp_Lt || pnc == pn_Cmp_Eq) {
+ relation = tarval_cmp(tv_shl, tv_shr);
+ if (relation == ir_relation_less || relation == ir_relation_equal) {
tv_shift = tarval_sub(tv_shr, tv_shl, NULL);
new_const = new_r_Const(irg, tv_shift);
if (need_shrs) {
new_shift = new_rd_Shr(dbgi, block, x, new_const, mode);
}
} else {
- assert(pnc == pn_Cmp_Gt);
+ assert(relation == ir_relation_greater);
tv_shift = tarval_sub(tv_shl, tv_shr, NULL);
new_const = new_r_Const(irg, tv_shift);
new_shift = new_rd_Shl(dbgi, block, x, new_const, mode);
/* first normalization step: try to move a constant to the false side,
* 0 preferred on false side too */
- if (is_Proj(sel)) {
- ir_node *cmp = get_Proj_pred(sel);
-
- if (is_Cmp(cmp) && is_Const(t) &&
- (!is_Const(f) || (is_Const_null(t) && !is_Const_null(f)))) {
- pn_Cmp pnc = get_Proj_pn_cmp(sel);
- ir_node *tmp = t;
- t = f;
- f = tmp;
-
- /* Mux(x, a, b) => Mux(not(x), b, a) */
- sel = new_r_Proj(cmp, mode_b,
- get_negated_pnc(pnc, get_irn_mode(get_Cmp_left(cmp))));
- n = new_rd_Mux(get_irn_dbg_info(n), get_nodes_block(n), sel, f, t, mode);
- }
+ if (is_Cmp(sel) && is_Const(t) &&
+ (!is_Const(f) || (is_Const_null(t) && !is_Const_null(f)))) {
+ dbg_info *seldbgi = get_irn_dbg_info(sel);
+ ir_node *block = get_nodes_block(sel);
+ ir_relation relation = get_Cmp_relation(sel);
+ ir_node *tmp = t;
+ t = f;
+ f = tmp;
+
+ /* Mux(x, a, b) => Mux(not(x), b, a) */
+ relation = get_negated_relation(relation);
+ sel = new_rd_Cmp(seldbgi, block, get_Cmp_left(sel),
+ get_Cmp_right(sel), relation);
+ n = new_rd_Mux(get_irn_dbg_info(n), get_nodes_block(n), sel, f, t, mode);
}
/* note: after normalization, false can only happen on default */
}
}
- if (is_Proj(sel)) {
- ir_node *cmp = get_Proj_pred(sel);
- long pn = get_Proj_proj(sel);
+ if (is_Cmp(sel)) {
+ ir_node *cmp_r = get_Cmp_right(sel);
+ if (is_Const(cmp_r) && is_Const_null(cmp_r)) {
+ ir_node *block = get_nodes_block(n);
+ ir_node *cmp_l = get_Cmp_left(sel);
- /*
- * Note: normalization puts the constant on the right side,
- * so we check only one case.
- */
- if (is_Cmp(cmp)) {
- ir_node *cmp_r = get_Cmp_right(cmp);
- if (is_Const(cmp_r) && is_Const_null(cmp_r)) {
- ir_node *block = get_nodes_block(n);
- ir_node *cmp_l = get_Cmp_left(cmp);
-
- if (mode_is_int(mode)) {
- /* integer only */
- if ((pn == pn_Cmp_Lg || pn == pn_Cmp_Eq) && is_And(cmp_l)) {
- /* Mux((a & b) != 0, c, 0) */
- ir_node *and_r = get_And_right(cmp_l);
- ir_node *and_l;
-
- if (and_r == t && f == cmp_r) {
- if (is_Const(t) && tarval_is_single_bit(get_Const_tarval(t))) {
- if (pn == pn_Cmp_Lg) {
- /* Mux((a & 2^C) != 0, 2^C, 0) */
+ if (mode_is_int(mode)) {
+ ir_relation relation = get_Cmp_relation(sel);
+ /* integer only */
+ if ((relation == ir_relation_less_greater || relation == ir_relation_equal) && is_And(cmp_l)) {
+ /* Mux((a & b) != 0, c, 0) */
+ ir_node *and_r = get_And_right(cmp_l);
+ ir_node *and_l;
+
+ if (and_r == t && f == cmp_r) {
+ if (is_Const(t) && tarval_is_single_bit(get_Const_tarval(t))) {
+ if (relation == ir_relation_less_greater) {
+ /* Mux((a & 2^C) != 0, 2^C, 0) */
+ n = cmp_l;
+ DBG_OPT_ALGSIM1(oldn, sel, sel, n, FS_OPT_MUX_TO_BITOP);
+ } else {
+ /* Mux((a & 2^C) == 0, 2^C, 0) */
+ n = new_rd_Eor(get_irn_dbg_info(n),
+ block, cmp_l, t, mode);
+ DBG_OPT_ALGSIM1(oldn, sel, sel, n, FS_OPT_MUX_TO_BITOP);
+ }
+ return n;
+ }
+ }
+ if (is_Shl(and_r)) {
+ ir_node *shl_l = get_Shl_left(and_r);
+ if (is_Const(shl_l) && is_Const_one(shl_l)) {
+ if (and_r == t && f == cmp_r) {
+ if (relation == ir_relation_less_greater) {
+ /* (a & (1 << n)) != 0, (1 << n), 0) */
n = cmp_l;
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_BITOP);
+ DBG_OPT_ALGSIM1(oldn, sel, sel, n, FS_OPT_MUX_TO_BITOP);
} else {
- /* Mux((a & 2^C) == 0, 2^C, 0) */
+ /* (a & (1 << n)) == 0, (1 << n), 0) */
n = new_rd_Eor(get_irn_dbg_info(n),
block, cmp_l, t, mode);
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_BITOP);
+ DBG_OPT_ALGSIM1(oldn, sel, sel, n, FS_OPT_MUX_TO_BITOP);
}
return n;
}
}
- if (is_Shl(and_r)) {
- ir_node *shl_l = get_Shl_left(and_r);
- if (is_Const(shl_l) && is_Const_one(shl_l)) {
- if (and_r == t && f == cmp_r) {
- if (pn == pn_Cmp_Lg) {
- /* (a & (1 << n)) != 0, (1 << n), 0) */
- n = cmp_l;
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_BITOP);
- } else {
- /* (a & (1 << n)) == 0, (1 << n), 0) */
- n = new_rd_Eor(get_irn_dbg_info(n),
- block, cmp_l, t, mode);
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_BITOP);
- }
- return n;
- }
- }
- }
- and_l = get_And_left(cmp_l);
- if (is_Shl(and_l)) {
- ir_node *shl_l = get_Shl_left(and_l);
- if (is_Const(shl_l) && is_Const_one(shl_l)) {
- if (and_l == t && f == cmp_r) {
- if (pn == pn_Cmp_Lg) {
- /* ((1 << n) & a) != 0, (1 << n), 0) */
- n = cmp_l;
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_BITOP);
- } else {
- /* ((1 << n) & a) == 0, (1 << n), 0) */
- n = new_rd_Eor(get_irn_dbg_info(n),
- block, cmp_l, t, mode);
- DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_BITOP);
- }
- return n;
+ }
+ and_l = get_And_left(cmp_l);
+ if (is_Shl(and_l)) {
+ ir_node *shl_l = get_Shl_left(and_l);
+ if (is_Const(shl_l) && is_Const_one(shl_l)) {
+ if (and_l == t && f == cmp_r) {
+ if (relation == ir_relation_less_greater) {
+ /* ((1 << n) & a) != 0, (1 << n), 0) */
+ n = cmp_l;
+ DBG_OPT_ALGSIM1(oldn, sel, sel, n, FS_OPT_MUX_TO_BITOP);
+ } else {
+ /* ((1 << n) & a) == 0, (1 << n), 0) */
+ n = new_rd_Eor(get_irn_dbg_info(n),
+ block, cmp_l, t, mode);
+ DBG_OPT_ALGSIM1(oldn, sel, sel, n, FS_OPT_MUX_TO_BITOP);
}
+ return n;
}
}
}
}
return n;
-} /* transform_node_Mux */
+}
/**
* optimize Sync nodes that have other syncs as input we simply add the inputs
switch (code) {
CASE(Add);
- CASE(Sub);
- CASE(Mul);
- CASE_PROJ_EX(Div);
- CASE_PROJ_EX(Mod);
- CASE_PROJ_EX(Cmp);
- CASE_PROJ_EX(Cond);
CASE(And);
+ CASE(Call);
+ CASE(Cmp);
+ CASE(Conv);
+ CASE(End);
CASE(Eor);
- CASE(Not);
CASE(Minus);
- CASE_PROJ(Load);
- CASE_PROJ(Store);
- CASE_PROJ(Bound);
- CASE_PROJ(CopyB);
- CASE(Proj);
- CASE(Phi);
+ CASE(Mul);
+ CASE(Mux);
+ CASE(Not);
CASE(Or);
+ CASE(Phi);
+ CASE(Proj);
+ CASE(Rotl);
CASE(Sel);
+ CASE(Shl);
CASE(Shr);
CASE(Shrs);
- CASE(Shl);
- CASE(Rotl);
- CASE(Conv);
- CASE(End);
- CASE(Mux);
+ CASE(Sub);
CASE(Sync);
- CASE(Call);
+ CASE_PROJ(Bound);
+ CASE_PROJ(CopyB);
+ CASE_PROJ(Load);
+ CASE_PROJ(Store);
+ CASE_PROJ_EX(Cond);
+ CASE_PROJ_EX(Div);
+ CASE_PROJ_EX(Mod);
default:
/* leave NULL */;
}
static int node_cmp_attr_Proj(const ir_node *a, const ir_node *b)
{
return a->attr.proj.proj != b->attr.proj.proj;
-} /* node_cmp_attr_Proj */
+}
/** Compares the attributes of two Alloc nodes. */
static int node_cmp_attr_Alloc(const ir_node *a, const ir_node *b)
const alloc_attr *pa = &a->attr.alloc;
const alloc_attr *pb = &b->attr.alloc;
return (pa->where != pb->where) || (pa->type != pb->type);
-} /* node_cmp_attr_Alloc */
+}
/** Compares the attributes of two Free nodes. */
static int node_cmp_attr_Free(const ir_node *a, const ir_node *b)
const free_attr *pa = &a->attr.free;
const free_attr *pb = &b->attr.free;
return (pa->where != pb->where) || (pa->type != pb->type);
-} /* node_cmp_attr_Free */
+}
/** Compares the attributes of two SymConst nodes. */
static int node_cmp_attr_SymConst(const ir_node *a, const ir_node *b)
const call_attr *pb = &b->attr.call;
return (pa->type != pb->type)
|| (pa->tail_call != pb->tail_call);
-} /* node_cmp_attr_Call */
+}
/** Compares the attributes of two Sel nodes. */
static int node_cmp_attr_Sel(const ir_node *a, const ir_node *b)
const ir_entity *a_ent = get_Sel_entity(a);
const ir_entity *b_ent = get_Sel_entity(b);
return a_ent != b_ent;
-} /* node_cmp_attr_Sel */
+}
/** Compares the attributes of two Phi nodes. */
static int node_cmp_attr_Phi(const ir_node *a, const ir_node *b)
return a->attr.phi.u.pos != b->attr.phi.u.pos;
}
return 0;
-} /* node_cmp_attr_Phi */
+}
/** Compares the attributes of two Conv nodes. */
static int node_cmp_attr_Conv(const ir_node *a, const ir_node *b)
{
return get_Conv_strict(a) != get_Conv_strict(b);
-} /* node_cmp_attr_Conv */
+}
/** Compares the attributes of two Cast nodes. */
static int node_cmp_attr_Cast(const ir_node *a, const ir_node *b)
{
return get_Cast_type(a) != get_Cast_type(b);
-} /* node_cmp_attr_Cast */
+}
/** Compares the attributes of two Load nodes. */
static int node_cmp_attr_Load(const ir_node *a, const ir_node *b)
return 1;
return get_Load_mode(a) != get_Load_mode(b);
-} /* node_cmp_attr_Load */
+}
/** Compares the attributes of two Store nodes. */
static int node_cmp_attr_Store(const ir_node *a, const ir_node *b)
/* NEVER do CSE on volatile Stores */
return (get_Store_volatility(a) == volatility_is_volatile ||
get_Store_volatility(b) == volatility_is_volatile);
-} /* node_cmp_attr_Store */
+}
/** Compares two exception attributes */
static int node_cmp_exception(const ir_node *a, const ir_node *b)
return ma->exc.pin_state != mb->exc.pin_state ||
ma->resmode != mb->resmode ||
ma->no_remainder != mb->no_remainder;
-} /* node_cmp_attr_Div */
+}
/** Compares the attributes of two Mod nodes. */
static int node_cmp_attr_Mod(const ir_node *a, const ir_node *b)
const mod_attr *mb = &b->attr.mod;
return ma->exc.pin_state != mb->exc.pin_state ||
ma->resmode != mb->resmode;
-} /* node_cmp_attr_Mod */
+}
+
+static int node_cmp_attr_Cmp(const ir_node *a, const ir_node *b)
+{
+ const cmp_attr *ma = &a->attr.cmp;
+ const cmp_attr *mb = &b->attr.cmp;
+ return ma->relation != mb->relation;
+}
/** Compares the attributes of two Confirm nodes. */
static int node_cmp_attr_Confirm(const ir_node *a, const ir_node *b)
{
- /* no need to compare the bound, as this is a input */
- return (get_Confirm_cmp(a) != get_Confirm_cmp(b));
-} /* node_cmp_attr_Confirm */
+ const confirm_attr *ma = &a->attr.confirm;
+ const confirm_attr *mb = &b->attr.confirm;
+ return ma->relation != mb->relation;
+}
/** Compares the attributes of two Builtin nodes. */
static int node_cmp_attr_Builtin(const ir_node *a, const ir_node *b)
{
/* no need to compare the type, equal kind means equal type */
return get_Builtin_kind(a) != get_Builtin_kind(b);
-} /* node_cmp_attr_Builtin */
+}
/** Compares the attributes of two ASM nodes. */
static int node_cmp_attr_ASM(const ir_node *a, const ir_node *b)
return 1;
}
return 0;
-} /* node_cmp_attr_ASM */
+}
/** Compares the inexistent attributes of two Dummy nodes. */
static int node_cmp_attr_Dummy(const ir_node *a, const ir_node *b)
CASE(Call);
CASE(Sel);
CASE(Phi);
+ CASE(Cmp);
CASE(Conv);
CASE(Cast);
CASE(Load);
} u;
} phi_attr;
+/**< Cmp attribute. */
+typedef struct cmp_attr {
+ ir_relation relation; /**< comparison condition. */
+} cmp_attr;
/**< Confirm attribute. */
typedef struct confirm_attr {
- pn_Cmp cmp; /**< The compare operation. */
+ ir_relation relation; /**< relation between value and bound */
} confirm_attr;
/** CopyB attribute. */
bad_attr bad; /**< for Bads: irg reference */
anchor_attr anchor; /**< for Anchor: irg reference */
block_attr block; /**< For Block: Fields needed to construct it */
+ cmp_attr cmp; /**< For Cmp. */
cond_attr cond; /**< For Cond. */
const_attr con; /**< For Const: contains the value of the constant and a type */
symconst_attr symc; /**< For SymConst. */
return 1;
}
-/**
- * verify a Proj(Cmp) node
- */
-static int verify_node_Proj_Cmp(ir_node *n, ir_node *p)
-{
- ir_mode *mode = get_irn_mode(p);
- long proj = get_Proj_proj(p);
- (void) n;
-
- ASSERT_AND_RET_DBG(
- (proj >= 0 && proj <= 15 && mode == mode_b),
- "wrong Proj from Cmp", 0,
- show_proj_failure(p);
- );
- ASSERT_AND_RET_DBG(
- (mode_is_float(get_irn_mode(get_Cmp_left(n))) || !(proj & pn_Cmp_Uo)),
- "unordered Proj for non-float Cmp (Did you use Ne instead of Lg?)", 0,
- show_proj_failure(p);
- );
- return 1;
-}
-
/**
* verify a Proj(Load) node
*/
/* Cmp: BB x datab x datab --> b16 */
mode_is_datab(op1mode) &&
op2mode == op1mode &&
- mymode == mode_T,
+ mymode == mode_b,
"Cmp node", 0,
show_binop_failure(n, "/* Cmp: BB x datab x datab --> b16 */");
);
CASE(Call);
CASE(Div);
CASE(Mod);
- CASE(Cmp);
CASE(Load);
CASE(Store);
CASE(Alloc);
*/
static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env)
{
- ir_node *cmp, *left, *right, *block;
+ ir_node *left, *right, *block;
ir_node *sel = get_Cond_selector(node);
ir_mode *m = get_irn_mode(sel);
ir_mode *cmp_mode;
const node_entry_t *lentry, *rentry;
ir_node *proj, *projT = NULL, *projF = NULL;
- ir_node *new_bl, *cmpH, *cmpL, *irn;
+ ir_node *new_bl, *irn;
ir_node *projHF, *projHT;
ir_node *dst_blk;
- pn_Cmp pnc;
+ ir_relation relation;
ir_graph *irg;
dbg_info *dbg;
return;
}
- if (!is_Proj(sel))
+ if (!is_Cmp(sel))
return;
- cmp = get_Proj_pred(sel);
- if (!is_Cmp(cmp))
- return;
-
- left = get_Cmp_left(cmp);
+ left = get_Cmp_left(sel);
cmp_mode = get_irn_mode(left);
if (cmp_mode != env->high_signed && cmp_mode != env->high_unsigned)
return;
- right = get_Cmp_right(cmp);
+ right = get_Cmp_right(sel);
lentry = get_node_entry(env, left);
rentry = get_node_entry(env, right);
assert(projT && projF);
/* create a new high compare */
- block = get_nodes_block(node);
- irg = get_Block_irg(block);
- dbg = get_irn_dbg_info(cmp);
- pnc = get_Proj_pn_cmp(sel);
+ block = get_nodes_block(node);
+ irg = get_Block_irg(block);
+ dbg = get_irn_dbg_info(sel);
+ relation = get_Cmp_relation(sel);
if (is_Const(right) && is_Const_null(right)) {
- if (pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) {
+ if (relation == ir_relation_equal || relation == ir_relation_less_greater) {
/* x ==/!= 0 ==> or(low,high) ==/!= 0 */
ir_mode *mode = env->low_unsigned;
ir_node *low = new_r_Conv(block, lentry->low_word, mode);
ir_node *high = new_r_Conv(block, lentry->high_word, mode);
ir_node *ornode = new_rd_Or(dbg, block, low, high, mode);
- ir_node *cmp = new_rd_Cmp(dbg, block, ornode, new_r_Const_long(irg, mode, 0));
-
- ir_node *proj = new_r_Proj(cmp, mode_b, pnc);
- set_Cond_selector(node, proj);
+ ir_node *cmp = new_rd_Cmp(dbg, block, ornode, new_r_Const_long(irg, mode, 0), relation);
+ set_Cond_selector(node, cmp);
return;
}
}
- cmpH = new_rd_Cmp(dbg, block, lentry->high_word, rentry->high_word);
-
- if (pnc == pn_Cmp_Eq) {
+ if (relation == ir_relation_equal) {
/* simple case:a == b <==> a_h == b_h && a_l == b_l */
pmap_entry *entry = pmap_find(env->proj_2_block, projF);
assert(entry);
dst_blk = (ir_node*)entry->value;
- irn = new_r_Proj(cmpH, mode_b, pn_Cmp_Eq);
+ irn = new_rd_Cmp(dbg, block, lentry->high_word, rentry->high_word,
+ ir_relation_equal);
dbg = get_irn_dbg_info(node);
irn = new_rd_Cond(dbg, block, irn);
new_bl = new_r_Block(irg, 1, &projHT);
- dbg = get_irn_dbg_info(cmp);
- cmpL = new_rd_Cmp(dbg, new_bl, lentry->low_word, rentry->low_word);
- irn = new_r_Proj(cmpL, mode_b, pn_Cmp_Eq);
+ dbg = get_irn_dbg_info(sel);
+ irn = new_rd_Cmp(dbg, new_bl, lentry->low_word, rentry->low_word,
+ ir_relation_equal);
dbg = get_irn_dbg_info(node);
irn = new_rd_Cond(dbg, new_bl, irn);
proj = new_r_Proj(irn, mode_X, pn_Cond_true);
mark_irn_visited(proj);
exchange(projT, proj);
- } else if (pnc == pn_Cmp_Lg) {
+ } else if (relation == ir_relation_less_greater) {
/* simple case:a != b <==> a_h != b_h || a_l != b_l */
pmap_entry *entry = pmap_find(env->proj_2_block, projT);
assert(entry);
dst_blk = (ir_node*)entry->value;
- irn = new_r_Proj(cmpH, mode_b, pn_Cmp_Lg);
+ irn = new_rd_Cmp(dbg, block, lentry->high_word, rentry->high_word,
+ ir_relation_less_greater);
dbg = get_irn_dbg_info(node);
irn = new_rd_Cond(dbg, block, irn);
new_bl = new_r_Block(irg, 1, &projHF);
- dbg = get_irn_dbg_info(cmp);
- cmpL = new_rd_Cmp(dbg, new_bl, lentry->low_word, rentry->low_word);
- irn = new_r_Proj(cmpL, mode_b, pn_Cmp_Lg);
+ dbg = get_irn_dbg_info(sel);
+ irn = new_rd_Cmp(dbg, new_bl, lentry->low_word, rentry->low_word,
+ ir_relation_less_greater);
dbg = get_irn_dbg_info(node);
irn = new_rd_Cond(dbg, new_bl, irn);
assert(entry);
dstF = (ir_node*)entry->value;
- irn = new_r_Proj(cmpH, mode_b, pnc & ~pn_Cmp_Eq);
+ irn = new_rd_Cmp(dbg, block, lentry->high_word, rentry->high_word,
+ relation & ~ir_relation_equal);
dbg = get_irn_dbg_info(node);
irn = new_rd_Cond(dbg, block, irn);
newbl_eq = new_r_Block(irg, 1, &projHF);
- irn = new_r_Proj(cmpH, mode_b, pn_Cmp_Eq);
+ irn = new_rd_Cmp(dbg, block, lentry->high_word, rentry->high_word,
+ ir_relation_equal);
irn = new_rd_Cond(dbg, newbl_eq, irn);
proj = new_r_Proj(irn, mode_X, pn_Cond_false);
newbl_l = new_r_Block(irg, 1, &proj);
- dbg = get_irn_dbg_info(cmp);
- cmpL = new_rd_Cmp(dbg, newbl_l, lentry->low_word, rentry->low_word);
- irn = new_r_Proj(cmpL, mode_b, pnc);
+ dbg = get_irn_dbg_info(sel);
+ irn = new_rd_Cmp(dbg, newbl_l, lentry->low_word, rentry->low_word,
+ relation);
dbg = get_irn_dbg_info(node);
irn = new_rd_Cond(dbg, newbl_l, irn);
}
/**
- * lower boolean Proj(Cmp)
+ * lower Cmp
*/
-static void lower_Proj_Cmp(lower_env_t *env, ir_node *proj)
+static void lower_Cmp(ir_node *cmp, ir_mode *m, lower_env_t *env)
{
- ir_node *cmp = get_Proj_pred(proj);
ir_node *l = get_Cmp_left(cmp);
ir_mode *mode = get_irn_mode(l);
ir_node *r, *low, *high, *t, *res;
- pn_Cmp pnc;
+ ir_relation relation;
ir_node *blk;
dbg_info *db;
const node_entry_t *lentry;
const node_entry_t *rentry;
+ (void) m;
if (mode != env->high_signed && mode != env->high_unsigned) {
return;
}
- r = get_Cmp_right(cmp);
- lentry = get_node_entry(env, l);
- rentry = get_node_entry(env, r);
- pnc = get_Proj_pn_cmp(proj);
- blk = get_nodes_block(cmp);
- db = get_irn_dbg_info(cmp);
- low = new_rd_Cmp(db, blk, lentry->low_word, rentry->low_word);
- high = new_rd_Cmp(db, blk, lentry->high_word, rentry->high_word);
+ r = get_Cmp_right(cmp);
+ lentry = get_node_entry(env, l);
+ rentry = get_node_entry(env, r);
+ relation = get_Cmp_relation(cmp);
+ blk = get_nodes_block(cmp);
+ db = get_irn_dbg_info(cmp);
- if (pnc == pn_Cmp_Eq) {
+ if (relation == ir_relation_equal) {
/* simple case:a == b <==> a_h == b_h && a_l == b_l */
- res = new_rd_And(db, blk,
- new_r_Proj(low, mode_b, pnc),
- new_r_Proj(high, mode_b, pnc),
- mode_b);
- } else if (pnc == pn_Cmp_Lg) {
+ low = new_rd_Cmp(db, blk, lentry->low_word, rentry->low_word,
+ relation);
+ high = new_rd_Cmp(db, blk, lentry->high_word, rentry->high_word,
+ relation);
+ res = new_rd_And(db, blk, low, high, mode_b);
+ } else if (relation == ir_relation_less_greater) {
/* simple case:a != b <==> a_h != b_h || a_l != b_l */
- res = new_rd_Or(db, blk,
- new_r_Proj(low, mode_b, pnc),
- new_r_Proj(high, mode_b, pnc),
- mode_b);
+ low = new_rd_Cmp(db, blk, lentry->low_word, rentry->low_word,
+ relation);
+ high = new_rd_Cmp(db, blk, lentry->high_word, rentry->high_word,
+ relation);
+ res = new_rd_Or(db, blk, low, high, mode_b);
} else {
- /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
- t = new_rd_And(db, blk,
- new_r_Proj(low, mode_b, pnc),
- new_r_Proj(high, mode_b, pn_Cmp_Eq),
- mode_b);
- res = new_rd_Or(db, blk,
- new_r_Proj(high, mode_b, pnc & ~pn_Cmp_Eq),
- t,
- mode_b);
- }
- exchange(proj, res);
-}
+ low = new_rd_Cmp(db, blk, lentry->low_word, rentry->low_word,
+ relation);
+ high = new_rd_Cmp(db, blk, lentry->high_word, rentry->high_word,
+ ir_relation_equal);
-static void lower_Proj(ir_node *node, ir_mode *mode, lower_env_t *env)
-{
- ir_node *pred = get_Proj_pred(node);
- (void) mode;
- if (is_Cmp(pred)) {
- lower_Proj_Cmp(env, node);
+ /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */
+ ir_node *high1 = new_rd_Cmp(db, blk, lentry->high_word,
+ rentry->high_word, relation & ~ir_relation_equal);
+ t = new_rd_And(db, blk, low, high, mode_b);
+ res = new_rd_Or(db, blk, high1, t, mode_b);
}
+ exchange(cmp, res);
}
/**
}
clear_irp_opcodes_generic_func();
+ enter_lower_func(op_ASM, lower_ASM);
enter_lower_func(op_Add, lower_binop);
enter_lower_func(op_And, lower_And);
- enter_lower_func(op_ASM, lower_ASM);
enter_lower_func(op_Call, lower_Call);
+ enter_lower_func(op_Cmp, lower_Cmp);
enter_lower_func(op_Cond, lower_Cond);
enter_lower_func(op_Const, lower_Const);
enter_lower_func(op_Conv, lower_Conv);
enter_lower_func(op_Mux, lower_Mux);
enter_lower_func(op_Not, lower_Not);
enter_lower_func(op_Or, lower_Or);
- enter_lower_func(op_Proj, lower_Proj);
enter_lower_func(op_Return, lower_Return);
enter_lower_func(op_Sel, lower_Sel);
enter_lower_func(op_Shl, lower_Shl);
ir_mode *mode = get_irn_mode(op);
dbg_info *dbg = get_irn_dbg_info(call);
ir_node *zero = new_r_Const(irg, get_mode_null(mode));
- ir_node *cmp = new_rd_Cmp(dbg, block, op, zero);
- ir_node *cond = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
+ ir_node *cmp = new_rd_Cmp(dbg, block, op, zero, ir_relation_less);
ir_node *minus_op = new_rd_Minus(dbg, block, op, mode);
ir_node *mux;
arch_allow_ifconv_func allow_ifconv = be_get_backend_param()->allow_ifconv;
(void) ctx;
/* mux allowed by backend? */
- if (!allow_ifconv(cond, op, minus_op))
+ if (!allow_ifconv(cmp, op, minus_op))
return 0;
/* construct Mux */
- mux = new_rd_Mux(dbg, block, cond, op, minus_op, mode);
+ mux = new_rd_Mux(dbg, block, cmp, op, minus_op, mode);
DBG_OPT_ALGSIM0(call, mux, FS_OPT_RTS_ABS);
replace_call(mux, call, mem, NULL, NULL);
return 1;
ir_tarval *tv_zeroc = get_mode_null(mode);
ir_node *zero_cmp = new_rd_Const(dbgi, irg, tv_zeroc);
- ir_node *cmp = new_rd_Cmp(dbgi, block, pred, zero_cmp);
- ir_node *proj = new_rd_Proj(dbgi, cmp, mode_b, pn_Cmp_Lg);
- res = config->create_set(proj);
+ ir_node *cmp = new_rd_Cmp(dbgi, block, pred, zero_cmp, ir_relation_less_greater);
+ res = config->create_set(cmp);
break;
}
- case iro_Proj: {
- ir_node *pred = get_Proj_pred(node);
-
- if (is_Cmp(pred)) {
- ir_node *left = get_Cmp_left(pred);
- ir_node *right = get_Cmp_right(pred);
- ir_mode *cmp_mode = get_irn_mode(left);
-
- if ((mode_is_int(cmp_mode) || mode_is_reference(cmp_mode)) &&
- (get_mode_size_bits(cmp_mode) < get_mode_size_bits(mode) ||
- (mode_is_signed(cmp_mode) && is_Const(right) && is_Const_null(right)))) {
- int pnc = get_Proj_proj(node);
- int need_not = 0;
- ir_node *a = NULL;
- ir_node *b = NULL;
- int bits;
- ir_tarval *tv;
- ir_node *shift_cnt;
-
- if (pnc == pn_Cmp_Lt) {
- /* a < b -> (a - b) >> 31 */
- a = left;
- b = right;
- } else if (pnc == pn_Cmp_Le) {
- /* a <= b -> ~(a - b) >> 31 */
- a = right;
- b = left;
- need_not = 1;
- } else if (pnc == pn_Cmp_Gt) {
- /* a > b -> (b - a) >> 31 */
- a = right;
- b = left;
- } else if (pnc == pn_Cmp_Ge) {
- /* a >= b -> ~(a - b) >> 31 */
- a = left;
- b = right;
- need_not = 1;
- } else {
- goto synth_zero_one;
- }
+ case iro_Cmp: {
+ ir_node *left = get_Cmp_left(node);
+ ir_node *right = get_Cmp_right(node);
+ ir_mode *cmp_mode = get_irn_mode(left);
+
+ if ((mode_is_int(cmp_mode) || mode_is_reference(cmp_mode)) &&
+ (get_mode_size_bits(cmp_mode) < get_mode_size_bits(mode) ||
+ (mode_is_signed(cmp_mode) && is_Const(right) && is_Const_null(right)))) {
+ ir_relation relation = get_Cmp_relation(node);
+ int need_not = 0;
+ ir_node *a = NULL;
+ ir_node *b = NULL;
+ int bits;
+ ir_tarval *tv;
+ ir_node *shift_cnt;
+
+ if (relation == ir_relation_less) {
+ /* a < b -> (a - b) >> 31 */
+ a = left;
+ b = right;
+ } else if (relation == ir_relation_less_equal) {
+ /* a <= b -> ~(a - b) >> 31 */
+ a = right;
+ b = left;
+ need_not = 1;
+ } else if (relation == ir_relation_greater) {
+ /* a > b -> (b - a) >> 31 */
+ a = right;
+ b = left;
+ } else if (relation == ir_relation_greater_equal) {
+ /* a >= b -> ~(a - b) >> 31 */
+ a = left;
+ b = right;
+ need_not = 1;
+ } else {
+ goto synth_zero_one;
+ }
- bits = get_mode_size_bits(mode);
- tv = new_tarval_from_long(bits-1, mode_Iu);
- shift_cnt = new_rd_Const(dbgi, irg, tv);
+ bits = get_mode_size_bits(mode);
+ tv = new_tarval_from_long(bits-1, mode_Iu);
+ shift_cnt = new_rd_Const(dbgi, irg, tv);
- if (cmp_mode != mode) {
- a = new_rd_Conv(dbgi, block, a, mode);
- b = new_rd_Conv(dbgi, block, b, mode);
- }
+ if (cmp_mode != mode) {
+ a = new_rd_Conv(dbgi, block, a, mode);
+ b = new_rd_Conv(dbgi, block, b, mode);
+ }
- res = new_rd_Sub(dbgi, block, a, b, mode);
- if (need_not) {
- res = new_rd_Not(dbgi, block, res, mode);
- }
- res = new_rd_Shr(dbgi, block, res, shift_cnt, mode);
- } else {
- /* synthesize the 0/1 value */
-synth_zero_one:
- res = config->create_set(node);
+ res = new_rd_Sub(dbgi, block, a, b, mode);
+ if (need_not) {
+ res = new_rd_Not(dbgi, block, res, mode);
}
- } else if (is_Proj(pred) && is_Call(get_Proj_pred(pred))) {
+ res = new_rd_Shr(dbgi, block, res, shift_cnt, mode);
+ } else {
+ /* synthesize the 0/1 value */
+synth_zero_one:
+ res = config->create_set(node);
+ }
+ break;
+ }
+
+ case iro_Proj: {
+ ir_node *pred = get_Proj_pred(node);
+
+ if (is_Proj(pred) && is_Call(get_Proj_pred(pred))) {
ir_type *type = get_Call_type(get_Proj_pred(pred));
adjust_method_type(type);
set_irn_mode(node, mode);
continue;
if (! config->lower_direct_cmp) {
- /* Proj(Cmp) as input for Cond and Mux nodes needs no changes.
+ /* Cmp as input for Cond and Mux nodes needs no changes.
(Mux with mode_b is an exception as it gets replaced by and/or
anyway so we still lower the inputs then) */
if (is_Cond(node) ||
(is_Mux(node) && get_irn_mode(node) != mode_b)) {
- if (is_Proj(in)) {
- ir_node *pred = get_Proj_pred(in);
- if (is_Cmp(pred))
- continue;
+ if (is_Cmp(in)) {
+ continue;
}
}
}
} else if (numcases == 1) {
/* only one case: "if (sel == val) goto target else goto default;" */
ir_node *val = new_r_Const_long(irg, cmp_mode, curcases[0].value);
- ir_node *cmp = new_rd_Cmp(dbgi, block, cmp_sel, val);
- ir_node *proj = new_r_Proj(cmp, mode_b, pn_Cmp_Eq);
- ir_node *cond = new_rd_Cond(dbgi, block, proj);
+ ir_node *cmp = new_rd_Cmp(dbgi, block, cmp_sel, val,
+ ir_relation_equal);
+ ir_node *cond = new_rd_Cond(dbgi, block, cmp);
ir_node *trueproj = new_r_Proj(cond, mode_X, pn_Cond_true);
ir_node *falseproj = new_r_Proj(cond, mode_X, pn_Cond_false);
} else if (numcases == 2) {
/* only two cases: "if (sel == val[0]) goto target[0];" */
ir_node *val = new_r_Const_long(irg, cmp_mode, curcases[0].value);
- ir_node *cmp = new_rd_Cmp(dbgi, block, cmp_sel, val);
- ir_node *proj = new_r_Proj(cmp, mode_b, pn_Cmp_Eq);
- ir_node *cond = new_rd_Cond(dbgi, block, proj);
+ ir_node *cmp = new_rd_Cmp(dbgi, block, cmp_sel, val,
+ ir_relation_equal);
+ ir_node *cond = new_rd_Cond(dbgi, block, cmp);
ir_node *trueproj = new_r_Proj(cond, mode_X, pn_Cond_true);
ir_node *falseproj = new_r_Proj(cond, mode_X, pn_Cond_false);
ir_node *in[1];
/* second part: "else if (sel == val[1]) goto target[1] else goto default;" */
val = new_r_Const_long(irg, cmp_mode, curcases[1].value);
- cmp = new_rd_Cmp(dbgi, neblock, cmp_sel, val);
- proj = new_r_Proj(cmp, mode_b, pn_Cmp_Eq);
- cond = new_rd_Cond(dbgi, neblock, proj);
+ cmp = new_rd_Cmp(dbgi, neblock, cmp_sel, val, ir_relation_equal);
+ cond = new_rd_Cond(dbgi, neblock, cmp);
trueproj = new_r_Proj(cond, mode_X, pn_Cond_true);
falseproj = new_r_Proj(cond, mode_X, pn_Cond_false);
set_Block_cfgpred(curcases[1].target, 0, trueproj);
int midcase = numcases / 2;
ir_node *val = new_r_Const_long(irg, cmp_mode,
curcases[midcase].value);
- ir_node *cmp = new_rd_Cmp(dbgi, block, cmp_sel, val);
- ir_node *proj = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
- ir_node *cond = new_rd_Cond(dbgi, block, proj);
+ ir_node *cmp = new_rd_Cmp(dbgi, block, cmp_sel, val, ir_relation_less);
+ ir_node *cond = new_rd_Cond(dbgi, block, cmp);
ir_node *in[1];
ir_node *ltblock;
ir_node *geblock;
ir_node *proj_true;
ir_node *proj_false;
ir_node *cmp;
- ir_node *proj_cmp;
ir_node *oob_cond;
ir_node *in[1];
ir_node *new_block;
/* check for out-of-bounds */
max_const = new_r_Const_long(irg, cmp_mode, env->switch_max);
- cmp = new_rd_Cmp(dbgi, block, sel, max_const);
- proj_cmp = new_r_Proj(cmp, mode_b, pn_Cmp_Le);
- oob_cond = new_rd_Cond(dbgi, block, proj_cmp);
+ cmp = new_rd_Cmp(dbgi, block, sel, max_const, ir_relation_less);
+ oob_cond = new_rd_Cond(dbgi, block, cmp);
proj_true = new_r_Proj(oob_cond, mode_X, pn_Cond_true);
proj_false = new_r_Proj(oob_cond, mode_X, pn_Cond_false);
#include "irpass.h"
#include "debug.h"
-/** Describes a pair of relative conditions lo < hi, lo pnc_lo x, hi pnc_hi x */
+/** Describes a pair of relative conditions lo < hi, lo rel_lo x, hi rel_hi x */
typedef struct cond_pair {
- ir_node *cmp_lo; /**< The lo compare node. */
- ir_node *cmp_hi; /**< The hi compare node. */
- pn_Cmp pnc_lo; /**< The lo relation node. */
- pn_Cmp pnc_hi; /**< The hi relation node. */
- ir_node *proj_lo; /**< The mode_b result proj of cmp_lo. */
- ir_node *proj_hi; /**< The mode_b result proj of cmp_hi. */
- ir_tarval *tv_lo; /**< The tarval of cmp_lo node. */
- ir_tarval *tv_hi; /**< The tarval of cmp_hi node. */
- ir_mode *lo_mode; /**< The mode of the cmp_lo operands. */
+ ir_node *cmp_lo; /**< The lo compare node. */
+ ir_node *cmp_hi; /**< The hi compare node. */
+ ir_relation rel_lo; /**< The lo relation node. */
+ ir_relation rel_hi; /**< The hi relation node. */
+ ir_tarval *tv_lo; /**< The tarval of cmp_lo node. */
+ ir_tarval *tv_hi; /**< The tarval of cmp_hi node. */
+ ir_mode *lo_mode; /**< The mode of the cmp_lo operands. */
} cond_pair;
/** Environment for all walker in boolopt. */
* Check if tho given nodes, l and r, represent two compares with
* ... . If yes, return non-zero and fill the res struct.
*/
-static int find_cond_pair(ir_node *const l, ir_node *const r, cond_pair *const res)
+static bool find_cond_pair(ir_node *const l, ir_node *const r, cond_pair *const res)
{
- if (is_Proj(l) && is_Proj(r)) {
- ir_node *const lo = get_Proj_pred(l);
- ir_node *const ro = get_Proj_pred(r);
-
- if (is_Cmp(lo) && is_Cmp(ro)) {
- ir_node *const lol = get_Cmp_left(lo);
- ir_node *const lor = get_Cmp_right(lo);
- ir_node *const rol = get_Cmp_left(ro);
- ir_node *const ror = get_Cmp_right(ro);
- pn_Cmp const pnc_l = get_Proj_pn_cmp(l);
- pn_Cmp const pnc_r = get_Proj_pn_cmp(r);
-
- if (is_Const(lor) && is_Const_null(lor) &&
- is_Const(ror) && is_Const_null(ror) &&
- pnc_l == pnc_r &&
- (pnc_l == pn_Cmp_Lg || pnc_l == pn_Cmp_Eq)) {
- /* lo == (lol !=|== NULL) && ro == (rol !=|== NULL) */
- res->cmp_lo = lo;
- res->cmp_hi = ro;
- res->pnc_lo = pnc_l;
- res->pnc_hi = pnc_l;
- res->proj_lo = l;
- res->proj_hi = r;
- res->tv_lo = get_Const_tarval(lor);
- res->tv_hi = get_Const_tarval(ror);
- res->lo_mode = get_irn_mode(lor);
-
- return 1;
- }
+ if (!is_Cmp(l) || !is_Cmp(r))
+ return false;
+
+ ir_node *const lol = get_Cmp_left(l);
+ ir_node *const lor = get_Cmp_right(l);
+ ir_node *const rol = get_Cmp_left(r);
+ ir_node *const ror = get_Cmp_right(r);
+ ir_relation const pnc_l = get_Cmp_relation(l);
+ ir_relation const pnc_r = get_Cmp_relation(r);
+
+ if (is_Const(lor) && is_Const_null(lor) &&
+ is_Const(ror) && is_Const_null(ror) &&
+ pnc_l == pnc_r &&
+ (pnc_l == ir_relation_less_greater || pnc_l == ir_relation_equal)) {
+ /* l == (lol !=|== NULL) && r == (rol !=|== NULL) */
+ res->cmp_lo = l;
+ res->cmp_hi = r;
+ res->rel_lo = pnc_l;
+ res->rel_hi = pnc_l;
+ res->tv_lo = get_Const_tarval(lor);
+ res->tv_hi = get_Const_tarval(ror);
+ res->lo_mode = get_irn_mode(lor);
+
+ return true;
+ }
- if (lol == rol && lor != ror && is_Const(lor) && is_Const(ror)) {
- /* lo == (x CMP c_l), ro == (x cmp c_r) */
- ir_tarval *const tv_l = get_Const_tarval(lor);
- ir_tarval *const tv_r = get_Const_tarval(ror);
- pn_Cmp const rel = tarval_cmp(tv_l, tv_r);
-
- res->lo_mode = get_irn_mode(lol);
-
- if (rel == pn_Cmp_Lt) {
- /* c_l < c_r */
- res->cmp_lo = lo;
- res->cmp_hi = ro;
- res->pnc_lo = pnc_l;
- res->pnc_hi = pnc_r;
- res->proj_lo = l;
- res->proj_hi = r;
- res->tv_lo = tv_l;
- res->tv_hi = tv_r;
- } else if (rel == pn_Cmp_Gt) {
- /* c_l > c_r */
- res->cmp_lo = ro;
- res->cmp_hi = lo;
- res->pnc_lo = pnc_r;
- res->pnc_hi = pnc_l;
- res->proj_lo = r;
- res->proj_hi = l;
- res->tv_lo = tv_r;
- res->tv_hi = tv_l;
- } else {
- /* The constants shall be unequal but comparable.
- * Local optimizations handle the equal case. */
- return 0;
- }
- return 1;
- }
+ if (lol == rol && lor != ror && is_Const(lor) && is_Const(ror)) {
+ /* l == (x CMP c_l), r == (x cmp c_r) */
+ ir_tarval *const tv_l = get_Const_tarval(lor);
+ ir_tarval *const tv_r = get_Const_tarval(ror);
+ ir_relation const rel = tarval_cmp(tv_l, tv_r);
+
+ res->lo_mode = get_irn_mode(lol);
+
+ if (rel == ir_relation_less) {
+ /* c_l < c_r */
+ res->cmp_lo = l;
+ res->cmp_hi = r;
+ res->rel_lo = pnc_l;
+ res->rel_hi = pnc_r;
+ res->tv_lo = tv_l;
+ res->tv_hi = tv_r;
+ } else if (rel == ir_relation_greater) {
+ /* c_l > c_r */
+ res->cmp_lo = r;
+ res->cmp_hi = l;
+ res->rel_lo = pnc_r;
+ res->rel_hi = pnc_l;
+ res->tv_lo = tv_r;
+ res->tv_hi = tv_l;
+ } else {
+ /* The constants shall be unequal but comparable.
+ * Local optimizations handle the equal case. */
+ return false;
}
+ return true;
}
- return 0;
+ return false;
}
/**
- * Handle (lo pnc_lo x) AND (hi pnc_hi x)
+ * Handle (lo rel_lo x) AND (hi rel_hi x)
*/
static ir_node *bool_and(cond_pair* const cpair, ir_node *dst_block)
{
ir_node *const cmp_lo = cpair->cmp_lo;
ir_node *const cmp_hi = cpair->cmp_hi;
- pn_Cmp pnc_lo = cpair->pnc_lo;
- pn_Cmp const pnc_hi = cpair->pnc_hi;
- ir_node *const proj_lo = cpair->proj_lo;
- ir_node *const proj_hi = cpair->proj_hi;
+ ir_relation rel_lo = cpair->rel_lo;
+ ir_relation const rel_hi = cpair->rel_hi;
ir_tarval * tv_lo = cpair->tv_lo;
ir_tarval * tv_hi = cpair->tv_hi;
ir_mode * mode = cpair->lo_mode;
ir_graph * irg = get_irn_irg(cmp_lo);
- if (pnc_lo == pn_Cmp_Eq && pnc_hi == pn_Cmp_Eq &&
+ if (rel_lo == ir_relation_equal && rel_hi == rel_lo &&
tarval_is_null(tv_lo) && tarval_is_null(tv_hi) &&
mode == get_tarval_mode(tv_hi)) {
/* p == NULL && q == NULL ==> (p&q) == NULL) */
hil = new_r_Conv(dst_block, hil, mode);
p = new_r_And(dst_block, lol, hil, mode);
c = new_r_Const(irg, tv_lo);
- cmp = new_r_Cmp(dst_block, p, c);
- p = new_r_Proj(cmp, mode_b, pn_Cmp_Eq);
- return p;
+ cmp = new_r_Cmp(dst_block, p, c, ir_relation_equal);
+ return cmp;
}
}
return 0;
/* Beware of NaN's, we can only check for (ordered) != here (which is Lg, not Ne) */
- if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le || pnc_lo == pn_Cmp_Eq) &&
- (pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) {
+ if ((rel_lo == ir_relation_less || rel_lo == ir_relation_less_equal || rel_lo == ir_relation_equal) &&
+ (rel_hi == ir_relation_equal || rel_hi == ir_relation_greater_equal || rel_hi == ir_relation_greater)) {
/* x <|<=|== lo && x ==|>=|> hi ==> false */
ir_node *const t = new_r_Const(irg, tarval_b_false);
return t;
- } else if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le || pnc_lo == pn_Cmp_Eq) &&
- (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Lg)) {
+ } else if ((rel_lo == ir_relation_less || rel_lo == ir_relation_less_equal || rel_lo == ir_relation_equal) &&
+ (rel_hi == ir_relation_less || rel_hi == ir_relation_less_equal || rel_hi == ir_relation_less_greater)) {
/* x <|<=|== lo && x <|<=|!= hi ==> x <|<=|== lo */
- return proj_lo;
- } else if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Lg) &&
- (pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) {
+ return cmp_lo;
+ } else if ((rel_lo == ir_relation_greater_equal || rel_lo == ir_relation_greater || rel_lo == ir_relation_less_greater) &&
+ (rel_hi == ir_relation_equal || rel_hi == ir_relation_greater_equal || rel_hi == ir_relation_greater)) {
/* x >=|>|!= lo && x ==|>=|> hi ==> x ==|>=|> hi */
- return proj_hi;
+ return cmp_hi;
} else if (tarval_is_one(tarval_sub(tv_hi, tv_lo, NULL))) { /* lo + 1 == hi */
- if (pnc_lo == pn_Cmp_Ge && pnc_hi == pn_Cmp_Lt) {
+ if (rel_lo == ir_relation_greater_equal && rel_hi == ir_relation_less) {
/* x >= c && x < c + 1 ==> x == c */
- ir_node *const p = new_r_Proj(cmp_lo, mode_b, pn_Cmp_Eq);
+ ir_node *const p = new_r_Proj(cmp_lo, mode_b, ir_relation_equal);
return p;
- } else if (pnc_lo == pn_Cmp_Gt) {
- if (pnc_hi == pn_Cmp_Lg) {
+ } else if (rel_lo == ir_relation_greater) {
+ if (rel_hi == ir_relation_less_greater) {
/* x > c && x != c + 1 ==> x > c + 1 */
- ir_node *const p = new_r_Proj(cmp_hi, mode_b, pn_Cmp_Gt);
+ ir_node *const p = new_r_Proj(cmp_hi, mode_b, ir_relation_greater);
return p;
- } else if (pnc_hi == pn_Cmp_Lt) {
+ } else if (rel_hi == ir_relation_less) {
/* x > c && x < c + 1 ==> false */
ir_node *const t = new_r_Const(irg, tarval_b_false);
return t;
- } else if (pnc_hi == pn_Cmp_Le) {
+ } else if (rel_hi == ir_relation_less_equal) {
/* x > c && x <= c + 1 ==> x != c + 1 */
- ir_node *const p = new_r_Proj(cmp_hi, mode_b, pn_Cmp_Eq);
+ ir_node *const p = new_r_Proj(cmp_hi, mode_b, ir_relation_equal);
return p;
}
- } else if (pnc_lo == pn_Cmp_Lg && pnc_hi == pn_Cmp_Lt) {
+ } else if (rel_lo == ir_relation_less_greater && rel_hi == ir_relation_less) {
/* x != c && c < c + 1 ==> x < c */
- ir_node *const p = new_r_Proj(cmp_lo, mode_b, pn_Cmp_Lt);
+ ir_node *const p = new_r_Proj(cmp_lo, mode_b, ir_relation_less);
return p;
}
- } else if ((pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Ge) &&
- (pnc_hi == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le) &&
+ } else if ((rel_lo == ir_relation_greater || rel_lo == ir_relation_greater_equal) &&
+ (rel_hi == ir_relation_less || rel_lo == ir_relation_less_equal) &&
get_mode_arithmetic(mode) == irma_twos_complement) {
/* works for two-complements only */
/* x >|\= lo && x <|<= hi ==> (x - lo) <u|<=u (hi-lo) */
- if (pnc_lo == pn_Cmp_Gt) {
+ if (rel_lo == ir_relation_greater) {
/* must convert to >= */
ir_mode *mode = get_tarval_mode(tv_lo);
ir_tarval *n = tarval_add(tv_lo, get_mode_one(mode));
- if (n != tarval_bad && tarval_cmp(n, tv_lo) == pn_Cmp_Gt) {
+ if (n != tarval_bad && tarval_cmp(n, tv_lo) == ir_relation_greater) {
/* no overflow */
tv_lo = n;
- pnc_lo = pn_Cmp_Ge;
+ rel_lo = ir_relation_greater_equal;
}
}
- if (pnc_lo == pn_Cmp_Ge) {
+ if (rel_lo == ir_relation_greater_equal) {
/* all fine */
ir_node *const block = get_nodes_block(cmp_hi);
ir_node * x = get_Cmp_left(cmp_hi);
ir_mode * mode = get_irn_mode(x);
- ir_node *sub, *cmp, *c, *subc, *p;
+ ir_node *sub, *cmp, *c, *subc;
if (mode_is_signed(mode)) {
/* convert to unsigned */
c = new_r_Const(irg, tv_lo);
sub = new_r_Sub(block, x, c, mode);
subc = new_r_Sub(block, new_r_Const(irg, tv_hi), c, mode);
- cmp = new_r_Cmp(block, sub, subc);
- p = new_r_Proj(cmp, mode_b, pnc_hi);
- return p;
+ cmp = new_r_Cmp(block, sub, subc, rel_hi);
+ return cmp;
}
}
return NULL;
}
/**
- * Handle (lo pnc_lo x) OR (hi pnc_hi x)
+ * Handle (lo rel_lo x) OR (hi rel_hi x)
*/
static ir_node *bool_or(cond_pair *const cpair, ir_node *dst_block)
{
- ir_node *const cmp_lo = cpair->cmp_lo;
- ir_node *const cmp_hi = cpair->cmp_hi;
- pn_Cmp pnc_lo = cpair->pnc_lo;
- pn_Cmp const pnc_hi = cpair->pnc_hi;
- ir_node *const proj_lo = cpair->proj_lo;
- ir_node *const proj_hi = cpair->proj_hi;
- ir_tarval * tv_lo = cpair->tv_lo;
- ir_tarval * tv_hi = cpair->tv_hi;
- ir_mode * mode = cpair->lo_mode;
- ir_graph * irg = get_irn_irg(cmp_lo);
-
- if (pnc_lo == pn_Cmp_Lg && pnc_hi == pn_Cmp_Lg &&
+ ir_node *const cmp_lo = cpair->cmp_lo;
+ ir_node *const cmp_hi = cpair->cmp_hi;
+ ir_relation rel_lo = cpair->rel_lo;
+ ir_relation const rel_hi = cpair->rel_hi;
+ ir_tarval * tv_lo = cpair->tv_lo;
+ ir_tarval * tv_hi = cpair->tv_hi;
+ ir_mode * mode = cpair->lo_mode;
+ ir_graph * irg = get_irn_irg(cmp_lo);
+
+ if (rel_lo == ir_relation_less_greater && rel_hi == ir_relation_less_greater &&
tarval_is_null(tv_lo) && tarval_is_null(tv_hi) &&
mode == get_tarval_mode(tv_hi)) {
/* p != NULL || q != NULL ==> (p|q) != NULL) */
hil = new_r_Conv(dst_block, hil, mode);
p = new_r_Or(dst_block, lol, hil, mode);
c = new_r_Const(irg, tv_lo);
- cmp = new_r_Cmp(dst_block, p, c);
- p = new_r_Proj(cmp, mode_b, pn_Cmp_Lg);
- return p;
+ cmp = new_r_Cmp(dst_block, p, c, ir_relation_less_greater);
+ return cmp;
}
}
return 0;
/* Beware of NaN's, we can only check for (ordered) != here (which is Lg, not Ne) */
- if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Lg) &&
- (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Lg)) {
+ if ((rel_lo == ir_relation_greater_equal || rel_lo == ir_relation_greater || rel_lo == ir_relation_less_greater) &&
+ (rel_hi == ir_relation_less || rel_hi == ir_relation_less_equal || rel_hi == ir_relation_less_greater)) {
/* x >=|>|!= lo | x <|<=|!= hi ==> true */
ir_node *const t = new_r_Const(irg, tarval_b_true);
return t;
- } else if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le || pnc_lo == pn_Cmp_Eq) &&
- (pnc_hi == pn_Cmp_Lt || pnc_hi == pn_Cmp_Le || pnc_hi == pn_Cmp_Lg)) {
+ } else if ((rel_lo == ir_relation_less || rel_lo == ir_relation_less_equal || rel_lo == ir_relation_equal) &&
+ (rel_hi == ir_relation_less || rel_hi == ir_relation_less_equal || rel_hi == ir_relation_less_greater)) {
/* x <|<=|== lo || x <|<=|!= hi ==> x <|<=|!= hi */
- return proj_hi;
- } else if ((pnc_lo == pn_Cmp_Ge || pnc_lo == pn_Cmp_Gt || pnc_lo == pn_Cmp_Lg) &&
- (pnc_hi == pn_Cmp_Eq || pnc_hi == pn_Cmp_Ge || pnc_hi == pn_Cmp_Gt)) {
+ return cmp_hi;
+ } else if ((rel_lo == ir_relation_greater_equal || rel_lo == ir_relation_greater || rel_lo == ir_relation_less_greater) &&
+ (rel_hi == ir_relation_equal || rel_hi == ir_relation_greater_equal || rel_hi == ir_relation_greater)) {
/* x >=|>|!= lo || x ==|>=|> hi ==> x >=|>|!= lo */
- return proj_lo;
+ return cmp_lo;
} else if (tarval_is_one(tarval_sub(tv_hi, tv_lo, NULL))) { /* lo + 1 == hi */
- if (pnc_lo == pn_Cmp_Lt && pnc_hi == pn_Cmp_Ge) {
+ if (rel_lo == ir_relation_less && rel_hi == ir_relation_greater_equal) {
/* x < c || x >= c + 1 ==> x != c */
- ir_node *const p = new_r_Proj(cmp_lo, mode_b, pn_Cmp_Lg);
+ ir_node *const p = new_r_Proj(cmp_lo, mode_b, ir_relation_less_greater);
return p;
- } else if (pnc_lo == pn_Cmp_Le) {
- if (pnc_hi == pn_Cmp_Eq) {
+ } else if (rel_lo == ir_relation_less_equal) {
+ if (rel_hi == ir_relation_equal) {
/* x <= c || x == c + 1 ==> x <= c + 1 */
- ir_node *const p = new_r_Proj(cmp_hi, mode_b, pn_Cmp_Le);
+ ir_node *const p = new_r_Proj(cmp_hi, mode_b, ir_relation_less_equal);
return p;
- } else if (pnc_hi == pn_Cmp_Ge) {
+ } else if (rel_hi == ir_relation_greater_equal) {
/* x <= c || x >= c + 1 ==> true */
ir_node *const t = new_r_Const(irg, tarval_b_true);
return t;
- } else if (pnc_hi == pn_Cmp_Gt) {
+ } else if (rel_hi == ir_relation_greater) {
/* x <= c || x > c + 1 ==> x != c + 1 */
- ir_node *const p = new_r_Proj(cmp_hi, mode_b, pn_Cmp_Lg);
+ ir_node *const p = new_r_Proj(cmp_hi, mode_b, ir_relation_less_greater);
return p;
}
- } else if (pnc_lo == pn_Cmp_Eq && pnc_hi == pn_Cmp_Ge) {
+ } else if (rel_lo == ir_relation_equal && rel_hi == ir_relation_greater_equal) {
/* x == c || x >= c + 1 ==> x >= c */
- ir_node *const p = new_r_Proj(cmp_lo, mode_b, pn_Cmp_Ge);
+ ir_node *const p = new_r_Proj(cmp_lo, mode_b, ir_relation_greater_equal);
return p;
}
- } else if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le) &&
- (pnc_hi == pn_Cmp_Gt || pnc_lo == pn_Cmp_Ge) &&
+ } else if ((rel_lo == ir_relation_less || rel_lo == ir_relation_less_equal) &&
+ (rel_hi == ir_relation_greater || rel_lo == ir_relation_greater_equal) &&
get_mode_arithmetic(mode) == irma_twos_complement) {
/* works for two-complements only */
/* x <|<= lo || x >|>= hi ==> (x - lo) >u|>=u (hi-lo) */
- if (pnc_lo == pn_Cmp_Le) {
+ if (rel_lo == ir_relation_less_equal) {
/* must convert to < */
ir_mode *mode = get_tarval_mode(tv_lo);
ir_tarval *n = tarval_add(tv_lo, get_mode_one(mode));
- if (n != tarval_bad && tarval_cmp(n, tv_lo) == pn_Cmp_Gt) {
+ if (n != tarval_bad && tarval_cmp(n, tv_lo) == ir_relation_greater) {
/* no overflow */
tv_lo = n;
- pnc_lo = pn_Cmp_Lt;
+ rel_lo = ir_relation_less;
}
}
- if (pnc_lo == pn_Cmp_Lt) {
+ if (rel_lo == ir_relation_less) {
/* all fine */
ir_node *const block = get_nodes_block(cmp_hi);
ir_node * x = get_Cmp_left(cmp_hi);
ir_mode * mode = get_irn_mode(x);
- ir_node *sub, *cmp, *c, *subc, *p;
+ ir_node *sub, *cmp, *c, *subc;
if (mode_is_signed(mode)) {
/* convert to unsigned */
c = new_r_Const(irg, tv_lo);
sub = new_r_Sub(block, x, c, mode);
subc = new_r_Sub(block, new_r_Const(irg, tv_hi), c, mode);
- cmp = new_r_Cmp(block, sub, subc);
- p = new_r_Proj(cmp, mode_b, pnc_hi);
- return p;
+ cmp = new_r_Cmp(block, sub, subc, rel_hi);
+ return cmp;
}
}
return NULL;
* \ |
* block
*
- * try to convert it into a (x pnc_lo c_lo) || (x pnc_hi c_hi)
+ * try to convert it into a (x rel_lo c_lo) || (x rel_hi c_hi)
* and optimize.
*/
static void find_cf_and_or_walker(ir_node *block, void *ctx)
ir_node *replacement;
cond_pair cpair;
- upper_cf = get_Block_cfgpred(block, up_idx);
- upper_cf = skip_empty_blocks(upper_cf);
+ upper_cf = get_Block_cfgpred(block, up_idx);
+ upper_cf = skip_empty_blocks(upper_cf);
if (is_Bad(upper_cf))
continue;
upper_block = get_nodes_block(upper_cf);
/* normalize pncs: we need the true case to jump into the
* common block (ie. conjunctive normal form) */
if (get_Proj_proj(lower_cf) == pn_Cond_false) {
- if (cpair.proj_lo == cond_selector) {
- ir_mode *mode = get_tarval_mode(cpair.tv_lo);
- ir_node *cmp = get_Proj_pred(cpair.proj_lo);
- cpair.pnc_lo = get_negated_pnc(cpair.pnc_lo, mode);
- cpair.proj_lo = new_r_Proj(cmp, mode_b, cpair.pnc_lo);
+ if (cpair.cmp_lo == cond_selector) {
+ ir_node *cmp = cpair.cmp_lo;
+ ir_node *block = get_nodes_block(cmp);
+ dbg_info *dbgi = get_irn_dbg_info(cmp);
+ cpair.rel_lo = get_negated_relation(cpair.rel_lo);
+ cpair.cmp_lo = new_rd_Cmp(dbgi, block,
+ get_Cmp_left(cmp), get_Cmp_right(cmp), cpair.rel_lo);
} else {
- ir_mode *mode = get_tarval_mode(cpair.tv_hi);
- ir_node *cmp = get_Proj_pred(cpair.proj_hi);
- assert(cpair.proj_hi == cond_selector);
- cpair.pnc_hi = get_negated_pnc(cpair.pnc_hi, mode);
- cpair.proj_hi = new_r_Proj(cmp, mode_b, cpair.pnc_hi);
+ ir_node *cmp = cpair.cmp_hi;
+ ir_node *block = get_nodes_block(cmp);
+ dbg_info *dbgi = get_irn_dbg_info(cmp);
+ assert(cmp == cond_selector);
+ cpair.rel_hi = get_negated_relation(cpair.rel_hi);
+ cpair.cmp_hi = new_rd_Cmp(dbgi, block,
+ get_Cmp_left(cmp), get_Cmp_right(cmp), cpair.rel_hi);
}
}
if (get_Proj_proj(upper_cf) == pn_Cond_false) {
- if (cpair.proj_lo == upper_cond_selector) {
- ir_mode *mode = get_tarval_mode(cpair.tv_lo);
- ir_node *cmp = get_Proj_pred(cpair.proj_lo);
- cpair.pnc_lo = get_negated_pnc(cpair.pnc_lo, mode);
- cpair.proj_lo = new_r_Proj(cmp, mode_b, cpair.pnc_lo);
+ if (cpair.cmp_lo == upper_cond_selector) {
+ ir_node *cmp = cpair.cmp_lo;
+ ir_node *block = get_nodes_block(cmp);
+ dbg_info *dbgi = get_irn_dbg_info(cmp);
+ cpair.rel_lo = get_negated_relation(cpair.rel_lo);
+ cpair.cmp_lo = new_rd_Cmp(dbgi, block,
+ get_Cmp_left(cmp), get_Cmp_right(cmp), cpair.rel_lo);
} else {
- ir_mode *mode = get_tarval_mode(cpair.tv_hi);
- ir_node *cmp = get_Proj_pred(cpair.proj_hi);
- assert(cpair.proj_hi == upper_cond_selector);
- cpair.pnc_hi = get_negated_pnc(cpair.pnc_hi, mode);
- cpair.proj_hi = new_r_Proj(cmp, mode_b, cpair.pnc_hi);
+ ir_node *cmp = cpair.cmp_hi;
+ ir_node *block = get_nodes_block(cmp);
+ dbg_info *dbgi = get_irn_dbg_info(cmp);
+ assert(cmp == upper_cond_selector);
+ cpair.rel_hi = get_negated_relation(cpair.rel_hi);
+ cpair.cmp_hi = new_rd_Cmp(dbgi, block,
+ get_Cmp_left(cmp), get_Cmp_right(cmp), cpair.rel_hi);
}
}
ir_graph_pass_t *opt_bool_pass(const char *name)
{
return def_graph_pass(name ? name : "opt_bool", opt_bool);
-} /* opt_bool_pass */
+}
*/
static void compute_Cmp(node_t *node)
{
- ir_node *cmp = node->node;
- node_t *l = get_irn_node(get_Cmp_left(cmp));
- node_t *r = get_irn_node(get_Cmp_right(cmp));
- lattice_elem_t a = l->type;
- lattice_elem_t b = r->type;
- ir_mode *mode = get_irn_mode(get_Cmp_left(cmp));
-
- if (a.tv == tarval_top || b.tv == tarval_top) {
- node->type.tv = tarval_top;
- } else if (r->part == l->part) {
- /* both nodes congruent, we can probably do something */
- if (mode_is_float(mode)) {
- /* beware of NaN's */
- node->type.tv = tarval_bottom;
- } else {
- node->type.tv = tarval_b_true;
- }
- } else if (is_con(a) && is_con(b)) {
- node->type.tv = tarval_b_true;
- } else {
- node->type.tv = tarval_bottom;
- }
-} /* compute_Cmp */
-
-/**
- * (Re-)compute the type for a Proj(Cmp).
- *
- * @param node the node
- * @param cond the predecessor Cmp node
- */
-static void compute_Proj_Cmp(node_t *node, ir_node *cmp)
-{
- ir_node *proj = node->node;
- node_t *l = get_irn_node(get_Cmp_left(cmp));
- node_t *r = get_irn_node(get_Cmp_right(cmp));
- lattice_elem_t a = l->type;
- lattice_elem_t b = r->type;
- pn_Cmp pnc = get_Proj_pn_cmp(proj);
+ ir_node *cmp = node->node;
+ node_t *l = get_irn_node(get_Cmp_left(cmp));
+ node_t *r = get_irn_node(get_Cmp_right(cmp));
+ lattice_elem_t a = l->type;
+ lattice_elem_t b = r->type;
+ ir_relation relation = get_Cmp_relation(cmp);
ir_tarval *tv;
if (a.tv == tarval_top || b.tv == tarval_top) {
* consistent with compute_Cmp, so don't do anything for floats)
*/
} else if (r->part == l->part && !mode_is_float(get_irn_mode(l->node))) {
- tv = pnc & pn_Cmp_Eq ? tarval_b_true : tarval_b_false;
+ tv = relation & ir_relation_equal ? tarval_b_true : tarval_b_false;
/* if the node was ONCE evaluated by all constants, but now
this breaks AND we get from the argument partitions a different
} else {
node->type.tv = tarval_bottom;
}
-} /* compute_Proj_Cmp */
+}
/**
* (Re-)compute the type for a Proj(Cond).
/* mode M is always bottom */
node->type.tv = tarval_bottom;
return;
+ } else if (mode == mode_X) {
+ /* handle mode_X nodes */
+ switch (get_irn_opcode(pred)) {
+ case iro_Start:
+ /* the Proj_X from the Start is always reachable.
+ However this is already handled at the top. */
+ node->type.tv = tarval_reachable;
+ return;
+ case iro_Cond:
+ compute_Proj_Cond(node, pred);
+ return;
+ default:
+ break;
+ }
}
- if (mode != mode_X) {
- if (is_Cmp(pred))
- compute_Proj_Cmp(node, pred);
- else
- default_compute(node);
- return;
- }
- /* handle mode_X nodes */
- switch (get_irn_opcode(pred)) {
- case iro_Start:
- /* the Proj_X from the Start is always reachable.
- However this is already handled at the top. */
- node->type.tv = tarval_reachable;
- break;
- case iro_Cond:
- compute_Proj_Cond(node, pred);
- break;
- default:
- default_compute(node);
- }
+ default_compute(node);
} /* compute_Proj */
/**
ir_node *confirm = node->node;
node_t *pred = get_irn_node(get_Confirm_value(confirm));
- if (get_Confirm_cmp(confirm) == pn_Cmp_Eq) {
+ if (get_Confirm_relation(confirm) == ir_relation_equal) {
node_t *bound = get_irn_node(get_Confirm_bound(confirm));
if (is_con(bound->type)) {
ir_tarval* const lzn = tarval_or(lz, tarval_neg(lz));
ir_tarval* const rzn = tarval_or(rz, tarval_neg(rz));
// Concatenate safe lower zeroes.
- if (tarval_cmp(lzn, rzn) == pn_Cmp_Lt) {
+ if (tarval_cmp(lzn, rzn) == ir_relation_less) {
z = tarval_mul(tarval_eor(lzn, tarval_shl(lzn, get_tarval_one(m))), rzn);
} else {
z = tarval_mul(tarval_eor(rzn, tarval_shl(rzn, get_tarval_one(m))), lzn);
break;
}
- case iro_Proj: {
- ir_node* const pred = get_Proj_pred(irn);
- if (is_Cmp(pred)) { // TODO generalize
- bitinfo* const l = get_bitinfo(get_Cmp_left(pred));
- bitinfo* const r = get_bitinfo(get_Cmp_right(pred));
- if (l == NULL || r == NULL) {
- goto result_unknown; // Cmp compares something we cannot evaluate.
- } else {
- ir_tarval* const lz = l->z;
- ir_tarval* const lo = l->o;
- ir_tarval* const rz = r->z;
- ir_tarval* const ro = r->o;
- pn_Cmp const pn = get_Proj_proj(irn);
- switch (pn) {
- case pn_Cmp_Lg:
- if (!tarval_is_null(tarval_andnot(ro, lz)) ||
- !tarval_is_null(tarval_andnot(lo, rz))) {
- // At least one bit differs.
- z = o = get_tarval_b_true();
- } else if (lz == lo && rz == ro && lz == rz) {
- z = o = get_tarval_b_false();
- } else {
- goto result_unknown;
- }
- break;
-
- case pn_Cmp_Eq:
- if (!tarval_is_null(tarval_andnot(ro, lz)) ||
- !tarval_is_null(tarval_andnot(lo, rz))) {
- // At least one bit differs.
- z = o = get_tarval_b_false();
- } else if (lz == lo && rz == ro && lz == rz) {
- z = o = get_tarval_b_true();
- } else {
- goto result_unknown;
- }
- break;
-
- case pn_Cmp_Le:
- case pn_Cmp_Lt:
- /* TODO handle negative values */
- if (tarval_is_negative(lz) || tarval_is_negative(lo) ||
- tarval_is_negative(rz) || tarval_is_negative(ro))
- goto result_unknown;
-
- if (tarval_cmp(lz, ro) & pn) {
- /* Left upper bound is smaller(/equal) than right lower bound. */
- z = o = get_tarval_b_true();
- } else if (!(tarval_cmp(lo, rz) & pn)) {
- /* Left lower bound is not smaller(/equal) than right upper bound. */
- z = o = get_tarval_b_false();
- } else {
- goto result_unknown;
- }
- break;
-
- case pn_Cmp_Ge:
- case pn_Cmp_Gt:
- /* TODO handle negative values */
- if (tarval_is_negative(lz) || tarval_is_negative(lo) ||
- tarval_is_negative(rz) || tarval_is_negative(ro))
- goto result_unknown;
-
- if (!(tarval_cmp(lz, ro) & pn)) {
- /* Left upper bound is not greater(/equal) than right lower bound. */
- z = o = get_tarval_b_false();
- } else if (tarval_cmp(lo, rz) & pn) {
- /* Left lower bound is greater(/equal) than right upper bound. */
- z = o = get_tarval_b_true();
- } else {
- goto result_unknown;
- }
- break;
-
- default:
- goto cannot_analyse;
- }
- }
+ case iro_Cmp: {
+ bitinfo* const l = get_bitinfo(get_Cmp_left(irn));
+ bitinfo* const r = get_bitinfo(get_Cmp_right(irn));
+ if (l == NULL || r == NULL) {
+ goto result_unknown; // Cmp compares something we cannot evaluate.
} else {
- goto cannot_analyse;
+ ir_tarval* const lz = l->z;
+ ir_tarval* const lo = l->o;
+ ir_tarval* const rz = r->z;
+ ir_tarval* const ro = r->o;
+ ir_relation const relation = get_Cmp_relation(irn);
+ switch (relation) {
+ case ir_relation_less_greater:
+ if (!tarval_is_null(tarval_andnot(ro, lz)) ||
+ !tarval_is_null(tarval_andnot(lo, rz))) {
+ // At least one bit differs.
+ z = o = get_tarval_b_true();
+ } else if (lz == lo && rz == ro && lz == rz) {
+ z = o = get_tarval_b_false();
+ } else {
+ goto result_unknown;
+ }
+ break;
+
+ case ir_relation_equal:
+ if (!tarval_is_null(tarval_andnot(ro, lz)) ||
+ !tarval_is_null(tarval_andnot(lo, rz))) {
+ // At least one bit differs.
+ z = o = get_tarval_b_false();
+ } else if (lz == lo && rz == ro && lz == rz) {
+ z = o = get_tarval_b_true();
+ } else {
+ goto result_unknown;
+ }
+ break;
+
+ case ir_relation_less_equal:
+ case ir_relation_less:
+ /* TODO handle negative values */
+ if (tarval_is_negative(lz) || tarval_is_negative(lo) ||
+ tarval_is_negative(rz) || tarval_is_negative(ro))
+ goto result_unknown;
+
+ if (tarval_cmp(lz, ro) & relation) {
+ /* Left upper bound is smaller(/equal) than right lower bound. */
+ z = o = get_tarval_b_true();
+ } else if (!(tarval_cmp(lo, rz) & relation)) {
+ /* Left lower bound is not smaller(/equal) than right upper bound. */
+ z = o = get_tarval_b_false();
+ } else {
+ goto result_unknown;
+ }
+ break;
+
+ case ir_relation_greater_equal:
+ case ir_relation_greater:
+ /* TODO handle negative values */
+ if (tarval_is_negative(lz) || tarval_is_negative(lo) ||
+ tarval_is_negative(rz) || tarval_is_negative(ro))
+ goto result_unknown;
+
+ if (!(tarval_cmp(lz, ro) & relation)) {
+ /* Left upper bound is not greater(/equal) than right lower bound. */
+ z = o = get_tarval_b_false();
+ } else if (tarval_cmp(lo, rz) & relation) {
+ /* Left lower bound is greater(/equal) than right upper bound. */
+ z = o = get_tarval_b_true();
+ } else {
+ goto result_unknown;
+ }
+ break;
+
+ default:
+ goto cannot_analyse;
+ }
}
break;
}
*/
#define DBG_EVAL_CONFIRM(n) \
do { \
- hook_merge_nodes(NULL, 0, &n, 1, HOOK_OPT_CONFIRM_E); \
+ hook_merge_nodes(NULL, 0, (ir_node**)&n, 1, HOOK_OPT_CONFIRM_E); \
} while(0)
/**
typedef struct jumpthreading_env_t {
ir_node *true_block;
ir_node *cmp; /**< The Compare node that might be partial evaluated */
- pn_Cmp pnc; /**< The Compare mode of the Compare node. */
+ ir_relation relation; /**< The Compare mode of the Compare node. */
ir_node *cnst;
ir_tarval *tv;
ir_visited_t visited_nr;
* returns whether the cmp evaluates to true or false, or can't be evaluated!
* 1: true, 0: false, -1: can't evaluate
*
- * @param pnc the compare mode of the Compare
+ * @param relation the compare mode of the Compare
* @param tv_left the left tarval
* @param tv_right the right tarval
*/
-static int eval_cmp_tv(pn_Cmp pnc, ir_tarval *tv_left, ir_tarval *tv_right)
+static int eval_cmp_tv(ir_relation relation, ir_tarval *tv_left,
+ ir_tarval *tv_right)
{
- pn_Cmp cmp_result = tarval_cmp(tv_left, tv_right);
+ ir_relation cmp_result = tarval_cmp(tv_left, tv_right);
/* does the compare evaluate to true? */
- if (cmp_result == pn_Cmp_False)
+ if (cmp_result == ir_relation_false)
return -1;
- if ((cmp_result & pnc) != cmp_result)
- return 0;
+ if ((cmp_result & relation) != 0)
+ return 1;
- return 1;
+ return 0;
}
+#if 0
+/* Matze: disabled, check first if the compare still is correct */
+
/**
* returns whether the cmp evaluates to true or false according to vrp
* information , or can't be evaluated!
* 1: true, 0: false, -1: can't evaluate
*
- * @param pnc the compare mode of the Compare
- * @param left the left node
- * @param right the right node
+ * @param relation the compare mode of the Compare
+ * @param left the left node
+ * @param right the right node
*/
-static int eval_cmp_vrp(pn_Cmp pnc, ir_node *left, ir_node *right)
+static int eval_cmp_vrp(ir_relation relation, ir_node *left, ir_node *right)
{
- pn_Cmp cmp_result = vrp_cmp(left, right);
+ ir_relation cmp_result = vrp_cmp(left, right);
/* does the compare evaluate to true? */
- if (cmp_result == pn_Cmp_False) {
+ if (cmp_result == ir_relation_false)
return -1;
- }
- if ((cmp_result & pnc) != cmp_result) {
- if ((cmp_result & pnc) != 0) {
+
+ if ((cmp_result & relation) != cmp_result) {
+ if ((cmp_result & relation) != 0) {
return -1;
}
return 0;
}
return 1;
}
+#endif
+
/**
* returns whether the cmp evaluates to true or false, or can't be evaluated!
* 1: true, 0: false, -1: can't evaluate
static int eval_cmp(jumpthreading_env_t *env, ir_node *cand)
{
if (is_Const(cand)) {
- ir_tarval *tv_cand = get_Const_tarval(cand);
- ir_tarval *tv_cmp = get_Const_tarval(env->cnst);
+ ir_tarval *tv_cand = get_Const_tarval(cand);
+ ir_tarval *tv_cmp = get_Const_tarval(env->cnst);
- return eval_cmp_tv(env->pnc, tv_cand, tv_cmp);
+ return eval_cmp_tv(env->relation, tv_cand, tv_cmp);
} else { /* a Confirm */
- ir_tarval *res = computed_value_Cmp_Confirm(env->cmp, cand, env->cnst, env->pnc);
+ ir_tarval *res = computed_value_Cmp_Confirm(env->cmp, cand, env->cnst, env->relation);
if (res == tarval_bad)
return -1;
return NULL;
if (is_Const_or_Confirm(value)) {
- if (eval_cmp(env, value) <= 0) {
+ if (eval_cmp(env, value) <= 0)
return NULL;
- }
DB((
dbg, LEVEL_1,
int i, arity;
/* the Phi has to be in the same Block as the Jmp */
- if (get_nodes_block(value) != block) {
+ if (get_nodes_block(value) != block)
return NULL;
- }
arity = get_irn_arity(value);
for (i = 0; i < arity; ++i) {
return copy_block;
}
}
- if (is_Proj(value)) {
- ir_node *left;
- ir_node *right;
- pn_Cmp pnc;
- ir_node *cmp = get_Proj_pred(value);
- if (!is_Cmp(cmp))
- return NULL;
-
- left = get_Cmp_left(cmp);
- right = get_Cmp_right(cmp);
- pnc = get_Proj_pn_cmp(value);
+ if (is_Cmp(value)) {
+ ir_node *cmp = value;
+ ir_node *left = get_Cmp_left(cmp);
+ ir_node *right = get_Cmp_right(cmp);
+ ir_relation relation = get_Cmp_relation(cmp);
/* we assume that the constant is on the right side, swap left/right
* if needed */
left = right;
right = t;
- pnc = get_inversed_pnc(pnc);
+ relation = get_inversed_relation(relation);
}
if (!is_Const(right))
- return 0;
+ return NULL;
- if (get_nodes_block(left) != block) {
- return 0;
- }
+ if (get_nodes_block(left) != block)
+ return NULL;
/* negate condition when we're looking for the false block */
if (env->tv == tarval_b_false) {
- pnc = get_negated_pnc(pnc, get_irn_mode(right));
+ relation = get_negated_relation(relation);
}
/* (recursively) look if a pred of a Phi is a constant or a Confirm */
- env->cmp = cmp;
- env->pnc = pnc;
- env->cnst = right;
+ env->cmp = cmp;
+ env->relation = relation;
+ env->cnst = right;
return find_const_or_confirm(env, jump, left);
}
/* handle cases that can be immediately evaluated */
selector_evaluated = -1;
- if (is_Proj(selector)) {
- ir_node *cmp = get_Proj_pred(selector);
- if (is_Cmp(cmp)) {
- ir_node *left = get_Cmp_left(cmp);
- ir_node *right = get_Cmp_right(cmp);
- if (is_Const(left) && is_Const(right)) {
- pn_Cmp pnc = get_Proj_pn_cmp(selector);
- ir_tarval *tv_left = get_Const_tarval(left);
- ir_tarval *tv_right = get_Const_tarval(right);
-
- selector_evaluated = eval_cmp_tv(pnc, tv_left, tv_right);
- }
- if (selector_evaluated < 0) {
- /* This is only the case if the predecessor nodes are not
- * constant or the comparison could not be evaluated.
- * Try with VRP information now.
- */
- pn_Cmp pnc = get_Proj_pn_cmp(selector);
-
- selector_evaluated = eval_cmp_vrp(pnc, left, right);
- }
+ if (is_Cmp(selector)) {
+ ir_node *left = get_Cmp_left(selector);
+ ir_node *right = get_Cmp_right(selector);
+ if (is_Const(left) && is_Const(right)) {
+ ir_relation relation = get_Cmp_relation(selector);
+ ir_tarval *tv_left = get_Const_tarval(left);
+ ir_tarval *tv_right = get_Const_tarval(right);
+
+ selector_evaluated = eval_cmp_tv(relation, tv_left, tv_right);
}
+#if 0
+ if (selector_evaluated < 0) {
+ /* This is only the case if the predecessor nodes are not
+ * constant or the comparison could not be evaluated.
+ * Try with VRP information now.
+ */
+ selector_evaluated = eval_cmp_vrp(relation, left, right);
+ }
+#endif
} else if (is_Const_or_Confirm(selector)) {
ir_tarval *tv = get_Const_or_Confirm_tarval(selector);
if (tv == tarval_b_true) {
if (tlower == tarval_bad || tupper == tarval_bad)
return NULL;
- if (tarval_cmp(tv, tlower) & pn_Cmp_Lt)
+ if (tarval_cmp(tv, tlower) == ir_relation_less)
return NULL;
- if (tarval_cmp(tupper, tv) & pn_Cmp_Lt)
+ if (tarval_cmp(tupper, tv) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
if (tlower == tarval_bad || tupper == tarval_bad)
return NULL;
- if (tarval_cmp(tv_index, tlower) & pn_Cmp_Lt)
+ if (tarval_cmp(tv_index, tlower) == ir_relation_less)
return NULL;
- if (tarval_cmp(tupper, tv_index) & pn_Cmp_Lt)
+ if (tarval_cmp(tupper, tv_index) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
if (tlower == tarval_bad || tupper == tarval_bad)
return NULL;
- if (tarval_cmp(tv_index, tlower) & pn_Cmp_Lt)
+ if (tarval_cmp(tv_index, tlower) == ir_relation_less)
return NULL;
- if (tarval_cmp(tupper, tv_index) & pn_Cmp_Lt)
+ if (tarval_cmp(tupper, tv_index) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
ir_graph *irg = get_irn_irg(op);
ir_node *block = get_nodes_block(op);
ir_node *zero = new_r_Const(irg, get_mode_null(mode));
- ir_node *cmp = new_r_Cmp(block, op, zero);
- ir_node *cond = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
+ ir_node *cmp = new_r_Cmp(block, op, zero, ir_relation_less);
ir_node *minus_op = new_r_Minus(block, op, mode);
- ir_node *mux = new_r_Mux(block, cond, op, minus_op, mode);
+ ir_node *mux = new_r_Mux(block, cmp, op, minus_op, mode);
return mux;
}
ir_node *block1, *count_block, *duff_block;
ir_node *ems, *ems_mod, *ems_div, *ems_mod_proj, *cmp_null,
- *cmp_proj, *ems_mode_cond, *x_true, *x_false, *const_null;
+ *ems_mode_cond, *x_true, *x_false, *const_null;
ir_node *true_val, *false_val;
ir_node *ins[2];
DB((dbg, LEVEL_4, "New module node %N\n", ems_mod));
ems_mod_proj = new_r_Proj(ems_mod, mode_Iu, pn_Mod_res);
- cmp_null = new_r_Cmp(block1, ems_mod_proj, const_null);
- cmp_proj = new_r_Proj(cmp_null, mode_b, pn_Cmp_Eq);
- ems_mode_cond = new_r_Cond(block1, cmp_proj);
-
+ cmp_null = new_r_Cmp(block1, ems_mod_proj, const_null, ir_relation_less);
+ ems_mode_cond = new_r_Cond(block1, cmp_null);
/* ems % step == 0 */
x_true = new_r_Proj(ems_mode_cond, mode_X, pn_Cond_true);
/* (end - start) / step + correction */
count = new_Add(count, correction, mode);
- cmp_bad_count = new_r_Cmp(count_block, count, const_null);
-
/* We preconditioned the loop to be tail-controlled.
* So, if count is something 'wrong' like 0,
* negative/positive (depending on step direction),
/* Depending on step direction, we have to check for > or < 0 */
if (loop_info.decreasing == 1) {
- bad_count_neg = new_r_Proj(cmp_bad_count, mode_b, pn_Cmp_Lt);
+ cmp_bad_count = new_r_Cmp(count_block, count, const_null,
+ ir_relation_less);
} else {
- bad_count_neg = new_r_Proj(cmp_bad_count, mode_b, pn_Cmp_Gt);
+ cmp_bad_count = new_r_Cmp(count_block, count, const_null,
+ ir_relation_greater);
}
- bad_count_neg = new_r_Cond(count_block, bad_count_neg);
+ bad_count_neg = new_r_Cond(count_block, cmp_bad_count);
good_count = new_Proj(bad_count_neg, mode_X, pn_Cond_true);
bad_count = new_Proj(ems_mode_cond, mode_X, pn_Cond_false);
return 1;
}
-/* Returns the mathematically inverted pn_Cmp. */
-static pn_Cmp get_math_inverted_case(pn_Cmp proj)
-{
- switch(proj) {
- case pn_Cmp_Eq:
- return pn_Cmp_Lg;
- case pn_Cmp_Lg:
- return pn_Cmp_Eq;
- case pn_Cmp_Lt:
- return pn_Cmp_Ge;
- case pn_Cmp_Le:
- return pn_Cmp_Gt;
- case pn_Cmp_Gt:
- return pn_Cmp_Le;
- case pn_Cmp_Ge:
- return pn_Cmp_Lt;
- default:
- panic("Unhandled pn_Cmp.");
- }
-}
-
/* Returns 1 if loop exits within 2 steps of the iv.
* Norm_proj means we do not exit the loop.*/
static unsigned simulate_next(ir_tarval **count_tar,
ir_tarval *stepped, ir_tarval *step_tar, ir_tarval *end_tar,
- pn_Cmp norm_proj)
+ ir_relation norm_proj)
{
ir_tarval *next;
DB((dbg, LEVEL_4, "Loop taken if (stepped)%ld %s (end)%ld ",
get_tarval_long(stepped),
- get_pnc_string((norm_proj)),
+ get_relation_string((norm_proj)),
get_tarval_long(end_tar)));
DB((dbg, LEVEL_4, "comparing latest value %d\n", loop_info.latest_value));
DB((dbg, LEVEL_4, "Result: (stepped)%ld IS %s (end)%ld\n",
get_tarval_long(stepped),
- get_pnc_string(tarval_cmp(stepped, end_tar)),
+ get_relation_string(tarval_cmp(stepped, end_tar)),
get_tarval_long(end_tar)));
/* next step */
DB((dbg, LEVEL_4, "Loop taken if %ld %s %ld ",
get_tarval_long(next),
- get_pnc_string(norm_proj),
+ get_relation_string(norm_proj),
get_tarval_long(end_tar)));
DB((dbg, LEVEL_4, "comparing latest value %d\n", loop_info.latest_value));
static ir_node *is_simple_loop(void)
{
int arity, i;
- ir_node *loop_block, *exit_block, *projx, *cond, *projres, *loop_condition;
+ ir_node *loop_block, *exit_block, *projx, *cond, *cmp;
/* Maximum of one condition, and no endless loops. */
if (loop_info.cf_outs != 1)
/* find value on which loop exit depends */
projx = loop_info.cf_out.pred;
cond = get_irn_n(projx, 0);
- projres = get_irn_n(cond, 0);
- loop_condition = get_irn_n(projres, 0);
+ cmp = get_irn_n(cond, 0);
- if (!is_Cmp(loop_condition))
+ if (!is_Cmp(cmp))
return NULL;
- DB((dbg, LEVEL_5, "projection is %s\n", get_pnc_string(get_Proj_proj(projx))));
+ DB((dbg, LEVEL_5, "projection is %s\n", get_relation_string(get_Proj_proj(projx))));
switch(get_Proj_proj(projx)) {
case pn_Cond_false:
}
DB((dbg, LEVEL_4, "Valid Cmp.\n"));
-
- return projres;
+ return cmp;
}
/* Returns 1 if all nodes are mode_Iu or mode_Is. */
/* TODO split. */
static unsigned get_unroll_decision_constant(void)
{
- ir_node *projres, *loop_condition, *iteration_path;
- unsigned success, is_latest_val;
- ir_tarval *start_tar, *end_tar, *step_tar, *diff_tar, *count_tar, *stepped;
- pn_Cmp proj_proj, norm_proj;
- ir_mode *mode;
+ ir_node *cmp, *iteration_path;
+ unsigned success, is_latest_val;
+ ir_tarval *start_tar, *end_tar, *step_tar, *diff_tar, *count_tar;
+ ir_tarval *stepped;
+ ir_relation proj_proj, norm_proj;
+ ir_mode *mode;
/* RETURN if loop is not 'simple' */
- projres = is_simple_loop();
- if (projres == NULL)
+ cmp = is_simple_loop();
+ if (cmp == NULL)
return 0;
/* One in of the loop condition needs to be loop invariant. => end_val
/\
*/
- loop_condition = get_irn_n(projres, 0);
-
- success = get_const_pred(loop_condition, &loop_info.end_val, &iteration_path);
+ success = get_const_pred(cmp, &loop_info.end_val, &iteration_path);
if (! success)
return 0;
DB((dbg, LEVEL_4, "stepped to %ld\n", get_tarval_long(stepped)));
- proj_proj = get_Proj_pn_cmp(projres);
+ proj_proj = get_Cmp_relation(cmp);
/* Assure that norm_proj is the stay-in-loop case. */
if (loop_info.exit_cond == 1)
- norm_proj = get_math_inverted_case(proj_proj);
+ norm_proj = get_negated_relation(proj_proj);
else
norm_proj = proj_proj;
- DB((dbg, LEVEL_4, "normalized projection %s\n", get_pnc_string(norm_proj)));
-
+ DB((dbg, LEVEL_4, "normalized projection %s\n", get_relation_string(norm_proj)));
/* Executed at most once (stay in counting loop if a Eq b) */
- if (norm_proj == pn_Cmp_Eq)
+ if (norm_proj == ir_relation_equal)
/* TODO Might be worth a warning. */
return 0;
#ifdef DEBUG_CONFIRM
-#define compare_iv(l_iv, r_iv, pnc) compare_iv_dbg(l_iv, r_iv, pnc)
+#define compare_iv(l_iv, r_iv, relation) compare_iv_dbg(l_iv, r_iv, relation)
/* forward */
-static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, pn_Cmp pnc);
+static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation);
/* triangle */
-#define DBG_OUT_TR(l_pnc, l_bound, r_pnc, r_bound, pnc, v) \
+#define DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, v) \
ir_printf("In %e:\na %= %n && b %= %n ==> a %= b == %s\n", \
get_irg_entity(current_ir_graph), \
- l_pnc, l_bound, r_pnc, r_bound, pnc, v);
+ l_relation, l_bound, r_relation, r_bound, relation, v);
/* right side */
-#define DBG_OUT_R(r_pnc, r_bound, left, pnc, right, v) \
+#define DBG_OUT_R(r_relation, r_bound, left, relation, right, v) \
ir_printf("In %e:\na %= %n ==> %n %= %n == %s\n", \
get_irg_entity(current_ir_graph), \
- r_pnc, r_bound, left, pnc, right, v);
+ r_relation, r_bound, left, relation, right, v);
/* left side */
-#define DBG_OUT_L(l_pnc, l_bound, left, pnc, right, v) \
+#define DBG_OUT_L(l_relation, l_bound, left, relation, right, v) \
ir_printf("In %e:\na %= %n ==> %n %= %n == %s\n", \
get_irg_entity(current_ir_graph), \
- l_pnc, l_bound, left, pnc, right, v);
+ l_relation, l_bound, left, relation, right, v);
#else
-#define DBG_OUT_TR(l_pnc, l_bound, r_pnc, r_bound, pnc, v)
-#define DBG_OUT_R(r_pnc, r_bound, left, pnc, right, v)
-#define DBG_OUT_L(l_pnc, l_bound, left, pnc, right, v)
+#define DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, v)
+#define DBG_OUT_R(r_relation, r_bound, left, relation, right, v)
+#define DBG_OUT_L(l_relation, l_bound, left, relation, right, v)
#endif /* DEBUG_CONFIRM */
ir_tarval *tv;
ir_mode *mode = get_irn_mode(n);
- pn_Cmp pnc;
+ ir_relation relation;
*confirm = NULL;
if (tv == tarval_bad)
return 0;
- pnc = tarval_cmp(tv, get_mode_null(mode));
+ relation = tarval_cmp(tv, get_mode_null(mode));
/*
* Beware: C might by a NaN. It is not clear, what we should do
*
* Note that only the C != 0 case need additional checking.
*/
- switch (get_Confirm_cmp(n)) {
- case pn_Cmp_Eq: /* n == C /\ C != 0 ==> n != 0 */
- RET_ON(pnc != pn_Cmp_Eq && pnc != pn_Cmp_Uo);
- case pn_Cmp_Lg: /* n != C /\ C == 0 ==> n != 0 */
- RET_ON(pnc == pn_Cmp_Eq);
- case pn_Cmp_Lt: /* n < C /\ C <= 0 ==> n != 0 */
- RET_ON(pnc == pn_Cmp_Lt || pnc == pn_Cmp_Eq);
- case pn_Cmp_Le: /* n <= C /\ C < 0 ==> n != 0 */
- RET_ON(pnc == pn_Cmp_Lt);
- case pn_Cmp_Ge: /* n >= C /\ C > 0 ==> n != 0 */
- RET_ON(pnc == pn_Cmp_Gt);
- case pn_Cmp_Gt: /* n > C /\ C >= 0 ==> n != 0 */
- RET_ON(pnc == pn_Cmp_Gt || pnc == pn_Cmp_Eq);
+ switch (get_Confirm_relation(n)) {
+ case ir_relation_equal: /* n == C /\ C != 0 ==> n != 0 */
+ RET_ON(relation != ir_relation_equal && relation != ir_relation_unordered);
+ case ir_relation_less_greater: /* n != C /\ C == 0 ==> n != 0 */
+ RET_ON(relation == ir_relation_equal);
+ case ir_relation_less: /* n < C /\ C <= 0 ==> n != 0 */
+ RET_ON(relation == ir_relation_less || relation == ir_relation_equal);
+ case ir_relation_less_equal: /* n <= C /\ C < 0 ==> n != 0 */
+ RET_ON(relation == ir_relation_less);
+ case ir_relation_greater_equal: /* n >= C /\ C > 0 ==> n != 0 */
+ RET_ON(relation == ir_relation_greater);
+ case ir_relation_greater: /* n > C /\ C >= 0 ==> n != 0 */
+ RET_ON(relation == ir_relation_greater || relation == ir_relation_equal);
default:
break;
}
if (tv == tarval_bad)
return 0;
- pnc = tarval_cmp(tv, get_mode_null(mode));
+ relation = tarval_cmp(tv, get_mode_null(mode));
/* again, need check for NaN */
- return (pnc != pn_Cmp_Eq) && (pnc != pn_Cmp_Uo);
+ return (relation != ir_relation_equal) && (relation != ir_relation_unordered);
#undef RET_ON
} /* value_not_zero */
} else {
/* check for more Confirms */
for (; is_Confirm(n); n = skip_Cast(get_Confirm_value(n))) {
- if (get_Confirm_cmp(n) == pn_Cmp_Lg) {
+ if (get_Confirm_relation(n) == ir_relation_less_greater) {
ir_node *bound = get_Confirm_bound(n);
ir_tarval *tv = value_of(bound);
{
ir_tarval *tv, *c;
ir_mode *mode;
- pn_Cmp cmp, ncmp;
+ ir_relation cmp, ncmp;
int negate = 1;
for (;;) {
* optimization possibilities, so we handle this
* different.
*/
- cmp = get_Confirm_cmp(n);
+ cmp = get_Confirm_relation(n);
switch (cmp) {
- case pn_Cmp_Lt:
+ case ir_relation_less:
/*
* must be x < c <= 1 to be useful if integer mode and -0 = 0
* x < c <= 0 to be useful else
*/
- case pn_Cmp_Le:
+ case ir_relation_less_equal:
/*
* must be x <= c < 1 to be useful if integer mode and -0 = 0
* x <= c < 0 to be useful else
get_mode_one(mode) : get_mode_null(mode);
ncmp = tarval_cmp(tv, c);
- if (ncmp == pn_Cmp_Eq)
- ncmp = pn_Cmp_Le;
+ if (ncmp == ir_relation_equal)
+ ncmp = ir_relation_less_equal;
- if (cmp != (ncmp ^ pn_Cmp_Eq))
+ if (cmp != (ncmp ^ ir_relation_equal))
return value_classified_unknown;
/* yep, negative */
return value_classified_negative * negate;
- case pn_Cmp_Ge:
+ case ir_relation_greater_equal:
/*
* must be x >= c > -1 to be useful if integer mode
* x >= c >= 0 to be useful else
*/
- case pn_Cmp_Gt:
+ case ir_relation_greater:
/*
* must be x > c >= -1 to be useful if integer mode
* x > c >= 0 to be useful else
c = get_mode_minus_one(mode);
ncmp = tarval_cmp(tv, c);
- if (ncmp == pn_Cmp_Eq)
- ncmp = pn_Cmp_Ge;
+ if (ncmp == ir_relation_equal)
+ ncmp = ir_relation_greater_equal;
- if (cmp != (ncmp ^ pn_Cmp_Eq))
+ if (cmp != (ncmp ^ ir_relation_equal))
return value_classified_unknown;
} else {
c = get_mode_minus_one(mode);
ncmp = tarval_cmp(tv, c);
- if (ncmp != pn_Cmp_Eq && ncmp != pn_Cmp_Gt)
+ if (ncmp != ir_relation_equal && ncmp != ir_relation_greater)
return value_classified_unknown;
}
/**
* construct an interval from a Confirm
*
- * @param iv an empty interval, will be filled
- * @param bound the bound value
- * @param pnc the Confirm compare relation
+ * @param iv an empty interval, will be filled
+ * @param bound the bound value
+ * @param relation the Confirm compare relation
*
* @return the filled interval or NULL if no interval
* can be created (happens only on floating point
*/
-static interval_t *get_interval(interval_t *iv, ir_node *bound, pn_Cmp pnc)
+static interval_t *get_interval(interval_t *iv, ir_node *bound, ir_relation relation)
{
ir_mode *mode = get_irn_mode(bound);
ir_tarval *tv = value_of(bound);
}
/* check which side is known */
- switch (pnc) {
- case pn_Cmp_Eq:
+ switch (relation) {
+ case ir_relation_equal:
/* [tv, tv] */
iv->min =
iv->max = tv;
iv->flags = MIN_INCLUDED | MAX_INCLUDED;
break;
- case pn_Cmp_Le:
+ case ir_relation_less_equal:
/* [-oo, tv] */
iv->min = get_mode_min(mode);
iv->max = tv;
iv->flags = MIN_INCLUDED | MAX_INCLUDED;
break;
- case pn_Cmp_Lt:
+ case ir_relation_less:
/* [-oo, tv) */
iv->min = get_mode_min(mode);
iv->max = tv;
iv->flags = MIN_INCLUDED | MAX_EXCLUDED;
break;
- case pn_Cmp_Gt:
+ case ir_relation_greater:
/* (tv, +oo] */
iv->min = tv;
iv->max = get_mode_max(mode);
iv->flags = MIN_EXCLUDED | MAX_INCLUDED;
break;
- case pn_Cmp_Ge:
+ case ir_relation_greater_equal:
/* [tv, +oo] */
iv->min = tv;
iv->max = get_mode_max(mode);
iv->flags = MIN_INCLUDED | MAX_INCLUDED;
break;
- case pn_Cmp_Leg:
+ case ir_relation_less_equal_greater:
/*
* Ordered means, that at least neither
* our bound nor our value ara NaN's
} /* get_interval */
/**
- * Try to evaluate l_iv pnc r_iv.
+ * Try to evaluate l_iv relation r_iv.
*
- * @param l_iv the left interval
- * @param r_iv the right interval
- * @param pnc the compare relation
+ * @param l_iv the left interval
+ * @param r_iv the right interval
+ * @param relation the compare relation
*
* @return
* tarval_b_true or tarval_b_false it it can be evaluated,
* tarval_bad else
*/
-static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, pn_Cmp pnc)
+static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation)
{
- pn_Cmp res;
- unsigned flags;
- ir_tarval *tv_true = tarval_b_true, *tv_false = tarval_b_false;
+ ir_relation res;
+ unsigned flags;
+ ir_tarval *tv_true = tarval_b_true, *tv_false = tarval_b_false;
/* if one interval contains NaNs, we cannot evaluate anything */
if (! l_iv || ! r_iv)
return tarval_bad;
/* we can only check ordered relations */
- if (pnc & pn_Cmp_Uo) {
+ if (relation & ir_relation_unordered) {
ir_tarval *t;
- pnc = get_negated_pnc(pnc, get_tarval_mode(l_iv->min));
+ relation = get_negated_relation(relation);
t = tv_true;
tv_true = tv_false;
tv_false = t;
}
/* if we have > or >=, we do the inverse to save some cases */
- if (pnc == pn_Cmp_Ge || pnc == pn_Cmp_Gt) {
+ if (relation == ir_relation_greater_equal || relation == ir_relation_greater) {
const interval_t *t;
- pnc = get_inversed_pnc(pnc);
- t = l_iv;
- l_iv = r_iv;
- r_iv = t;
+ relation = get_inversed_relation(relation);
+ t = l_iv;
+ l_iv = r_iv;
+ r_iv = t;
}
/* now, only the following cases remains */
- switch (pnc) {
- case pn_Cmp_Eq:
+ switch (relation) {
+ case ir_relation_equal:
/* two intervals can be compared for equality only if they are a single value */
if (l_iv->min == l_iv->max && r_iv->min == r_iv->max)
- return tarval_cmp(l_iv->min, r_iv->min) == pn_Cmp_Eq ? tv_true : tv_false;
+ return tarval_cmp(l_iv->min, r_iv->min) == ir_relation_equal ? tv_true : tv_false;
/* if both intervals do not intersect, it is never equal */
res = tarval_cmp(l_iv->max, r_iv->min);
/* b < c ==> [a,b] != [c,d] */
- if (res == pn_Cmp_Lt)
+ if (res == ir_relation_less)
return tv_false;
/* b <= c ==> [a,b) != [c,d] AND [a,b] != (c,d] */
if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED)
- && (res == pn_Cmp_Eq))
+ && (res == ir_relation_equal))
return tv_false;
res = tarval_cmp(r_iv->max, l_iv->min);
/* d < a ==> [c,d] != [a,b] */
- if (res == pn_Cmp_Lt)
+ if (res == ir_relation_less)
return tv_false;
/* d <= a ==> [c,d) != [a,b] AND [c,d] != (a,b] */
if ((r_iv->flags & MAX_EXCLUDED || l_iv->flags & MIN_EXCLUDED)
- && (res == pn_Cmp_Eq))
+ && (res == ir_relation_equal))
return tv_false;
break;
- case pn_Cmp_Lg:
+ case ir_relation_less_greater:
/* two intervals can be compared for not equality only if they are a single value */
if (l_iv->min == l_iv->max && r_iv->min == r_iv->max)
- return tarval_cmp(l_iv->min, r_iv->min) != pn_Cmp_Eq ? tv_true : tv_false;
+ return tarval_cmp(l_iv->min, r_iv->min) != ir_relation_equal ? tv_true : tv_false;
break;
- case pn_Cmp_Lt:
+ case ir_relation_less:
res = tarval_cmp(l_iv->max, r_iv->min);
/* [a, b] < [c, d] <==> b < c */
- if (res == pn_Cmp_Lt)
+ if (res == ir_relation_less)
return tv_true;
/* if one border is excluded, b <= c is enough */
if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED) &&
- res == pn_Cmp_Eq)
+ res == ir_relation_equal)
return tv_true;
/* [a, b] >= [c, d] <==> a > d */
res = tarval_cmp(l_iv->min, r_iv->max);
- if (res == pn_Cmp_Gt)
+ if (res == ir_relation_greater)
return tv_false;
/* if one border is excluded, a >= d is enough */
if ((l_iv->flags & MIN_EXCLUDED || r_iv->flags & MAX_EXCLUDED) &&
- res == pn_Cmp_Eq)
+ res == ir_relation_equal)
return tv_false;
break;
- case pn_Cmp_Le:
+ case ir_relation_less_equal:
/* [a, b) <= [c, d] or [a, b] <= (c, d] <==> b <= c */
flags = (l_iv->flags & MAX_EXCLUDED) | (r_iv->flags & MIN_EXCLUDED);
if (flags) {
res = tarval_cmp(l_iv->max, r_iv->min);
- if (res == pn_Cmp_Lt || res == pn_Cmp_Eq)
+ if (res == ir_relation_less || res == ir_relation_equal)
return tv_true;
}
res = tarval_cmp(l_iv->min, r_iv->max);
/* [a, b] > [c, d] <==> a > d */
- if (res == pn_Cmp_Gt)
+ if (res == ir_relation_greater)
return tv_false;
/* if one border is excluded, a >= d is enough */
if ((l_iv->flags & MIN_EXCLUDED || r_iv->flags & MAX_EXCLUDED) &&
- res == pn_Cmp_Eq)
+ res == ir_relation_equal)
return tv_false;
break;
- case pn_Cmp_Leg:
+ case ir_relation_less_equal_greater:
/* Hmm. if both are intervals, we can find an order */
return tv_true;
/**
* Returns non-zero, if a given relation is transitive.
*/
-static int is_transitive(pn_Cmp pnc)
+static int is_transitive(ir_relation relation)
{
- return (pn_Cmp_False < pnc && pnc < pn_Cmp_Lg);
+ return (ir_relation_false < relation && relation < ir_relation_less_greater);
} /* is_transitive */
/**
* Return the value of a Cmp if one or both predecessors
* are Confirm nodes.
*
- * @param cmp the Cmp node
- * @param left the left operand of the Cmp
- * @param right the right operand of the Cmp
- * @param pnc the compare relation
+ * @param cmp the Cmp node
+ * @param left the left operand of the Cmp
+ * @param right the right operand of the Cmp
+ * @param relation the compare relation
*/
-FIRM_API ir_tarval *computed_value_Cmp_Confirm(ir_node *cmp, ir_node *left, ir_node *right, pn_Cmp pnc)
+FIRM_API ir_tarval *computed_value_Cmp_Confirm(const ir_node *cmp, ir_node *left, ir_node *right, ir_relation relation)
{
ir_node *l_bound;
- pn_Cmp l_pnc, res_pnc, neg_pnc;
+ ir_relation l_relation, res_relation, neg_relation;
interval_t l_iv, r_iv;
ir_tarval *tv;
ir_mode *mode;
right = left;
left = t;
- pnc = get_inversed_pnc(pnc);
+ relation = get_inversed_relation(relation);
} else if (! is_Confirm(left)) {
/* nothing more found */
tv = tarval_bad;
}
/* ok, here at least left is a Confirm, right might be */
- l_bound = get_Confirm_bound(left);
- l_pnc = get_Confirm_cmp(left);
+ l_bound = get_Confirm_bound(left);
+ l_relation = get_Confirm_relation(left);
if (is_Confirm(right)) {
/*
* both sides are Confirm's. Check some rare cases first.
*/
- ir_node *r_bound = get_Confirm_bound(right);
- pn_Cmp r_pnc = get_Confirm_cmp(right);
+ ir_node *r_bound = get_Confirm_bound(right);
+ ir_relation r_relation = get_Confirm_relation(right);
/*
* some check can be made WITHOUT constant bounds
*/
if (r_bound == l_bound) {
- if (is_transitive(l_pnc)) {
- pn_Cmp r_inc_pnc = get_inversed_pnc(r_pnc);
+ if (is_transitive(l_relation)) {
+ ir_relation r_inc_relation = get_inversed_relation(r_relation);
/*
* triangle inequality:
*
* We handle correctly cases with some <=/>= here
*/
- if ((l_pnc & ~pn_Cmp_Eq) == (r_inc_pnc & ~pn_Cmp_Eq)) {
- res_pnc = (l_pnc & ~pn_Cmp_Eq) | (l_pnc & r_inc_pnc & pn_Cmp_Eq);
+ if ((l_relation & ~ir_relation_equal) == (r_inc_relation & ~ir_relation_equal)) {
+ res_relation = (l_relation & ~ir_relation_equal) | (l_relation & r_inc_relation & ir_relation_equal);
- if ((pnc == res_pnc) || ((pnc & ~pn_Cmp_Eq) == res_pnc)) {
- DBG_OUT_TR(l_pnc, l_bound, r_pnc, r_bound, pnc, "true");
+ if ((relation == res_relation) || ((relation & ~ir_relation_equal) == res_relation)) {
+ DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, "true");
DBG_EVAL_CONFIRM(cmp);
return tarval_b_true;
} else {
- pn_Cmp neg_pnc = get_negated_pnc(pnc, get_irn_mode(left));
+ ir_relation neg_relation = get_negated_relation(relation);
- if ((neg_pnc == res_pnc) || ((neg_pnc & ~pn_Cmp_Eq) == res_pnc)) {
- DBG_OUT_TR(l_pnc, l_bound, r_pnc, r_bound, pnc, "false");
+ if ((neg_relation == res_relation) || ((neg_relation & ~ir_relation_equal) == res_relation)) {
+ DBG_OUT_TR(l_relation, l_bound, r_relation, r_bound, relation, "false");
DBG_EVAL_CONFIRM(cmp);
return tarval_b_false;
}
*/
if (left == r_bound) {
/*
- * l == bound(r) AND pnc(r) == pnc:
+ * l == bound(r) AND relation(r) == relation:
*
* We know that a CMP b and check for that
*/
- if ((r_pnc == pnc) || (r_pnc == (pnc & ~pn_Cmp_Eq))) {
- DBG_OUT_R(r_pnc, r_bound, left, pnc, right, "true");
+ if ((r_relation == relation) || (r_relation == (relation & ~ir_relation_equal))) {
+ DBG_OUT_R(r_relation, r_bound, left, relation, right, "true");
DBG_EVAL_CONFIRM(cmp);
return tarval_b_true;
}
/*
- * l == bound(r) AND pnc(r) != pnc:
+ * l == bound(r) AND relation(r) != relation:
*
* We know that a CMP b and check for a ~CMP b
*/
else {
mode = get_irn_mode(left);
- neg_pnc = get_negated_pnc(pnc, mode);
+ neg_relation = get_negated_relation(relation);
- if ((r_pnc == neg_pnc) || (r_pnc == (neg_pnc & ~pn_Cmp_Eq))) {
- DBG_OUT_R(r_pnc, r_bound, left, pnc, right, "false");
+ if ((r_relation == neg_relation) || (r_relation == (neg_relation & ~ir_relation_equal))) {
+ DBG_OUT_R(r_relation, r_bound, left, relation, right, "false");
DBG_EVAL_CONFIRM(cmp);
return tarval_b_false;
}
/* now, try interval magic */
tv = compare_iv(
- get_interval(&l_iv, l_bound, l_pnc),
- get_interval(&r_iv, r_bound, r_pnc),
- pnc);
+ get_interval(&l_iv, l_bound, l_relation),
+ get_interval(&r_iv, r_bound, r_relation),
+ relation);
if (tv != tarval_bad) {
DBG_EVAL_CONFIRM(cmp);
*/
if (right == l_bound) {
/*
- * r == bound(l) AND pnc(l) == pnc:
+ * r == bound(l) AND relation(l) == relation:
*
* We know that a CMP b and check for that
*/
- if ((l_pnc == pnc) || (l_pnc == (pnc & ~pn_Cmp_Eq))) {
- DBG_OUT_L(l_pnc, l_bound, left, pnc, right, "true");
+ if ((l_relation == relation) || (l_relation == (relation & ~ir_relation_equal))) {
+ DBG_OUT_L(l_relation, l_bound, left, relation, right, "true");
DBG_EVAL_CONFIRM(cmp);
return tarval_b_true;
}
/*
- * r == bound(l) AND pnc(l) is Not(pnc):
+ * r == bound(l) AND relation(l) is Not(relation):
*
* We know that a CMP b and check for a ~CMP b
*/
else {
mode = get_irn_mode(left);
- neg_pnc = get_negated_pnc(pnc, mode);
+ neg_relation = get_negated_relation(relation);
- if ((l_pnc == neg_pnc) || (l_pnc == (neg_pnc & ~pn_Cmp_Eq))) {
- DBG_OUT_L(l_pnc, l_bound, left, pnc, right, "false");
+ if ((l_relation == neg_relation) || (l_relation == (neg_relation & ~ir_relation_equal))) {
+ DBG_OUT_L(l_relation, l_bound, left, relation, right, "false");
DBG_EVAL_CONFIRM(cmp);
return tarval_b_false;
}
if (tv != tarval_bad) {
tv = compare_iv(
- get_interval(&l_iv, l_bound, l_pnc),
+ get_interval(&l_iv, l_bound, l_relation),
get_interval_from_tv(&r_iv, tv),
- pnc);
+ relation);
} else {
check_null_case:
/* check some other cases */
- if ((pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) &&
+ if ((relation == ir_relation_equal || relation == ir_relation_less_greater) &&
is_Const(right) && is_Const_null(right)) {
/* for == 0 or != 0 we have some special tools */
ir_mode *mode = get_irn_mode(left);
const ir_node *dummy;
if (mode_is_reference(mode)) {
if (value_not_null(left, &dummy)) {
- tv = pnc == pn_Cmp_Eq ? tarval_b_false : tarval_b_true;
+ tv = relation == ir_relation_equal ? tarval_b_false : tarval_b_true;
}
} else {
if (value_not_zero(left, &dummy)) {
- tv = pnc == pn_Cmp_Eq ? tarval_b_false : tarval_b_true;
+ tv = relation == ir_relation_equal ? tarval_b_false : tarval_b_true;
}
}
}
/**
* For debugging. Prints an interval compare.
*
- * @param l_iv the left interval
- * @param r_iv the right interval
- * @param pnc the compare relation
+ * @param l_iv the left interval
+ * @param r_iv the right interval
+ * @param relation the compare relation
*/
-static void print_iv_cmp(const interval_t *l_iv, const interval_t *r_iv, pn_Cmp pnc)
+static void print_iv_cmp(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation)
{
char sl[128], sr[128];
iv_snprintf(sl, sizeof(sl), l_iv);
iv_snprintf(sr, sizeof(sr), r_iv);
- ir_printf("%s %= %s", sl, pnc, sr);
+ ir_printf("%s %= %s", sl, relation, sr);
} /* print_iv_cmp */
/**
* For debugging. call *compare_iv() and prints inputs and result.
*
- * @param l_iv the left interval
- * @param r_iv the right interval
- * @param pnc the compare relation
+ * @param l_iv the left interval
+ * @param r_iv the right interval
+ * @param relation the compare relation
*/
-static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, pn_Cmp pnc)
+static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation)
{
- tarval *tv = (compare_iv)(l_iv, r_iv, pnc);
+ tarval *tv = (compare_iv)(l_iv, r_iv, relation);
if (tv == tarval_bad)
return tv;
ir_printf("In %e:\n", get_irg_entity(current_ir_graph));
- print_iv_cmp(l_iv, r_iv, pnc);
+ print_iv_cmp(l_iv, r_iv, relation);
ir_printf(" = %T\n", tv);
return tv;
} /* compare_iv_dbg */
if (tlower == tarval_bad || tupper == tarval_bad)
return NULL;
- if (tarval_cmp(tv, tlower) & pn_Cmp_Lt)
+ if (tarval_cmp(tv, tlower) == ir_relation_less)
return NULL;
- if (tarval_cmp(tupper, tv) & pn_Cmp_Lt)
+ if (tarval_cmp(tupper, tv) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
if (tlower == tarval_bad || tupper == tarval_bad)
return NULL;
- if (tarval_cmp(tv_index, tlower) & pn_Cmp_Lt)
+ if (tarval_cmp(tv_index, tlower) == ir_relation_less)
return NULL;
- if (tarval_cmp(tupper, tv_index) & pn_Cmp_Lt)
+ if (tarval_cmp(tupper, tv_index) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
if (tlower == tarval_bad || tupper == tarval_bad)
return NULL;
- if (tarval_cmp(tv_index, tlower) & pn_Cmp_Lt)
+ if (tarval_cmp(tv_index, tlower) == ir_relation_less)
return NULL;
- if (tarval_cmp(tupper, tv_index) & pn_Cmp_Lt)
+ if (tarval_cmp(tupper, tv_index) == ir_relation_less)
return NULL;
/* ok, bounds check finished */
/*
* comparison
*/
-pn_Cmp tarval_cmp(ir_tarval *a, ir_tarval *b)
+ir_relation tarval_cmp(ir_tarval *a, ir_tarval *b)
{
carry_flag = -1;
}
if (a == tarval_undefined || b == tarval_undefined)
- return pn_Cmp_False;
+ return ir_relation_false;
if (a->mode != b->mode)
- return pn_Cmp_False;
+ return ir_relation_false;
if (get_mode_n_vector_elems(a->mode) > 1) {
/* vector arithmetic not implemented yet */
case irms_memory:
case irms_auxiliary:
if (a == b)
- return pn_Cmp_Eq;
- return pn_Cmp_False;
+ return ir_relation_equal;
+ return ir_relation_false;
case irms_float_number:
- /* it should be safe to enable this even if other arithmetic is disabled */
- /*if (no_float)
- return pn_Cmp_False;*/
/*
* BEWARE: we cannot compare a == b here, because
* a NaN is always Unordered to any other value, even to itself!
*/
switch (fc_comp((const fp_value*) a->value, (const fp_value*) b->value)) {
- case -1: return pn_Cmp_Lt;
- case 0: return pn_Cmp_Eq;
- case 1: return pn_Cmp_Gt;
- case 2: return pn_Cmp_Uo;
- default: return pn_Cmp_False;
+ case -1: return ir_relation_less;
+ case 0: return ir_relation_equal;
+ case 1: return ir_relation_greater;
+ case 2: return ir_relation_unordered;
+ default: return ir_relation_false;
}
case irms_reference:
case irms_int_number:
if (a == b)
- return pn_Cmp_Eq;
- return sc_comp(a->value, b->value) == 1 ? pn_Cmp_Gt : pn_Cmp_Lt;
+ return ir_relation_equal;
+ return sc_comp(a->value, b->value) == 1 ? ir_relation_greater : ir_relation_less;
case irms_internal_boolean:
if (a == b)
- return pn_Cmp_Eq;
- return a == tarval_b_true ? pn_Cmp_Gt : pn_Cmp_Lt;
+ return ir_relation_equal;
+ return a == tarval_b_true ? ir_relation_greater : ir_relation_less;
}
- return pn_Cmp_False;
+ return ir_relation_false;
}
/*
elif type == "long" and node.name == "Proj":
importcmd = "long %s = read_long(env);" % attrname
exportcmd = """write_long(env, %(val)s);"""
- elif type == "pn_Cmp" or type == "ir_where_alloc":
+ elif type == "ir_relation" or type == "ir_where_alloc":
importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
exportcmd = """write_long(env, (long) %(val)s);"""
elif type == "ir_cons_flags" and node.name == "Store":
init = "assert(is_atomic_type(type));"
class Cmp(Binop):
- """Returns the relation of 2 operands"""
- outs = [
- ("False", "always false", "0"),
- ("Eq", "equal", "1"),
- ("Lt", "less", "2"),
- ("Le", "less or equal", "pn_Cmp_Eq|pn_Cmp_Lt"),
- ("Gt", "greater", "4"),
- ("Ge", "greater or equal", "pn_Cmp_Eq|pn_Cmp_Gt"),
- ("Lg", "less or greater ('not equal' for integer numbers)", "pn_Cmp_Lt|pn_Cmp_Gt"),
- ("Leg", "less, equal or greater ('not unordered')", "pn_Cmp_Lt|pn_Cmp_Eq|pn_Cmp_Gt"),
- ("Uo", "unordered", "8"),
- ("Ue", "unordered or equal", "pn_Cmp_Uo|pn_Cmp_Eq"),
- ("Ul", "unordered or less", "pn_Cmp_Uo|pn_Cmp_Lt"),
- ("Ule", "unordered, less or equal", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Eq"),
- ("Ug", "unordered or greater", "pn_Cmp_Uo|pn_Cmp_Gt"),
- ("Uge", "onordered, greater or equal", "pn_Cmp_Uo|pn_Cmp_Gt|pn_Cmp_Eq"),
- ("Ne", "unordered, less or greater ('not equal' for floatingpoint numbers)", "pn_Cmp_Uo|pn_Cmp_Lt|pn_Cmp_Gt"),
- ("True", "always true", "15"),
- ]
+ """Compares its two operands and checks wether a specified
+ relation (like less or equal) is fulfilled."""
flags = []
+ mode = "mode_b"
+ attrs = [
+ dict(
+ type = "ir_relation",
+ name = "relation",
+ comment = "Comparison relation"
+ )
+ ]
+ attr_struct = "cmp_attr"
class Cond(Op):
"""Conditionally change control flow. There are two versions of this node:
pinned = "yes"
attrs = [
dict(
- name = "cmp",
- type = "pn_Cmp",
- comment = "compare operation",
+ name = "relation",
+ type = "ir_relation",
+ comment = "relation of value to bound",
),
]
attr_struct = "confirm_attr"