tree-optimization/107919 - uninit diagnostic predicate simplification
authorRichard Biener <rguenther@suse.de>
Wed, 30 Nov 2022 09:55:03 +0000 (10:55 +0100)
committerRichard Biener <rguenther@suse.de>
Wed, 30 Nov 2022 11:00:56 +0000 (12:00 +0100)
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.

gcc/gimple-predicate-analysis.cc
gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C [new file with mode: 0644]

index 5013a44..23be4b6 100644 (file)
@@ -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 (file)
index 0000000..dd631dc
--- /dev/null
@@ -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);
+}