I noticed that for binary expressions VRP contains the same bugs
that CCP once did (it treats UNDEFINED * 0 as UNDEFINED).  Then
I noticed we never hit this bug because we never end up with
any range being UNDEFINED - which is bad, because this way we miss
value-ranges for all conditionally initialized variables.

Thus, the following patch fixes this and conservatively handles
the binary expression case (which is only of academic interest
anyway - the important part is to handle UNDEFINED in PHIs).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2011-07-29  Richard Guenther  <rguent...@suse.de>

        * tree-vrp.c (get_value_range): Only set parameter default
        definitions to varying, leave others at undefined.
        (extract_range_from_binary_expr): Fix undefined handling.
        (vrp_visit_phi_node): Handle merged undefined state.

        * gcc.dg/uninit-suppress.c: Also disable VRP.
        * gcc.dg/uninit-suppress_2.c: Likewise.

Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c      (revision 176869)
+++ gcc/tree-vrp.c      (working copy)
@@ -692,16 +692,16 @@ get_value_range (const_tree var)
   /* Defer allocating the equivalence set.  */
   vr->equiv = NULL;
 
-  /* If VAR is a default definition, the variable can take any value
-     in VAR's type.  */
+  /* If VAR is a default definition of a parameter, the variable can
+     take any value in VAR's type.  */
   sym = SSA_NAME_VAR (var);
-  if (SSA_NAME_IS_DEFAULT_DEF (var))
+  if (SSA_NAME_IS_DEFAULT_DEF (var)
+      && TREE_CODE (sym) == PARM_DECL)
     {
       /* Try to use the "nonnull" attribute to create ~[0, 0]
         anti-ranges for pointers.  Note that this is only valid with
         default definitions of PARM_DECLs.  */
-      if (TREE_CODE (sym) == PARM_DECL
-         && POINTER_TYPE_P (TREE_TYPE (sym))
+      if (POINTER_TYPE_P (TREE_TYPE (sym))
          && nonnull_arg_p (sym))
        set_value_range_to_nonnull (vr, TREE_TYPE (sym));
       else
@@ -2225,12 +2225,20 @@ extract_range_from_binary_expr (value_ra
   else
     set_value_range_to_varying (&vr1);
 
-  /* If either range is UNDEFINED, so is the result.  */
-  if (vr0.type == VR_UNDEFINED || vr1.type == VR_UNDEFINED)
+  /* If both ranges are UNDEFINED, so is the result.  */
+  if (vr0.type == VR_UNDEFINED && vr1.type == VR_UNDEFINED)
     {
       set_value_range_to_undefined (vr);
       return;
     }
+  /* If one of the ranges is UNDEFINED drop it to VARYING for the following
+     code.  At some point we may want to special-case operations that
+     have UNDEFINED result for all or some value-ranges of the not UNDEFINED
+     operand.  */
+  else if (vr0.type == VR_UNDEFINED)
+    set_value_range_to_varying (&vr0);
+  else if (vr1.type == VR_UNDEFINED)
+    set_value_range_to_varying (&vr1);
 
   /* The type of the resulting value range defaults to VR0.TYPE.  */
   type = vr0.type;
@@ -6642,6 +6650,8 @@ vrp_visit_phi_node (gimple phi)
 
   if (vr_result.type == VR_VARYING)
     goto varying;
+  else if (vr_result.type == VR_UNDEFINED)
+    goto update_range;
 
   old_edges = vr_phi_edge_counts[SSA_NAME_VERSION (lhs)];
   vr_phi_edge_counts[SSA_NAME_VERSION (lhs)] = edges;
@@ -6713,6 +6723,7 @@ vrp_visit_phi_node (gimple phi)
 
   /* If the new range is different than the previous value, keep
      iterating.  */
+update_range:
   if (update_value_range (lhs, &vr_result))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))

Index: gcc/testsuite/gcc.dg/uninit-suppress.c
===================================================================
*** gcc/testsuite/gcc.dg/uninit-suppress.c      (revision 176869)
--- gcc/testsuite/gcc.dg/uninit-suppress.c      (working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-fno-tree-ccp -O2 -Wuninitialized -Wno-maybe-uninitialized" 
} */
  void blah();
  int gflag;
  
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-fno-tree-ccp -fno-tree-vrp -O2 -Wuninitialized 
-Wno-maybe-uninitialized" } */
  void blah();
  int gflag;
  
Index: gcc/testsuite/gcc.dg/uninit-suppress_2.c
===================================================================
*** gcc/testsuite/gcc.dg/uninit-suppress_2.c    (revision 176869)
--- gcc/testsuite/gcc.dg/uninit-suppress_2.c    (working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-fno-tree-ccp -O2 -Wuninitialized -Werror=uninitialized 
-Wno-error=maybe-uninitialized" } */
  void blah();
  int gflag;
  
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-fno-tree-ccp -fno-tree-vrp -O2 -Wuninitialized 
-Werror=uninitialized -Wno-error=maybe-uninitialized" } */
  void blah();
  int gflag;
  

Reply via email to