ia32: prefere != over < or > relation where possible
authorMatthias Braun <matze@braunis.de>
Mon, 28 Feb 2011 15:53:53 +0000 (16:53 +0100)
committerMatthias Braun <matze@braunis.de>
Mon, 28 Feb 2011 16:49:11 +0000 (17:49 +0100)
include/libfirm/iropt.h
ir/be/betranshlp.c
ir/be/ia32/ia32_transform.c
ir/ir/iropt.c
ir/ir/iropt_t.h

index 30fcd0e..72d29d7 100644 (file)
@@ -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
index c095e94..07e4991 100644 (file)
@@ -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 */
index ba5c056..72eff3f 100644 (file)
@@ -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);
index f613df6..08351c5 100644 (file)
@@ -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;
index 9fa4cb4..93a3ea1 100644 (file)
@@ -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;