aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2022-02-04 09:46:43 +0100
committerRichard Biener <rguenther@suse.de>2022-02-10 10:56:14 +0100
commit0f58ba4dd6b25b16d25494ae18d15dfa681f9b65 (patch)
tree72fb407291d3a50d206b43c977c237a49a41e642
parent4a8083285c3edf50088a095870b217ab0881dff0 (diff)
downloadgcc-0f58ba4dd6b25b16d25494ae18d15dfa681f9b65.zip
gcc-0f58ba4dd6b25b16d25494ae18d15dfa681f9b65.tar.gz
gcc-0f58ba4dd6b25b16d25494ae18d15dfa681f9b65.tar.bz2
tree-optimization/104373 - early diagnostic on unreachable code
The following improves early uninit diagnostics by computing edge reachability using VN and ignoring unreachable blocks when looking for uninitialized uses. To not ICE with -fdump-tree-all the early uninit pass needs a dumpfile since VN tries to dump statistics. 2022-02-04 Richard Biener <rguenther@suse.de> PR tree-optimization/104373 * tree-ssa-sccvn.h (do_rpo_vn): New export exposing the walk kind. * tree-ssa-sccvn.cc (do_rpo_vn): Export, get the default walk kind as argument. (run_rpo_vn): Adjust. (pass_fre::execute): Likewise. * tree-ssa-uninit.cc (warn_uninitialized_vars): Skip blocks not reachable. (execute_late_warn_uninitialized): Mark all edges as executable. (execute_early_warn_uninitialized): Use VN to compute executable edges. (pass_data_early_warn_uninitialized): Enable a dump file, change dump name to warn_uninit. * g++.dg/warn/Wuninitialized-32.C: New testcase. * gcc.dg/uninit-pr20644-O0.c: Remove XFAIL.
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-32.C14
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr20644-O0.c2
-rw-r--r--gcc/tree-ssa-sccvn.cc18
-rw-r--r--gcc/tree-ssa-sccvn.h1
-rw-r--r--gcc/tree-ssa-uninit.cc39
5 files changed, 58 insertions, 16 deletions
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-32.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-32.C
new file mode 100644
index 0000000..8b02b5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-32.C
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-additional-options "-Wall" }
+
+void* operator new[](unsigned long, void* __p);
+
+struct allocator
+{
+ ~allocator();
+};
+
+void *foo (void *p)
+{
+ return p ? new(p) allocator[1] : new allocator[1]; // { dg-bogus "uninitialized" }
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-pr20644-O0.c b/gcc/testsuite/gcc.dg/uninit-pr20644-O0.c
index 8ae697a..a335d8c 100644
--- a/gcc/testsuite/gcc.dg/uninit-pr20644-O0.c
+++ b/gcc/testsuite/gcc.dg/uninit-pr20644-O0.c
@@ -7,7 +7,7 @@ int foo ()
int j;
if (1 == i)
- return j; /* { dg-bogus "uninitialized" "uninitialized" { xfail *-*-* } } */
+ return j; /* { dg-bogus "uninitialized" "uninitialized" } */
return 0;
}
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index a03f0aa..eb17549 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -7034,15 +7034,14 @@ eliminate_with_rpo_vn (bitmap inserted_exprs)
return walker.eliminate_cleanup ();
}
-static unsigned
+unsigned
do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
- bool iterate, bool eliminate);
+ bool iterate, bool eliminate, vn_lookup_kind kind);
void
run_rpo_vn (vn_lookup_kind kind)
{
- default_vn_walk_kind = kind;
- do_rpo_vn (cfun, NULL, NULL, true, false);
+ do_rpo_vn (cfun, NULL, NULL, true, false, kind);
/* ??? Prune requirement of these. */
constant_to_value_id = new hash_table<vn_constant_hasher> (23);
@@ -7740,11 +7739,12 @@ do_unwind (unwind_state *to, rpo_elim &avail)
executed and iterate. If ELIMINATE is true then perform
elimination, otherwise leave that to the caller. */
-static unsigned
+unsigned
do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
- bool iterate, bool eliminate)
+ bool iterate, bool eliminate, vn_lookup_kind kind)
{
unsigned todo = 0;
+ default_vn_walk_kind = kind;
/* We currently do not support region-based iteration when
elimination is requested. */
@@ -8164,8 +8164,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
unsigned
do_rpo_vn (function *fn, edge entry, bitmap exit_bbs)
{
- default_vn_walk_kind = VN_WALKREWRITE;
- unsigned todo = do_rpo_vn (fn, entry, exit_bbs, false, true);
+ unsigned todo = do_rpo_vn (fn, entry, exit_bbs, false, true, VN_WALKREWRITE);
free_rpo_vn ();
return todo;
}
@@ -8221,8 +8220,7 @@ pass_fre::execute (function *fun)
if (iterate_p)
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
- default_vn_walk_kind = VN_WALKREWRITE;
- todo = do_rpo_vn (fun, NULL, NULL, iterate_p, true);
+ todo = do_rpo_vn (fun, NULL, NULL, iterate_p, true, VN_WALKREWRITE);
free_rpo_vn ();
if (iterate_p)
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index f161b80..aeed070 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -291,6 +291,7 @@ value_id_constant_p (unsigned int v)
tree fully_constant_vn_reference_p (vn_reference_t);
tree vn_nary_simplify (vn_nary_op_t);
+unsigned do_rpo_vn (function *, edge, bitmap, bool, bool, vn_lookup_kind);
unsigned do_rpo_vn (function *, edge, bitmap);
void run_rpo_vn (vn_lookup_kind);
unsigned eliminate_with_rpo_vn (bitmap);
diff --git a/gcc/tree-ssa-uninit.cc b/gcc/tree-ssa-uninit.cc
index 02e88d5..ab83a4b 100644
--- a/gcc/tree-ssa-uninit.cc
+++ b/gcc/tree-ssa-uninit.cc
@@ -38,8 +38,9 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "calls.h"
#include "gimple-range.h"
-
#include "gimple-predicate-analysis.h"
+#include "domwalk.h"
+#include "tree-ssa-sccvn.h"
/* This implements the pass that does predicate aware warning on uses of
possibly uninitialized variables. The pass first collects the set of
@@ -986,7 +987,19 @@ warn_uninitialized_vars (bool wmaybe_uninit)
basic_block bb;
FOR_EACH_BB_FN (bb, cfun)
{
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (e->flags & EDGE_EXECUTABLE)
+ break;
+ /* Skip unreachable blocks. For early analysis we use VN to
+ determine edge executability when wmaybe_uninit. */
+ if (!e)
+ continue;
+
basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ /* ??? This could be improved when we use a greedy walk and have
+ some edges marked as not executable. */
wlims.always_executed = dominated_by_p (CDI_POST_DOMINATORS, succ, bb);
if (wlims.always_executed)
@@ -1319,6 +1332,11 @@ execute_late_warn_uninitialized (function *fun)
calculate_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_POST_DOMINATORS);
+
+ /* Mark all edges executable, warn_uninitialized_vars will skip
+ unreachable blocks. */
+ set_all_edges_as_executable (fun);
+
/* Re-do the plain uninitialized variable check, as optimization may have
straightened control flow. Do this first so that we don't accidentally
get a "may be" warning when we'd have seen an "is" warning later. */
@@ -1388,7 +1406,7 @@ make_pass_late_warn_uninitialized (gcc::context *ctxt)
}
static unsigned int
-execute_early_warn_uninitialized (void)
+execute_early_warn_uninitialized (struct function *fun)
{
/* Currently, this pass runs always but
execute_late_warn_uninitialized only runs with optimization. With
@@ -1398,6 +1416,17 @@ execute_early_warn_uninitialized (void)
calculate_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_POST_DOMINATORS);
+ /* Use VN in its cheapest incarnation and without doing any
+ elimination to compute edge reachability. Don't bother when
+ we only warn for unconditionally executed code though. */
+ if (!optimize)
+ {
+ do_rpo_vn (fun, NULL, NULL, false, false, VN_NOWALK);
+ free_rpo_vn ();
+ }
+ else
+ set_all_edges_as_executable (fun);
+
warn_uninitialized_vars (/*warn_maybe_uninitialized=*/!optimize);
/* Post-dominator information cannot be reliably updated. Free it
@@ -1412,7 +1441,7 @@ namespace {
const pass_data pass_data_early_warn_uninitialized =
{
GIMPLE_PASS, /* type */
- "*early_warn_uninitialized", /* name */
+ "early_uninit", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_TREE_UNINIT, /* tv_id */
PROP_ssa, /* properties_required */
@@ -1431,9 +1460,9 @@ public:
/* opt_pass methods: */
virtual bool gate (function *) { return gate_warn_uninitialized (); }
- virtual unsigned int execute (function *)
+ virtual unsigned int execute (function *fun)
{
- return execute_early_warn_uninitialized ();
+ return execute_early_warn_uninitialized (fun);
}
}; // class pass_early_warn_uninitialized