fold-const.c (fold_binary_loc): Move simplifying of comparisons against the highest...
authorRichard Biener <rguenther@suse.de>
Fri, 24 Jul 2015 12:36:00 +0000 (12:36 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 24 Jul 2015 12:36:00 +0000 (12:36 +0000)
2015-07-24  Richard Biener  <rguenther@suse.de>

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

From-SVN: r226153

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd

index 6f8ae02f199dc9f82066ece848fb0300edaadc86..d7f6ca5c77c99016355769e7693aefa4743b3d8f 100644 (file)
@@ -1,3 +1,9 @@
+2015-07-24  Richard Biener  <rguenther@suse.de>
+
+       * fold-const.c (fold_binary_loc): Move simplifying of comparisons
+       against the highest or lowest possible integer ...
+       * match.pd: ... as patterns here.
+
 2015-07-24  Richard Biener  <rguenther@suse.de>
 
        * genmatch.c (struct capture_info): Add same_as field.
index c404857e87121adbd1b80b94ba0b900b0153119b..739a3a98e29e73a95f1686f10cf7cc9dbd292b84 100644 (file)
@@ -11617,123 +11617,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 398378d25446858fc2175b78730de4f4052a5d59..3d53abffe25712ef18aa36171a928a8d055ee608 100644 (file)
@@ -1824,6 +1824,73 @@ along with GCC; see the file COPYING3.  If not see
    { 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)