]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold-const.c (make_range): Correctly handle cases of converting from unsigned to...
authorJeff Law <law@gcc.gnu.org>
Tue, 23 Sep 1997 18:35:51 +0000 (12:35 -0600)
committerJeff Law <law@gcc.gnu.org>
Tue, 23 Sep 1997 18:35:51 +0000 (12:35 -0600)
        * fold-const.c (make_range): Correctly handle cases of converting
        from unsigned to signed type.

        * fold-const.c (merge_ranges): Make sure that if one range is subset
        of another, it will always be the second range.  Correct (+,-) case to
        account for this.

Brought over from gcc2; fixes sparc bug.

From-SVN: r15678

gcc/ChangeLog
gcc/fold-const.c

index 9eb883e9e53a6980a058425d210362c9156aff96..6b7c829773563795cc2a715013a6ab3e6abfa61e 100644 (file)
@@ -1,3 +1,14 @@
+Tue Sep 23 12:34:51 1997  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * fold-const.c (make_range): Correctly handle cases of converting
+       from unsigned to signed type.
+
+Tue Sep 23 12:34:51 1997  Bernd Schmidt  <crux@pool.informatik.rwth-aachen.de>
+
+       * fold-const.c (merge_ranges): Make sure that if one range is subset
+       of another, it will always be the second range.  Correct (+,-) case to
+       account for this.
+
 Tue Sep 23 01:15:50 1997  David S. Miller  <davem@tanya.rutgers.edu>
 
        * expmed.c (expand_divmod): If compute_mode is not the same as
index 10b13f33f7c76239dc79d7778e30e4869a37e9ca..def96bfa627a048a95ad5354d264366f85295123 100644 (file)
@@ -2863,14 +2863,62 @@ make_range (exp, pin_p, plow, phigh)
              || (high != 0 && ! int_fits_type_p (high, type)))
            break;
 
-         if (low != 0)
-           low = convert (type, low);
+         n_low = low, n_high = high;
 
-         if (high != 0)
-           high = convert (type, high);
+         if (n_low != 0)
+           n_low = convert (type, n_low);
+
+         if (n_high != 0)
+           n_high = convert (type, n_high);
+
+         /* If we're converting from an unsigned to a signed type,
+            we will be doing the comparison as unsigned.  The tests above
+            have already verified that LOW and HIGH are both positive.
+
+            So we have to make sure that the original unsigned value will
+            be interpreted as positive.  */
+         if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
+           {
+             tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
+             tree high_positive
+               = fold (build (RSHIFT_EXPR, type,
+                              convert (type,
+                                       TYPE_MAX_VALUE (equiv_type)),
+                              convert (type, integer_one_node)));
+                       
+             /* If the low bound is specified, "and" the range with the
+                range for which the original unsigned value will be
+                positive.  */
+             if (low != 0)
+               {
+                 if (! merge_ranges (&n_in_p, &n_low, &n_high,
+                                     1, n_low, n_high,
+                                     1, convert (type, integer_zero_node),
+                                     high_positive))
+                   break;
+
+                 in_p = (n_in_p == in_p);
+               }
+             else
+               {
+                 /* Otherwise, "or" the range with the range of the input
+                    that will be interpreted as negative.  */
+                 if (! merge_ranges (&n_in_p, &n_low, &n_high,
+                                     0, n_low, n_high,
+                                     1, convert (type, integer_zero_node),
+                                     high_positive))
+                   break;
+
+                 in_p = (in_p != n_in_p);
+               }
+           }
 
          exp = arg0;
+         low = n_low, high = n_high;
          continue;
+
+       default:
+         break;
        }
 
       break;
@@ -2956,15 +3004,20 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
   tree tem;
   int in_p;
   tree low, high;
-
-  /* Make range 0 be the range that starts first.  Swap them if it isn't.  */
+  int lowequal = ((low0 == 0 && low1 == 0)
+                 || integer_onep (range_binop (EQ_EXPR, integer_type_node,
+                                               low0, 0, low1, 0)));
+  int highequal = ((high0 == 0 && high1 == 0)
+                  || integer_onep (range_binop (EQ_EXPR, integer_type_node,
+                                                high0, 1, high1, 1)));
+
+  /* Make range 0 be the range that starts first, or ends last if they
+     start at the same value.  Swap them if it isn't.  */
   if (integer_onep (range_binop (GT_EXPR, integer_type_node, 
                                 low0, 0, low1, 0))
-      || (((low0 == 0 && low1 == 0)
-          || integer_onep (range_binop (EQ_EXPR, integer_type_node,
-                                        low0, 0, low1, 0)))
+      || (lowequal
          && integer_onep (range_binop (GT_EXPR, integer_type_node,
-                                       high0, 1, high1, 1))))
+                                       high1, 1, high0, 1))))
     {
       temp = in0_p, in0_p = in1_p, in1_p = temp;
       tem = low0, low0 = low1, low1 = tem;
@@ -2996,27 +3049,32 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
 
   else if (in0_p && ! in1_p)
     {
-      /* If they don't overlap, the result is the first range.  If the
-        second range is a subset of the first, we can't describe this as
-        a single range unless both ranges end at the same place.  If both
-        ranges start in the same place, then the result is false.
-        Otherwise, we go from the start of the first range to just before
-        the start of the second.  */
+      /* 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
+        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.
+        Otherwise, we can't describe this as a single range.  */
       if (no_overlap)
        in_p = 1, low = low0, high = high0;
-      else if (subset
-              && integer_zerop (range_binop (EQ_EXPR, integer_type_node,
-                                             high0, 1, high1, 0)))
-       return 0;
-      else if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
-                                         low0, 0, low1, 0)))
+      else if (lowequal && highequal)
        in_p = 0, low = high = 0;
-      else
+      else if (subset && lowequal)
+       {
+         in_p = 1, high = high0;
+         low = range_binop (PLUS_EXPR, NULL_TREE, high1, 0,
+                            integer_one_node, 0);        
+       }
+      else if (! subset || highequal)
        {
          in_p = 1, low = low0;
          high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0,
                              integer_one_node, 0);
        }
+      else
+       return 0;
     }
 
   else if (! in0_p && in1_p)