tree-optimization/112766 - improve pruning of uninit diagnostics

Message ID 20231130123358.2AD2C3857C44@sourceware.org
State New
Headers
Series tree-optimization/112766 - improve pruning of uninit diagnostics |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm warning Patch is already merged
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch is already merged

Commit Message

Richard Biener Nov. 30, 2023, 12:30 p.m. UTC
  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.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

	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              | 78 +++++++------------
 .../g++.dg/torture/uninit-pr112766.C          | 17 ++++
 2 files changed, 47 insertions(+), 48 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/torture/uninit-pr112766.C
  

Patch

diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc
index ad2c35524ce..5e231a6a469 100644
--- a/gcc/gimple-predicate-analysis.cc
+++ b/gcc/gimple-predicate-analysis.cc
@@ -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
index 00000000000..028056e92d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/uninit-pr112766.C
@@ -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" }
+}
+