* fold-const.c (build_range_check): Make sure to use a valid type to
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Mar 2006 16:11:00 +0000 (16:11 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Mar 2006 16:11:00 +0000 (16:11 +0000)
apply the "(c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low)"
transformation.

(range_predecessor): New static function.
(range_successor): Likewise.
(merge_ranges): Use them to compute predecessors and successors of
range bounds.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111866 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c

index 5539174..5a138e2 100644 (file)
@@ -1,3 +1,14 @@
+2006-03-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * fold-const.c (build_range_check): Make sure to use a valid type to
+       apply the "(c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low)"
+       transformation.
+
+       (range_predecessor): New static function.
+       (range_successor): Likewise.
+       (merge_ranges): Use them to compute predecessors and successors of
+       range bounds.
+
 2006-03-09  Roger Sayle  <roger@eyesopen.com>
 
        PR middle-end/26561
index be0c461..582b496 100644 (file)
@@ -108,6 +108,8 @@ static int all_ones_mask_p (tree, int);
 static tree sign_bit_p (tree, tree);
 static int simple_operand_p (tree);
 static tree range_binop (enum tree_code, tree, tree, int, tree, int);
+static tree range_predecessor (tree);
+static tree range_successor (tree);
 static tree make_range (tree, int *, tree *, tree *);
 static tree build_range_check (tree, tree, int, tree, tree);
 static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
@@ -3722,6 +3724,32 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
   return constant_boolean_node (result, type);
 }
 \f
+/* Return the predecessor of VAL in its type, handling the infinite case.  */
+
+static tree
+range_predecessor (tree val)
+{
+  tree type = TREE_TYPE (val);
+
+  if (INTEGRAL_TYPE_P (type) && val == TYPE_MIN_VALUE (type))
+    return 0;
+  else
+    return range_binop (MINUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
+}
+
+/* Return the successor of VAL in its type, handling the infinite case.  */
+
+static tree
+range_successor (tree val)
+{
+  tree type = TREE_TYPE (val);
+
+  if (INTEGRAL_TYPE_P (type) && val == TYPE_MAX_VALUE (type))
+    return 0;
+  else
+    return range_binop (PLUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
+}
+
 /* Given EXP, a logical expression, set the range it is testing into
    variables denoted by PIN_P, PLOW, and PHIGH.  Return the expression
    actually being tested.  *PLOW and *PHIGH will be made of the same type
@@ -4089,60 +4117,59 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
        }
     }
 
-  value = const_binop (MINUS_EXPR, high, low, 0);
-  if (value != 0 && (!flag_wrapv || TREE_OVERFLOW (value))
-      && ! TYPE_UNSIGNED (etype))
+  /* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
+     This requires wrap-around arithmetics for the type of the expression.  */
+  switch (TREE_CODE (etype))
+    {
+    case INTEGER_TYPE:
+      /* There is no requirement that LOW be within the range of ETYPE
+        if the latter is a subtype.  It must, however, be within the base
+        type of ETYPE.  So be sure we do the subtraction in that type.  */
+      if (TREE_TYPE (etype))
+       etype = TREE_TYPE (etype);
+      break;
+
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+      etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+                                             TYPE_UNSIGNED (etype));
+      break;
+
+    default:
+      break;
+    }
+
+  /* If we don't have wrap-around arithmetics upfront, try to force it.  */
+  if (TREE_CODE (etype) == INTEGER_TYPE
+      && !TYPE_UNSIGNED (etype) && !flag_wrapv)
     {
       tree utype, minv, maxv;
 
       /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
         for the type in question, as we rely on this here.  */
-      switch (TREE_CODE (etype))
-       {
-       case INTEGER_TYPE:
-       case ENUMERAL_TYPE:
-         /* There is no requirement that LOW be within the range of ETYPE
-            if the latter is a subtype.  It must, however, be within the base
-            type of ETYPE.  So be sure we do the subtraction in that type.  */
-         if (TREE_TYPE (etype))
-           etype = TREE_TYPE (etype);
-         utype = lang_hooks.types.unsigned_type (etype);
-         maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
-         maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
-                             integer_one_node, 1);
-         minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
-         if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
-                                         minv, 1, maxv, 1)))
-           {
-             etype = utype;
-             high = fold_convert (etype, high);
-             low = fold_convert (etype, low);
-             exp = fold_convert (etype, exp);
-             value = const_binop (MINUS_EXPR, high, low, 0);
-           }
-         break;
-       default:
-         break;
-       }
+      utype = lang_hooks.types.unsigned_type (etype);
+      maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
+      maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
+                         integer_one_node, 1);
+      minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
+
+      if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
+                                     minv, 1, maxv, 1)))
+       etype = utype;
+      else
+       return 0;
     }
 
-  if (value != 0 && ! TREE_OVERFLOW (value))
-    {
-      /* There is no requirement that LOW be within the range of ETYPE
-        if the latter is a subtype.  It must, however, be within the base
-        type of ETYPE.  So be sure we do the subtraction in that type.  */
-      if (INTEGRAL_TYPE_P (etype) && TREE_TYPE (etype))
-       {
-         etype = TREE_TYPE (etype);
-         exp = fold_convert (etype, exp);
-         low = fold_convert (etype, low);
-         value = fold_convert (etype, value);
-       }
+  high = fold_convert (etype, high);
+  low = fold_convert (etype, low);
+  exp = fold_convert (etype, exp);
 
-      return build_range_check (type,
-                               fold_build2 (MINUS_EXPR, etype, exp, low),
-                               1, build_int_cst (etype, 0), value);
-    }
+  value = const_binop (MINUS_EXPR, high, low, 0);
+
+  if (value != 0 && !TREE_OVERFLOW (value))
+    return build_range_check (type,
+                             fold_build2 (MINUS_EXPR, etype, exp, low),
+                             1, build_int_cst (etype, 0), value);
 
   return 0;
 }
@@ -4208,7 +4235,7 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
       /* If they don't overlap, the result is the first range.  If they are
         equal, the result is false.  If the second range is a subset of the
         first, and the ranges begin at the same place, we go from just after
-        the end of the first range to the end of the second.  If the second
+        the end of the second range to the end of the first.  If the second
         range is not a subset of the first, or if it is a subset and both
         ranges end at the same place, the range starts at the start of the
         first range and ends just before the second range.
@@ -4219,15 +4246,15 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
        in_p = 0, low = high = 0;
       else if (subset && lowequal)
        {
-         in_p = 1, high = high0;
-         low = range_binop (PLUS_EXPR, NULL_TREE, high1, 0,
-                            integer_one_node, 0);
+         low = range_successor (high1);
+         high = high0;
+         in_p = (low != 0);
        }
       else if (! subset || highequal)
        {
-         in_p = 1, low = low0;
-         high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0,
-                             integer_one_node, 0);
+         low = low0;
+         high = range_predecessor (low1);
+         in_p = (high != 0);
        }
       else
        return 0;
@@ -4245,9 +4272,9 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
        in_p = 0, low = high = 0;
       else
        {
-         in_p = 1, high = high1;
-         low = range_binop (PLUS_EXPR, NULL_TREE, high0, 1,
-                            integer_one_node, 0);
+         low = range_successor (high0);
+         high = high1;
+         in_p = (low != 0);
        }
     }
 
@@ -4262,9 +4289,7 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
       if (no_overlap)
        {
          if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
-                                        range_binop (PLUS_EXPR, NULL_TREE,
-                                                     high0, 1,
-                                                     integer_one_node, 1),
+                                        range_successor (high0),
                                         1, low1, 0)))
            in_p = 0, low = low0, high = high1;
          else