]> gcc.gnu.org Git - gcc.git/commitdiff
tree-optimization/112766 - improve pruning of uninit diagnostics
authorRichard Biener <rguenther@suse.de>
Thu, 30 Nov 2023 09:58:13 +0000 (10:58 +0100)
committerRichard Biener <rguenther@suse.de>
Thu, 30 Nov 2023 12:31:25 +0000 (13:31 +0100)
Uninit diagnostics has code to prune based on incoming PHI args
that prove the uninit code is never executed.  But that only
looks at the first found flag candidate while in the PRs case
only the second candidate would be the one to prune on.  The
following patch makes us consider all of the flag candidates
which is cycles well spent IMHO.

PR tree-optimization/112766
* gimple-predicate-analysis.cc (find_var_cmp_const):
Support continuing the iteration and report every candidate.
(uninit_analysis::overlap): Iterate over all flag var
candidates.

* g++.dg/torture/uninit-pr112766.C: New testcase.

gcc/gimple-predicate-analysis.cc
gcc/testsuite/g++.dg/torture/uninit-pr112766.C [new file with mode: 0644]

index ad2c35524ce12987e8cf202d1446a0da1f5264d6..5e231a6a469fdbd4bba6efe83de9fc2f24be6f66 100644 (file)
@@ -244,21 +244,18 @@ find_matching_predicate_in_rest_chains (const pred_info &pred,
    of that's the form "FLAG_VAR CMP FLAG_VAR" with value range info.
    PHI is the phi node whose incoming (interesting) paths need to be
    examined.  On success, return the comparison code, set defintion
-   gimple of FLAG_DEF and BOUNDARY_CST.  Otherwise return ERROR_MARK.  */
+   gimple of FLAG_DEF and BOUNDARY_CST.  Otherwise return ERROR_MARK.
+   I is the running iterator so the function can be called repeatedly
+   to gather all candidates.  */
 
 static tree_code
 find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
-                   tree *boundary_cst)
+                   tree *boundary_cst, unsigned &i)
 {
-  tree_code vrinfo_code = ERROR_MARK;
-  gimple *vrinfo_def = NULL;
-  tree vrinfo_cst = NULL;
-
   gcc_assert (preds.length () > 0);
   pred_chain chain = preds[0];
-  for (unsigned i = 0; i < chain.length (); i++)
+  for (; i < chain.length (); i++)
     {
-      bool use_vrinfo_p = false;
       const pred_info &pred = chain[i];
       tree cond_lhs = pred.pred_lhs;
       tree cond_rhs = pred.pred_rhs;
@@ -282,8 +279,7 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
        }
       /* Check if we can take advantage of FLAG_VAR COMP FLAG_VAR predicate
         with value range info.  Note only first of such case is handled.  */
-      else if (vrinfo_code == ERROR_MARK
-              && TREE_CODE (cond_lhs) == SSA_NAME
+      else if (TREE_CODE (cond_lhs) == SSA_NAME
               && TREE_CODE (cond_rhs) == SSA_NAME)
        {
          gimple* lhs_def = SSA_NAME_DEF_STMT (cond_lhs);
@@ -331,8 +327,6 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
            cond_rhs = wide_int_to_tree (type, min);
          else
            continue;
-
-         use_vrinfo_p = true;
        }
       else
        continue;
@@ -345,27 +339,13 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
          || !find_matching_predicate_in_rest_chains (pred, preds))
        continue;
 
-      /* Return if any "flag_var comp const" predicate is found.  */
-      if (!use_vrinfo_p)
-       {
-         *boundary_cst = cond_rhs;
-         return code;
-       }
-      /* Record if any "flag_var comp flag_var[vinfo]" predicate is found.  */
-      else if (vrinfo_code == ERROR_MARK)
-       {
-         vrinfo_code = code;
-         vrinfo_def = *flag_def;
-         vrinfo_cst = cond_rhs;
-       }
-    }
-  /* Return the "flag_var cmp flag_var[vinfo]" predicate we found.  */
-  if (vrinfo_code != ERROR_MARK)
-    {
-      *flag_def = vrinfo_def;
-      *boundary_cst = vrinfo_cst;
+      /* Return predicate found.  */
+      *boundary_cst = cond_rhs;
+      ++i;
+      return code;
     }
-  return vrinfo_code;
+
+  return ERROR_MARK;
 }
 
 /* Return true if all interesting opnds are pruned, false otherwise.
@@ -641,27 +621,29 @@ uninit_analysis::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited,
 {
   gimple *flag_def = NULL;
   tree boundary_cst = NULL_TREE;
-  bitmap visited_flag_phis = NULL;
 
   /* Find within the common prefix of multiple predicate chains
      a predicate that is a comparison of a flag variable against
      a constant.  */
-  tree_code cmp_code = find_var_cmp_const (use_preds.chain (), phi, &flag_def,
-                                          &boundary_cst);
-  if (cmp_code == ERROR_MARK)
-    return true;
-
-  /* Now check all the uninit incoming edges have a constant flag
-     value that is in conflict with the use guard/predicate.  */
-  gphi *phi_def = as_a<gphi *> (flag_def);
-  bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst,
-                                    cmp_code, visited,
-                                    &visited_flag_phis);
-
-  if (visited_flag_phis)
-    BITMAP_FREE (visited_flag_phis);
+  unsigned i = 0;
+  tree_code cmp_code;
+  while ((cmp_code = find_var_cmp_const (use_preds.chain (), phi, &flag_def,
+                                        &boundary_cst, i)) != ERROR_MARK)
+    {
+      /* Now check all the uninit incoming edges have a constant flag
+        value that is in conflict with the use guard/predicate.  */
+      bitmap visited_flag_phis = NULL;
+      gphi *phi_def = as_a<gphi *> (flag_def);
+      bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst,
+                                        cmp_code, visited,
+                                        &visited_flag_phis);
+      if (visited_flag_phis)
+       BITMAP_FREE (visited_flag_phis);
+      if (all_pruned)
+       return false;
+    }
 
-  return !all_pruned;
+  return true;
 }
 
 /* Return true if two predicates PRED1 and X2 are equivalent.  Assume
diff --git a/gcc/testsuite/g++.dg/torture/uninit-pr112766.C b/gcc/testsuite/g++.dg/torture/uninit-pr112766.C
new file mode 100644 (file)
index 0000000..028056e
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-additional-options "-Wuninitialized" }
+
+void* operator new[](__SIZE_TYPE__, void* __p) ;
+
+class Result
+{
+public:
+  Result();
+  ~Result();
+};
+
+void *foo(long nElements, void *p)
+{
+  return p ? new((int*)p) Result[nElements] : new Result[nElements]; // { dg-bogus "uninitialized" }
+}
+
This page took 0.070163 seconds and 5 git commands to generate.