aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-02-25 10:16:55 +0100
committerJakub Jelinek <jakub@redhat.com>2021-02-25 10:16:55 +0100
commit3cf52b87ff6938e30883b8f8f542a638635d507d (patch)
treeff9120fdd9a7cb6eb72e94e883ec5e08d491d687 /gcc
parent5e7c0927cbd115d488d527c86dfc671b22c378db (diff)
downloadgcc-3cf52b87ff6938e30883b8f8f542a638635d507d.zip
gcc-3cf52b87ff6938e30883b8f8f542a638635d507d.tar.gz
gcc-3cf52b87ff6938e30883b8f8f542a638635d507d.tar.bz2
vrp: Handle VCE in vrp_simplify_cond_using_ranges [PR80635]
> So I wonder what other optimizations are prevented here? > Why does uninit warn with VCE but not with NOP_EXPR? Or does the > warning disappear because of those other optimizations you mention? The optimization that it prevents is in this particular case in tree-vrp.c (vrp_simplify_cond_using_ranges): if (!is_gimple_assign (def_stmt) || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))) return; so it punts on VIEW_CONVERT_EXPR, with NOP_EXPR it optimizes that: _9 = (bool) maybe_a$4_7; if (_9 != 0) into: _9 = (bool) maybe_a$4_7; if (maybe_a$4_7 != 0) Now, if I apply my patch but manually disable this vrp_simplify_cond_using_ranges optimization, then the uninit warning is back, so on the uninit side it is not about VIEW_CONVERT_EXPR vs. NOP_EXPR, both are bad there, uninit wants the guarding condition to be that SSA_NAME and not some demotion cast thereof. We have: # maybe_a$m_6 = PHI <_5(4), maybe_a$m_4(D)(6)> # maybe_a$4_7 = PHI <1(4), 0(6)> ... One of: _9 = VIEW_CONVERT_EXPR<bool>(maybe_a$4_7); if (_9 != 0) or: _9 = (bool) maybe_a$4_7; if (_9 != 0) or: if (maybe_a$4_7 != 0) followed by: goto <bb 11>; [0.00%] else goto <bb 14>; [0.00%] ... <bb 11> [count: 0]: set (maybe_a$m_6); and uninit wants to see that maybe_a$m_4(D) is not used if bb 11 is encountered. This patch fixes it by teaching vrp_simplify_cond_using_ranges to handle VCE (when from an integral type) in addition to NOP_EXPR/CONVERT_EXPR, of course as long as the VCE or demotion doesn't change any values, i.e. when the range of the VCE or conversion operand fits into the target type. 2021-02-25 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/80635 * tree-vrp.c (vrp_simplify_cond_using_ranges): Also handle VIEW_CONVERT_EXPR if modes are the same, innerop is integral and has mode precision. * g++.dg/warn/pr80635-1.C: New test. * g++.dg/warn/pr80635-2.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/g++.dg/warn/pr80635-1.C46
-rw-r--r--gcc/testsuite/g++.dg/warn/pr80635-2.C31
-rw-r--r--gcc/tree-vrp.c17
3 files changed, 91 insertions, 3 deletions
diff --git a/gcc/testsuite/g++.dg/warn/pr80635-1.C b/gcc/testsuite/g++.dg/warn/pr80635-1.C
new file mode 100644
index 0000000..8478791
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr80635-1.C
@@ -0,0 +1,46 @@
+// PR tree-optimization/80635
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Wmaybe-uninitialized" }
+
+using size_t = decltype (sizeof (1));
+inline void *operator new (size_t, void *p) { return p; }
+template<typename T>
+struct optional
+{
+ optional () : m_dummy (), live (false) {}
+ void emplace () { new (&m_item) T (); live = true; }
+ ~optional () { if (live) m_item.~T (); }
+
+ union
+ {
+ struct {} m_dummy;
+ T m_item;
+ };
+ bool live;
+};
+
+extern int get ();
+extern void set (int);
+
+struct A
+{
+ A () : m (get ()) {}
+ ~A () { set (m); } // { dg-bogus "may be used uninitialized in this function" }
+
+ int m;
+};
+
+struct B
+{
+ B ();
+ ~B ();
+};
+
+void func ()
+{
+ optional<A> maybe_a;
+ optional<B> maybe_b;
+
+ maybe_a.emplace ();
+ maybe_b.emplace ();
+}
diff --git a/gcc/testsuite/g++.dg/warn/pr80635-2.C b/gcc/testsuite/g++.dg/warn/pr80635-2.C
new file mode 100644
index 0000000..9f57547
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr80635-2.C
@@ -0,0 +1,31 @@
+// PR tree-optimization/80635
+// { dg-do compile { target c++17 } }
+// { dg-options "-O2 -Wmaybe-uninitialized" }
+
+#include <optional>
+
+extern int get ();
+extern void set (int);
+
+struct A
+{
+ A () : m (get ()) {}
+ ~A () { set (m); } // { dg-bogus "may be used uninitialized in this function" }
+
+ int m;
+};
+
+struct B
+{
+ B ();
+ ~B ();
+};
+
+void func ()
+{
+ std::optional<A> maybe_a;
+ std::optional<B> maybe_b;
+
+ maybe_a.emplace ();
+ maybe_b.emplace ();
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 53eaf9c..8d638ae 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -4390,11 +4390,22 @@ vrp_simplify_cond_using_ranges (vr_values *query, gcond *stmt)
gimple *def_stmt = SSA_NAME_DEF_STMT (op0);
tree innerop;
- if (!is_gimple_assign (def_stmt)
- || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
+ if (!is_gimple_assign (def_stmt))
return;
- innerop = gimple_assign_rhs1 (def_stmt);
+ switch (gimple_assign_rhs_code (def_stmt))
+ {
+ CASE_CONVERT:
+ innerop = gimple_assign_rhs1 (def_stmt);
+ break;
+ case VIEW_CONVERT_EXPR:
+ innerop = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop)))
+ return;
+ break;
+ default:
+ return;
+ }
if (TREE_CODE (innerop) == SSA_NAME
&& !POINTER_TYPE_P (TREE_TYPE (innerop))