This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR64614
- From: Richard Biener <rguenther at suse dot de>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 16 Jan 2015 14:17:55 +0100 (CET)
- Subject: Re: [PATCH] Fix PR64614
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot LSU dot 2 dot 11 dot 1501161358380 dot 12482 at zhemvz dot fhfr dot qr> <20150116131643 dot GO1405 at tucnak dot redhat dot com>
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" } */
+ }