From 3cf52b87ff6938e30883b8f8f542a638635d507d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 25 Feb 2021 10:16:55 +0100 Subject: [PATCH] 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(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 ; [0.00%] else goto ; [0.00%] ... [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 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. --- gcc/testsuite/g++.dg/warn/pr80635-1.C | 46 +++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/warn/pr80635-2.C | 31 +++++++++++++++++++++++ gcc/tree-vrp.c | 17 ++++++++++--- 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/pr80635-1.C create mode 100644 gcc/testsuite/g++.dg/warn/pr80635-2.C 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 +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 maybe_a; + optional 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 + +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 maybe_a; + std::optional 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)) -- 2.7.4