From 666e8e0603d805541983e493354e96685bf0437d Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 16 Jan 2015 13:26:10 +0000 Subject: [PATCH] re PR middle-end/64614 (bogus used initialized warning (in gcc 4.9.2); switch statement versus &) 2015-01-16 Richard Biener 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. From-SVN: r219739 --- gcc/ChangeLog | 10 ++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/uninit-18.c | 24 +++++++++ gcc/tree-ssa-uninit.c | 87 ++++++++++++++++++++++++++++---- 4 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/uninit-18.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c9a70702d52..89738ad25b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-01-16 Richard Biener + + 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). + 2015-01-16 Richard Biener PR tree-optimization/64568 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 81645b11cae..b542f771434 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-01-16 Richard Biener + + PR middle-end/64614 + * gcc.dg/uninit-18.c: New testcase. + 2015-01-16 Richard Biener PR tree-optimization/64568 diff --git a/gcc/testsuite/gcc.dg/uninit-18.c b/gcc/testsuite/gcc.dg/uninit-18.c new file mode 100644 index 00000000000..223983e107e --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-18.c @@ -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" } */ +} diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index da400885ca8..25aae19f566 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #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 @@ -411,6 +412,7 @@ find_control_equiv_block (basic_block bb) #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 @@ -592,17 +594,63 @@ convert_control_dep_chain_into_preds (vec *dep_chains, 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 (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; } - 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 +1377,10 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2) 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 +2022,25 @@ normalize_one_pred_1 (pred_chain_union *norm_preds, } 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) -- 2.30.2