diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2020-06-26 10:18:52 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2020-06-26 10:18:52 -0400 |
commit | f69ab586f69b0a3a73af12bdd71e18f81bc5ba4a (patch) | |
tree | 7f61f7f18dd5b7197cfbd15cff91312a2369bec1 /gcc/gimple-range-vrp.cc | |
parent | f67c1bddaf9f855a7d03d8c078fd734de96f7ade (diff) | |
download | gcc-devel/ranger.zip gcc-devel/ranger.tar.gz gcc-devel/ranger.tar.bz2 |
ranger restructuringdevel/ranger
Diffstat (limited to 'gcc/gimple-range-vrp.cc')
-rw-r--r-- | gcc/gimple-range-vrp.cc | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/gcc/gimple-range-vrp.cc b/gcc/gimple-range-vrp.cc new file mode 100644 index 0000000..4956813 --- /dev/null +++ b/gcc/gimple-range-vrp.cc @@ -0,0 +1,190 @@ +/* Value range propagation pass using the ranger. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by 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/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "tree.h" +#include "gimple.h" +#include "tree-pass.h" +#include "ssa.h" +#include "gimple-pretty-print.h" +#include "cfganal.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-iterator.h" +#include "tree-cfg.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop.h" +#include "cfgloop.h" +#include "tree-scalar-evolution.h" +#include "tree-ssa-propagate.h" +#include "alloc-pool.h" +#include "domwalk.h" +#include "tree-cfgcleanup.h" +#include "vr-values.h" +#include "gimple-ssa-evrp-analyze.h" +#include "gimple-range.h" + +class rvrp_ranger : public range_store +{ +public: + rvrp_ranger () : range_pool ("rvrp value range pool") { } + ~rvrp_ranger () + { + range_pool.release (); + } + // This is the range getter for the simplifier, but is really only + // used for the conditional folding which still uses equivalences. + virtual const value_range_equiv *get_value_range (const_tree expr, + gimple *stmt) OVERRIDE + { + widest_irange r; + if (ranger.range_of_expr (r, const_cast<tree> (expr), stmt)) + return new (range_pool.allocate ()) value_range_equiv (r); + return new (range_pool.allocate ()) value_range_equiv (TREE_TYPE (expr)); + } + virtual bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL) + { + return ranger.range_of_expr (r, expr, stmt); + } + gimple_ranger ranger; +private: + object_allocator<value_range_equiv> range_pool; +}; + +class rvrp_folder : public substitute_and_fold_engine +{ +public: + rvrp_folder (bool allow_il_changes) + : simplifier (&ranger), allow_il_changes (allow_il_changes) { } + + tree get_value (tree op, gimple *stmt) OVERRIDE + { + widest_irange r; + tree singleton; + if (ranger.ranger.range_of_expr (r, op, stmt) && r.singleton_p (&singleton) + && allow_il_changes) + return singleton; + return NULL; + } + + bool fold_cond (gcond *cond) + { + if (!irange::supports_type_p (gimple_expr_type (cond))) + return false; + + widest_irange r; + if (ranger.ranger.range_of_stmt (r, cond) && r.singleton_p ()) + { + if (allow_il_changes) + { + if (r.zero_p ()) + gimple_cond_make_false (cond); + else + gimple_cond_make_true (cond); + return true; + } + } + return false; + } + + bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE + { + gcond *cond = dyn_cast <gcond *> (gsi_stmt (*gsi)); + if (cond && fold_cond (cond)) + return true; + + if (allow_il_changes) + return simplifier.simplify (gsi); + return false; + } + +private: + rvrp_ranger ranger; + simplify_using_ranges simplifier; + bool allow_il_changes; +}; + +static unsigned int +execute_ranger_vrp (bool allow_il_changes) +{ + loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); + rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); + scev_initialize (); + calculate_dominance_info (CDI_DOMINATORS); + + rvrp_folder folder (allow_il_changes); + folder.substitute_and_fold (); + + scev_finalize (); + loop_optimizer_finalize (); + return 0; +} + +namespace { + +const pass_data pass_data_ranger_vrp = +{ + GIMPLE_PASS, // type + "rvrp", // name + OPTGROUP_NONE, // optinfo_flags + TV_TREE_EARLY_VRP, // tv_id + PROP_ssa, // properties_required + 0, // properties_provided + 0, // properties_destroyed + 0, // todo_flags_start + ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ), +}; + +class pass_ranger_vrp : public gimple_opt_pass +{ +public: + pass_ranger_vrp (gcc::context *ctxt) + : gimple_opt_pass (pass_data_ranger_vrp, ctxt) + { + static int pass = 1; + rvrp_pass_num = pass; + pass++; + } + opt_pass *clone () { return new pass_ranger_vrp (m_ctxt); } + virtual bool gate (function *) + { return flag_tree_vrp != 0; } + virtual unsigned int execute (function *) + { + if (rvrp_pass_num == 1) + allow_il_changes = flag_rvrp1_changes; + if (rvrp_pass_num == 2) + allow_il_changes = flag_rvrp2_changes; + return execute_ranger_vrp (allow_il_changes); + } +private: + bool allow_il_changes; + int rvrp_pass_num; +}; + +} // anon namespace + +gimple_opt_pass * +make_pass_ranger_vrp (gcc::context *ctxt) +{ + return new pass_ranger_vrp (ctxt); +} |