diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2020-10-06 12:53:09 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2020-10-06 13:03:13 -0400 |
commit | fcae5121154d1c3382b056bcc2c563cedac28e74 (patch) | |
tree | 7f1a992410f82963ee9df115586cf45e39a53583 /gcc/gimple-ssa-evrp.c | |
parent | 90e88fd376bb9ad6223a1f5ccd803d1bd9539b05 (diff) | |
download | gcc-fcae5121154d1c3382b056bcc2c563cedac28e74.zip gcc-fcae5121154d1c3382b056bcc2c563cedac28e74.tar.gz gcc-fcae5121154d1c3382b056bcc2c563cedac28e74.tar.bz2 |
Hybrid EVRP and testcases
Provide a hybrid EVRP pass which uses legacy EVRP and adds additonal
enhancements from the new ranger infrastructure.
A New option is also provided, -fevrp-mode=
And adjust testcases
gcc/ChangeLog:
2020-10-06 Andrew MacLeod <amacleod@redhat.com>
* flag-types.h (enum evrp_mode): New enumerated type EVRP_MODE_*.
* common.opt (fevrp-mode): New undocumented flag.
* gimple-ssa-evrp.c: Include gimple-range.h
(class rvrp_folder): EVRP folding using ranger exclusively.
(rvrp_folder::rvrp_folder): New.
(rvrp_folder::~rvrp_folder): New.
(rvrp_folder::value_of_expr): New. Use rangers value_of_expr.
(rvrp_folder::value_on_edge): New. Use rangers value_on_edge.
(rvrp_folder::value_of_Stmt): New. Use rangers value_of_stmt.
(rvrp_folder::fold_stmt): New. Call the simplifier.
(class hybrid_folder): EVRP folding using both engines.
(hybrid_folder::hybrid_folder): New.
(hybrid_folder::~hybrid_folder): New.
(hybrid_folder::fold_stmt): New. Simplify with one engne, then the
other.
(hybrid_folder::value_of_expr): New. Use both value routines.
(hybrid_folder::value_on_edge): New. Use both value routines.
(hybrid_folder::value_of_stmt): New. Use both value routines.
(hybrid_folder::choose_value): New. Choose between range_analzyer and
rangers values.
(execute_early_vrp): Choose a folder based on flag_evrp_mode.
* vr-values.c (simplify_using_ranges::fold_cond): Try range_of_stmt
first to see if it returns a value.
(simplify_using_ranges::simplify_switch_using_ranges): Return true if
any changes were made to the switch.
gcc/testsuite/ChangeLog:
2020-10-06 Andrew MacLeod <amacleod@redhat.com>
* gcc.dg/pr81192.c: Disable EVRP pass.
* gcc.dg/tree-ssa/pr77445-2.c: Ditto.
* gcc.dg/tree-ssa/ssa-dom-thread-6.c: Adjust.
* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Ditto.
Diffstat (limited to 'gcc/gimple-ssa-evrp.c')
-rw-r--r-- | gcc/gimple-ssa-evrp.c | 221 |
1 files changed, 218 insertions, 3 deletions
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c index 60bf82a..6be32d7a 100644 --- a/gcc/gimple-ssa-evrp.c +++ b/gcc/gimple-ssa-evrp.c @@ -41,6 +41,10 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfgcleanup.h" #include "vr-values.h" #include "gimple-ssa-evrp-analyze.h" +#include "gimple-range.h" + +// This is the classic EVRP folder which uses a dominator walk and pushes +// ranges into the next block if it is a single predecessor block. class evrp_folder : public substitute_and_fold_engine { @@ -98,12 +102,195 @@ public: m_range_analyzer.set_defs_to_varying (stmt); } -private: +protected: DISABLE_COPY_AND_ASSIGN (evrp_folder); evrp_range_analyzer m_range_analyzer; simplify_using_ranges simplifier; }; +// This is a ranger based folder which continues to use the dominator +// walk to access the substitute and fold machinery. Ranges are calculated +// on demand. + +class rvrp_folder : public substitute_and_fold_engine +{ +public: + + rvrp_folder () : substitute_and_fold_engine (), m_simplifier () + { + if (flag_evrp_mode & EVRP_MODE_TRACE) + m_ranger = new trace_ranger (); + else + m_ranger = new gimple_ranger (); + m_simplifier.set_range_query (m_ranger); + } + + ~rvrp_folder () + { + if (dump_file && (dump_flags & TDF_DETAILS)) + m_ranger->dump (dump_file); + delete m_ranger; + } + + tree value_of_expr (tree name, gimple *s = NULL) OVERRIDE + { + return m_ranger->value_of_expr (name, s); + } + + tree value_on_edge (edge e, tree name) OVERRIDE + { + return m_ranger->value_on_edge (e, name); + } + + tree value_of_stmt (gimple *s, tree name = NULL) OVERRIDE + { + return m_ranger->value_of_stmt (s, name); + } + + bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE + { + return m_simplifier.simplify (gsi); + } + +private: + DISABLE_COPY_AND_ASSIGN (rvrp_folder); + gimple_ranger *m_ranger; + simplify_using_ranges m_simplifier; +}; + +// In a hybrid folder, start with an EVRP folder, and add the required +// fold_stmt bits to either try the ranger first or second. +// +// The 3 value_* routines will always query both EVRP and the ranger for +// a result, and ensure they return the same value. If either returns a value +// when the other doesn't, it is flagged in the listing, and the discoverd +// value is returned. +// +// The simplifier is unable to process 2 different sources, thus we try to +// use one engine, and if it fails to simplify, try using the other engine. +// It is reported when the first attempt fails and the second succeeds. + +class hybrid_folder : public evrp_folder +{ +public: + hybrid_folder (bool evrp_first) + { + if (flag_evrp_mode & EVRP_MODE_TRACE) + m_ranger = new trace_ranger (); + else + m_ranger = new gimple_ranger (); + + if (evrp_first) + { + first = &m_range_analyzer; + second = m_ranger; + } + else + { + first = m_ranger; + second = &m_range_analyzer; + } + } + + ~hybrid_folder () + { + if (dump_file && (dump_flags & TDF_DETAILS)) + m_ranger->dump (dump_file); + delete m_ranger; + } + + bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE + { + simplifier.set_range_query (first); + if (simplifier.simplify (gsi)) + return true; + + simplifier.set_range_query (second); + if (simplifier.simplify (gsi)) + { + if (dump_file) + fprintf (dump_file, "EVRP:hybrid: Second query simplifed stmt\n"); + return true; + } + return false; + } + + tree value_of_expr (tree name, gimple *) OVERRIDE; + tree value_on_edge (edge, tree name) OVERRIDE; + tree value_of_stmt (gimple *, tree name) OVERRIDE; + +private: + DISABLE_COPY_AND_ASSIGN (hybrid_folder); + gimple_ranger *m_ranger; + range_query *first; + range_query *second; + tree choose_value (tree evrp_val, tree ranger_val); +}; + + +tree +hybrid_folder::value_of_expr (tree op, gimple *stmt) +{ + tree evrp_ret = evrp_folder::value_of_expr (op, stmt); + tree ranger_ret = m_ranger->value_of_expr (op, stmt); + return choose_value (evrp_ret, ranger_ret); +} + +tree +hybrid_folder::value_on_edge (edge e, tree op) +{ + tree evrp_ret = evrp_folder::value_on_edge (e, op); + tree ranger_ret = m_ranger->value_on_edge (e, op); + return choose_value (evrp_ret, ranger_ret); +} + +tree +hybrid_folder::value_of_stmt (gimple *stmt, tree op) +{ + tree evrp_ret = evrp_folder::value_of_stmt (stmt, op); + tree ranger_ret = m_ranger->value_of_stmt (stmt, op); + return choose_value (evrp_ret, ranger_ret); +} + +// Given trees returned by EVRP and Ranger, choose/report the value to use +// by the folder. + +tree +hybrid_folder::choose_value (tree evrp_val, tree ranger_val) +{ + if (!ranger_val) + { + // If neither returned a value, return NULL_TREE. + if (!evrp_val) + return NULL_TREE; + + // Otherwise EVRP found something. + if (dump_file) + { + fprintf (dump_file, "EVRP:hybrid: EVRP found singleton "); + print_generic_expr (dump_file, evrp_val); + fprintf (dump_file, "\n"); + } + return evrp_val; + } + + // Otherwise ranger found a value, if they match we're good. + if (evrp_val && !compare_values (evrp_val, ranger_val)) + return evrp_val; + + // We should never get different singletons. + gcc_checking_assert (!evrp_val); + + // Now ranger has found a value, but EVRP did not. + if (dump_file) + { + fprintf (dump_file, "EVRP:hybrid: RVRP found singleton "); + print_generic_expr (dump_file, ranger_val); + fprintf (dump_file, "\n"); + } + return ranger_val; +} + /* Main entry point for the early vrp pass which is a simplified non-iterative version of vrp where basic blocks are visited in dominance order. Value ranges discovered in early vrp will also be used by ipa-vrp. */ @@ -120,8 +307,36 @@ execute_early_vrp () scev_initialize (); calculate_dominance_info (CDI_DOMINATORS); - evrp_folder folder; - folder.substitute_and_fold (); + // only the last 2 bits matter for choosing the folder. + switch (flag_evrp_mode & EVRP_MODE_RVRP_FIRST) + { + case EVRP_MODE_EVRP_ONLY: + { + evrp_folder folder; + folder.substitute_and_fold (); + break; + } + case EVRP_MODE_RVRP_ONLY: + { + rvrp_folder folder; + folder.substitute_and_fold (); + break; + } + case EVRP_MODE_EVRP_FIRST: + { + hybrid_folder folder (true); + folder.substitute_and_fold (); + break; + } + case EVRP_MODE_RVRP_FIRST: + { + hybrid_folder folder (false); + folder.substitute_and_fold (); + break; + } + default: + gcc_unreachable (); + } scev_finalize (); loop_optimizer_finalize (); |