Abstract tracing routines into a class.

Generalize range tracing into a class and integrae it with gimple_ranger.
Remove the old derived trace_ranger class.

	* Makefile.in (OBJS): Add gimple-range-trace.o.
	* gimple-range-cache.h (enable_new_values): Remove unused prototype.
	* gimple-range-fold.cc: Adjust headers.
	* gimple-range-trace.cc: New.
	* gimple-range-trace.h: New.
	* gimple-range.cc (gimple_ranger::gimple_ranger): Enable tracer.
	(gimple_ranger::range_of_expr): Add tracing.
	(gimple_ranger::range_on_entry): Ditto.
	(gimple_ranger::range_on_exit): Ditto.
	(gimple_ranger::range_on_edge): Ditto.
	(gimple_ranger::fold_range_internal): Ditto.
	(gimple_ranger::dump_bb): Do not calculate edge range twice.
	(trace_ranger::*): Remove.
	(enable_ranger): Never create a trace_ranger.
	(debug_seed_ranger): Move to gimple-range-trace.cc.
	(dump_ranger): Ditto.
	(debug_ranger): Ditto.
	* gimple-range.h: Include gimple-range-trace.h.
	(range_on_entry, range_on_exit): No longer virtual.
	(class trace_ranger): Remove.
	(DEBUG_RANGE_CACHE): Move to gimple-range-trace.h.
This commit is contained in:
Andrew MacLeod 2021-07-30 15:15:29 -04:00
parent b48d4e6818
commit e68c8280fa
7 changed files with 377 additions and 326 deletions

View File

@ -1406,6 +1406,7 @@ OBJS = \
gimple-range-edge.o \ gimple-range-edge.o \
gimple-range-fold.o \ gimple-range-fold.o \
gimple-range-gori.o \ gimple-range-gori.o \
gimple-range-trace.o \
gimple-ssa-backprop.o \ gimple-ssa-backprop.o \
gimple-ssa-evrp.o \ gimple-ssa-evrp.o \
gimple-ssa-evrp-analyze.o \ gimple-ssa-evrp-analyze.o \

View File

@ -103,7 +103,6 @@ public:
bool get_non_stale_global_range (irange &r, tree name); bool get_non_stale_global_range (irange &r, tree name);
void set_global_range (tree name, const irange &r); void set_global_range (tree name, const irange &r);
bool enable_new_values (bool state);
non_null_ref m_non_null; non_null_ref m_non_null;
gori_compute m_gori; gori_compute m_gori;

View File

@ -42,9 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "range.h" #include "range.h"
#include "value-query.h" #include "value-query.h"
#include "range-op.h" #include "range-op.h"
#include "gimple-range-fold.h" #include "gimple-range.h"
#include "gimple-range-edge.h"
#include "gimple-range-gori.h"
// Construct a fur_source, and set the m_query field. // Construct a fur_source, and set the m_query field.
fur_source::fur_source (range_query *q) fur_source::fur_source (range_query *q)

206
gcc/gimple-range-trace.cc Normal file
View File

@ -0,0 +1,206 @@
/* Code for GIMPLE range trace and debugging related routines.
Copyright (C) 2019-2021 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/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "gimple-pretty-print.h"
#include "gimple-iterator.h"
#include "tree-cfg.h"
#include "fold-const.h"
#include "tree-cfg.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "gimple-range.h"
// Breakpoint to trap at a specific index. From GDB, this provides a simple
// place to put a breakpoint to stop at a given trace line.
// ie. b range_tracer::breakpoint if index == 45678
void
range_tracer::breakpoint (unsigned index ATTRIBUTE_UNUSED)
{
}
// Construct a range_tracer with component NAME.
range_tracer::range_tracer (const char *name)
{
gcc_checking_assert (strlen(name) < name_len -1);
strcpy (component, name);
indent = 0;
tracing = false;
}
// This routine does the initial line spacing/indenting for a trace.
// If BLANKS is false, then IDX is printed, otherwise spaces.
void
range_tracer::print_prefix (unsigned idx, bool blanks)
{
// Print counter index as well as INDENT spaces.
if (!blanks)
fprintf (dump_file, "%-7u ", idx);
else
fprintf (dump_file, " ");
fprintf (dump_file, "%s ", component);
unsigned x;
for (x = 0; x< indent; x++)
fputc (' ', dump_file);
}
// If dumping, return the next call index and print the prefix for the next
// output line. If not, retrurn 0.
// Counter is static to monotonically increase across the compilation unit.
unsigned
range_tracer::do_header (const char *str)
{
static unsigned trace_count = 0;
unsigned idx = ++trace_count;
print_prefix (idx, false);
fprintf (dump_file, "%s", str);
indent += bump;
breakpoint (idx);
return idx;
}
// Print a line without starting or ending a trace.
void
range_tracer::print (unsigned counter, const char *str)
{
print_prefix (counter, true);
fprintf (dump_file, "%s", str);
}
// End a trace and print the CALLER, NAME, and RESULT and range R,
void
range_tracer::trailer (unsigned counter, const char *caller, bool result,
tree name, const irange &r)
{
gcc_checking_assert (tracing && counter != 0);
indent -= bump;
print_prefix (counter, true);
fputs(result ? "TRUE : " : "FALSE : ", dump_file);
fprintf (dump_file, "(%u) ", counter);
fputs (caller, dump_file);
fputs (" (",dump_file);
if (name)
print_generic_expr (dump_file, name, TDF_SLIM);
fputs (") ",dump_file);
if (result)
{
r.dump (dump_file);
fputc('\n', dump_file);
}
else
fputc('\n', dump_file);
}
// =========================================
// Debugging helpers.
// =========================================
// Query all statements in the IL to precalculate computable ranges in RANGER.
static DEBUG_FUNCTION void
debug_seed_ranger (gimple_ranger &ranger)
{
// Recalculate SCEV to make sure the dump lists everything.
if (scev_initialized_p ())
{
scev_finalize ();
scev_initialize ();
}
basic_block bb;
int_range_max r;
gimple_stmt_iterator gsi;
FOR_EACH_BB_FN (bb, cfun)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
if (is_gimple_debug (stmt))
continue;
ranger.range_of_stmt (r, stmt);
}
}
// Dump all that ranger knows for the current function.
DEBUG_FUNCTION void
dump_ranger (FILE *out)
{
gimple_ranger ranger;
debug_seed_ranger (ranger);
ranger.dump (out);
}
DEBUG_FUNCTION void
debug_ranger ()
{
dump_ranger (stderr);
}
// Dump all that ranger knows on a path of BBs.
//
// Note that the blocks are in reverse order, thus the exit block is
// path[0].
DEBUG_FUNCTION void
dump_ranger (FILE *dump_file, const vec<basic_block> &path)
{
if (path.length () == 0)
{
fprintf (dump_file, "empty\n");
return;
}
gimple_ranger ranger;
debug_seed_ranger (ranger);
unsigned i = path.length ();
do
{
i--;
ranger.dump_bb (dump_file, path[i]);
}
while (i > 0);
}
DEBUG_FUNCTION void
debug_ranger (const vec<basic_block> &path)
{
dump_ranger (stderr, path);
}
#include "gimple-range-tests.cc"

64
gcc/gimple-range-trace.h Normal file
View File

@ -0,0 +1,64 @@
/* Header file for the GIMPLE range tracing/debugging facilties.
Copyright (C) 2021 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_TRACE_H
#define GCC_GIMPLE_RANGE_TRACE_H
// This class manages range tracing for the ranger and gori components.
// Tracing will provide a unique integer index whenever a new trace
// is started. This can be used to identify where a calculation has gone wrong.
class range_tracer
{
public:
range_tracer (const char *name = "");
unsigned header (const char *str);
void trailer (unsigned counter, const char *caller, bool result, tree name,
const irange &r);
void print (unsigned counter, const char *str);
inline void enable_trace () { tracing = true; }
inline void disable_trace () { tracing = false; }
virtual void breakpoint (unsigned index);
private:
unsigned do_header (const char *str);
void print_prefix (unsigned idx, bool blanks);
static const unsigned bump = 2;
unsigned indent;
static const unsigned name_len = 100;
char component[name_len];
bool tracing;
};
// If tracing is enabled, start a new trace header, returning the trace index.
// Otherwise return 0.
inline unsigned
range_tracer::header (const char *str)
{
if (tracing)
return do_header (str);
return 0;
}
#define DEBUG_RANGE_CACHE (dump_file && (param_evrp_mode & EVRP_MODE_DEBUG))
#endif // GCC_GIMPLE_RANGE_TRACE_H

View File

@ -35,46 +35,61 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "gimple-range.h" #include "gimple-range.h"
gimple_ranger::gimple_ranger () gimple_ranger::gimple_ranger () : tracer ("")
{ {
// If the cache has a relation oracle, use it. // If the cache has a relation oracle, use it.
m_oracle = m_cache.oracle (); m_oracle = m_cache.oracle ();
if (dump_file && (param_evrp_mode & EVRP_MODE_TRACE))
tracer.enable_trace ();
} }
bool bool
gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt) gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
{ {
unsigned idx;
if (!gimple_range_ssa_p (expr)) if (!gimple_range_ssa_p (expr))
return get_tree_range (r, expr, stmt); return get_tree_range (r, expr, stmt);
if ((idx = tracer.header ("range_of_expr(")))
{
print_generic_expr (dump_file, expr, TDF_SLIM);
fputs (")", dump_file);
if (stmt)
{
fputs (" at stmt ", dump_file);
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
else
fputs ("\n", dump_file);
}
// If there is no statement, just get the global value. // If there is no statement, just get the global value.
if (!stmt) if (!stmt)
{ {
if (!m_cache.get_global_range (r, expr)) if (!m_cache.get_global_range (r, expr))
r = gimple_range_global (expr); r = gimple_range_global (expr);
return true;
} }
// For a debug stmt, pick the best value currently available, do not // For a debug stmt, pick the best value currently available, do not
// trigger new value calculations. PR 100781. // trigger new value calculations. PR 100781.
if (is_gimple_debug (stmt)) else if (is_gimple_debug (stmt))
{ m_cache.range_of_expr (r, expr, stmt);
m_cache.range_of_expr (r, expr, stmt);
return true;
}
basic_block bb = gimple_bb (stmt);
gimple *def_stmt = SSA_NAME_DEF_STMT (expr);
// If name is defined in this block, try to get an range from S.
if (def_stmt && gimple_bb (def_stmt) == bb)
{
range_of_stmt (r, def_stmt, expr);
m_cache.m_non_null.adjust_range (r, expr, bb, true);
}
else else
// Otherwise OP comes from outside this block, use range on entry. {
range_on_entry (r, bb, expr); basic_block bb = gimple_bb (stmt);
gimple *def_stmt = SSA_NAME_DEF_STMT (expr);
// If name is defined in this block, try to get an range from S.
if (def_stmt && gimple_bb (def_stmt) == bb)
{
range_of_stmt (r, def_stmt, expr);
m_cache.m_non_null.adjust_range (r, expr, bb, true);
}
// Otherwise OP comes from outside this block, use range on entry.
else
range_on_entry (r, bb, expr);
}
if (idx)
tracer.trailer (idx, "range_of_expr", true, expr, r);
return true; return true;
} }
@ -86,6 +101,13 @@ gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
int_range_max entry_range; int_range_max entry_range;
gcc_checking_assert (gimple_range_ssa_p (name)); gcc_checking_assert (gimple_range_ssa_p (name));
unsigned idx;
if ((idx = tracer.header ("range_on_entry (")))
{
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, ") to BB %d\n", bb->index);
}
// Start with any known range // Start with any known range
range_of_stmt (r, SSA_NAME_DEF_STMT (name), name); range_of_stmt (r, SSA_NAME_DEF_STMT (name), name);
@ -94,6 +116,9 @@ gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
r.intersect (entry_range); r.intersect (entry_range);
m_cache.m_non_null.adjust_range (r, name, bb, true); m_cache.m_non_null.adjust_range (r, name, bb, true);
if (idx)
tracer.trailer (idx, "range_on_entry", true, name, r);
} }
// Calculate the range for NAME at the end of block BB and return it in R. // Calculate the range for NAME at the end of block BB and return it in R.
@ -106,6 +131,13 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)); gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
gcc_checking_assert (gimple_range_ssa_p (name)); gcc_checking_assert (gimple_range_ssa_p (name));
unsigned idx;
if ((idx = tracer.header ("range_on_exit (")))
{
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, ") from BB %d\n", bb->index);
}
gimple *s = SSA_NAME_DEF_STMT (name); gimple *s = SSA_NAME_DEF_STMT (name);
basic_block def_bb = gimple_bb (s); basic_block def_bb = gimple_bb (s);
// If this is not the definition block, get the range on the last stmt in // If this is not the definition block, get the range on the last stmt in
@ -119,6 +151,9 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
range_on_entry (r, bb, name); range_on_entry (r, bb, name);
gcc_checking_assert (r.undefined_p () gcc_checking_assert (r.undefined_p ()
|| range_compatible_p (r.type (), TREE_TYPE (name))); || range_compatible_p (r.type (), TREE_TYPE (name)));
if (idx)
tracer.trailer (idx, "range_on_exit", true, name, r);
} }
// Calculate a range for NAME on edge E and return it in R. // Calculate a range for NAME on edge E and return it in R.
@ -133,6 +168,13 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
if (!gimple_range_ssa_p (name)) if (!gimple_range_ssa_p (name))
return range_of_expr (r, name); return range_of_expr (r, name);
unsigned idx;
if ((idx = tracer.header ("range_on_edge (")))
{
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, ") on edge %d->%d\n", e->src->index, e->dest->index);
}
range_on_exit (r, e->src, name); range_on_exit (r, e->src, name);
gcc_checking_assert (r.undefined_p () gcc_checking_assert (r.undefined_p ()
|| range_compatible_p (r.type(), TREE_TYPE (name))); || range_compatible_p (r.type(), TREE_TYPE (name)));
@ -141,6 +183,8 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
if (m_cache.range_on_edge (edge_range, e, name)) if (m_cache.range_on_edge (edge_range, e, name))
r.intersect (edge_range); r.intersect (edge_range);
if (idx)
tracer.trailer (idx, "range_on_edge", true, name, r);
return true; return true;
} }
@ -163,33 +207,50 @@ gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name)
bool bool
gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
{ {
bool res;
r.set_undefined (); r.set_undefined ();
unsigned idx;
if ((idx = tracer.header ("range_of_stmt (")))
{
if (name)
print_generic_expr (dump_file, name, TDF_SLIM);
fputs (") at stmt ", dump_file);
print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
}
if (!name) if (!name)
name = gimple_get_lhs (s); name = gimple_get_lhs (s);
// If no name, simply call the base routine. // If no name, simply call the base routine.
if (!name) if (!name)
return fold_range_internal (r, s, NULL_TREE); res = fold_range_internal (r, s, NULL_TREE);
else if (!gimple_range_ssa_p (name))
if (!gimple_range_ssa_p (name)) res = false;
return false;
// Check if the stmt has already been processed, and is not stale. // Check if the stmt has already been processed, and is not stale.
if (m_cache.get_non_stale_global_range (r, name)) else if (m_cache.get_non_stale_global_range (r, name))
return true; {
if (idx)
tracer.trailer (idx, " cached", true, name, r);
return true;
}
else
{
// Otherwise calculate a new value.
int_range_max tmp;
fold_range_internal (tmp, s, name);
// Otherwise calculate a new value. // Combine the new value with the old value. This is required because
int_range_max tmp; // the way value propagation works, when the IL changes on the fly we
fold_range_internal (tmp, s, name); // can sometimes get different results. See PR 97741.
r.intersect (tmp);
m_cache.set_global_range (name, r);
res = true;
}
// Combine the new value with the old value. This is required because if (idx)
// the way value propagation works, when the IL changes on the fly we tracer.trailer (idx, "range_of_stmt", res, name, r);
// can sometimes get different results. See PR 97741. return res;
r.intersect (tmp);
m_cache.set_global_range (name, r);
return true;
} }
// This routine will export whatever global ranges are known to GCC // This routine will export whatever global ranges are known to GCC
@ -243,7 +304,7 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb)
unsigned x; unsigned x;
edge_iterator ei; edge_iterator ei;
edge e; edge e;
int_range_max range; int_range_max range, tmp_range;
fprintf (f, "\n=========== BB %d ============\n", bb->index); fprintf (f, "\n=========== BB %d ============\n", bb->index);
m_cache.dump_bb (f, bb); m_cache.dump_bb (f, bb);
@ -282,10 +343,9 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb)
// the on entry cache for either end of the edge is // the on entry cache for either end of the edge is
// set. // set.
if ((s && bb == gimple_bb (s)) || if ((s && bb == gimple_bb (s)) ||
m_cache.block_range (range, bb, name, false) || m_cache.block_range (tmp_range, bb, name, false) ||
m_cache.block_range (range, e->dest, name, false)) m_cache.block_range (tmp_range, e->dest, name, false))
{ {
m_cache.range_on_edge (range, e, name);
if (!range.varying_p ()) if (!range.varying_p ())
{ {
fprintf (f, "%d->%d ", e->src->index, fprintf (f, "%d->%d ", e->src->index,
@ -321,182 +381,12 @@ gimple_ranger::dump (FILE *f)
m_cache.dump (f); m_cache.dump (f);
} }
// trace_ranger implementation.
trace_ranger::trace_ranger ()
{
indent = 0;
trace_count = 0;
}
// If dumping, return true and print the prefix for the next output line.
bool
trace_ranger::dumping (unsigned counter, bool trailing)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
// Print counter index as well as INDENT spaces.
if (!trailing)
fprintf (dump_file, " %-7u ", counter);
else
fprintf (dump_file, " ");
unsigned x;
for (x = 0; x< indent; x++)
fputc (' ', dump_file);
return true;
}
return false;
}
// After calling a routine, if dumping, print the CALLER, NAME, and RESULT,
// returning RESULT.
bool
trace_ranger::trailer (unsigned counter, const char *caller, bool result,
tree name, const irange &r)
{
if (dumping (counter, true))
{
indent -= bump;
fputs(result ? "TRUE : " : "FALSE : ", dump_file);
fprintf (dump_file, "(%u) ", counter);
fputs (caller, dump_file);
fputs (" (",dump_file);
if (name)
print_generic_expr (dump_file, name, TDF_SLIM);
fputs (") ",dump_file);
if (result)
{
r.dump (dump_file);
fputc('\n', dump_file);
}
else
fputc('\n', dump_file);
// Marks the end of a request.
if (indent == 0)
fputc('\n', dump_file);
}
return result;
}
// Tracing version of range_on_edge. Call it with printing wrappers.
bool
trace_ranger::range_on_edge (irange &r, edge e, tree name)
{
unsigned idx = ++trace_count;
if (dumping (idx))
{
fprintf (dump_file, "range_on_edge (");
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, ") on edge %d->%d\n", e->src->index, e->dest->index);
indent += bump;
}
bool res = gimple_ranger::range_on_edge (r, e, name);
trailer (idx, "range_on_edge", true, name, r);
return res;
}
// Tracing version of range_on_entry. Call it with printing wrappers.
void
trace_ranger::range_on_entry (irange &r, basic_block bb, tree name)
{
unsigned idx = ++trace_count;
if (dumping (idx))
{
fprintf (dump_file, "range_on_entry (");
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, ") to BB %d\n", bb->index);
indent += bump;
}
gimple_ranger::range_on_entry (r, bb, name);
trailer (idx, "range_on_entry", true, name, r);
}
// Tracing version of range_on_exit. Call it with printing wrappers.
void
trace_ranger::range_on_exit (irange &r, basic_block bb, tree name)
{
unsigned idx = ++trace_count;
if (dumping (idx))
{
fprintf (dump_file, "range_on_exit (");
print_generic_expr (dump_file, name, TDF_SLIM);
fprintf (dump_file, ") from BB %d\n", bb->index);
indent += bump;
}
gimple_ranger::range_on_exit (r, bb, name);
trailer (idx, "range_on_exit", true, name, r);
}
// Tracing version of range_of_stmt. Call it with printing wrappers.
bool
trace_ranger::range_of_stmt (irange &r, gimple *s, tree name)
{
bool res;
unsigned idx = ++trace_count;
if (dumping (idx))
{
fprintf (dump_file, "range_of_stmt (");
if (name)
print_generic_expr (dump_file, name, TDF_SLIM);
fputs (") at stmt ", dump_file);
print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
indent += bump;
}
res = gimple_ranger::range_of_stmt (r, s, name);
return trailer (idx, "range_of_stmt", res, name, r);
}
// Tracing version of range_of_expr. Call it with printing wrappers.
bool
trace_ranger::range_of_expr (irange &r, tree name, gimple *s)
{
bool res;
unsigned idx = ++trace_count;
if (dumping (idx))
{
fprintf (dump_file, "range_of_expr(");
print_generic_expr (dump_file, name, TDF_SLIM);
fputs (")", dump_file);
if (s)
{
fputs (" at stmt ", dump_file);
print_gimple_stmt (dump_file, s, 0, TDF_SLIM);
}
else
fputs ("\n", dump_file);
indent += bump;
}
res = gimple_ranger::range_of_expr (r, name, s);
return trailer (idx, "range_of_expr", res, name, r);
}
gimple_ranger * gimple_ranger *
enable_ranger (struct function *fun) enable_ranger (struct function *fun)
{ {
gimple_ranger *r; gimple_ranger *r;
if (param_evrp_mode & EVRP_MODE_TRACE) r = new gimple_ranger;
r = new trace_ranger;
else
r = new gimple_ranger;
fun->x_range_query = r; fun->x_range_query = r;
return r; return r;
@ -509,84 +399,3 @@ disable_ranger (struct function *fun)
fun->x_range_query = &global_ranges; fun->x_range_query = &global_ranges;
} }
// =========================================
// Debugging helpers.
// =========================================
// Query all statements in the IL to precalculate computable ranges in RANGER.
static DEBUG_FUNCTION void
debug_seed_ranger (gimple_ranger &ranger)
{
// Recalculate SCEV to make sure the dump lists everything.
if (scev_initialized_p ())
{
scev_finalize ();
scev_initialize ();
}
basic_block bb;
int_range_max r;
gimple_stmt_iterator gsi;
FOR_EACH_BB_FN (bb, cfun)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
if (is_gimple_debug (stmt))
continue;
ranger.range_of_stmt (r, stmt);
}
}
// Dump all that ranger knows for the current function.
DEBUG_FUNCTION void
dump_ranger (FILE *out)
{
gimple_ranger ranger;
debug_seed_ranger (ranger);
ranger.dump (out);
}
DEBUG_FUNCTION void
debug_ranger ()
{
dump_ranger (stderr);
}
// Dump all that ranger knows on a path of BBs.
//
// Note that the blocks are in reverse order, thus the exit block is
// path[0].
DEBUG_FUNCTION void
dump_ranger (FILE *dump_file, const vec<basic_block> &path)
{
if (path.length () == 0)
{
fprintf (dump_file, "empty\n");
return;
}
gimple_ranger ranger;
debug_seed_ranger (ranger);
unsigned i = path.length ();
do
{
i--;
ranger.dump_bb (dump_file, path[i]);
}
while (i > 0);
}
DEBUG_FUNCTION void
debug_ranger (const vec<basic_block> &path)
{
dump_ranger (stderr, path);
}
#include "gimple-range-tests.cc"

View File

@ -22,10 +22,10 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_GIMPLE_RANGE_H #ifndef GCC_GIMPLE_RANGE_H
#define GCC_GIMPLE_RANGE_H #define GCC_GIMPLE_RANGE_H
#include "range.h" #include "range.h"
#include "value-query.h" #include "value-query.h"
#include "range-op.h" #include "range-op.h"
#include "gimple-range-trace.h"
#include "gimple-range-edge.h" #include "gimple-range-edge.h"
#include "gimple-range-fold.h" #include "gimple-range-fold.h"
#include "gimple-range-gori.h" #include "gimple-range-gori.h"
@ -43,7 +43,6 @@ along with GCC; see the file COPYING3. If not see
// type is not supported, then false is returned. Non-statement // type is not supported, then false is returned. Non-statement
// related methods return whatever the current global value is. // related methods return whatever the current global value is.
class gimple_ranger : public range_query class gimple_ranger : public range_query
{ {
public: public:
@ -51,8 +50,8 @@ public:
virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL) OVERRIDE; virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL) OVERRIDE;
virtual bool range_of_expr (irange &r, tree name, gimple * = NULL) OVERRIDE; virtual bool range_of_expr (irange &r, tree name, gimple * = NULL) OVERRIDE;
virtual bool range_on_edge (irange &r, edge e, tree name) OVERRIDE; virtual bool range_on_edge (irange &r, edge e, tree name) OVERRIDE;
virtual void range_on_entry (irange &r, basic_block bb, tree name); void range_on_entry (irange &r, basic_block bb, tree name);
virtual void range_on_exit (irange &r, basic_block bb, tree name); void range_on_exit (irange &r, basic_block bb, tree name);
void export_global_ranges (); void export_global_ranges ();
inline gori_compute &gori () { return m_cache.m_gori; } inline gori_compute &gori () { return m_cache.m_gori; }
virtual void dump (FILE *f) OVERRIDE; virtual void dump (FILE *f) OVERRIDE;
@ -60,34 +59,9 @@ public:
protected: protected:
bool fold_range_internal (irange &r, gimple *s, tree name); bool fold_range_internal (irange &r, gimple *s, tree name);
ranger_cache m_cache; ranger_cache m_cache;
range_tracer tracer;
}; };
// This class overloads the ranger routines to provide tracing facilties
// Entry and exit values to each of the APIs is placed in the dumpfile.
class trace_ranger : public gimple_ranger
{
public:
trace_ranger ();
virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
virtual bool range_of_expr (irange &r, tree name, gimple *s = NULL);
virtual bool range_on_edge (irange &r, edge e, tree name);
virtual void range_on_entry (irange &r, basic_block bb, tree name);
virtual void range_on_exit (irange &r, basic_block bb, tree name);
private:
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);
};
// Flag to enable debugging the various internal Caches.
#define DEBUG_RANGE_CACHE (dump_file && (param_evrp_mode & EVRP_MODE_DEBUG))
extern gimple_ranger *enable_ranger (struct function *); extern gimple_ranger *enable_ranger (struct function *);
extern void disable_ranger (struct function *); extern void disable_ranger (struct function *);