public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-4802] Improve uninitialized warning with value range info
@ 2020-11-06 21:21 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2020-11-06 21:21 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7987a8d29a78eb373b5e054d539e332d75e92e92

commit r11-4802-g7987a8d29a78eb373b5e054d539e332d75e92e92
Author: Bin Cheng <bin.cheng@linux.alibaba.com>
Date:   Fri Nov 6 16:19:40 2020 -0500

    Improve uninitialized warning with value range info
    
    Function use_pred_not_overlap_with_undef_path_pred of
    pass_late_warn_uninitialized
    checks if predicate of variable use overlaps with predicate of undefined
    control flow path.
    For now, it only checks ssa_var comparing against constant, this can be
    improved where
    ssa_var compares against another ssa_var with value range info, as described in
    comment:
    
    +         /* Check value range info of rhs, do following transforms:
    +              flag_var < [min, max]  ->  flag_var < max
    +              flag_var > [min, max]  ->  flag_var > min
    +
    +            We can also transform LE_EXPR/GE_EXPR to LT_EXPR/GT_EXPR:
    +              flag_var <= [min, max] ->  flag_var < [min, max+1]
    +              flag_var >= [min, max] ->  flag_var > [min-1, max]
    +            if no overflow/wrap.  */
    
    gcc/
    
            * tree-ssa-uninit.c (find_var_cmp_const): New function.
            (use_pred_not_overlap_with_undef_path_pred): Call above.

Diff:
---
 gcc/tree-ssa-uninit.c | 192 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 129 insertions(+), 63 deletions(-)

diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 7ed16866afa..f23514395e0 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -1345,21 +1345,18 @@ value_sat_pred_p (tree val, tree boundary, enum tree_code cmpc,
 }
 
 /* Returns true if PRED is common among all the predicate
-   chains (PREDS) (and therefore can be factored out).
-   NUM_PRED_CHAIN is the size of array PREDS.  */
+   chains (PREDS) (and therefore can be factored out).  */
 
 static bool
-find_matching_predicate_in_rest_chains (pred_info pred,
-					pred_chain_union preds,
-					size_t num_pred_chains)
+find_matching_predicate_in_rest_chains (pred_info pred, pred_chain_union preds)
 {
   size_t i, j, n;
 
   /* Trival case.  */
-  if (num_pred_chains == 1)
+  if (preds.length () == 1)
     return true;
 
-  for (i = 1; i < num_pred_chains; i++)
+  for (i = 1; i < preds.length (); i++)
     {
       bool found = false;
       pred_chain one_chain = preds[i];
@@ -1530,6 +1527,129 @@ prune_uninit_phi_opnds (gphi *phi, unsigned uninit_opnds, gphi *flag_def,
   return true;
 }
 
+/* A helper function finds predicate which will be examined against uninit
+   paths.  If there is no "flag_var cmp const" form predicate, the function
+   tries to find predicate of form like "flag_var cmp flag_var" with value
+   range info.  PHI is the phi node whose incoming (undefined) paths need to
+   be examined.  On success, the function returns the comparsion code, sets
+   defintion gimple of the flag_var to FLAG_DEF, sets boundary_cst to
+   BOUNDARY_CST.  On fail, the function returns ERROR_MARK.  */
+
+static enum tree_code
+find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
+		    tree *boundary_cst)
+{
+  enum tree_code vrinfo_code = ERROR_MARK, code;
+  gimple *vrinfo_def = NULL;
+  tree vrinfo_cst = NULL, cond_lhs, cond_rhs;
+
+  gcc_assert (preds.length () > 0);
+  pred_chain the_pred_chain = preds[0];
+  for (unsigned i = 0; i < the_pred_chain.length (); i++)
+    {
+      bool use_vrinfo_p = false;
+      pred_info the_pred = the_pred_chain[i];
+      cond_lhs = the_pred.pred_lhs;
+      cond_rhs = the_pred.pred_rhs;
+      if (cond_lhs == NULL_TREE || cond_rhs == NULL_TREE)
+	continue;
+
+      code = get_cmp_code (the_pred.cond_code, false, the_pred.invert);
+      if (code == ERROR_MARK)
+	continue;
+
+      if (TREE_CODE (cond_lhs) == SSA_NAME && is_gimple_constant (cond_rhs))
+	;
+      else if (TREE_CODE (cond_rhs) == SSA_NAME
+	       && is_gimple_constant (cond_lhs))
+	{
+	  std::swap (cond_lhs, cond_rhs);
+	  if ((code = get_cmp_code (code, true, false)) == ERROR_MARK)
+	    continue;
+	}
+      /* 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
+	       && TREE_CODE (cond_rhs) == SSA_NAME)
+	{
+	  gimple* lhs_def = SSA_NAME_DEF_STMT (cond_lhs);
+	  if (!lhs_def || gimple_code (lhs_def) != GIMPLE_PHI
+	      || gimple_bb (lhs_def) != gimple_bb (phi))
+	    {
+	      std::swap (cond_lhs, cond_rhs);
+	      if ((code = get_cmp_code (code, true, false)) == ERROR_MARK)
+		continue;
+	    }
+
+	  /* Check value range info of rhs, do following transforms:
+	       flag_var < [min, max]  ->  flag_var < max
+	       flag_var > [min, max]  ->  flag_var > min
+
+	     We can also transform LE_EXPR/GE_EXPR to LT_EXPR/GT_EXPR:
+	       flag_var <= [min, max] ->  flag_var < [min, max+1]
+	       flag_var >= [min, max] ->  flag_var > [min-1, max]
+	     if no overflow/wrap.  */
+	  wide_int min, max;
+	  tree type = TREE_TYPE (cond_lhs);
+	  if (!INTEGRAL_TYPE_P (type)
+	      || get_range_info (cond_rhs, &min, &max) != VR_RANGE)
+	    continue;
+	  if (code == LE_EXPR
+	      && max != wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
+	    {
+	      code = LT_EXPR;
+	      max = max + 1;
+	    }
+	  if (code == GE_EXPR
+	      && min != wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
+	    {
+	      code = GT_EXPR;
+	      min = min - 1;
+	    }
+	  if (code == LT_EXPR)
+	    cond_rhs = wide_int_to_tree (type, max);
+	  else if (code == GT_EXPR)
+	    cond_rhs = wide_int_to_tree (type, min);
+	  else
+	    continue;
+
+	  use_vrinfo_p = true;
+	}
+      else
+	continue;
+
+      if ((*flag_def = SSA_NAME_DEF_STMT (cond_lhs)) == NULL)
+	continue;
+
+      if (gimple_code (*flag_def) != GIMPLE_PHI
+	  || gimple_bb (*flag_def) != gimple_bb (phi)
+	  || !find_matching_predicate_in_rest_chains (the_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 vrinfo_code;
+}
+
 /* A helper function that determines if the predicate set
    of the use is not overlapping with that of the uninit paths.
    The most common senario of guarded use is in Example 1:
@@ -1607,75 +1727,21 @@ use_pred_not_overlap_with_undef_path_pred (pred_chain_union preds,
 					   gphi *phi, unsigned uninit_opnds,
 					   hash_set<gphi *> *visited_phis)
 {
-  unsigned int i, n;
   gimple *flag_def = 0;
   tree boundary_cst = 0;
   enum tree_code cmp_code;
-  bool swap_cond = false;
-  bool invert = false;
-  pred_chain the_pred_chain = vNULL;
   bitmap visited_flag_phis = NULL;
   bool all_pruned = false;
-  size_t num_preds = preds.length ();
 
-  gcc_assert (num_preds > 0);
   /* Find within the common prefix of multiple predicate chains
      a predicate that is a comparison of a flag variable against
      a constant.  */
-  the_pred_chain = preds[0];
-  n = the_pred_chain.length ();
-  for (i = 0; i < n; i++)
-    {
-      tree cond_lhs, cond_rhs, flag = 0;
-
-      pred_info the_pred = the_pred_chain[i];
-
-      invert = the_pred.invert;
-      cond_lhs = the_pred.pred_lhs;
-      cond_rhs = the_pred.pred_rhs;
-      cmp_code = the_pred.cond_code;
-
-      if (cond_lhs != NULL_TREE && TREE_CODE (cond_lhs) == SSA_NAME
-	  && cond_rhs != NULL_TREE && is_gimple_constant (cond_rhs))
-	{
-	  boundary_cst = cond_rhs;
-	  flag = cond_lhs;
-	}
-      else if (cond_rhs != NULL_TREE && TREE_CODE (cond_rhs) == SSA_NAME
-	       && cond_lhs != NULL_TREE && is_gimple_constant (cond_lhs))
-	{
-	  boundary_cst = cond_lhs;
-	  flag = cond_rhs;
-	  swap_cond = true;
-	}
-
-      if (!flag)
-	continue;
-
-      flag_def = SSA_NAME_DEF_STMT (flag);
-
-      if (!flag_def)
-	continue;
-
-      if ((gimple_code (flag_def) == GIMPLE_PHI)
-	  && (gimple_bb (flag_def) == gimple_bb (phi))
-	  && find_matching_predicate_in_rest_chains (the_pred, preds,
-						     num_preds))
-	break;
-
-      flag_def = 0;
-    }
-
-  if (!flag_def)
+  cmp_code = find_var_cmp_const (preds, phi, &flag_def, &boundary_cst);
+  if (cmp_code == ERROR_MARK)
     return false;
 
   /* Now check all the uninit incoming edge has a constant flag value
      that is in conflict with the use guard/predicate.  */
-  cmp_code = get_cmp_code (cmp_code, swap_cond, invert);
-
-  if (cmp_code == ERROR_MARK)
-    return false;
-
   all_pruned = prune_uninit_phi_opnds
     (phi, uninit_opnds, as_a<gphi *> (flag_def), boundary_cst, cmp_code,
      visited_phis, &visited_flag_phis);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-06 21:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-06 21:21 [gcc r11-4802] Improve uninitialized warning with value range info Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).