]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/107937 - uninit predicate simplification fixup
authorRichard Biener <rguenther@suse.de>
Thu, 1 Dec 2022 09:12:28 +0000 (10:12 +0100)
committerRichard Biener <rguenther@suse.de>
Thu, 1 Dec 2022 09:53:41 +0000 (10:53 +0100)
The following changes the predicate representation to record the
value of a predicate with an empty set of AND predicates.  That's
necessary to properly represent the conservative fallback for the
def vs use predicates.  Since simplification now can result in
such an empty set this distinction becomes important and we need
to check for this as we otherwise ICE.

PR tree-optimization/107937
* gimple-predicate-analysis.h (predicate::is_true): New.
(predicate::is_false): Likewise.
(predicate::empty_val): Likewise.
(uninit_analysis::uninit_analysis): Properly initialize
def_preds.
* gimple-predicate-analysis.cc (simplify_1b): Indicate
whether the chain became empty.
(predicate::simplify): Release emptied chain before removing it.
(predicate::normalize): Replace temporary object with assertion.
(uninit_analysis::is_use_guarded): Deal with predicates
that simplify to true/false.

* gcc.dg/pr107937.c: New testcase.

gcc/gimple-predicate-analysis.cc
gcc/gimple-predicate-analysis.h
gcc/testsuite/gcc.dg/pr107937.c [new file with mode: 0644]

index ce2e1d10e431bacbd9e6f601fd257c18529edcb9..afe01e7f4b8d95e513da9903205e7e0cee2ba53c 100644 (file)
@@ -1249,7 +1249,7 @@ simplify_1a (pred_chain &chain)
 }
 
 /* Implement rule 1b above.  PREDS is the AND predicate to simplify
-   in place.  Returns true if CHAIN simplifies to true.  */
+   in place.  Returns true if CHAIN simplifies to true or false.  */
 
 static bool
 simplify_1b (pred_chain &chain)
@@ -1290,6 +1290,8 @@ simplify_1b (pred_chain &chain)
            {
              chain.ordered_remove (j);
              chain.ordered_remove (i);
+             if (chain.is_empty ())
+               return true;
              i--;
              break;
            }
@@ -1503,6 +1505,7 @@ predicate::simplify (gimple *use_or_def, bool is_use)
       ::simplify_1a (m_preds[i]);
       if (::simplify_1b (m_preds[i]))
        {
+         m_preds[i].release ();
          m_preds.ordered_remove (i);
          i--;
        }
@@ -1719,10 +1722,11 @@ predicate::normalize (const pred_chain &chain)
   while (!work_list.is_empty ())
     {
       pred_info pi = work_list.pop ();
-      predicate pred;
       /* The predicate object is not modified here, only NORM_CHAIN and
         WORK_LIST are appended to.  */
-      pred.normalize (&norm_chain, pi, BIT_AND_EXPR, &work_list, &mark_set);
+      unsigned oldlen = m_preds.length ();
+      normalize (&norm_chain, pi, BIT_AND_EXPR, &work_list, &mark_set);
+      gcc_assert (m_preds.length () == oldlen);
     }
 
   m_preds.safe_push (norm_chain);
@@ -1740,7 +1744,7 @@ predicate::normalize (gimple *use_or_def, bool is_use)
       dump (dump_file, use_or_def, is_use ? "[USE]:\n" : "[DEF]:\n");
     }
 
-  predicate norm_preds;
+  predicate norm_preds (empty_val ());
   for (unsigned i = 0; i < m_preds.length (); i++)
     {
       if (m_preds[i].length () != 1)
@@ -2076,6 +2080,8 @@ predicate::operator= (const predicate &rhs)
   if (this == &rhs)
     return *this;
 
+  m_cval = rhs.m_cval;
+
   unsigned n = m_preds.length ();
   for (unsigned i = 0; i != n; ++i)
     m_preds[i].release ();
@@ -2204,11 +2210,15 @@ uninit_analysis::is_use_guarded (gimple *use_stmt, basic_block use_bb,
   /* Try to build the predicate expression under which the PHI flows
      into its use.  This will be empty if the PHI is defined and used
      in the same bb.  */
-  predicate use_preds;
+  predicate use_preds (true);
   if (!init_use_preds (use_preds, def_bb, use_bb))
     return false;
 
   use_preds.simplify (use_stmt, /*is_use=*/true);
+  if (use_preds.is_false ())
+    return true;
+  if (use_preds.is_true ())
+    return false;
   use_preds.normalize (use_stmt, /*is_use=*/true);
 
   /* Try to prune the dead incoming phi edges.  */
@@ -2227,6 +2237,10 @@ uninit_analysis::is_use_guarded (gimple *use_stmt, basic_block use_bb,
        return false;
 
       m_phi_def_preds.simplify (phi);
+      if (m_phi_def_preds.is_false ())
+       return false;
+      if (m_phi_def_preds.is_true ())
+       return true;
       m_phi_def_preds.normalize (phi);
     }
 
index 972af5e0b2da1e56125f7db86b79c3a2f406651a..c4a7ed51967b563c8d4fad45db58de72d3ee638f 100644 (file)
@@ -45,7 +45,7 @@ class predicate
 {
  public:
   /* Construct with the specified EVAL object.  */
-  predicate () : m_preds (vNULL) { }
+  predicate (bool empty_val) : m_preds (vNULL), m_cval (empty_val) { }
 
   /* Copy.  */
   predicate (const predicate &rhs) : m_preds (vNULL) { *this = rhs; }
@@ -60,6 +60,21 @@ class predicate
     return m_preds.is_empty ();
   }
 
+  bool is_true () const
+  {
+    return is_empty () && m_cval;
+  }
+
+  bool is_false () const
+  {
+    return is_empty () && !m_cval;
+  }
+
+  bool empty_val () const
+  {
+    return m_cval;
+  }
+
   const pred_chain_union chain () const
   {
     return m_preds;
@@ -92,8 +107,10 @@ private:
   bool simplify_3 ();
   bool simplify_4 ();
 
-  /* Representation of the predicate expression(s).  */
+  /* Representation of the predicate expression(s).  The predicate is
+     m_cval || m_preds[0] || ...  */
   pred_chain_union m_preds;
+  bool m_cval;
 };
 
 /* Represents a complex Boolean predicate expression.  */
@@ -119,7 +136,7 @@ class uninit_analysis
 
   /* Construct with the specified EVAL object.  */
   uninit_analysis (func_t &eval)
-    : m_phi_def_preds (), m_eval (eval) { }
+    : m_phi_def_preds (false), m_eval (eval) { }
 
   /* Copy.  */
   uninit_analysis (const uninit_analysis &rhs) = delete;
diff --git a/gcc/testsuite/gcc.dg/pr107937.c b/gcc/testsuite/gcc.dg/pr107937.c
new file mode 100644 (file)
index 0000000..524850b
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -Wuninitialized" } */
+
+int _setjmp(int);
+int regs, vm_debug_engine_vp_0, vm_debug_engine_vp_2;
+
+void
+vm_dispatch_hook();
+
+
+void
+vm_debug_engine() {
+  int fp;
+  void *jump_table = &&l_nop;
+l_nop:
+  if (__builtin_expect(vm_debug_engine_vp_2, 0))
+    vm_dispatch_hook();
+  if (_setjmp(regs)) {
+    fp = fp;
+    vm_dispatch_hook();
+    goto *jump_table;
+  }
+  vm_debug_engine_vp_0 = fp;
+}