public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/aldyh/heads/ranger-staging)] Audit/comment/cleamup gimple-range-edge
@ 2020-09-26 3:38 Andrew Macleod
0 siblings, 0 replies; only message in thread
From: Andrew Macleod @ 2020-09-26 3:38 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:205e38144973c86bc888cd7dd2321b187dbe763f
commit 205e38144973c86bc888cd7dd2321b187dbe763f
Author: Andrew MacLeod <amacleod@redhat.com>
Date: Fri Sep 25 23:37:38 2020 -0400
Audit/comment/cleamup gimple-range-edge
Diff:
---
gcc/gimple-range-edge.cc | 81 +++++++++++++++++++++++++-----------------------
gcc/gimple-range-edge.h | 15 ++++++++-
2 files changed, 57 insertions(+), 39 deletions(-)
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index 4a4878722e8..b7c0603e136 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -32,6 +32,25 @@ along with GCC; see the file COPYING3. If not see
#include "tree-cfg.h"
#include "gimple-range.h"
+// If there is a range control statment at the end of block BB, return it.
+// Otherwise return NULL.
+
+gimple *
+gimple_outgoing_range_stmt_p (basic_block bb)
+{
+ gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
+ if (!gsi_end_p (gsi))
+ {
+ gimple *s = gsi_stmt (gsi);
+ if (is_a<gcond *> (s) && gimple_range_handler (s))
+ return gsi_stmt (gsi);
+ gswitch *sw = dyn_cast<gswitch *> (s);
+ if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
+ return gsi_stmt (gsi);
+ }
+ return NULL;
+}
+
outgoing_range::outgoing_range ()
{
@@ -44,6 +63,10 @@ outgoing_range::~outgoing_range ()
delete m_edge_table;
}
+
+// Get a range for a switch edge E from statement S and return it in R.
+// Use a cached value if it exists, or calculate it if not.
+
bool
outgoing_range::get_edge_range (irange &r, gimple *s, edge e)
{
@@ -53,7 +76,7 @@ outgoing_range::get_edge_range (irange &r, gimple *s, edge e)
// ADA currently has cases where the index is 64 bits and the case
// arguments are 32 bit, causing a trap when we create a case_range.
// Until this is resolved (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87798)
- // punt on these switches.
+ // punt on switches where the labels dont match the argument.
if (gimple_switch_num_labels (sw) > 1 &&
TYPE_PRECISION (TREE_TYPE (CASE_LOW (gimple_switch_label (sw, 1)))) !=
TYPE_PRECISION (TREE_TYPE (gimple_switch_index (sw))))
@@ -73,6 +96,8 @@ outgoing_range::get_edge_range (irange &r, gimple *s, edge e)
return true;
}
+
+// calculate all switch edges from SW and cache them in the hash table.
void
outgoing_range::calc_switch_ranges (gswitch *sw)
{
@@ -83,11 +108,14 @@ outgoing_range::calc_switch_ranges (gswitch *sw)
edge default_edge = gimple_switch_default_edge (cfun, sw);
irange *&default_slot = m_edge_table->get_or_insert (default_edge, &existed);
+
// This should be the first call into this switch.
// For the default range case, start with varying and intersect each other
// case from it.
+
gcc_assert (!existed);
- // Allocatea int_range_max for default case.
+
+ // Allocate an int_range_max for default case.
default_slot = range_pool.allocate (255);
default_slot->set_varying (type);
@@ -97,14 +125,14 @@ outgoing_range::calc_switch_ranges (gswitch *sw)
// If this edge is the same as the default edge, do nothing else.
if (e == default_edge)
- continue;
+ continue;
tree low = CASE_LOW (gimple_switch_label (sw, x));
tree high = CASE_HIGH (gimple_switch_label (sw, x));
if (!high)
high = low;
- // intersect the case from the default case.
+ // Remove the case range from the default case.
int_range_max def_range (low, high);
range_cast (def_range, type);
def_range.invert ();
@@ -115,42 +143,22 @@ outgoing_range::calc_switch_ranges (gswitch *sw)
range_cast (case_range, type);
irange *&slot = m_edge_table->get_or_insert (e, &existed);
if (existed)
- case_range.union_ (*slot);
- // If there was an existing range, we lose the memory, but it'll get
- // reclaimed when the obstack is freed. This seems less intrusive than
- // allocating max ranges for each case.
+ {
+ case_range.union_ (*slot);
+ if (slot->fits_p (case_range))
+ {
+ *slot = case_range;
+ continue;
+ }
+ }
+ // If there was an existing range and it doesn't fit, we lose the memory.
+ // it'll get reclaimed when the obstack is freed. This seems less
+ // intrusive than allocating max ranges for each case.
slot = range_pool.allocate (case_range);
}
}
-// If there is a range control statment at the end of block BB, return it.
-
-static inline gimple_stmt_iterator
-gsi_outgoing_range_stmt (basic_block bb)
-{
- gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
- if (!gsi_end_p (gsi))
- {
- gimple *s = gsi_stmt (gsi);
- if (is_a<gcond *> (s) && gimple_range_handler (s))
- return gsi;
- gswitch *sw = dyn_cast<gswitch *> (s);
- if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
- return gsi;
- }
- return gsi_none ();
-}
-
-// If there is a range control statment at the end of block BB, return it.
-gimple *
-gimple_outgoing_range_stmt_p (basic_block bb)
-{
- // This will return NULL if there is not a branch statement.
- gimple *stmt = gsi_stmt (gsi_outgoing_range_stmt (bb));
- return stmt;
-}
-
// Calculate the range forced on on edge E by control flow, return it
// in R. Return the statment which defines the range, otherwise
// return NULL
@@ -186,6 +194,3 @@ outgoing_range::edge_range_p (irange &r, edge e)
return NULL;
}
-
-
-
diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
index 82a1aec49a7..6e161306c06 100644
--- a/gcc/gimple-range-edge.h
+++ b/gcc/gimple-range-edge.h
@@ -22,6 +22,19 @@ along with GCC; see the file COPYING3. If not see
#ifndef GIMPLE_RANGE_EDGE_H
#define GIMPLE_RANGE_EDGE_H
+// This class is used to query ranges on constant edges in GIMPLE.
+//
+// For a COND_EXPR, the TRUE edge will return [1,1] and the false edge a [0,0].
+//
+// For SWITCH_EXPR it is awkward to calculate ranges. When a request
+// is made, the entire switch is evalauted and the results cached.
+// Any future requests to that switch will use the cached value, providing
+// dramatic decrease in computation time.
+//
+// The API is simple. just ask for the range on the edge.
+// The return value is NULL for no range, or the branch statement which the
+// edge gets the range from, along with the range.
+
class outgoing_range
{
public:
@@ -36,7 +49,7 @@ private:
irange_pool range_pool;
};
-
+// If there is a range control statment at the end of block BB, return it.
gimple *gimple_outgoing_range_stmt_p (basic_block bb);
#endif // GIMPLE_RANGE_EDGE_H
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-09-26 3:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-26 3:38 [gcc(refs/users/aldyh/heads/ranger-staging)] Audit/comment/cleamup gimple-range-edge Andrew Macleod
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).