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]

Re: [PATCH] Fix PR64614


On Fri, 16 Jan 2015, Jakub Jelinek wrote:

> On Fri, Jan 16, 2015 at 02:02:37PM +0100, Richard Biener wrote:
> > 
> > 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?
> 
> The pass already has various other limits:
> #define MAX_NUM_CHAINS 8
> #define MAX_CHAIN_LEN 5
> #define MAX_POSTDOM_CHECK 8
> I'd just add MAX_SWITCH_CASES 40

Done, committed as follows.

Richard.

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

	PR middle-end/64614
	* tree-ssa-uninit.c: Include tree-cfg.h.
	(MAX_SWITCH_CASES): New define.
	(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.orig	2015-01-16 14:14:18.135193759 +0100
--- gcc/tree-ssa-uninit.c	2015-01-16 14:16:16.635189656 +0100
*************** along with GCC; see the file COPYING3.
*** 58,63 ****
--- 58,64 ----
  #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
*************** find_control_equiv_block (basic_block bb
*** 411,416 ****
--- 412,418 ----
  #define MAX_NUM_CHAINS 8
  #define MAX_CHAIN_LEN 5
  #define MAX_POSTDOM_CHECK 8
+ #define MAX_SWITCH_CASES 40
  
  /* Computes the control dependence chains (paths of edges)
     for DEP_BB up to the dominating basic block BB (the head node of a
*************** convert_control_dep_chain_into_preds (ve
*** 592,608 ****
                if (skip)
                  continue;
              }
!           if (gimple_code (cond_stmt) != GIMPLE_COND)
              {
                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)
--- 594,656 ----
                if (skip)
                  continue;
              }
!           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))
! 	    {
! 	      /* Avoid quadratic behavior.  */
! 	      if (gimple_switch_num_labels (gs) > MAX_SWITCH_CASES)
! 		{
! 		  has_valid_pred = false;
! 		  break;
! 		}
! 	      /* Find the case label.  */
! 	      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;
              }
          }
  
        if (!has_valid_pred)
*************** is_pred_expr_subset_of (pred_info expr1,
*** 1329,1334 ****
--- 1377,1386 ----
    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;
  
*************** normalize_one_pred_1 (pred_chain_union *
*** 1970,1977 ****
      }
    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);
      }
    else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))
  	   == tcc_comparison)
--- 2022,2046 ----
      }
    else if (gimple_assign_rhs_code (def_stmt) == and_or_code)
      {
!       /* 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
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/uninit-18.c	2015-01-16 14:14:28.304193407 +0100
***************
*** 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]