This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR64614


The following fixes PR64614, maybe-uninit warnings in switches
and guards like X & 3.

The support for switches is quite limited (because the predicate
infrastructure in the pass is quite limited), but it seems to
handle this particular case at least.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Any idea how to better handle the case label lookup?  Unfortunately
the pass doesn't have a general information gathering phase or a
lattice...  Maybe we just don't care?  Or put in an arbitrary
limit on gimple_switch_num_labels we handle?

Thanks,
Richard.

2015-01-16  Richard Biener  <rguenther@suse.de>

	PR middle-end/64614
	* tree-ssa-uninit.c: Include tree-cfg.h.
	(convert_control_dep_chain_into_preds): Handle switch statements.
	(is_pred_expr_subset_of): Handle x == CST vs. (x & CST) != 0.
	(normalize_one_pred_1): Do not split bit-manipulations.
	Record (x & CST).

	* gcc.dg/uninit-18.c: New testcase.

Index: gcc/tree-ssa-uninit.c
===================================================================
--- gcc/tree-ssa-uninit.c	(revision 219724)
+++ gcc/tree-ssa-uninit.c	(working copy)
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.
 #include "tree-pass.h"
 #include "diagnostic-core.h"
 #include "params.h"
+#include "tree-cfg.h"
 
 /* This implements the pass that does predicate aware warning on uses of
    possibly uninitialized variables. The pass first collects the set of
@@ -592,17 +593,58 @@ convert_control_dep_chain_into_preds (ve
               if (skip)
                 continue;
             }
-          if (gimple_code (cond_stmt) != GIMPLE_COND)
+          if (gimple_code (cond_stmt) == GIMPLE_COND)
+	    {
+	      one_pred.pred_lhs = gimple_cond_lhs (cond_stmt);
+	      one_pred.pred_rhs = gimple_cond_rhs (cond_stmt);
+	      one_pred.cond_code = gimple_cond_code (cond_stmt);
+	      one_pred.invert = !!(e->flags & EDGE_FALSE_VALUE);
+	      t_chain.safe_push (one_pred);
+	      has_valid_pred = true;
+	    }
+	  else if (gswitch *gs = dyn_cast <gswitch *> (cond_stmt))
+	    {
+	      /* Find the case label.
+	         ???  Ugh, this is quadratic.  */
+	      tree l = NULL_TREE;
+	      unsigned idx;
+	      for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
+		{
+		  tree tl = gimple_switch_label (gs, idx);
+		  if (e->dest == label_to_block (CASE_LABEL (tl)))
+		    {
+		      if (!l)
+			l = tl;
+		      else
+			{
+			  l = NULL_TREE;
+			  break;
+			}
+		    }
+		}
+	      /* If more than one label reaches this block or the case
+	         label doesn't have a single value (like the default one)
+		 fail.  */
+	      if (!l
+		  || !CASE_LOW (l)
+		  || (CASE_HIGH (l) && !operand_equal_p (CASE_LOW (l),
+							 CASE_HIGH (l), 0)))
+		{
+		  has_valid_pred = false;
+		  break;
+		}
+	      one_pred.pred_lhs = gimple_switch_index (gs);
+	      one_pred.pred_rhs = CASE_LOW (l);
+	      one_pred.cond_code = EQ_EXPR;
+	      one_pred.invert = false;
+	      t_chain.safe_push (one_pred);
+	      has_valid_pred = true;
+	    }
+	  else
             {
               has_valid_pred = false;
               break;
             }
-          one_pred.pred_lhs = gimple_cond_lhs (cond_stmt);
-          one_pred.pred_rhs = gimple_cond_rhs (cond_stmt);
-          one_pred.cond_code = gimple_cond_code (cond_stmt);
-          one_pred.invert = !!(e->flags & EDGE_FALSE_VALUE);
-          t_chain.safe_push (one_pred);
-	  has_valid_pred = true;
         }
 
       if (!has_valid_pred)
@@ -1329,6 +1371,10 @@ is_pred_expr_subset_of (pred_info expr1,
   if (expr2.invert)
     code2 = invert_tree_comparison (code2, false);
 
+  if (code1 == EQ_EXPR && code2 == BIT_AND_EXPR)
+    return wi::eq_p (expr1.pred_rhs,
+		     wi::bit_and (expr1.pred_rhs, expr2.pred_rhs));
+
   if (code1 != code2 && code2 != NE_EXPR)
     return false;
 
@@ -1970,8 +2016,25 @@ normalize_one_pred_1 (pred_chain_union *
     }
   else if (gimple_assign_rhs_code (def_stmt) == and_or_code)
     {
-      push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set);
-      push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set);
+      /* Avoid splitting up bit manipulations like x & 3 or y | 1.  */
+      if (is_gimple_min_invariant (gimple_assign_rhs2 (def_stmt)))
+	{
+	  /* But treat x & 3 as condition.  */
+	  if (and_or_code == BIT_AND_EXPR)
+	    {
+	      pred_info n_pred;
+	      n_pred.pred_lhs = gimple_assign_rhs1 (def_stmt);
+	      n_pred.pred_rhs = gimple_assign_rhs2 (def_stmt);
+	      n_pred.cond_code = and_or_code;
+	      n_pred.invert = false;
+	      norm_chain->safe_push (n_pred);
+	    }
+	}
+      else
+	{
+	  push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set);
+	  push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set);
+	}
     }
   else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))
 	   == tcc_comparison)
Index: gcc/testsuite/gcc.dg/uninit-18.c
===================================================================
--- gcc/testsuite/gcc.dg/uninit-18.c	(revision 0)
+++ gcc/testsuite/gcc.dg/uninit-18.c	(working copy)
@@ -0,0 +1,24 @@
+/* { dg-do compile }  */
+/* { dg-options "-O -Wuninitialized" } */
+
+char *foo(int bar, char *baz)
+{
+  char *tmp;
+
+  if (bar & 3)
+    tmp = baz;
+
+  switch (bar) {
+  case 1:
+    tmp[5] = 7;    /* { dg-bogus "may be used uninitialized" } */
+    break;
+  case 2:
+    tmp[11] = 15;  /* { dg-bogus "may be used uninitialized" } */
+    break;
+  default:
+    tmp = 0;
+    break;
+  }
+
+  return tmp;      /* { dg-bogus "may be used uninitialized" } */
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]