]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/gimple-ssa-evrp.c
[Ada] Get rid of more references to Universal_Integer in expanded code
[thirdparty/gcc.git] / gcc / gimple-ssa-evrp.c
index 27a983dd9ae8eb6f251f3d495d5f7d3b77b3778a..599e1459f00694a972b01f534a61548429a7b660 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for Value Range Propagation (VRP).
-   Copyright (C) 2005-2017 Free Software Foundation, Inc.
+   Copyright (C) 2005-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,8 +46,13 @@ class evrp_folder : public substitute_and_fold_engine
 {
  public:
   tree get_value (tree) FINAL OVERRIDE;
-
+  evrp_folder (class vr_values *vr_values_) : vr_values (vr_values_) { }
+  bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+    { return vr_values->simplify_stmt_using_ranges (gsi); }
   class vr_values *vr_values;
+
+ private:
+  DISABLE_COPY_AND_ASSIGN (evrp_folder);
 };
 
 tree
@@ -63,7 +68,10 @@ evrp_folder::get_value (tree op)
 class evrp_dom_walker : public dom_walker
 {
 public:
-  evrp_dom_walker () : dom_walker (CDI_DOMINATORS)
+  evrp_dom_walker ()
+    : dom_walker (CDI_DOMINATORS),
+      evrp_range_analyzer (true),
+      evrp_folder (evrp_range_analyzer.get_vr_values ())
     {
       need_eh_cleanup = BITMAP_ALLOC (NULL);
     }
@@ -82,14 +90,7 @@ public:
   auto_vec<gimple *> stmts_to_remove;
 
   class evrp_range_analyzer evrp_range_analyzer;
-
-  /* Temporary delegators.  */
-  value_range *get_value_range (const_tree op)
-    { return evrp_range_analyzer.vr_values.get_value_range (op); }
-  tree op_with_constant_singleton_value_range (tree op)
-    { return evrp_range_analyzer.vr_values.op_with_constant_singleton_value_range (op); }
-  void vrp_visit_cond_stmt (gcond *cond, edge *e)
-    { evrp_range_analyzer.vr_values.vrp_visit_cond_stmt (cond, e); }
+  class evrp_folder evrp_folder;
 };
 
 edge
@@ -108,9 +109,10 @@ evrp_dom_walker::before_dom_children (basic_block bb)
       if (virtual_operand_p (lhs))
        continue;
 
+      const value_range_equiv *vr = evrp_range_analyzer.get_value_range (lhs);
       /* Mark PHIs whose lhs we fully propagate for removal.  */
-      tree val = op_with_constant_singleton_value_range (lhs);
-      if (val && may_propagate_copy (lhs, val))
+      tree val;
+      if (vr->singleton_p (&val) && may_propagate_copy (lhs, val))
        {
          stmts_to_remove.safe_push (phi);
          continue;
@@ -135,11 +137,11 @@ evrp_dom_walker::before_dom_children (basic_block bb)
          print_gimple_stmt (dump_file, stmt, 0);
        }
 
-      evrp_range_analyzer.record_ranges_from_stmt (stmt);
+      evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
 
       if (gcond *cond = dyn_cast <gcond *> (stmt))
        {
-         vrp_visit_cond_stmt (cond, &taken_edge);
+         evrp_range_analyzer.vrp_visit_cond_stmt (cond, &taken_edge);
          if (taken_edge)
            {
              if (taken_edge->flags & EDGE_TRUE_VALUE)
@@ -153,18 +155,17 @@ evrp_dom_walker::before_dom_children (basic_block bb)
        }
       else if (stmt_interesting_for_vrp (stmt))
        {
-         value_range vr = VR_INITIALIZER;
          output = get_output_for_vrp (stmt);
          if (output)
            {
-             tree val;
-             vr = *get_value_range (output);
+             const value_range_equiv *vr
+               = evrp_range_analyzer.get_value_range (output);
 
              /* Mark stmts whose output we fully propagate for removal.  */
-             if ((vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
-                 && (val = op_with_constant_singleton_value_range (output))
+             tree val;
+             if (vr->singleton_p (&val)
                  && may_propagate_copy (output, val)
-                 && !stmt_could_throw_p (stmt)
+                 && !stmt_could_throw_p (cfun, stmt)
                  && !gimple_has_side_effects (stmt))
                {
                  stmts_to_remove.safe_push (stmt);
@@ -174,9 +175,9 @@ evrp_dom_walker::before_dom_children (basic_block bb)
        }
 
       /* Try folding stmts with the VR discovered.  */
-      class evrp_folder evrp_folder;
-      evrp_folder.vr_values = &evrp_range_analyzer.vr_values;
       bool did_replace = evrp_folder.replace_uses_in (stmt);
+      gimple_stmt_iterator prev_gsi = gsi;
+      gsi_prev (&prev_gsi);
       if (fold_stmt (&gsi, follow_single_use_edges)
          || did_replace)
        {
@@ -184,9 +185,30 @@ evrp_dom_walker::before_dom_children (basic_block bb)
          update_stmt (stmt);
          did_replace = true;
        }
+      if (evrp_folder.simplify_stmt_using_ranges (&gsi))
+       {
+         stmt = gsi_stmt (gsi);
+         update_stmt (stmt);
+         did_replace = true;
+       }
 
       if (did_replace)
        {
+         /* If we wound up generating new stmts during folding
+            drop all their defs to VARYING.  We can't easily
+            process them because we've already instantiated
+            ranges on uses on STMT that only hold after it.  */
+         if (gsi_end_p (prev_gsi))
+           prev_gsi = gsi_start_bb (bb);
+         else
+           gsi_next (&prev_gsi);
+         while (gsi_stmt (prev_gsi) != gsi_stmt (gsi))
+           {
+             evrp_range_analyzer.get_vr_values ()
+               ->set_defs_to_varying (gsi_stmt (prev_gsi));
+             gsi_next (&prev_gsi);
+           }
+
          /* If we cleaned up EH information from the statement,
             remove EH edges.  */
          if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
@@ -222,8 +244,10 @@ evrp_dom_walker::before_dom_children (basic_block bb)
          if (TREE_CODE (arg) != SSA_NAME
              || virtual_operand_p (arg))
            continue;
-         tree val = op_with_constant_singleton_value_range (arg);
-         if (val && may_propagate_copy (arg, val))
+         const value_range_equiv
+           *vr = evrp_range_analyzer.get_value_range (arg);
+         tree val;
+         if (vr->singleton_p (&val) && may_propagate_copy (arg, val))
            propagate_value (use_p, val);
        }
     }
@@ -245,7 +269,7 @@ evrp_dom_walker::cleanup (void)
   if (dump_file)
     {
       fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
-      evrp_range_analyzer.vr_values.dump_all_value_ranges (dump_file);
+      evrp_range_analyzer.dump_all_value_ranges (dump_file);
       fprintf (dump_file, "\n");
     }
 
@@ -282,6 +306,8 @@ evrp_dom_walker::cleanup (void)
       gimple *stmt = stmts_to_fixup.pop ();
       fixup_noreturn_call (stmt);
     }
+
+  evrp_folder.vr_values->cleanup_edges_and_switches ();
 }
 
 /* Main entry point for the early vrp pass which is a simplified non-iterative