This moves simplifying of comparisons against the highest or lowest 
possible integer.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

This needs the GENERIC code-gen fix, otherwise we miscompile GCC.

Richard.

2015-07-24  Richard Biener  <rguent...@suse.de>

        * fold-const.c (fold_binary_loc): Move simplifying of comparisons
        against the highest or lowest possible integer ...
        * match.pd: ... as patterns here.

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 226140)
+++ gcc/fold-const.c    (working copy)
@@ -11651,123 +11463,6 @@ fold_binary_loc (location_t loc,
            }
        }
 
-      /* Comparisons with the highest or lowest possible integer of
-        the specified precision will have known values.  */
-      {
-       tree arg1_type = TREE_TYPE (arg1);
-       unsigned int prec = TYPE_PRECISION (arg1_type);
-
-       if (TREE_CODE (arg1) == INTEGER_CST
-           && (INTEGRAL_TYPE_P (arg1_type) || POINTER_TYPE_P (arg1_type)))
-         {
-           wide_int max = wi::max_value (arg1_type);
-           wide_int signed_max = wi::max_value (prec, SIGNED);
-           wide_int min = wi::min_value (arg1_type);
-
-           if (wi::eq_p (arg1, max))
-             switch (code)
-               {
-               case GT_EXPR:
-                 return omit_one_operand_loc (loc, type, integer_zero_node, 
arg0);
-
-               case GE_EXPR:
-                 return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
-
-               case LE_EXPR:
-                 return omit_one_operand_loc (loc, type, integer_one_node, 
arg0);
-
-               case LT_EXPR:
-                 return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
-
-               /* The GE_EXPR and LT_EXPR cases above are not normally
-                  reached because of previous transformations.  */
-
-               default:
-                 break;
-               }
-           else if (wi::eq_p (arg1, max - 1))
-             switch (code)
-               {
-               case GT_EXPR:
-                 arg1 = const_binop (PLUS_EXPR, arg1,
-                                     build_int_cst (TREE_TYPE (arg1), 1));
-                 return fold_build2_loc (loc, EQ_EXPR, type,
-                                     fold_convert_loc (loc,
-                                                       TREE_TYPE (arg1), arg0),
-                                     arg1);
-               case LE_EXPR:
-                 arg1 = const_binop (PLUS_EXPR, arg1,
-                                     build_int_cst (TREE_TYPE (arg1), 1));
-                 return fold_build2_loc (loc, NE_EXPR, type,
-                                     fold_convert_loc (loc, TREE_TYPE (arg1),
-                                                       arg0),
-                                     arg1);
-               default:
-                 break;
-               }
-           else if (wi::eq_p (arg1, min))
-             switch (code)
-               {
-               case LT_EXPR:
-                 return omit_one_operand_loc (loc, type, integer_zero_node, 
arg0);
-
-               case LE_EXPR:
-                 return fold_build2_loc (loc, EQ_EXPR, type, op0, op1);
-
-               case GE_EXPR:
-                 return omit_one_operand_loc (loc, type, integer_one_node, 
arg0);
-
-               case GT_EXPR:
-                 return fold_build2_loc (loc, NE_EXPR, type, op0, op1);
-
-               default:
-                 break;
-               }
-           else if (wi::eq_p (arg1, min + 1))
-             switch (code)
-               {
-               case GE_EXPR:
-                 arg1 = const_binop (MINUS_EXPR, arg1,
-                                     build_int_cst (TREE_TYPE (arg1), 1));
-                 return fold_build2_loc (loc, NE_EXPR, type,
-                                     fold_convert_loc (loc,
-                                                       TREE_TYPE (arg1), arg0),
-                                     arg1);
-               case LT_EXPR:
-                 arg1 = const_binop (MINUS_EXPR, arg1,
-                                     build_int_cst (TREE_TYPE (arg1), 1));
-                 return fold_build2_loc (loc, EQ_EXPR, type,
-                                     fold_convert_loc (loc, TREE_TYPE (arg1),
-                                                       arg0),
-                                     arg1);
-               default:
-                 break;
-               }
-
-           else if (wi::eq_p (arg1, signed_max)
-                    && TYPE_UNSIGNED (arg1_type)
-                    /* We will flip the signedness of the comparison operator
-                       associated with the mode of arg1, so the sign bit is
-                       specified by this mode.  Check that arg1 is the signed
-                       max associated with this sign bit.  */
-                    && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type))
-                    /* signed_type does not work on pointer types.  */
-                    && INTEGRAL_TYPE_P (arg1_type))
-             {
-               /* The following case also applies to X < signed_max+1
-                  and X >= signed_max+1 because previous transformations.  */
-               if (code == LE_EXPR || code == GT_EXPR)
-                 {
-                   tree st = signed_type_for (arg1_type);
-                   return fold_build2_loc (loc,
-                                       code == LE_EXPR ? GE_EXPR : LT_EXPR,
-                                       type, fold_convert_loc (loc, st, arg0),
-                                       build_int_cst (st, 0));
-                 }
-             }
-         }
-      }
-
       /* If we are comparing an ABS_EXPR with a constant, we can
         convert all the cases into explicit comparisons, but they may
         well not be faster than doing the ABS and one comparison.
Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 226140)
+++ gcc/match.pd        (working copy)
@@ -1807,6 +1864,73 @@ (define_operator_list CBRT BUILT_IN_CBRT
    { constant_boolean_node (cmp == NE_EXPR, type); })))
 
 
+/* Non-equality compare simplifications from fold_binary  */
+(for cmp (lt gt le ge)
+ /* Comparisons with the highest or lowest possible integer of
+    the specified precision will have known values.  */
+ (simplify
+  (cmp (convert?@2 @0) INTEGER_CST@1)
+  (if ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
+       && tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0)))
+   (with
+    {
+      tree arg1_type = TREE_TYPE (@1);
+      unsigned int prec = TYPE_PRECISION (arg1_type);
+      wide_int max = wi::max_value (arg1_type);
+      wide_int signed_max = wi::max_value (prec, SIGNED);
+      wide_int min = wi::min_value (arg1_type);
+    }
+    (switch
+     (if (wi::eq_p (@1, max))
+      (switch
+       (if (cmp == GT_EXPR)
+       { constant_boolean_node (false, type); })
+       (if (cmp == GE_EXPR)
+       (eq @2 @1))
+       (if (cmp == LE_EXPR)
+       { constant_boolean_node (true, type); })
+       (if (cmp == LT_EXPR)
+       (ne @2 @1))))
+     (if (wi::eq_p (@1, max - 1))
+      (switch
+       (if (cmp == GT_EXPR)
+        (eq @2 { wide_int_to_tree (TREE_TYPE (@1), wi::add (@1, 1)); }))
+       (if (cmp == LE_EXPR)
+        (ne @2 { wide_int_to_tree (TREE_TYPE (@1), wi::add (@1, 1)); }))))
+     (if (wi::eq_p (@1, min))
+      (switch
+       (if (cmp == LT_EXPR)
+        { constant_boolean_node (false, type); })
+       (if (cmp == LE_EXPR)
+        (eq @2 @1))
+       (if (cmp == GE_EXPR)
+        { constant_boolean_node (true, type); })
+       (if (cmp == GT_EXPR)
+        (ne @2 @1))))
+     (if (wi::eq_p (@1, min + 1))
+      (switch
+       (if (cmp == GE_EXPR)
+        (ne @2 { wide_int_to_tree (TREE_TYPE (@1), wi::sub (@1, 1)); }))
+       (if (cmp == LT_EXPR)
+        (eq @2 { wide_int_to_tree (TREE_TYPE (@1), wi::sub (@1, 1)); }))))
+     (if (wi::eq_p (@1, signed_max)
+         && TYPE_UNSIGNED (arg1_type)
+         /* We will flip the signedness of the comparison operator
+            associated with the mode of @1, so the sign bit is
+            specified by this mode.  Check that @1 is the signed
+            max associated with this sign bit.  */
+         && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type))
+         /* signed_type does not work on pointer types.  */
+         && INTEGRAL_TYPE_P (arg1_type))
+      /* The following case also applies to X < signed_max+1
+        and X >= signed_max+1 because previous transformations.  */
+      (if (cmp == LE_EXPR || cmp == GT_EXPR)
+       (with { tree st = signed_type_for (arg1_type); }
+        (if (cmp == LE_EXPR)
+        (ge (convert:st @0) { build_zero_cst (st); })
+        (lt (convert:st @0) { build_zero_cst (st); }))))))))))
+ 
+
 /* bool_var != 0 becomes bool_var.  */
 (simplify
  (ne @0 integer_zerop@1)

Reply via email to