The byte tracking of call LHS didn't properly handle possibly throwing calls correctly which cases bogus DSE and in turn, for the testcase a bogus uninit diagnostic and (unreliable) wrong-code.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/109434 * tree-ssa-dse.cc (initialize_ao_ref_for_dse): Properly handle possibly throwing calls when processing the LHS and may-defs are not OK. * g++.dg/opt/pr109434.C: New testcase. --- gcc/testsuite/g++.dg/opt/pr109434.C | 28 ++++++++++++++++++++++++++++ gcc/tree-ssa-dse.cc | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr109434.C diff --git a/gcc/testsuite/g++.dg/opt/pr109434.C b/gcc/testsuite/g++.dg/opt/pr109434.C new file mode 100644 index 00000000000..cffa327fd9b --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr109434.C @@ -0,0 +1,28 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } +// { dg-options "-O2 -Wall" } + +#include <optional> +#include <stdexcept> + +std::optional<int> foo() +{ + volatile int x = 1; + if (x) + throw std::runtime_error("haha"); + return 42; +} + +int main() +{ + std::optional<int> optInt; + try { + // We falsely DSEd the LHS of the call even though foo throws + // which results in an uninitialized diagnostic + optInt = foo(); + } catch (...) { + return optInt.has_value(); + } + std::optional<double> optDbl{optInt}; + return optDbl ? optDbl.value () : 2.0; +} diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index 4f8a44fbba0..eabe8ba4522 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -179,7 +179,8 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write, bool may_def_ok = false) } if (tree lhs = gimple_get_lhs (stmt)) { - if (TREE_CODE (lhs) != SSA_NAME) + if (TREE_CODE (lhs) != SSA_NAME + && (may_def_ok || !stmt_could_throw_p (cfun, stmt))) { ao_ref_init (write, lhs); return true; -- 2.35.3