aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2022-11-30 10:55:03 +0100
committerRichard Biener <rguenther@suse.de>2022-11-30 12:00:56 +0100
commit9500877d05c56cef7bfbdcecaab3b1af2610bff3 (patch)
tree060d420699da00ccf5c95ca0a34bec48ec781143 /gcc
parent7716ee1e90412f785cba20acffd59fc7461302cb (diff)
downloadgcc-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.cc71
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C15
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);
+}