From: Matthias Braun Date: Mon, 28 Feb 2011 15:53:53 +0000 (+0100) Subject: ia32: prefere != over < or > relation where possible X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=ce7643e41305a037d682b3087da7e1f927f84b5e;p=libfirm ia32: prefere != over < or > relation where possible --- diff --git a/include/libfirm/iropt.h b/include/libfirm/iropt.h index 30fcd0e1d..72d29d73f 100644 --- a/include/libfirm/iropt.h +++ b/include/libfirm/iropt.h @@ -91,6 +91,18 @@ FIRM_API ir_tarval *computed_value(const ir_node *n); */ FIRM_API ir_node *optimize_in_place(ir_node *n); +/** + * checks wether 1 value is the negated other value + */ +FIRM_API int ir_is_negated_value(const ir_node *a, const ir_node *b); + +/** + * (conservatively) approximates all possible relations when comparing + * the value @p left and @p right + */ +FIRM_API ir_relation ir_get_possible_cmp_relations(const ir_node *left, + const ir_node *right); + #include "end.h" #endif diff --git a/ir/be/betranshlp.c b/ir/be/betranshlp.c index c095e94b1..07e49911e 100644 --- a/ir/be/betranshlp.c +++ b/ir/be/betranshlp.c @@ -493,7 +493,7 @@ int be_mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false) if ((relation & ir_relation_less_greater) == 0) return 0; - if (!is_negated_value(mux_true, mux_false)) + if (!ir_is_negated_value(mux_true, mux_false)) return 0; /* must be x cmp 0 */ diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index ba5c0569f..72eff3fa8 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -2007,41 +2007,49 @@ static ir_node *get_flags_node_cmp(ir_node *cmp, ia32_condition_code_t *cc_out) { /* must have a Cmp as input */ ir_relation relation = get_Cmp_relation(cmp); + ir_relation possible; ir_node *l = get_Cmp_left(cmp); + ir_node *r = get_Cmp_right(cmp); ir_mode *mode = get_irn_mode(l); ir_node *flags; /* check for bit-test */ 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 *la = get_And_left(l); - ir_node *ra = get_And_right(l); - if (is_Shl(ra)) { - ir_node *tmp = la; - la = ra; - ra = tmp; - } - if (is_Shl(la)) { - ir_node *c = get_Shl_left(la); - if (is_Const_1(c) && is_Const_0(r)) { - /* (1 << n) & ra) */ - ir_node *n = get_Shl_right(la); - flags = gen_bt(cmp, ra, n); - /* the bit is copied into the CF flag */ - 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 */ - return flags; - } + || (!mode_is_signed(mode) && ((relation & ir_relation_greater_equal) == ir_relation_greater))) + && is_And(l)) { + ir_node *la = get_And_left(l); + ir_node *ra = get_And_right(l); + if (is_Shl(ra)) { + ir_node *tmp = la; + la = ra; + ra = tmp; + } + if (is_Shl(la)) { + ir_node *c = get_Shl_left(la); + if (is_Const_1(c) && is_Const_0(r)) { + /* (1 << n) & ra) */ + ir_node *n = get_Shl_right(la); + flags = gen_bt(cmp, ra, n); + /* the bit is copied into the CF flag */ + 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 */ + return flags; } } } + /* the middle-end tries to eliminate impossible relations, so a ptr != 0 + * test becomes ptr > 0. But for x86 an equal comparison is preferable to + * a >0 (we can sometimes eliminate the cmp in favor of flags produced by + * a predecessor node). So add the < bit */ + possible = ir_get_possible_cmp_relations(l, r); + if (((relation & ir_relation_less) && !(possible & ir_relation_greater)) + || ((relation & ir_relation_greater) && !(possible & ir_relation_less))) + relation |= ir_relation_less_greater; + /* just do a normal transformation of the Cmp */ *cc_out = relation_to_condition_code(relation, mode); flags = be_transform_node(cmp); diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index f613df68b..08351c564 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -447,8 +447,8 @@ static ir_tarval *computed_value_Confirm(const ir_node *n) * gives a (conservative) estimation of possible relation when comparing * left+right */ -static ir_relation determine_possible_cmp_relations(const ir_node *left, - const ir_node *right) +ir_relation ir_get_possible_cmp_relations(const ir_node *left, + const ir_node *right) { ir_relation possible = ir_relation_true; ir_tarval *tv_l = value_of(left); @@ -498,7 +498,7 @@ 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 possible = ir_get_possible_cmp_relations(left, right); ir_relation relation = get_Cmp_relation(cmp); /* if none of the requested relations is possible, return false */ @@ -3800,7 +3800,7 @@ static ir_node *transform_node_Cmp(ir_node *n) bool changed = false; bool changedc = false; ir_relation relation = get_Cmp_relation(n); - ir_relation possible = determine_possible_cmp_relations(left, right); + ir_relation possible = ir_get_possible_cmp_relations(left, right); /* mask out impossible relations */ ir_relation new_relation = relation & possible; @@ -4774,7 +4774,7 @@ static ir_node *transform_node_Or_Rotl(ir_node *irn_or) /* Note: the obvious rot formulation (a << x) | (a >> (32-x)) gets * transformed to (a << x) | (a >> -x) by transform_node_shift_modulo() */ - if (!is_negated_value(c1, c2)) { + if (!ir_is_negated_value(c1, c2)) { return irn_or; } @@ -5356,7 +5356,7 @@ static ir_node *transform_node_End(ir_node *n) return n; } /* transform_node_End */ -bool is_negated_value(ir_node *a, ir_node *b) +int ir_is_negated_value(const ir_node *a, const ir_node *b) { if (is_Minus(a) && get_Minus_op(a) == b) return true; diff --git a/ir/ir/iropt_t.h b/ir/ir/iropt_t.h index 9fa4cb4f1..93a3ea18c 100644 --- a/ir/ir/iropt_t.h +++ b/ir/ir/iropt_t.h @@ -131,13 +131,6 @@ static inline ir_tarval *value_of(const ir_node *n) */ ir_op_ops *firm_set_default_operations(unsigned code, ir_op_ops *ops); -/** - * Returns true if a == -b - */ -bool is_negated_value(ir_node *a, ir_node *b); - - - /** NOTE: Survive DCE is considered a bad hack - don't use */ typedef struct survive_dce_t survive_dce_t;