Commit 666e8e06 by Richard Biener Committed by Richard Biener

re PR middle-end/64614 (bogus used initialized warning (in gcc 4.9.2); switch statement versus &)

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.

From-SVN: r219739
parent 6220fdff
2015-01-16 Richard Biener <rguenther@suse.de> 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).
2015-01-16 Richard Biener <rguenther@suse.de>
PR tree-optimization/64568 PR tree-optimization/64568
* tree-ssa-forwprop.c (pass_forwprop::execute): Guard * tree-ssa-forwprop.c (pass_forwprop::execute): Guard
complex load rewriting for TARGET_MEM_REFs. complex load rewriting for TARGET_MEM_REFs.
......
2015-01-16 Richard Biener <rguenther@suse.de> 2015-01-16 Richard Biener <rguenther@suse.de>
PR middle-end/64614
* gcc.dg/uninit-18.c: New testcase.
2015-01-16 Richard Biener <rguenther@suse.de>
PR tree-optimization/64568 PR tree-optimization/64568
* g++.dg/torture/pr64568-2.C: New testcase. * g++.dg/torture/pr64568-2.C: New testcase.
......
/* { 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" } */
}
...@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h" #include "tree-pass.h"
#include "diagnostic-core.h" #include "diagnostic-core.h"
#include "params.h" #include "params.h"
#include "tree-cfg.h"
/* This implements the pass that does predicate aware warning on uses of /* This implements the pass that does predicate aware warning on uses of
possibly uninitialized variables. The pass first collects the set of possibly uninitialized variables. The pass first collects the set of
...@@ -411,6 +412,7 @@ find_control_equiv_block (basic_block bb) ...@@ -411,6 +412,7 @@ find_control_equiv_block (basic_block bb)
#define MAX_NUM_CHAINS 8 #define MAX_NUM_CHAINS 8
#define MAX_CHAIN_LEN 5 #define MAX_CHAIN_LEN 5
#define MAX_POSTDOM_CHECK 8 #define MAX_POSTDOM_CHECK 8
#define MAX_SWITCH_CASES 40
/* Computes the control dependence chains (paths of edges) /* Computes the control dependence chains (paths of edges)
for DEP_BB up to the dominating basic block BB (the head node of a 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<edge> *dep_chains, ...@@ -592,17 +594,63 @@ convert_control_dep_chain_into_preds (vec<edge> *dep_chains,
if (skip) if (skip)
continue; 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))
{
/* 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; has_valid_pred = false;
break; 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) if (!has_valid_pred)
...@@ -1329,6 +1377,10 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2) ...@@ -1329,6 +1377,10 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
if (expr2.invert) if (expr2.invert)
code2 = invert_tree_comparison (code2, false); 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) if (code1 != code2 && code2 != NE_EXPR)
return false; return false;
...@@ -1970,8 +2022,25 @@ normalize_one_pred_1 (pred_chain_union *norm_preds, ...@@ -1970,8 +2022,25 @@ normalize_one_pred_1 (pred_chain_union *norm_preds,
} }
else if (gimple_assign_rhs_code (def_stmt) == and_or_code) else if (gimple_assign_rhs_code (def_stmt) == and_or_code)
{ {
push_to_worklist (gimple_assign_rhs1 (def_stmt), work_list, mark_set); /* Avoid splitting up bit manipulations like x & 3 or y | 1. */
push_to_worklist (gimple_assign_rhs2 (def_stmt), work_list, mark_set); 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)) else if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt))
== tcc_comparison) == tcc_comparison)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment