tree-ssa-loop-ivopts.c (find_inv_vars): Fix a comment typo.
[gcc.git] / gcc / tree-ssa-uninit.c
index 6930a243deb22fd0e5f26b8555b6400f2ade57f4..55a55a05c96604ed3ca6c6f94e18aba37e3787a1 100644 (file)
@@ -1,5 +1,5 @@
 /* Predicate aware uninitialized variable warning.
-   Copyright (C) 2001-2018 Free Software Foundation, Inc.
+   Copyright (C) 2001-2019 Free Software Foundation, Inc.
    Contributed by Xinliang David Li <davidxl@google.com>
 
 This file is part of GCC.
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa.h"
 #include "params.h"
 #include "tree-cfg.h"
+#include "cfghooks.h"
 
 /* This implements the pass that does predicate aware warning on uses of
    possibly uninitialized variables.  The pass first collects the set of
@@ -177,6 +178,7 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
   cfun_loc = DECL_SOURCE_LOCATION (cfun->decl);
   xloc = expand_location (location);
   floc = expand_location (cfun_loc);
+  auto_diagnostic_group d;
   if (warning_at (location, wc, gmsgid, expr))
     {
       TREE_NO_WARNING (expr) = 1;
@@ -543,9 +545,6 @@ compute_control_dep_chain (basic_block bb, basic_block dep_bb,
   bool found_cd_chain = false;
   size_t cur_chain_len = 0;
 
-  if (EDGE_COUNT (bb->succs) < 2)
-    return false;
-
   if (*num_calls > PARAM_VALUE (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS))
     return false;
   ++*num_calls;
@@ -671,6 +670,11 @@ convert_control_dep_chain_into_preds (vec<edge> *dep_chains,
          e = one_cd_chain[j];
          guard_bb = e->src;
          gsi = gsi_last_bb (guard_bb);
+         /* Ignore empty forwarder blocks.  */
+         if (empty_block_p (guard_bb) && single_succ_p (guard_bb))
+           continue;
+         /* An empty basic block here is likely a PHI, and is not one
+            of the cases we handle below.  */
          if (gsi_end_p (gsi))
            {
              has_valid_pred = false;
@@ -721,7 +725,7 @@ convert_control_dep_chain_into_preds (vec<edge> *dep_chains,
              for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
                {
                  tree tl = gimple_switch_label (gs, idx);
-                 if (e->dest == label_to_block (CASE_LABEL (tl)))
+                 if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
                    {
                      if (!l)
                        l = tl;
@@ -916,38 +920,49 @@ find_def_preds (pred_chain_union *preds, gphi *phi)
   return has_valid_pred;
 }
 
+/* Dump a pred_info.  */
+
+static void
+dump_pred_info (pred_info one_pred)
+{
+  if (one_pred.invert)
+    fprintf (dump_file, " (.NOT.) ");
+  print_generic_expr (dump_file, one_pred.pred_lhs);
+  fprintf (dump_file, " %s ", op_symbol_code (one_pred.cond_code));
+  print_generic_expr (dump_file, one_pred.pred_rhs);
+}
+
+/* Dump a pred_chain.  */
+
+static void
+dump_pred_chain (pred_chain one_pred_chain)
+{
+  size_t np = one_pred_chain.length ();
+  for (size_t j = 0; j < np; j++)
+    {
+      dump_pred_info (one_pred_chain[j]);
+      if (j < np - 1)
+       fprintf (dump_file, " (.AND.) ");
+      else
+       fprintf (dump_file, "\n");
+    }
+}
+
 /* Dumps the predicates (PREDS) for USESTMT.  */
 
 static void
 dump_predicates (gimple *usestmt, pred_chain_union preds, const char *msg)
 {
-  size_t i, j;
-  pred_chain one_pred_chain = vNULL;
   fprintf (dump_file, "%s", msg);
-  print_gimple_stmt (dump_file, usestmt, 0);
-  fprintf (dump_file, "is guarded by :\n\n");
+  if (usestmt)
+    {
+      print_gimple_stmt (dump_file, usestmt, 0);
+      fprintf (dump_file, "is guarded by :\n\n");
+    }
   size_t num_preds = preds.length ();
-  /* Do some dumping here:  */
-  for (i = 0; i < num_preds; i++)
+  for (size_t i = 0; i < num_preds; i++)
     {
-      size_t np;
-
-      one_pred_chain = preds[i];
-      np = one_pred_chain.length ();
-
-      for (j = 0; j < np; j++)
-       {
-         pred_info one_pred = one_pred_chain[j];
-         if (one_pred.invert)
-           fprintf (dump_file, " (.NOT.) ");
-         print_generic_expr (dump_file, one_pred.pred_lhs);
-         fprintf (dump_file, " %s ", op_symbol_code (one_pred.cond_code));
-         print_generic_expr (dump_file, one_pred.pred_rhs);
-         if (j < np - 1)
-           fprintf (dump_file, " (.AND.) ");
-         else
-           fprintf (dump_file, "\n");
-       }
+      dump_pred_chain (preds[i]);
       if (i < num_preds - 1)
        fprintf (dump_file, "(.OR.)\n");
       else
@@ -1449,7 +1464,7 @@ pred_expr_equal_p (pred_info x1, tree x2)
 
 /* Returns true of the domain of single predicate expression
    EXPR1 is a subset of that of EXPR2.  Returns false if it
-   can not be proved.  */
+   cannot be proved.  */
 
 static bool
 is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
@@ -1487,7 +1502,7 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
 }
 
 /* Returns true if the domain of PRED1 is a subset
-   of that of PRED2.  Returns false if it can not be proved so.  */
+   of that of PRED2.  Returns false if it cannot be proved so.  */
 
 static bool
 is_pred_chain_subset_of (pred_chain pred1, pred_chain pred2)
@@ -1549,8 +1564,8 @@ is_included_in (pred_chain one_pred, pred_chain_union preds)
    individual predicate chains (won't be a compile time problem
    as the chains are pretty short).  When the function returns
    false, it does not necessarily mean *PREDS1 is not a superset
-   of *PREDS2, but mean it may not be so since the analysis can
-   not prove it.  In such cases, false warnings may still be
+   of *PREDS2, but mean it may not be so since the analysis cannot
+   prove it.  In such cases, false warnings may still be
    emitted.  */
 
 static bool
@@ -1571,16 +1586,6 @@ is_superset_of (pred_chain_union preds1, pred_chain_union preds2)
   return true;
 }
 
-/* Returns true if TC is AND or OR.  */
-
-static inline bool
-is_and_or_or_p (enum tree_code tc, tree type)
-{
-  return (tc == BIT_IOR_EXPR
-         || (tc == BIT_AND_EXPR
-             && (type == 0 || TREE_CODE (type) == BOOLEAN_TYPE)));
-}
-
 /* Returns true if X1 is the negate of X2.  */
 
 static inline bool
@@ -2259,12 +2264,19 @@ normalize_preds (pred_chain_union preds, gimple *use_or_def, bool is_use)
 }
 
 /* Return TRUE if PREDICATE can be invalidated by any individual
-   predicate in WORKLIST.  */
+   predicate in USE_GUARD.  */
 
 static bool
 can_one_predicate_be_invalidated_p (pred_info predicate,
                                    pred_chain use_guard)
 {
+  if (dump_file && dump_flags & TDF_DETAILS)
+    {
+      fprintf (dump_file, "Testing if this predicate: ");
+      dump_pred_info (predicate);
+      fprintf (dump_file, "\n...can be invalidated by a USE guard of: ");
+      dump_pred_chain (use_guard);
+    }
   for (size_t i = 0; i < use_guard.length (); ++i)
     {
       /* NOTE: This is a very simple check, and only understands an
@@ -2273,7 +2285,15 @@ can_one_predicate_be_invalidated_p (pred_info predicate,
         invalidate with say [i > 5] or [i == 8].  There is certainly
         room for improvement here.  */
       if (pred_neg_p (predicate, use_guard[i]))
-       return true;
+       {
+         if (dump_file && dump_flags & TDF_DETAILS)
+           {
+             fprintf (dump_file, "  Predicate was invalidated by: ");
+             dump_pred_info (use_guard[i]);
+             fputc ('\n', dump_file);
+           }
+         return true;
+       }
     }
   return false;
 }
@@ -2287,12 +2307,22 @@ can_chain_union_be_invalidated_p (pred_chain_union uninit_pred,
 {
   if (uninit_pred.is_empty ())
     return false;
+  if (dump_file && dump_flags & TDF_DETAILS)
+    dump_predicates (NULL, uninit_pred,
+                    "Testing if anything here can be invalidated: ");
   for (size_t i = 0; i < uninit_pred.length (); ++i)
     {
       pred_chain c = uninit_pred[i];
-      for (size_t j = 0; j < c.length (); ++j)
-       if (!can_one_predicate_be_invalidated_p (c[j], use_guard))
-         return false;
+      size_t j;
+      for (j = 0; j < c.length (); ++j)
+       if (can_one_predicate_be_invalidated_p (c[j], use_guard))
+         break;
+
+      /* If we were unable to invalidate any predicate in C, then there
+        is a viable path from entry to the PHI where the PHI takes
+        an uninitialized value and continues to a use of the PHI.  */
+      if (j == c.length ())
+       return false;
     }
   return true;
 }
@@ -2334,7 +2364,7 @@ uninit_uses_cannot_happen (gphi *phi, unsigned uninit_opnds,
 
       /* Build the control dependency chain for uninit operand `i'...  */
       uninit_preds = vNULL;
-      if (!compute_control_dep_chain (find_dom (e->src),
+      if (!compute_control_dep_chain (ENTRY_BLOCK_PTR_FOR_FN (cfun),
                                      e->src, dep_chains, &num_chains,
                                      &cur_chain, &num_calls))
        {
@@ -2342,10 +2372,16 @@ uninit_uses_cannot_happen (gphi *phi, unsigned uninit_opnds,
          break;
        }
       /* ...and convert it into a set of predicates.  */
-      convert_control_dep_chain_into_preds (dep_chains, num_chains,
-                                           &uninit_preds);
+      bool has_valid_preds
+       = convert_control_dep_chain_into_preds (dep_chains, num_chains,
+                                               &uninit_preds);
       for (size_t j = 0; j < num_chains; ++j)
        dep_chains[j].release ();
+      if (!has_valid_preds)
+       {
+         ret = false;
+         break;
+       }
       simplify_preds (&uninit_preds, NULL, false);
       uninit_preds = normalize_preds (uninit_preds, NULL, false);
 
@@ -2368,7 +2404,7 @@ uninit_uses_cannot_happen (gphi *phi, unsigned uninit_opnds,
    USE_STMT is guarded with a predicate set not overlapping with
    predicate sets of all runtime paths that do not have a definition.
 
-   Returns false if it is not or it can not be determined.  USE_BB is
+   Returns false if it is not or it cannot be determined.  USE_BB is
    the bb of the use (for phi operand use, the bb is not the bb of
    the phi stmt, but the src bb of the operand edge).
 
@@ -2699,7 +2735,7 @@ execute_early_warn_uninitialized (void)
 
   warn_uninitialized_vars (/*warn_possibly_uninitialized=*/!optimize);
 
-  /* Post-dominator information can not be reliably updated.  Free it
+  /* Post-dominator information cannot be reliably updated.  Free it
      after the use.  */
 
   free_dominance_info (CDI_POST_DOMINATORS);