diff options
author | Richard Biener <rguenther@suse.de> | 2022-11-30 10:55:03 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2022-11-30 12:00:56 +0100 |
commit | 9500877d05c56cef7bfbdcecaab3b1af2610bff3 (patch) | |
tree | 060d420699da00ccf5c95ca0a34bec48ec781143 /gcc | |
parent | 7716ee1e90412f785cba20acffd59fc7461302cb (diff) | |
download | gcc-9500877d05c56cef7bfbdcecaab3b1af2610bff3.zip gcc-9500877d05c56cef7bfbdcecaab3b1af2610bff3.tar.gz gcc-9500877d05c56cef7bfbdcecaab3b1af2610bff3.tar.bz2 |
tree-optimization/107919 - uninit diagnostic predicate simplification
We fail to simplify
((_145 != 0B) AND (_531 == 2) AND (_109 == 0))
OR ((NOT (_145 != 0B)) AND (_531 == 2) AND (_109 == 0))
OR ((NOT (_531 == 2)) AND (_109 == 0))
because the existing simplification of !A && B || A && B is implemented
too simplistic. The following re-implements that which fixes the
bogus uninit diagnostic when using -O1 but not yet at -O2.
PR tree-optimization/107919
* gimple-predicate-analysis.cc (predicate::simplify_2):
Handle predicates of arbitrary length.
* g++.dg/warn/Wuninitialized-pr107919-1.C: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/gimple-predicate-analysis.cc | 71 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C | 15 |
2 files changed, 43 insertions, 43 deletions
diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc index 5013a44..23be4b69 100644 --- a/gcc/gimple-predicate-analysis.cc +++ b/gcc/gimple-predicate-analysis.cc @@ -1257,64 +1257,49 @@ predicate::simplify_2 () /* (X AND Y) OR (!X AND Y) is equivalent to Y. (X AND Y) OR (X AND !Y) is equivalent to X. */ - unsigned n = m_preds.length (); - for (unsigned i = 0; i < n; i++) + for (unsigned i = 0; i < m_preds.length (); i++) { pred_chain &a_chain = m_preds[i]; - if (a_chain.length () != 2) - continue; - - /* Create copies since the chain may be released below before - the copy is added to the other chain. */ - const pred_info x = a_chain[0]; - const pred_info y = a_chain[1]; - for (unsigned j = 0; j < n; j++) + for (unsigned j = i + 1; j < m_preds.length (); j++) { - if (j == i) - continue; - pred_chain &b_chain = m_preds[j]; - if (b_chain.length () != 2) + if (b_chain.length () != a_chain.length ()) continue; - const pred_info &x2 = b_chain[0]; - const pred_info &y2 = b_chain[1]; - - if (pred_equal_p (x, x2) && pred_neg_p (y, y2)) + unsigned neg_idx = -1U; + for (unsigned k = 0; k < a_chain.length (); ++k) { - /* Kill a_chain. */ - b_chain.release (); - a_chain.release (); - b_chain.safe_push (x); - simplified = true; - break; + if (pred_equal_p (a_chain[k], b_chain[k])) + continue; + if (neg_idx != -1U) + { + neg_idx = -1U; + break; + } + if (pred_neg_p (a_chain[k], b_chain[k])) + neg_idx = k; + else + break; } - if (pred_neg_p (x, x2) && pred_equal_p (y, y2)) + /* If we found equal chains with one negated predicate + simplify. */ + if (neg_idx != -1U) { - /* Kill a_chain. */ - a_chain.release (); - b_chain.release (); - b_chain.safe_push (y); + a_chain.ordered_remove (neg_idx); + m_preds.ordered_remove (j); simplified = true; + if (a_chain.is_empty ()) + { + /* A && !A simplifies to true, wipe the whole predicate. */ + for (unsigned k = 0; k < m_preds.length (); ++k) + m_preds[k].release (); + m_preds.truncate (0); + } break; } } } - /* Now clean up the chain. */ - if (simplified) - { - pred_chain_union s_preds = vNULL; - for (unsigned i = 0; i < n; i++) - { - if (m_preds[i].is_empty ()) - continue; - s_preds.safe_push (m_preds[i]); - } - m_preds.release (); - m_preds = s_preds; - s_preds = vNULL; - } return simplified; } diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C new file mode 100644 index 0000000..dd631dc --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } +// { dg-options "-O -Wuninitialized" } + +#include <memory> +#include <variant> + +using Event = std::variant<std::variant<std::tuple<std::unique_ptr<int>>>, int, char>; + +void do_something(void* storage) +{ + Event event {}; + auto& swappedValue = *reinterpret_cast<Event*>(storage); + std::swap(event, swappedValue); +} |