]> git.ipfire.org Git - people/ms/gcc.git/commitdiff
Merge from trunk at:
authorAldy Hernandez <aldyh@redhat.com>
Wed, 17 Jun 2020 11:50:57 +0000 (07:50 -0400)
committerAldy Hernandez <aldyh@redhat.com>
Wed, 17 Jun 2020 11:50:57 +0000 (07:50 -0400)
commit 56638b9b1853666f575928f8baf17f70e4ed3517
Author: GCC Administrator <gccadmin@gcc.gnu.org>
Date:   Wed Jun 17 00:16:36 2020 +0000

    Daily bump.

25 files changed:
1  2 
gcc/Makefile.in
gcc/common.opt
gcc/dbgcnt.def
gcc/dumpfile.c
gcc/dumpfile.h
gcc/gimple-pretty-print.c
gcc/gimple-range-gori.h
gcc/gimple-ssa-evrp.c
gcc/ipa-cp.c
gcc/ipa-fnsummary.c
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/opts.c
gcc/passes.def
gcc/testsuite/gcc.dg/tree-ssa/dse-points-to.c
gcc/toplev.c
gcc/tree-pass.h
gcc/tree-ssa-dom.c
gcc/tree-ssa-propagate.c
gcc/tree-vrp.c
gcc/tree-vrp.h
gcc/value-range-equiv.cc
gcc/value-range-equiv.h
gcc/vr-values.c
gcc/vr-values.h

diff --cc gcc/Makefile.in
Simple merge
diff --cc gcc/common.opt
Simple merge
diff --cc gcc/dbgcnt.def
Simple merge
diff --cc gcc/dumpfile.c
Simple merge
diff --cc gcc/dumpfile.h
Simple merge
Simple merge
index d3669e30f898ea8b9580c2abc2d1685ce5c77ce4,0000000000000000000000000000000000000000..4724b6812b891b8f5e994a719508c933118b176a
mode 100644,000000..100644
--- /dev/null
@@@ -1,261 -1,0 +1,261 @@@
-   virtual const value_range_equiv *get_value_range (const_tree expr,
-                                                   gimple *stmt = NULL);
 +/* Header file for gimple range GORI structures.
 +   Copyright (C) 2017-2020 Free Software Foundation, Inc.
 +   Contributed by Andrew MacLeod <amacleod@redhat.com>
 +   and Aldy Hernandez <aldyh@redhat.com>.
 +
 +This file is part of GCC.
 +
 +GCC is free software; you can redistribute it and/or modify it under
 +the terms of the GNU General Public License as published by the Free
 +Software Foundation; either version 3, or (at your option) any later
 +version.
 +
 +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 +WARRANTY; without even the implied warranty of MERCHANTABILITY or
 +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 + for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with GCC; see the file COPYING3.  If not see
 +<http://www.gnu.org/licenses/>.  */
 +
 +#ifndef GCC_GIMPLE_RANGE_GORI_H
 +#define GCC_GIMPLE_RANGE_GORI_H
 +
 +/* RANGE_DEF_CHAIN is used to determine what SSA names in a block can
 +   have range information calculated for them, and what the
 +   dependencies on each other are.
 +
 +   Information for a basic block is calculated once and stored.  It is
 +   only calculated the first time a query is made, so if no queries
 +   are made, there is little overhead.
 +
 +   The def_chain bitmap is indexed by SSA_NAME_VERSION.  Bits are set
 +   within this bitmap to indicate SSA names that are defined in the
 +   SAME block and used to calculate this SSA name.
 +
 +   One import is maintained per def-chain.  An IMPORT is defined as an
 +   SSA name in the def chain which occurs outside the basic block. A
 +   change in the value of this SSA name can change the value of any
 +   name in the chain.
 +
 +   If there is more than one import, or an ssa_name originates WITHIN
 +   the same basic block, but is defined by a statement that the range
 +   engine does not know how to calculate, then there is no import for
 +   the entire chain.
 +
 +    <bb 2> :
 +      _1 = x_4(D) + -2;
 +      _2 = _1 * 4;
 +      j_7 = foo ();
 +      q_5 = _2 + 3;
 +      if (q_5 <= 13)
 +
 +    _1  : (import : x_4(D))  :x_4(D)
 +    _2  : (import : x_4(D))  :_1  x_4(D)
 +    q_5  : (import : x_4(D))  :_1  _2  x_4(D)
 +
 +    This dump indicates the bits set in the def_chain vector and their
 +    import, as well as demonstrates the def_chain bits for the related
 +    ssa_names.
 +
 +    Checking the chain for _2 indicates that _1 and x_4 are used in
 +    its evaluation, and with x_4 being an import.
 +
 +    For the purpose of defining an import, PHI node defintions are
 +    considered imports as they don't really reside in the block, but
 +    are accumulators of values from incoming edges.
 +
 +    Def chains also only include statements which are valid gimple
 +    so a def chain will only span statements for which the range
 +    engine implements operations for.  */
 +
 +
 +class range_def_chain
 +{
 +public:
 +  range_def_chain ();
 +  ~range_def_chain ();
 +  tree terminal_name (tree name);
 +  bool has_def_chain (tree name);
 +  bitmap get_def_chain (tree name);
 +  bool in_chain_p (tree name, tree def);
 +private:
 +  vec<bitmap> m_def_chain;    // SSA_NAME : def chain components.
 +  vec<tree> m_terminal;               // SSA_NAME : chain terminal name.
 +  tree build_def_chain (tree name, bitmap result, basic_block bb);
 +};
 +
 +
 +/* GORI_MAP is used to accumulate what SSA names in a block can
 +   generate range information, and provides tools for the block ranger
 +   to enable it to efficiently calculate these ranges.
 +
 +   GORI stands for "Generates Outgoing Range Information."
 +
 +   It utilizes the range_def_chain class to contruct def_chains.
 +   Information for a basic block is calculated once and stored.  It is
 +   only calculated the first time a query is made.  If no queries are
 +   made, there is little overhead.
 +
 +   2 bitmaps are maintained for each basic block:
 +
 +   m_outgoing  : a set bit indicates a range can be generated for a name.
 +   m_incoming  : a set bit means a this name come from outside the
 +               block and is used in the calculation of some outgoing
 +               range.
 +
 +   Generally speaking, the m_outgoing vector is the union of the
 +   entire def_chain of all SSA names used in the last statement of the
 +   block which generate ranges.  The m_incoming vector is the union of
 +   all the terminal names of those def chains.  They act as a one-stop
 +   summary for the block.  */
 +
 +class gori_map : public range_def_chain
 +{
 +public:
 +  gori_map ();
 +  ~gori_map ();
 +
 +  bool is_export_p (tree name, basic_block bb);
 +  bool def_chain_in_export_p (tree name, basic_block bb);
 +  bool is_import_p (tree name, basic_block bb);
 +
 +  void dump (FILE *f);
 +  void dump (FILE *f, basic_block bb);
 +private:
 +  bitmap_obstack m_bitmaps;
 +  vec<bitmap> m_outgoing;     // BB: Outgoing ranges calculatable on edges
 +  vec<bitmap> m_incoming;     // BB: block imports
 +  void maybe_add_gori (tree name, basic_block bb);
 +  void calculate_gori (basic_block bb);
 +  bitmap imports (basic_block bb);
 +public:
 +  // FIXME: Temporarily set as public.
 +  bitmap exports (basic_block bb);
 +};
 +
 +// Generic object to return a range for an SSA.
 +class range_store
 +{
 +public:
 +  virtual bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL) = 0;
++  virtual const class value_range_equiv *get_value_range (const_tree expr,
++                                                        gimple *stmt = NULL);
 +};
 +
 +// This class utilizes a GORI map to determine which SSA_NAMES can
 +// have ranges calculated for them on outgoing edges from basic
 +// blocks.
 +
 +class gori_compute : public range_store
 +{
 +public:
 +  gori_compute ();
 +  /*  Destructor is virtual to silence:
 +
 +      warning: deleting object of polymorphic class type ‘vr_values’
 +      which has non-virtual destructor might cause undefined
 +      behavior.  */
 +  virtual ~gori_compute ();
 +  virtual bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL);
 +  virtual bool outgoing_edge_range_p (irange &r, edge e, tree name,
 +                                    const irange *name_range = NULL);
 +protected:
 +  virtual void range_of_ssa_name (irange &r, tree name, gimple *stmt = NULL);
 +  virtual bool compute_operand_range (irange &r, gimple *stmt,
 +                                    const irange &lhs,
 +                                    tree name,
 +                                    const irange *name_range = NULL);
 +  bool has_edge_range_p (edge e, tree name);
 +  virtual bool compute_logical_operands (irange &r, gimple *stmt,
 +                                       const irange &lhs,
 +                                       tree name, const irange *name_range);
 +  void compute_logical_operands_in_chain (class tf_range &range,
 +                                        gimple *stmt, const irange &lhs,
 +                                        tree name,
 +                                        const irange *name_range,
 +                                        tree op, bool op_in_chain);
 +  bool optimize_logical_operands (tf_range &range,
 +                                gimple *stmt, const irange &lhs,
 +                                tree name, const irange *name_range,
 +                                tree op);
 +
 +  bool logical_combine (irange &r, enum tree_code code,
 +                      const irange &lhs,
 +                      const class tf_range &op1_range,
 +                      const class tf_range &op2_range);
 +  int_range<1> m_bool_zero;           // Boolean false cached.
 +  int_range<1> m_bool_one;            // Boolean true cached.
 +
 +  gori_map m_gori_map;
 +private:
 +  void get_tree_range (irange &, tree expr, tree name,
 +                     const irange *range_of_name);
 +  bool compute_operand_range_switch (irange &r, gswitch *stmt,
 +                                   const irange &lhs,
 +                                   tree name, const irange *name_range);
 +  bool compute_name_range_op (irange &r, gimple *stmt,
 +                            const irange &lhs,
 +                            tree name, const irange *name_range);
 +  bool compute_operand1_range (irange &r, gimple *stmt,
 +                             const irange &lhs,
 +                             tree name, const irange *name_range);
 +  bool compute_operand2_range (irange &r, gimple *stmt,
 +                             const irange &lhs,
 +                             tree name, const irange *name_range);
 +  bool compute_operand1_and_operand2_range
 +                              (irange &r, gimple *stmt,
 +                               const irange &lhs,
 +                               tree name, const irange *name_range);
 +};
 +
 +class gori_compute_cache : public gori_compute
 +{
 +public:
 +  gori_compute_cache ();
 +  ~gori_compute_cache ();
 +protected:
 +  virtual bool compute_operand_range (irange &r, gimple *stmt,
 +                                    const irange &lhs,
 +                                    tree name,
 +                                    const irange *name_range = NULL);
 +private:
 +  void cache_comparison (gimple *);
 +  void cache_comparison_with_int (gimple *, enum tree_code,
 +                                tree op1, tree op2);
 +  void cache_comparison_with_ssa (gimple *, enum tree_code,
 +                                tree op1, tree op2);
 +  typedef gori_compute super;
 +  class logical_stmt_cache *m_cache;
 +};
 +
 +class trace_gori_compute : public gori_compute_cache
 +{
 +public:
 +  trace_gori_compute ();
 +  virtual bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL);
 +  virtual bool outgoing_edge_range_p (irange &r, edge e, tree name,
 +                                    const irange *name_range = NULL);
 +protected:
 +  virtual void range_of_ssa_name (irange &r, tree name, gimple *stmt = NULL);
 +  virtual bool compute_operand_range (irange &r, gimple *stmt,
 +                                    const irange &lhs,
 +                                    tree name,
 +                                    const irange *name_range = NULL);
 +  virtual bool compute_logical_operands (irange &r, gimple *stmt,
 +                                       const irange &lhs,
 +                                       tree name, const irange *name_range);
 +private:
 +  typedef gori_compute_cache super;
 +protected:
 +  static const unsigned bump = 2;
 +  unsigned indent;
 +  unsigned trace_count;               // Current trace index count.
 +
 +  bool dumping (unsigned counter, bool trailing = false);
 +  bool trailer (unsigned counter, const char *caller, bool result, tree name,
 +              const irange &r);
 +};
 +
 +#endif // GCC_GIMPLE_RANGE_GORI_H
index 024ade3fe89de7de53b76adb9edb755f120ad792,af780fd0519d37eb1371098bcef983fee40da1d9..bc43dc2f40bec7f98e2dc88d7c158243763b4862
@@@ -41,290 -41,19 +41,19 @@@ along with GCC; see the file COPYING3
  #include "tree-cfgcleanup.h"
  #include "vr-values.h"
  #include "gimple-ssa-evrp-analyze.h"
 +#include "misc.h"
  
  class evrp_folder : public substitute_and_fold_engine
- {
-  public:
-   tree get_value (tree, gimple *) FINAL OVERRIDE;
-   evrp_folder (class vr_values *vr_values_)
-     : vr_values (vr_values_),
-     simplifier (vr_values_) { }
-   bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
-     {
-       return simplifier.simplify (gsi);
-     }
-   class vr_values *vr_values;
-  private:
-   DISABLE_COPY_AND_ASSIGN (evrp_folder);
-   simplify_using_ranges simplifier;
- };
- tree
- evrp_folder::get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED)
- {
-   return vr_values->op_with_constant_singleton_value_range (op);
- }
- /* evrp_dom_walker visits the basic blocks in the dominance order and set
-    the Value Ranges (VR) for SSA_NAMEs in the scope.  Use this VR to
-    discover more VRs.  */
- class evrp_dom_walker : public dom_walker
- {
- public:
-   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);
-     }
-   ~evrp_dom_walker ()
-     {
-       BITMAP_FREE (need_eh_cleanup);
-     }
-   virtual edge before_dom_children (basic_block);
-   virtual void after_dom_children (basic_block);
-   void cleanup (void);
-  private:
-   DISABLE_COPY_AND_ASSIGN (evrp_dom_walker);
-   bitmap need_eh_cleanup;
-   auto_vec<gimple *> stmts_to_fixup;
-   auto_vec<gimple *> stmts_to_remove;
-   class evrp_range_analyzer evrp_range_analyzer;
-   class evrp_folder evrp_folder;
- };
- edge
- evrp_dom_walker::before_dom_children (basic_block bb)
- {
-   if (dump_file && (dump_flags & TDF_DETAILS))
-     fprintf (dump_file, "Visiting BB%d\n", bb->index);
-   evrp_range_analyzer.enter (bb);
-   for (gphi_iterator gpi = gsi_start_phis (bb);
-        !gsi_end_p (gpi); gsi_next (&gpi))
-     {
-       gphi *phi = gpi.phi ();
-       tree lhs = PHI_RESULT (phi);
-       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;
-       if (vr->singleton_p (&val) && may_propagate_copy (lhs, val))
-       {
-         stmts_to_remove.safe_push (phi);
-         continue;
-       }
-     }
-   edge taken_edge = NULL;
-   /* Visit all other stmts and discover any new VRs possible.  */
-   for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
-        !gsi_end_p (gsi); gsi_next (&gsi))
-     {
-       gimple *stmt = gsi_stmt (gsi);
-       tree output = NULL_TREE;
-       gimple *old_stmt = stmt;
-       bool was_noreturn = (is_gimple_call (stmt)
-                          && gimple_call_noreturn_p (stmt));
-       if (dump_file && (dump_flags & TDF_DETAILS))
-       {
-         fprintf (dump_file, "Visiting stmt ");
-         print_gimple_stmt (dump_file, stmt, 0);
-       }
-       evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
-       if (gcond *cond = dyn_cast <gcond *> (stmt))
-       {
-         evrp_range_analyzer.vrp_visit_cond_stmt (cond, &taken_edge);
-         if (taken_edge)
-           {
-             if (taken_edge->flags & EDGE_TRUE_VALUE)
-               gimple_cond_make_true (cond);
-             else if (taken_edge->flags & EDGE_FALSE_VALUE)
-               gimple_cond_make_false (cond);
-             else
-               gcc_unreachable ();
-             update_stmt (stmt);
-           }
-       }
-       else if (stmt_interesting_for_vrp (stmt))
-       {
-         output = get_output_for_vrp (stmt);
-         if (output)
-           {
-             const value_range_equiv *vr
-               = evrp_range_analyzer.get_value_range (output);
-             /* Mark stmts whose output we fully propagate for removal.  */
-             tree val;
-             if (vr->singleton_p (&val)
-                 && may_propagate_copy (output, val)
-                 && !stmt_could_throw_p (cfun, stmt)
-                 && !gimple_has_side_effects (stmt))
-               {
-                 stmts_to_remove.safe_push (stmt);
-                 continue;
-               }
-           }
-       }
-       /* Try folding stmts with the VR discovered.  */
-       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)
-       {
-         stmt = gsi_stmt (gsi);
-         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))
-           bitmap_set_bit (need_eh_cleanup, bb->index);
-         /* If we turned a not noreturn call into a noreturn one
-            schedule it for fixup.  */
-         if (!was_noreturn
-             && is_gimple_call (stmt)
-             && gimple_call_noreturn_p (stmt))
-           stmts_to_fixup.safe_push (stmt);
-         if (gimple_assign_single_p (stmt))
-           {
-             tree rhs = gimple_assign_rhs1 (stmt);
-             if (TREE_CODE (rhs) == ADDR_EXPR)
-               recompute_tree_invariant_for_addr_expr (rhs);
-           }
-       }
-     }
-   /* Visit BB successor PHI nodes and replace PHI args.  */
-   edge e;
-   edge_iterator ei;
-   FOR_EACH_EDGE (e, ei, bb->succs)
-     {
-       for (gphi_iterator gpi = gsi_start_phis (e->dest);
-          !gsi_end_p (gpi); gsi_next (&gpi))
-       {
-         gphi *phi = gpi.phi ();
-         use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
-         tree arg = USE_FROM_PTR (use_p);
-         if (TREE_CODE (arg) != SSA_NAME
-             || virtual_operand_p (arg))
-           continue;
-         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);
-       }
-     }
-  
-   return taken_edge;
- }
- void
- evrp_dom_walker::after_dom_children (basic_block bb)
- {
-   evrp_range_analyzer.leave (bb);
- }
- /* Perform any cleanups after the main phase of EVRP has completed.  */
- void
- evrp_dom_walker::cleanup (void)
- {
-   if (dump_file)
-     {
-       fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
-       evrp_range_analyzer.dump_all_value_ranges (dump_file);
-       fprintf (dump_file, "\n");
-     }
-   /* Remove stmts in reverse order to make debug stmt creation possible.  */
-   while (! stmts_to_remove.is_empty ())
-     {
-       gimple *stmt = stmts_to_remove.pop ();
-       if (dump_file && dump_flags & TDF_DETAILS)
-       {
-         fprintf (dump_file, "Removing dead stmt ");
-         print_gimple_stmt (dump_file, stmt, 0);
-         fprintf (dump_file, "\n");
-       }
-       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-       if (gimple_code (stmt) == GIMPLE_PHI)
-       remove_phi_node (&gsi, true);
-       else
-       {
-         unlink_stmt_vdef (stmt);
-         gsi_remove (&gsi, true);
-         release_defs (stmt);
-       }
-     }
-   if (!bitmap_empty_p (need_eh_cleanup))
-     gimple_purge_all_dead_eh_edges (need_eh_cleanup);
-   /* Fixup stmts that became noreturn calls.  This may require splitting
-      blocks and thus isn't possible during the dominator walk.  Do this
-      in reverse order so we don't inadvertedly remove a stmt we want to
-      fixup by visiting a dominating now noreturn call first.  */
-   while (!stmts_to_fixup.is_empty ())
-     {
-       gimple *stmt = stmts_to_fixup.pop ();
-       fixup_noreturn_call (stmt);
-     }
- }
- class xevrp_folder : public substitute_and_fold_engine
  {
  public:
-   xevrp_folder () : range_analyzer (true),
-     vr_values (range_analyzer.get_vr_values ()),
-     simplifier (vr_values)
+   evrp_folder () : m_range_analyzer (/*update_global_ranges=*/true),
 -    m_vr_values (m_range_analyzer.get_vr_values ())
++    m_vr_values (m_range_analyzer.get_vr_values ()),
++    simplifier (m_vr_values)
    {
    }
  
-   ~xevrp_folder ()
+   ~evrp_folder ()
    {
 -    m_vr_values->cleanup_edges_and_switches ();
 -
      if (dump_file)
        {
        fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
-       fprintf (dump_file, "Visiting stmt ");
+       fprintf (dump_file, "evrp visiting stmt ");
        print_gimple_stmt (dump_file, stmt, 0);
        }
-     range_analyzer.record_ranges_from_stmt (stmt, false);
 +    m_gimple_state.set_orig_stmt (stmt);
+     m_range_analyzer.record_ranges_from_stmt (stmt, false);
    }
  
-   void tmp_stats_remove_stmt (gimple *stmt, tree lhs) OVERRIDE
+   bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
    {
-     m_gimple_state.maybe_dump_differences_and_trap (stmt, lhs);
 -    return m_vr_values->simplify_stmt_using_ranges (gsi);
++    bool res = simplifier.simplify (gsi);
++    if (m_modified || res)
++      m_gimple_state.maybe_dump_differences_and_trap (gsi_stmt (*gsi));
++    return res;
    }
  
-   void tmp_stats_changed_phi (gphi *orig_phi, gphi *new_phi) OVERRIDE
+   void post_fold_bb (basic_block bb) OVERRIDE
    {
-     gimple *save = m_gimple_state.set_orig_stmt (orig_phi);
-     m_gimple_state.maybe_dump_differences_and_trap (new_phi);
-     m_gimple_state.set_orig_stmt (save);
+     m_range_analyzer.leave (bb);
    }
  
-   void tmp_stats_set_modified (bool modified) OVERRIDE
+   void post_new_stmt (gimple *stmt) OVERRIDE
    {
-     m_modified = modified;
 -    m_vr_values->set_defs_to_varying (stmt);
++    m_range_analyzer.get_vr_values ()->set_defs_to_varying (stmt);
 +  }
 +
-   bool fold_stmt (gimple_stmt_iterator *gsi)
++  void tmp_stats_remove_stmt (gimple *stmt, tree lhs) OVERRIDE
 +  {
-     bool res = simplifier.simplify (gsi);
-     if (m_modified || res)
-       m_gimple_state.maybe_dump_differences_and_trap (gsi_stmt (*gsi));
-     return res;
++    m_gimple_state.maybe_dump_differences_and_trap (stmt, lhs);
 +  }
 +
-   void post_fold_bb (basic_block bb)
++  void tmp_stats_changed_phi (gphi *orig_phi, gphi *new_phi) OVERRIDE
 +  {
-     range_analyzer.leave (bb);
++    gimple *save = m_gimple_state.set_orig_stmt (orig_phi);
++    m_gimple_state.maybe_dump_differences_and_trap (new_phi);
++    m_gimple_state.set_orig_stmt (save);
 +  }
 +
-   void post_new_stmt (gimple *stmt)
++  void tmp_stats_set_modified (bool modified) OVERRIDE
 +  {
-     range_analyzer.get_vr_values ()->set_defs_to_varying (stmt);
++    m_modified = modified;
    }
  
  private:
-   DISABLE_COPY_AND_ASSIGN (xevrp_folder);
-   class evrp_range_analyzer range_analyzer;
-   class vr_values *vr_values;
+   DISABLE_COPY_AND_ASSIGN (evrp_folder);
+   class evrp_range_analyzer m_range_analyzer;
+   class vr_values *m_vr_values;
++
 +  simplify_using_ranges simplifier;
 +  class gimple_state m_gimple_state;
 +  bool m_modified;
  };
  
  /* Main entry point for the early vrp pass which is a simplified non-iterative
diff --cc gcc/ipa-cp.c
Simple merge
Simple merge
diff --cc gcc/ipa-prop.c
Simple merge
diff --cc gcc/ipa-prop.h
Simple merge
diff --cc gcc/opts.c
Simple merge
diff --cc gcc/passes.def
Simple merge
index a279998cafa844ebcbde477eca7090737f6762d7,762d672014338ab8d3ff95f5e4aa5734965828be..c96c31b6caf0a1b93b247acc4d7697445b4e1b38
@@@ -1,6 -1,5 +1,6 @@@
  /* { dg-do compile } */
- /* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fno-tree-vrp -fdisable-tree-evrp-copyprop" } */
- /* { dg-additional-options "-fdump-tree-dse1-details" } */
+ /* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fno-tree-vrp -fdump-tree-dse1-details" } */
++/* { dg-additional-options "-fdisable-tree-evrp-copyprop" } */
  
  int
  f ()
diff --cc gcc/toplev.c
Simple merge
diff --cc gcc/tree-pass.h
Simple merge
Simple merge
Simple merge
diff --cc gcc/tree-vrp.c
index 275c3d8edc485703b52ed89d594008ce379f2614,c39a6f5e3748f8cbcf3af511734bbcf5359cfe53..5e48709cedeb2cef35f18d8615057157a9b7a8ca
@@@ -3446,14 -3370,14 +3371,14 @@@ public
    enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
    enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
  
-   void vrp_initialize (void);
+   struct function *fun;
+   void vrp_initialize (struct function *);
 -  void vrp_finalize (bool);
 +  void vrp_finalize (class vrp_folder *, bool);
-   void check_all_array_refs (void);
-   bool check_array_ref (location_t, tree, bool);
-   bool check_mem_ref (location_t, tree, bool);
-   void search_for_addr_array (tree, location_t);
  
    class vr_values vr_values;
+ private:
    /* Temporary delegator to minimize code churn.  */
    const value_range_equiv *get_value_range (const_tree op)
      { return vr_values.get_value_range (op); }
@@@ -4796,27 -3938,23 +3939,28 @@@ vrp_prop::visit_phi (gphi *phi
  
  class vrp_folder : public substitute_and_fold_engine
  {
 -public:
 -  vrp_folder () : substitute_and_fold_engine (/* Fold all stmts.  */ true) {  }
 + public:
 +  vrp_folder (vr_values *v)
 +    : substitute_and_fold_engine (/* Fold all stmts.  */ true),
 +      m_vr_values (v), simplifier (v)
 +    {  }
-   tree get_value (tree, gimple *) FINAL OVERRIDE;
+   tree get_value (tree, gimple *stmt) FINAL OVERRIDE;
    bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
-   bool fold_predicate_in (gimple_stmt_iterator *);
  
 -  class vr_values *vr_values;
++  class vr_values *m_vr_values;
+ private:
+   bool fold_predicate_in (gimple_stmt_iterator *);
    /* Delegators.  */
    tree vrp_evaluate_conditional (tree_code code, tree op0,
                                 tree op1, gimple *stmt)
 -    { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); }
 +    { return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
    bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 -    { return vr_values->simplify_stmt_using_ranges (gsi); }
 +    { return simplifier.simplify (gsi); }
   tree op_with_constant_singleton_value_range (tree op)
 -    { return vr_values->op_with_constant_singleton_value_range (op); }
 +    { return m_vr_values->op_with_constant_singleton_value_range (op); }
 +
- private:
-   vr_values *m_vr_values;
 +  simplify_using_ranges simplifier;
  };
  
  /* If the statement pointed by SI has a predicate whose value can be
@@@ -5237,12 -4374,17 +4381,15 @@@ vrp_prop::vrp_finalize (vrp_folder *fol
       check_array_bounds_dom_walker's ctor; vrp_folder may clear
       it from some edges.  */
    if (warn_array_bounds && warn_array_bounds_p)
-     set_all_edges_as_executable (cfun);
+     set_all_edges_as_executable (fun);
  
 -  class vrp_folder vrp_folder;
 -  vrp_folder.vr_values = &vr_values;
 -  vrp_folder.substitute_and_fold ();
 +  folder->substitute_and_fold ();
  
    if (warn_array_bounds && warn_array_bounds_p)
-     check_all_array_refs ();
+     {
+       array_bounds_checker array_checker (fun, &vr_values);
+       array_checker.check ();
+     }
  }
  
  /* Main entry point to VRP (Value Range Propagation).  This pass is
@@@ -5308,12 -4451,9 +4456,12 @@@ execute_vrp (struct function *fun, boo
    mark_dfs_back_edges ();
  
    class vrp_prop vrp_prop;
-   vrp_prop.vrp_initialize ();
+   vrp_prop.vrp_initialize (fun);
    vrp_prop.ssa_propagate ();
 -  vrp_prop.vrp_finalize (warn_array_bounds_p);
 +  /* Instantiate the folder here, so that edge cleanups happen at the
 +     end of this function.  */
 +  vrp_folder folder (&vrp_prop.vr_values);
 +  vrp_prop.vrp_finalize (&folder, warn_array_bounds_p);
  
    /* We must identify jump threading opportunities before we release
       the datastructures built by VRP.  */
      {
        gimple *last = last_stmt (bb);
        if (last && gimple_code (last) == GIMPLE_COND)
 -      vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a <gcond *> (last));
 +      simplify_cond_using_ranges_2 (&vrp_prop.vr_values,
 +                                    as_a <gcond *> (last));
      }
  
-   free_numbers_of_iterations_estimates (cfun);
+   free_numbers_of_iterations_estimates (fun);
  
    /* ASSERT_EXPRs must be removed before finalizing jump threads
       as finalizing jump threads calls the CFG cleanup code which
diff --cc gcc/tree-vrp.h
Simple merge
index 0000000000000000000000000000000000000000,24132e3546e729beddb28d125683a74d1d4c0b28..ab901666f3501a91bf6b201c5d092b7a1fef0d1d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,322 +1,353 @@@
 -value_range_equiv::intersect (const value_range_equiv *other)
+ /* Support routines for value ranges with equivalences.
+    Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "ssa.h"
+ #include "tree-pretty-print.h"
+ #include "value-range-equiv.h"
+ value_range_equiv::value_range_equiv (tree min, tree max, bitmap equiv,
+                                     value_range_kind kind)
+ {
++  m_discriminator = VRANGE_KIND_INT_WITH_EQUIVS;
+   m_equiv = NULL;
+   set (min, max, equiv, kind);
+ }
+ value_range_equiv::value_range_equiv (const value_range &other)
+ {
++  m_discriminator = VRANGE_KIND_INT_WITH_EQUIVS;
+   m_equiv = NULL;
+   set (other.min(), other.max (), NULL, other.kind ());
+ }
+ void
+ value_range_equiv::set (tree min, tree max, bitmap equiv,
+                       value_range_kind kind)
+ {
+   value_range::set (min, max, kind);
+   set_equiv (equiv);
+   if (flag_checking)
+     check ();
+ }
+ void
+ value_range_equiv::set (tree val)
+ {
+   gcc_assert (TREE_CODE (val) == SSA_NAME || is_gimple_min_invariant (val));
+   if (TREE_OVERFLOW_P (val))
+     val = drop_tree_overflow (val);
+   set (val, val);
+ }
+ void
+ value_range_equiv::set_undefined ()
+ {
+   set (NULL, NULL, NULL, VR_UNDEFINED);
+ }
+ void
+ value_range_equiv::set_varying (tree type)
+ {
+   value_range::set_varying (type);
+   equiv_clear ();
+ }
+ /* Like set, but keep the equivalences in place.  */
+ void
+ value_range_equiv::update (tree min, tree max, value_range_kind kind)
+ {
+   set (min, max,
+        (kind != VR_UNDEFINED && kind != VR_VARYING) ? m_equiv : NULL, kind);
+ }
+ /* Copy value_range in FROM into THIS while avoiding bitmap sharing.
+    Note: The code that avoids the bitmap sharing looks at the existing
+    this->m_equiv, so this function cannot be used to initalize an
+    object.  Use the constructors for initialization.  */
+ void
+ value_range_equiv::deep_copy (const value_range_equiv *from)
+ {
+   set (from->min (), from->max (), from->m_equiv, from->m_kind);
+ }
+ void
+ value_range_equiv::move (value_range_equiv *from)
+ {
+   set (from->min (), from->max (), NULL, from->m_kind);
+   m_equiv = from->m_equiv;
+   from->m_equiv = NULL;
+ }
+ void
+ value_range_equiv::set_equiv (bitmap equiv)
+ {
+   if (undefined_p () || varying_p ())
+     equiv = NULL;
+   /* Since updating the equivalence set involves deep copying the
+      bitmaps, only do it if absolutely necessary.
+      All equivalence bitmaps are allocated from the same obstack.  So
+      we can use the obstack associated with EQUIV to allocate vr->equiv.  */
+   if (m_equiv == NULL
+       && equiv != NULL)
+     m_equiv = BITMAP_ALLOC (equiv->obstack);
+   if (equiv != m_equiv)
+     {
+       if (equiv && !bitmap_empty_p (equiv))
+       bitmap_copy (m_equiv, equiv);
+       else
+       bitmap_clear (m_equiv);
+     }
+ }
+ void
+ value_range_equiv::check ()
+ {
+   value_range::check ();
+   switch (m_kind)
+     {
+     case VR_UNDEFINED:
+     case VR_VARYING:
+       gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
+     default:;
+     }
+ }
+ /* Return true if the bitmaps B1 and B2 are equal.  */
+ static bool
+ vr_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
+ {
+   return (b1 == b2
+         || ((!b1 || bitmap_empty_p (b1))
+             && (!b2 || bitmap_empty_p (b2)))
+         || (b1 && b2
+             && bitmap_equal_p (b1, b2)));
+ }
+ /* Returns TRUE if THIS == OTHER.  Ignores the equivalence bitmap if
+    IGNORE_EQUIVS is TRUE.  */
+ bool
+ value_range_equiv::equal_p (const value_range_equiv &other,
+                           bool ignore_equivs) const
+ {
+   return (value_range::equal_p (other)
+         && (ignore_equivs || vr_bitmap_equal_p (m_equiv, other.m_equiv)));
+ }
+ void
+ value_range_equiv::equiv_clear ()
+ {
+   if (m_equiv)
+     bitmap_clear (m_equiv);
+ }
+ /* Add VAR and VAR's equivalence set (VAR_VR) to the equivalence
+    bitmap.  If no equivalence table has been created, OBSTACK is the
+    obstack to use (NULL for the default obstack).
+    This is the central point where equivalence processing can be
+    turned on/off.  */
+ void
+ value_range_equiv::equiv_add (const_tree var,
+                             const value_range_equiv *var_vr,
+                             bitmap_obstack *obstack)
+ {
+   if (!m_equiv)
+     m_equiv = BITMAP_ALLOC (obstack);
+   unsigned ver = SSA_NAME_VERSION (var);
+   bitmap_set_bit (m_equiv, ver);
+   if (var_vr && var_vr->m_equiv)
+     bitmap_ior_into (m_equiv, var_vr->m_equiv);
+ }
+ void
 -value_range_equiv::union_ (const value_range_equiv *other)
++value_range_equiv::intersect (const vrange &vother)
+ {
++  if (!is_a <const value_range_equiv *> (&vother))
++    {
++      irange::intersect (vother);
++      return;
++    }
++  const value_range_equiv *other = as_a <const value_range_equiv *> (&vother);
++  gcc_checking_assert (other != NULL);
++
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "Intersecting\n  ");
+       dump_value_range (dump_file, this);
+       fprintf (dump_file, "\nand\n  ");
+       dump_value_range (dump_file, other);
+       fprintf (dump_file, "\n");
+     }
+   /* If THIS is varying we want to pick up equivalences from OTHER.
+      Just special-case this here rather than trying to fixup after the
+      fact.  */
+   if (this->varying_p ())
+     this->deep_copy (other);
+   else
+     {
+       value_range tem = intersect_helper (this, other);
+       this->update (tem.min (), tem.max (), tem.kind ());
+       /* If the result is VR_UNDEFINED there is no need to mess with
+        equivalencies.  */
+       if (!undefined_p ())
+       {
+         /* The resulting set of equivalences for range intersection
+            is the union of the two sets.  */
+         if (m_equiv && other->m_equiv && m_equiv != other->m_equiv)
+           bitmap_ior_into (m_equiv, other->m_equiv);
+         else if (other->m_equiv && !m_equiv)
+           {
+             /* All equivalence bitmaps are allocated from the same
+                obstack.  So we can use the obstack associated with
+                VR to allocate this->m_equiv.  */
+             m_equiv = BITMAP_ALLOC (other->m_equiv->obstack);
+             bitmap_copy (m_equiv, other->m_equiv);
+           }
+       }
+     }
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "to\n  ");
+       dump_value_range (dump_file, this);
+       fprintf (dump_file, "\n");
+     }
+ }
+ void
 -      value_range tem = union_helper (this, other);
++value_range_equiv::intersect (const value_range_equiv *other)
++{
++  intersect (*other);
++}
++
++void
++value_range_equiv::union_ (const vrange &vother)
+ {
++  if (!is_a <const value_range_equiv *> (&vother))
++    {
++      irange::union_ (vother);
++      return;
++    }
++  const value_range_equiv *other = as_a <const value_range_equiv *> (&vother);
++  gcc_checking_assert (other != NULL);
++
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "Meeting\n  ");
+       dump_value_range (dump_file, this);
+       fprintf (dump_file, "\nand\n  ");
+       dump_value_range (dump_file, other);
+       fprintf (dump_file, "\n");
+     }
+   /* If THIS is undefined we want to pick up equivalences from OTHER.
+      Just special-case this here rather than trying to fixup after the fact.  */
+   if (this->undefined_p ())
+     this->deep_copy (other);
+   else
+     {
++      gcc_checking_assert (other->simple_ranges_p ());
++      value_range tem = union_helper (this, (const value_range *) other);
+       this->update (tem.min (), tem.max (), tem.kind ());
+       /* The resulting set of equivalences is always the intersection of
+        the two sets.  */
+       if (this->m_equiv && other->m_equiv && this->m_equiv != other->m_equiv)
+       bitmap_and_into (this->m_equiv, other->m_equiv);
+       else if (this->m_equiv && !other->m_equiv)
+       bitmap_clear (this->m_equiv);
+     }
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "to\n  ");
+       dump_value_range (dump_file, this);
+       fprintf (dump_file, "\n");
+     }
+ }
++void
++value_range_equiv::union_ (const value_range_equiv *other)
++{
++  union_ (*other);
++}
++
+ void
+ value_range_equiv::dump (FILE *file) const
+ {
+   value_range::dump (file);
+   if ((m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE)
+       && m_equiv)
+     {
+       bitmap_iterator bi;
+       unsigned i, c = 0;
+       fprintf (file, "  EQUIVALENCES: { ");
+       EXECUTE_IF_SET_IN_BITMAP (m_equiv, 0, i, bi)
+       {
+         print_generic_expr (file, ssa_name (i));
+         fprintf (file, " ");
+         c++;
+       }
+       fprintf (file, "} (%u elements)", c);
+     }
+ }
+ void
+ value_range_equiv::dump () const
+ {
+   dump (stderr);
+ }
+ void
+ dump_value_range (FILE *file, const value_range_equiv *vr)
+ {
+   if (!vr)
+     fprintf (file, "[]");
+   else
+     vr->dump (file);
+ }
+ DEBUG_FUNCTION void
+ debug (const value_range_equiv *vr)
+ {
+   dump_value_range (stderr, vr);
+ }
+ DEBUG_FUNCTION void
+ debug (const value_range_equiv &vr)
+ {
+   dump_value_range (stderr, &vr);
+ }
index 0000000000000000000000000000000000000000,274221226e61cc2c5556d79befb36e9347e87d81..7cf4bcb8532814e3fdd7b501b8515ca75cf08874
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,82 +1,104 @@@
 -  value_range_equiv () : value_range () { m_equiv = NULL; }
+ /* Support routines for value ranges with equivalences.
+    Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of GCC.
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ #ifndef GCC_VALUE_RANGE_EQUIV_H
+ #define GCC_VALUE_RANGE_EQUIV_H
+ #include "value-range.h"
+ /* Note value_range_equiv cannot currently be used with GC memory,
+    only value_range is fully set up for this.  */
+ class GTY((user)) value_range_equiv : public value_range
+ {
+  public:
++  value_range_equiv () : value_range ()
++    {
++      m_discriminator = VRANGE_KIND_INT_WITH_EQUIVS;
++      m_equiv = NULL;
++    }
+   value_range_equiv (const value_range &);
+   /* Deep-copies equiv bitmap argument.  */
+   value_range_equiv (tree, tree, bitmap = NULL, value_range_kind = VR_RANGE);
+   /* Shallow-copies equiv bitmap.  */
+   value_range_equiv (const value_range_equiv &) /* = delete */;
+   /* Shallow-copies equiv bitmap.  */
+   value_range_equiv& operator=(const value_range_equiv &) /* = delete */;
+   /* Move equiv bitmap from source range.  */
+   void move (value_range_equiv *);
+   /* Leaves equiv bitmap alone.  */
+   void update (tree, tree, value_range_kind = VR_RANGE);
+   /* Deep-copies equiv bitmap argument.  */
+   void set (tree, tree, bitmap = NULL, value_range_kind = VR_RANGE);
+   void set (tree);
+   bool operator== (const value_range_equiv &) const /* = delete */;
+   bool operator!= (const value_range_equiv &) const /* = delete */;
+   void intersect (const value_range_equiv *);
+   void union_ (const value_range_equiv *);
++  virtual void intersect (const vrange &);
++  virtual void union_ (const vrange &);
+   bool equal_p (const value_range_equiv &, bool ignore_equivs) const;
+   /* Types of value ranges.  */
+   void set_undefined ();
+   void set_varying (tree);
+   /* Equivalence bitmap methods.  */
+   bitmap equiv () const { return m_equiv; }
+   void equiv_clear ();
+   void equiv_add (const_tree, const value_range_equiv *,
+                 bitmap_obstack * = NULL);
+   /* Misc methods.  */
+   void deep_copy (const value_range_equiv *);
+   void dump (FILE *) const;
+   void dump () const;
+  private:
+   /* Deep-copies bitmap argument.  */
+   void set_equiv (bitmap);
+   void check ();
+   /* Set of SSA names whose value ranges are equivalent to this one.
+      This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE.  */
+   bitmap m_equiv;
+ };
+ extern void dump_value_range (FILE *, const value_range_equiv *);
++template <>
++template <>
++inline bool
++is_a_helper <const value_range_equiv *>::test (const vrange *p)
++{
++  return p && p->m_discriminator == VRANGE_KIND_INT_WITH_EQUIVS;
++}
++
++template <>
++template <>
++inline bool
++is_a_helper <value_range_equiv *>::test (vrange *p)
++{
++  return p && p->m_discriminator == VRANGE_KIND_INT_WITH_EQUIVS;
++}
++
+ #endif // GCC_VALUE_RANGE_EQUIV_H
diff --cc gcc/vr-values.c
index 0a8f14a169660e668b08998c029da3864678eb6b,e95df78870aba4b528039e96679ca1976b3558d2..d86d30f46e2b3080fd855fc19c5cb7afd2742556
@@@ -3591,9 -3550,11 +3591,11 @@@ range_fits_type_p (const value_range *v
    return true;
  }
  
+ /* If COND can be folded entirely as TRUE or FALSE, rewrite the
+    conditional as such, and return TRUE.  */
  bool
- simplify_using_ranges::simplify_cond_using_ranges_when_edge_is_known
-                                               (gcond *cond)
 -vr_values::fold_cond (gcond *cond)
++simplify_using_ranges::fold_cond (gcond *cond)
  {
    /* ?? vrp_folder::fold_predicate_in() is a superset of this.  At
       some point we should merge all variants of this code.  */
diff --cc gcc/vr-values.h
index 4b2cbceabc80be6e65ce46fb6bba1a0c86b0cfe4,ac25139762af8828218a5821b1fa502c604f6b46..17e71b757658999cb855c4bdbb0a5a00dce7b7ab
@@@ -20,66 -20,7 +20,67 @@@ along with GCC; see the file COPYING3
  #ifndef GCC_VR_VALUES_H
  #define GCC_VR_VALUES_H
  
-   bool simplify_cond_using_ranges_when_edge_is_known (gcond *);
+ #include "value-range-equiv.h"
 +#include "gimple-range-gori.h"
 +
 +class simplify_using_ranges
 +{
 +public:
 +  simplify_using_ranges (range_store *);
 +  ~simplify_using_ranges ();
 +  bool simplify (gimple_stmt_iterator *);
 +
 +  // ?? These should be cleaned, merged, and made private.
 +  tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
 +  void vrp_visit_cond_stmt (gcond *, edge *);
 +  tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
 +                                              tree, tree, bool,
 +                                              bool *, bool *);
 +
 +private:
 +  // This is named differently than get_value_range to make it obvious
 +  // that it returns an equivalence.  Only use this for calculations
 +  // that may take equivalences, otherwise use range_of_expr.
 +  const value_range_equiv *get_value_range_equiv (const_tree op,
 +                                                gimple *stmt = NULL)
 +  { return store->get_value_range (op, stmt); }
 +  bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
 +  bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *);
 +  bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *);
 +  bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *);
 +  bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *);
 +  bool simplify_cond_using_ranges_1 (gcond *);
++  bool fold_cond (gcond *);
 +  bool simplify_switch_using_ranges (gswitch *);
 +  bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *,
 +                                             gimple *);
 +  bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *);
 +
 +  bool two_valued_val_range_p (tree, tree *, tree *);
 +  bool op_with_boolean_value_range_p (tree, gimple *);
 +  tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
 +  tree compare_names (enum tree_code, tree, tree, bool *);
 +  const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
 +  tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
 +                                                           tree, tree,
 +                                                           bool *);
 +  void cleanup_edges_and_switches (void);
 +
 +  /* Vectors of edges that need removing and switch statements that
 +     need updating.  It is expected that a pass using the simplification
 +     routines will, at the end of the pass, clean up the edges and
 +     switch statements.  The class dtor will try to detect cases
 +     that do not follow that expectation.  */
 +  struct switch_update {
 +    gswitch *stmt;
 +    tree vec;
 +  };
 +
 +  vec<edge> to_remove_edges;
 +  vec<switch_update> to_update_switch_stmts;
 +  gimple *m_stmt;
 +  range_store *store;
 +};
  
  /* The VR_VALUES class holds the current view of range information
     for all the SSA_NAMEs in the IL.