2012-09-07 Tom de Vries <tom@codesourcery.com>
authorvries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Sep 2012 09:21:11 +0000 (09:21 +0000)
committervries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Sep 2012 09:21:11 +0000 (09:21 +0000)
PR tree-optimization/53986
* tree-vrp.c (extract_range_from_multiplicative_op_1): Allow
LSHIFT_EXPR.
(extract_range_from_binary_expr_1): Handle LSHIFT with constant range as
shift amount.

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

gcc/ChangeLog
gcc/tree-vrp.c

index 3539781..3e3cf36 100644 (file)
@@ -1,3 +1,11 @@
+2012-09-07  Tom de Vries  <tom@codesourcery.com>
+
+       PR tree-optimization/53986
+       * tree-vrp.c (extract_range_from_multiplicative_op_1): Allow
+       LSHIFT_EXPR.
+       (extract_range_from_binary_expr_1): Handle LSHIFT with constant range as
+       shift amount.
+
 2012-09-07  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * config/rs6000/aix43.h (RS6000_CALL_GLUE): Delete.
index 9309264..47c68d8 100644 (file)
@@ -2066,7 +2066,8 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr,
              || code == CEIL_DIV_EXPR
              || code == EXACT_DIV_EXPR
              || code == ROUND_DIV_EXPR
-             || code == RSHIFT_EXPR);
+             || code == RSHIFT_EXPR
+             || code == LSHIFT_EXPR);
   gcc_assert ((vr0->type == VR_RANGE
               || (code == MULT_EXPR && vr0->type == VR_ANTI_RANGE))
              && vr0->type == vr1->type);
@@ -2762,6 +2763,27 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              flag_wrapv = saved_flag_wrapv;
              return;
            }
+         else if (code == LSHIFT_EXPR
+                  && range_int_cst_p (&vr0))
+           {
+             int overflow_pos = TYPE_PRECISION (expr_type);
+             int bound_shift;
+             double_int bound;
+
+             if (!TYPE_UNSIGNED (expr_type))
+               overflow_pos -= 1;
+
+             bound_shift = overflow_pos - TREE_INT_CST_LOW (vr1.max);
+             bound = double_int_one.llshift (bound_shift,
+                                             TYPE_PRECISION (expr_type));
+             if (tree_to_double_int (vr0.max).ult (bound))
+               {
+                 /* In the absense of overflow, (a << b) is equivalent
+                    to (a * 2^b).  */
+                 extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
+                 return;
+               }
+           }
        }
       set_value_range_to_varying (vr);
       return;