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  <rguent...@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" } */
+ }

Reply via email to