gimple-pretty-print.c (dump_ssaname_info): Print newline also in case of VR_VARYING.
authorJakub Jelinek <jakub@redhat.com>
Thu, 31 Oct 2013 13:55:31 +0000 (14:55 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 31 Oct 2013 13:55:31 +0000 (14:55 +0100)
* gimple-pretty-print.c (dump_ssaname_info): Print newline also
in case of VR_VARYING.  Print get_nonzero_bits if not all ones.
* tree-ssanames.h (struct range_info_def): Add nonzero_bits field.
(set_nonzero_bits, get_nonzero_bits): New prototypes.
* tree-ssa-ccp.c (get_default_value): Use get_range_info to see if
a default def isn't partially constant.
(ccp_finalize): If after IPA, set_range_info if integral SSA_NAME
is known to be partially zero.
(evaluate_stmt): If we'd return otherwise VARYING, use get_range_info
to see if a default def isn't partially constant.
* tree-ssanames.c (set_range_info): Initialize nonzero_bits upon
creation of a range, if VR_RANGE, try to improve nonzero_bits from
the range.
(set_nonzero_bits, get_nonzero_bits): New functions.

* g++.dg/warn/pr33738.C (main): Initialize a2 again to make sure
we warn about it already during VRP1 pass.

From-SVN: r204256

gcc/ChangeLog
gcc/gimple-pretty-print.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/pr33738.C
gcc/tree-ssa-ccp.c
gcc/tree-ssanames.c
gcc/tree-ssanames.h

index e46ad1529a3695c6d4520c44685fa58dbe6e0892..0e072c4725c9df3aa2e4ce82a2ec792bebf774ad 100644 (file)
@@ -1,5 +1,20 @@
 2013-10-31  Jakub Jelinek  <jakub@redhat.com>
 
+       * gimple-pretty-print.c (dump_ssaname_info): Print newline also
+       in case of VR_VARYING.  Print get_nonzero_bits if not all ones.
+       * tree-ssanames.h (struct range_info_def): Add nonzero_bits field.
+       (set_nonzero_bits, get_nonzero_bits): New prototypes.
+       * tree-ssa-ccp.c (get_default_value): Use get_range_info to see if
+       a default def isn't partially constant.
+       (ccp_finalize): If after IPA, set_range_info if integral SSA_NAME
+       is known to be partially zero.
+       (evaluate_stmt): If we'd return otherwise VARYING, use get_range_info
+       to see if a default def isn't partially constant.
+       * tree-ssanames.c (set_range_info): Initialize nonzero_bits upon
+       creation of a range, if VR_RANGE, try to improve nonzero_bits from
+       the range.
+       (set_nonzero_bits, get_nonzero_bits): New functions.
+
        * tree-cfg.c (assert_unreachable_fallthru_edge_p): New function.
        * tree-cfg.h (assert_unreachable_fallthru_edge_p): New prototype.
        * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function.
index 248dfea01af449b5aeb4b672eb3c259df476760f..6842213199af8f1edcdce0176587aaee08b6f130 100644 (file)
@@ -1737,7 +1737,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
   if (!POINTER_TYPE_P (TREE_TYPE (node))
       && SSA_NAME_RANGE_INFO (node))
     {
-      double_int min, max;
+      double_int min, max, nonzero_bits;
       value_range_type range_type = get_range_info (node, &min, &max);
 
       if (range_type == VR_VARYING)
@@ -1750,8 +1750,20 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
          pp_printf (buffer, ", ");
          pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node)));
          pp_printf (buffer, "]");
-         newline_and_indent (buffer, spc);
        }
+      nonzero_bits = get_nonzero_bits (node);
+      if (nonzero_bits != double_int_minus_one
+         && (nonzero_bits
+             != double_int::mask (TYPE_PRECISION (TREE_TYPE (node)))))
+       {
+         pp_string (buffer, " NONZERO ");
+         sprintf (pp_buffer (buffer)->digit_buffer,
+                  HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+                  (unsigned HOST_WIDE_INT) nonzero_bits.high,
+                  nonzero_bits.low);
+         pp_string (buffer, pp_buffer (buffer)->digit_buffer);
+       }
+      newline_and_indent (buffer, spc);
     }
 }
 
index f663aca60eb1f1d711d6509a0e76310aff494797..769209d795ac1d7010dbd1611c145e93e846d60e 100644 (file)
@@ -1,3 +1,8 @@
+2013-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/warn/pr33738.C (main): Initialize a2 again to make sure
+       we warn about it already during VRP1 pass.
+
 2013-10-31  Martin Jambor  <mjambor@suse.cz>
 
        PR rtl-optimization/58934
index e84fece13f669bb2e9e16a876892b3a9af4f6a5a..60ee0b4841237ff0d630f7268595b16b3232d43e 100644 (file)
@@ -18,6 +18,7 @@ int main() {
  if (a2 == -1) {       // { dg-warning "always false due" }
     link_error ();
  }
+ a2 = static_cast<Alpha>(GetM1());
  if (-1 == a2) {       // { dg-warning "always false due" }
     link_error ();
  }
index d30bd8b2493fe93f0af315a0ffb809c630c15400..5b6c0dbea28adfb1cbdf1a7758ffb2fbfec7b960 100644 (file)
@@ -260,6 +260,19 @@ get_default_value (tree var)
        {
          val.lattice_val = VARYING;
          val.mask = double_int_minus_one;
+         if (flag_tree_bit_ccp)
+           {
+             double_int nonzero_bits = get_nonzero_bits (var);
+             double_int mask
+               = double_int::mask (TYPE_PRECISION (TREE_TYPE (var)));
+             if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
+               {
+                 val.lattice_val = CONSTANT;
+                 val.value = build_zero_cst (TREE_TYPE (var));
+                 /* CCP wants the bits above precision set.  */
+                 val.mask = nonzero_bits | ~mask;
+               }
+           }
        }
     }
   else if (is_gimple_assign (stmt))
@@ -828,7 +841,8 @@ ccp_finalize (void)
   do_dbg_cnt ();
 
   /* Derive alignment and misalignment information from partially
-     constant pointers in the lattice.  */
+     constant pointers in the lattice or nonzero bits from partially
+     constant integers.  */
   for (i = 1; i < num_ssa_names; ++i)
     {
       tree name = ssa_name (i);
@@ -836,7 +850,11 @@ ccp_finalize (void)
       unsigned int tem, align;
 
       if (!name
-         || !POINTER_TYPE_P (TREE_TYPE (name)))
+         || (!POINTER_TYPE_P (TREE_TYPE (name))
+             && (!INTEGRAL_TYPE_P (TREE_TYPE (name))
+                 /* Don't record nonzero bits before IPA to avoid
+                    using too much memory.  */
+                 || first_pass_instance)))
        continue;
 
       val = get_value (name);
@@ -844,13 +862,24 @@ ccp_finalize (void)
          || TREE_CODE (val->value) != INTEGER_CST)
        continue;
 
-      /* Trailing constant bits specify the alignment, trailing value
-        bits the misalignment.  */
-      tem = val->mask.low;
-      align = (tem & -tem);
-      if (align > 1)
-       set_ptr_info_alignment (get_ptr_info (name), align,
-                               TREE_INT_CST_LOW (val->value) & (align - 1));
+      if (POINTER_TYPE_P (TREE_TYPE (name)))
+       {
+         /* Trailing mask bits specify the alignment, trailing value
+            bits the misalignment.  */
+         tem = val->mask.low;
+         align = (tem & -tem);
+         if (align > 1)
+           set_ptr_info_alignment (get_ptr_info (name), align,
+                                   (TREE_INT_CST_LOW (val->value)
+                                    & (align - 1)));
+       }
+      else
+       {
+         double_int nonzero_bits = val->mask;
+         nonzero_bits = nonzero_bits | tree_to_double_int (val->value);
+         nonzero_bits &= get_nonzero_bits (name);
+         set_nonzero_bits (name, nonzero_bits);
+       }
     }
 
   /* Perform substitutions based on the known constant values.  */
@@ -1671,6 +1700,39 @@ evaluate_stmt (gimple stmt)
       is_constant = (val.lattice_val == CONSTANT);
     }
 
+  if (flag_tree_bit_ccp
+      && ((is_constant && TREE_CODE (val.value) == INTEGER_CST)
+         || (!is_constant && likelyvalue != UNDEFINED))
+      && gimple_get_lhs (stmt)
+      && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME)
+    {
+      tree lhs = gimple_get_lhs (stmt);
+      double_int nonzero_bits = get_nonzero_bits (lhs);
+      double_int mask = double_int::mask (TYPE_PRECISION (TREE_TYPE (lhs)));
+      if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
+       {
+         if (!is_constant)
+           {
+             val.lattice_val = CONSTANT;
+             val.value = build_zero_cst (TREE_TYPE (lhs));
+             /* CCP wants the bits above precision set.  */
+             val.mask = nonzero_bits | ~mask;
+             is_constant = true;
+           }
+         else
+           {
+             double_int valv = tree_to_double_int (val.value);
+             if (!(valv & ~nonzero_bits & mask).is_zero ())
+               val.value = double_int_to_tree (TREE_TYPE (lhs),
+                                               valv & nonzero_bits);
+             if (nonzero_bits.is_zero ())
+               val.mask = double_int_zero;
+             else
+               val.mask = val.mask & (nonzero_bits | ~mask);
+           }
+       }
+    }
+
   if (!is_constant)
     {
       /* The statement produced a nonconstant value.  If the statement
index 435cdc78965c0bc1ddbfc456447b05c60e910c17..00bd436c008c2148e4be6805b70b273d6013795d 100644 (file)
@@ -189,11 +189,30 @@ set_range_info (tree name, double_int min, double_int max)
     {
       ri = ggc_alloc_cleared_range_info_def ();
       SSA_NAME_RANGE_INFO (name) = ri;
+      ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
     }
 
   /* Set the values.  */
   ri->min = min;
   ri->max = max;
+
+  /* If it is a range, try to improve nonzero_bits from the min/max.  */
+  if (min.cmp (max, TYPE_UNSIGNED (TREE_TYPE (name))) != 1)
+    {
+      int prec = TYPE_PRECISION (TREE_TYPE (name));
+      double_int xorv;
+
+      min = min.zext (prec);
+      max = max.zext (prec);
+      xorv = min ^ max;
+      if (xorv.high)
+       xorv = double_int::mask (2 * HOST_BITS_PER_WIDE_INT
+                                - clz_hwi (xorv.high));
+      else if (xorv.low)
+       xorv = double_int::mask (HOST_BITS_PER_WIDE_INT
+                                - clz_hwi (xorv.low));
+      ri->nonzero_bits = ri->nonzero_bits & (min | xorv);
+    }
 }
 
 
@@ -233,6 +252,47 @@ get_range_info (tree name, double_int *min, double_int *max)
   return range_type;
 }
 
+/* Change non-zero bits bitmask of NAME.  */
+
+void
+set_nonzero_bits (tree name, double_int mask)
+{
+  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+  if (SSA_NAME_RANGE_INFO (name) == NULL)
+    set_range_info (name,
+                   tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))),
+                   tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name))));
+  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+  ri->nonzero_bits
+    = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
+}
+
+/* Return a double_int with potentially non-zero bits in SSA_NAME
+   NAME, or double_int_minus_one if unknown.  */
+
+double_int
+get_nonzero_bits (tree name)
+{
+  if (POINTER_TYPE_P (TREE_TYPE (name)))
+    {
+      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
+      if (pi && pi->align)
+       {
+         double_int al = double_int::from_uhwi (pi->align - 1);
+         return ((double_int::mask (TYPE_PRECISION (TREE_TYPE (name))) & ~al)
+                 | double_int::from_uhwi (pi->misalign));
+       }
+      return double_int_minus_one;
+    }
+
+  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+  if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
+             > 2 * HOST_BITS_PER_WIDE_INT))
+    return double_int_minus_one;
+
+  return ri->nonzero_bits;
+}
+
 /* We no longer need the SSA_NAME expression VAR, release it so that
    it may be reused.
 
index f80e0b2ce33cee011e98209fa8f9ffcb9af49490..1d02d966fd7c4d893c785a59c1f2ea5dc524c0f0 100644 (file)
@@ -52,6 +52,8 @@ struct GTY (()) range_info_def {
   double_int min;
   /* Maximum for value range.  */
   double_int max;
+  /* Non-zero bits - bits not set are guaranteed to be always zero.  */
+  double_int nonzero_bits;
 };
 
 
@@ -68,10 +70,11 @@ struct GTY (()) range_info_def {
 enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
 
 /* Sets the value range to SSA.  */
-extern void set_range_info (tree ssa, double_int min, double_int max);
+extern void set_range_info (tree, double_int, double_int);
 /* Gets the value range from SSA.  */
-extern enum value_range_type  get_range_info (tree name, double_int *min,
-                                             double_int *max);
+extern enum value_range_type get_range_info (tree, double_int *, double_int *);
+extern void set_nonzero_bits (tree, double_int);
+extern double_int get_nonzero_bits (tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (void);
 extern void ssanames_print_statistics (void);