aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-range-gori.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimple-range-gori.cc')
-rw-r--r--gcc/gimple-range-gori.cc572
1 files changed, 219 insertions, 353 deletions
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 8d90ae7..2a59f0a 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -29,9 +29,74 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "ssa.h"
#include "gimple-pretty-print.h"
-#include "gimple-range-stmt.h"
-#include "gimple-range-gori.h"
-#include "fold-const.h"
+#include "gimple-range.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);
+};
+
+
// Construct a range_def_chain
@@ -233,6 +298,54 @@ range_def_chain::get_def_chain (tree name)
return m_def_chain[v];
}
+// -------------------------------------------------------------------
+
+/* 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);
+ bitmap exports (basic_block bb);
+};
+
// Initialize a gori-map structure.
@@ -312,8 +425,10 @@ gori_map::maybe_add_gori (tree name, basic_block bb)
{
if (name)
{
+ gimple *s = SSA_NAME_DEF_STMT (name);
bitmap r = get_def_chain (name);
- if (r)
+ // Check if there is a def chain, and it is in this block.
+ if (r && gimple_bb (s) == bb)
{
bitmap_copy (m_outgoing[bb->index], r);
tree im = terminal_name (name);
@@ -324,7 +439,7 @@ gori_map::maybe_add_gori (tree name, basic_block bb)
{
// If there is no def chain, and name originates outside
// this block then this name is also an import.
- if (gimple_bb (SSA_NAME_DEF_STMT (name)) != bb)
+ if (!s || gimple_bb (s) != bb)
bitmap_set_bit (m_incoming[bb->index], SSA_NAME_VERSION (name));
}
// Def chain doesn't include itself, and even if there isn't a
@@ -479,90 +594,18 @@ debug (gori_map &g)
g.dump (stderr);
}
-const value_range_equiv *
-range_store::get_value_range (const_tree expr ATTRIBUTE_UNUSED,
- gimple *stmt ATTRIBUTE_UNUSED)
-{
- gcc_unreachable ();
- return NULL;
-}
+// -------------------------------------------------------------------
-// Return the legacy global known value for NAME in R.
void
-gori_compute::range_of_ssa_name (irange &r, tree name,
- gimple *stmt ATTRIBUTE_UNUSED)
+gori_compute::expr_range_in_bb (irange &r, tree expr, basic_block bb)
{
- r = gimple_range_global (name);
-}
-
-
-// This function returns a range for a tree node. If optional
-// statement STMT is present, then the range would be if it were to
-// appear as a use on STMT. Return false if ranges are not supported for
-// the type of EXPR.
-
-bool
-gori_compute::range_of_expr (irange &r, tree expr, gimple *stmt)
-{
- tree type;
- if (TYPE_P (expr))
- type = expr;
+ if (gimple_range_ssa_p (expr))
+ ssa_range_in_bb (r, expr, bb);
else
- type = TREE_TYPE (expr);
-
- // Return false if the type isn't suported.
- if (!irange::supports_type_p (type))
- return false;
-
- switch (TREE_CODE (expr))
- {
- case INTEGER_CST:
- r.set (expr, expr);
- return true;
-
- case SSA_NAME:
- range_of_ssa_name (r, expr, stmt);
- return true;
-
- case ADDR_EXPR:
- {
- // Handle &var which can show up in phi arguments.
- bool ov;
- if (tree_single_nonzero_warnv_p (expr, &ov))
- {
- r = range_nonzero (type);
- return true;
- }
- break;
- }
-
- default:
- break;
- }
- r.set_varying (type);
- return true;
-}
-
-// Same as range_of_expr, but no statement option, and perform
-// substitution of NAME with RANGE_OF_NAME if expr happens to match
-// it. Since there is no statement, this enforces that ranges for
-// ssa-names invoked won't go off and calculate a range in derived
-// bases.
-
-void
-gori_compute::get_tree_range (irange &r, tree expr, tree name,
- const irange *range_of_name)
-{
- if (expr == name && range_of_name)
- {
- r = *range_of_name;
- return;
- }
- gcc_assert (range_of_expr (r, expr));
+ get_tree_range (r, expr);
}
-
// Calculate the range for NAME if the lhs of statement S has the
// range LHS. If present, NAME_RANGE is any known range for NAME
// coming into this stmt. Return the result in R. Return false if no
@@ -570,9 +613,7 @@ gori_compute::get_tree_range (irange &r, tree expr, tree name,
bool
gori_compute::compute_name_range_op (irange &r, gimple *stmt,
- const irange &lhs,
- tree name,
- const irange *name_range)
+ const irange &lhs, tree name)
{
widest_irange op1_range, op2_range;
@@ -582,37 +623,31 @@ gori_compute::compute_name_range_op (irange &r, gimple *stmt,
// Operand 1 is the name being looked for, evaluate it.
if (op1 == name)
{
+ expr_range_in_bb (op1_range, op1, gimple_bb (stmt));
if (!op2)
{
// The second parameter to a unary operation is the range
// for the type of operand1, but if it can be reduced
// further, the results will be better. Start with what we
- // know of the range of OP1.
- get_tree_range (op1_range, op1, name, name_range);
- return gimple_range_calc_op1 (stmt, r, lhs, op1_range);
+ // know of the range of OP1 instead of the full type.
+ return gimple_range_calc_op1 (r, stmt, lhs, op1_range);
}
// If we need the second operand, get a value and evaluate.
- get_tree_range (op2_range, op2, name, name_range);
- if (gimple_range_calc_op1 (stmt, r, lhs, op2_range))
- {
- // If op1 also has a range, intersect the 2 ranges.
- if (name_range)
- r.intersect (*name_range);
- return true;
- }
- return false;
+ expr_range_in_bb (op2_range, op2, gimple_bb (stmt));
+ if (gimple_range_calc_op1 (r, stmt, lhs, op2_range))
+ r.intersect (op1_range);
+ else
+ r = op1_range;
+ return true;
}
if (op2 == name)
{
- get_tree_range (op1_range, op1, name, name_range);
- if (gimple_range_calc_op2 (stmt, r, lhs, op1_range))
- {
- // If op2 also has a range, intersect the 2 ranges.
- if (name_range)
- r.intersect (*name_range);
- return true;
- }
+ expr_range_in_bb (op1_range, op1, gimple_bb (stmt));
+ expr_range_in_bb (r, op2, gimple_bb (stmt));
+ if (gimple_range_calc_op2 (op2_range, stmt, lhs, op1_range))
+ r.intersect (op2_range);
+ return true;
}
return false;
}
@@ -626,12 +661,14 @@ gori_compute::gori_compute ()
// Create a boolean_type true and false range.
m_bool_zero = int_range<1> (boolean_false_node, boolean_false_node);
m_bool_one = int_range<1> (boolean_true_node, boolean_true_node);
+ m_gori_map = new gori_map;
}
// Destruct a gori_compute_object
gori_compute::~gori_compute ()
{
+ delete m_gori_map;
}
// Given the switch S, return an evaluation in R for NAME when the lhs
@@ -642,8 +679,7 @@ gori_compute::~gori_compute ()
bool
gori_compute::compute_operand_range_switch (irange &r, gswitch *s,
const irange &lhs,
- tree name,
- const irange *name_range)
+ tree name)
{
tree op1 = gimple_switch_index (s);
@@ -653,16 +689,12 @@ gori_compute::compute_operand_range_switch (irange &r, gswitch *s,
if (op1 == name || lhs.undefined_p ())
{
r = lhs;
- // If this is also the terminal
- if (name && name_range)
- r.intersect (*name_range);
return true;
}
// If op1 is in the defintion chain, pass lhs back.
- if (gimple_range_ssa_p (op1) && m_gori_map.in_chain_p (name, op1))
- return compute_operand_range (r, SSA_NAME_DEF_STMT (op1), lhs, name,
- name_range);
+ if (gimple_range_ssa_p (op1) && m_gori_map->in_chain_p (name, op1))
+ return compute_operand_range (r, SSA_NAME_DEF_STMT (op1), lhs, name);
return false;
}
@@ -702,9 +734,7 @@ is_gimple_logical_p (const gimple *gs)
bool
gori_compute::compute_operand_range (irange &r, gimple *stmt,
- const irange &lhs,
- tree name,
- const irange *name_range)
+ const irange &lhs, tree name)
{
// Empty ranges are viral as they are on an unexecutable path.
if (lhs.undefined_p ())
@@ -713,8 +743,7 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt,
return true;
}
if (is_a<gswitch *> (stmt))
- return compute_operand_range_switch (r, as_a<gswitch *> (stmt), lhs,
- name, name_range);
+ return compute_operand_range_switch (r, as_a<gswitch *> (stmt), lhs, name);
if (!gimple_range_handler (stmt))
return false;
@@ -723,21 +752,21 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt,
// The base ranger handles NAME on this statement.
if (op1 == name || op2 == name)
- return compute_name_range_op (r, stmt, lhs, name, name_range);
+ return compute_name_range_op (r, stmt, lhs, name);
if (is_gimple_logical_p (stmt))
- return compute_logical_operands (r, stmt, lhs, name, name_range);
+ return compute_logical_operands (r, stmt, lhs, name);
// NAME is not in this stmt, but one of the names in it ought to be
// derived from it.
- bool op1_in_chain = op1 && m_gori_map.in_chain_p (name, op1);
- bool op2_in_chain = op2 && m_gori_map.in_chain_p (name, op2);
+ bool op1_in_chain = op1 && m_gori_map->in_chain_p (name, op1);
+ bool op2_in_chain = op2 && m_gori_map->in_chain_p (name, op2);
if (op1_in_chain && op2_in_chain)
- return compute_operand1_and_operand2_range (r, stmt, lhs, name, name_range);
+ return compute_operand1_and_operand2_range (r, stmt, lhs, name);
if (op1_in_chain)
- return compute_operand1_range (r, stmt, lhs, name, name_range);
+ return compute_operand1_range (r, stmt, lhs, name);
if (op2_in_chain)
- return compute_operand2_range (r, stmt, lhs, name, name_range);
+ return compute_operand2_range (r, stmt, lhs, name);
// If neither operand is derived, this statement tells us nothing.
return false;
@@ -891,7 +920,6 @@ gori_compute::optimize_logical_operands (tf_range &range,
gimple *stmt,
const irange &lhs,
tree name,
- const irange *name_range,
tree op)
{
enum tree_code code = gimple_expr_code (stmt);
@@ -900,8 +928,8 @@ gori_compute::optimize_logical_operands (tf_range &range,
if ((code == BIT_IOR_EXPR || code == TRUTH_OR_EXPR) && lhs.zero_p ())
{
if (!compute_operand_range (range.false_range, SSA_NAME_DEF_STMT (op),
- m_bool_zero, name, name_range))
- get_tree_range (range.false_range, name, name, name_range);
+ m_bool_zero, name))
+ expr_range_in_bb (range.false_range, name, gimple_bb (stmt));
range.true_range = range.false_range;
return true;
}
@@ -909,8 +937,8 @@ gori_compute::optimize_logical_operands (tf_range &range,
if ((code == BIT_AND_EXPR || code == TRUTH_AND_EXPR) && lhs == m_bool_one)
{
if (!compute_operand_range (range.true_range, SSA_NAME_DEF_STMT (op),
- m_bool_one, name, name_range))
- get_tree_range (range.true_range, name, name, name_range);
+ m_bool_one, name))
+ expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
range.false_range = range.true_range;
return true;
}
@@ -927,27 +955,26 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range,
gimple *stmt,
const irange &lhs,
tree name,
- const irange *name_range,
tree op, bool op_in_chain)
{
if (!op_in_chain)
{
// If op is not in chain, use its known value.
- get_tree_range (range.true_range, name, name, name_range);
+ expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
range.false_range = range.true_range;
return;
}
- if (optimize_logical_operands (range, stmt, lhs, name, name_range, op))
+ if (optimize_logical_operands (range, stmt, lhs, name, op))
return;
// Calulate ranges for true and false on both sides, since the false
// path is not always a simple inversion of the true side.
if (!compute_operand_range (range.true_range, SSA_NAME_DEF_STMT (op),
- m_bool_one, name, name_range))
- get_tree_range (range.true_range, name, name, name_range);
+ m_bool_one, name))
+ expr_range_in_bb (range.true_range, name, gimple_bb (stmt));
if (!compute_operand_range (range.false_range, SSA_NAME_DEF_STMT (op),
- m_bool_zero, name, name_range))
- get_tree_range (range.false_range, name, name, name_range);
+ m_bool_zero, name))
+ expr_range_in_bb (range.false_range, name, gimple_bb (stmt));
}
// Given a logical STMT, calculate true and false for each potential
@@ -958,8 +985,7 @@ gori_compute::compute_logical_operands_in_chain (tf_range &range,
bool
gori_compute::compute_logical_operands (irange &r, gimple *stmt,
const irange &lhs,
- tree name,
- const irange *name_range)
+ tree name)
{
// Reaching this point means NAME is not in this stmt, but one of
// the names in it ought to be derived from it. */
@@ -968,9 +994,9 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt,
gcc_checking_assert (op1 != name && op2 != name);
bool op1_in_chain = (gimple_range_ssa_p (op1)
- && m_gori_map.in_chain_p (name, op1));
+ && m_gori_map->in_chain_p (name, op1));
bool op2_in_chain = (gimple_range_ssa_p (op2)
- && m_gori_map.in_chain_p (name, op2));
+ && m_gori_map->in_chain_p (name, op2));
// If neither operand is derived, then this stmt tells us nothing.
if (!op1_in_chain && !op2_in_chain)
@@ -978,9 +1004,9 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt,
tf_range op1_range, op2_range;
compute_logical_operands_in_chain (op1_range, stmt, lhs,
- name, name_range, op1, op1_in_chain);
+ name, op1, op1_in_chain);
compute_logical_operands_in_chain (op2_range, stmt, lhs,
- name, name_range, op2, op2_in_chain);
+ name, op2, op2_in_chain);
return logical_combine (r, gimple_expr_code (stmt), lhs,
op1_range, op2_range);
}
@@ -992,20 +1018,19 @@ gori_compute::compute_logical_operands (irange &r, gimple *stmt,
bool
gori_compute::compute_operand1_range (irange &r, gimple *stmt,
- const irange &lhs, tree name,
- const irange *name_range)
+ const irange &lhs, tree name)
{
widest_irange op1_range, op2_range;
tree op1 = gimple_range_operand1 (stmt);
tree op2 = gimple_range_operand2 (stmt);
- get_tree_range (op1_range, op1, name, name_range);
+ expr_range_in_bb (op1_range, op1, gimple_bb (stmt));
// Now calcuated the operand and put that result in r.
if (op2)
{
- get_tree_range (op2_range, op2, name, name_range);
- if (!gimple_range_calc_op1 (stmt, r, lhs, op2_range))
+ expr_range_in_bb (op2_range, op2, gimple_bb (stmt));
+ if (!gimple_range_calc_op1 (r, stmt, lhs, op2_range))
return false;
}
else
@@ -1013,16 +1038,25 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
// We pass op1_range to the unary operation. Nomally it's a
// hidden range_for_type parameter, but sometimes having the
// actual range can result in better information.
- if (!gimple_range_calc_op1 (stmt, r, lhs, op1_range))
+ if (!gimple_range_calc_op1 (r, stmt, lhs, op1_range))
return false;
}
// Intersect the calculated result with the known result.
op1_range.intersect (r);
+ gimple *src_stmt = SSA_NAME_DEF_STMT (op1);
+ // If defstmt is outside of this BB, then name must be an import.
+ if (!src_stmt || (gimple_bb (src_stmt) != gimple_bb (stmt)))
+ {
+ // IF this isn't the right import statement, then abort calculation
+ if (!src_stmt || gimple_get_lhs (src_stmt) != name)
+ return false;
+ return compute_name_range_op (r, src_stmt, op1_range, name);
+ }
+ else
// Then feed this range back as the LHS of the defining statement.
- return compute_operand_range (r, SSA_NAME_DEF_STMT (op1), op1_range, name,
- name_range);
+ return compute_operand_range (r, src_stmt, op1_range, name);
}
@@ -1033,32 +1067,31 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
bool
gori_compute::compute_operand2_range (irange &r, gimple *stmt,
- const irange &lhs, tree name,
- const irange *name_range)
+ const irange &lhs, tree name)
{
widest_irange op1_range, op2_range;
tree op1 = gimple_range_operand1 (stmt);
tree op2 = gimple_range_operand2 (stmt);
- get_tree_range (op1_range, op1, name, name_range);
+ expr_range_in_bb (op1_range, op1, gimple_bb (stmt));
+ expr_range_in_bb (op2_range, op2, gimple_bb (stmt));
+
+ // INtersect with range for op2 based on lhs and op1.
+ if (gimple_range_calc_op2 (r, stmt, lhs, op1_range))
+ op2_range.intersect (r);
- // Calculate the range for op2 based on lhs and op1.
- if (!gimple_range_calc_op2 (stmt, op2_range, lhs, op1_range))
+ gimple *src_stmt = SSA_NAME_DEF_STMT (op2);
+ // If defstmt is outside of this BB, then name must be an import.
+ if (!src_stmt || (gimple_bb (src_stmt) != gimple_bb (stmt)))
{
- get_tree_range (op2_range, op2, name, name_range);
- if (op2_range.varying_p ())
- return false;
+ // IF this isn't the right src statement, then abort calculation
+ if (!src_stmt || gimple_get_lhs (src_stmt) != name)
+ return false;
+ return compute_name_range_op (r, src_stmt, op2_range, name);
}
-
- // Also pick up what is known about op2's range at this point
- get_tree_range (r, op2, name, name_range);
-
- // And intersect it with the calculated result.
- op2_range.intersect (r);
-
+ else
// Then feed this range back as the LHS of the defining statement.
- return compute_operand_range (r, SSA_NAME_DEF_STMT (op2), op2_range, name,
- name_range);
+ return compute_operand_range (r, src_stmt, op2_range, name);
}
// Calculate a range for NAME from both operand positions of S
@@ -1071,18 +1104,17 @@ gori_compute::compute_operand1_and_operand2_range
(irange &r,
gimple *stmt,
const irange &lhs,
- tree name,
- const irange *name_range)
+ tree name)
{
widest_irange op_range;
// Calculate a good a range for op2. Since op1 == op2, this will
// have already included whatever the actual range of name is.
- if (!compute_operand2_range (op_range, stmt, lhs, name, name_range))
+ if (!compute_operand2_range (op_range, stmt, lhs, name))
return false;
// Now get the range thru op1...
- if (!compute_operand1_range (r, stmt, lhs, name, name_range))
+ if (!compute_operand1_range (r, stmt, lhs, name))
return false;
// Whichever range is the most permissive is the one we need to
@@ -1094,8 +1126,15 @@ gori_compute::compute_operand1_and_operand2_range
bool
gori_compute::has_edge_range_p (edge e, tree name)
{
- return (m_gori_map.is_export_p (name, e->src)
- || m_gori_map.def_chain_in_export_p (name, e->src));
+ return (m_gori_map->is_export_p (name, e->src)
+ || m_gori_map->def_chain_in_export_p (name, e->src));
+}
+
+
+void
+gori_compute::dump (FILE *f)
+{
+ m_gori_map->dump (f);
}
@@ -1104,8 +1143,7 @@ gori_compute::has_edge_range_p (edge e, tree name)
// control edge or NAME is not defined by this edge.
bool
-gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
- const irange *name_range)
+gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name)
{
widest_irange lhs;
@@ -1116,8 +1154,8 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
return false;
// If NAME can be calculated on the edge, use that.
- if (m_gori_map.is_export_p (name, e->src))
- return compute_operand_range (r, stmt, lhs, name, name_range);
+ if (m_gori_map->is_export_p (name, e->src))
+ return compute_operand_range (r, stmt, lhs, name);
// Otherwise see if NAME is derived from something that can be
// calculated. This performs no dynamic lookups whatsover, so it is
@@ -1125,177 +1163,8 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
return false;
}
-// Tracing wrapper implementation for gori_compute.
-
-trace_gori_compute::trace_gori_compute ()
-{
- indent = 0;
- trace_count = 0;
-}
-
-// If dumping, return true and print the prefix for the next output line.
-
-bool
-trace_gori_compute::dumping (unsigned counter, bool trailing)
-{
- if (dump_file && (dump_flags & TDF_GORI))
- {
- // Print counter index as well as INDENT spaces.
- if (!trailing)
- fprintf (dump_file, " %-7u ", counter);
- else
- fprintf (dump_file, " ");
- for (unsigned 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_gori_compute::trailer (unsigned counter, const char *caller, bool result,
- tree name, const irange &r)
-{
- indent -= bump;
- if (dumping (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);
- }
- // Marks the end of a request.
- if (indent == 0)
- fputc ('\n', dump_file);
- return result;
-}
-
-void
-trace_gori_compute::range_of_ssa_name (irange &r, tree name, gimple *stmt)
-{
- unsigned idx = ++trace_count;
- if (dumping (idx))
- {
- fprintf (dump_file, "range_of_ssa_name (");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, ") at stmt ");
- if (stmt)
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- else
- fprintf (dump_file, " NULL\n");
- indent += bump;
- }
- super::range_of_ssa_name (r, name, stmt);
- trailer (idx, "range_of_ssa_name", true, name, r);
-}
-bool
-trace_gori_compute::range_of_expr (irange &r, tree name, gimple *stmt)
-{
- unsigned idx = ++trace_count;
- if (dumping (idx))
- {
- fprintf (dump_file, "range_of_expr (");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, ") at stmt ");
- if (stmt)
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- else
- fprintf (dump_file, " NULL\n");
- indent += bump;
- }
- bool res = super::range_of_expr (r, name, stmt);
- return trailer (idx, "range_of_expr", res, name, r);
-}
-bool
-trace_gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
- const irange *name_range)
-{
- unsigned idx = ++trace_count;
- if (dumping (idx))
- {
- fprintf (dump_file, "outgoing_edge_range_p (");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, ") on edge %d->%d, with range ", e->src->index,
- e->dest->index);
- if (name_range)
- {
- name_range->dump (dump_file);
- fprintf (dump_file, "\n");
- }
- else
- fputs ("NULL\n", dump_file);
- indent += bump;
- }
- bool res = super::outgoing_edge_range_p (r, e, name, name_range);
- return trailer (idx, "outgoing_edge_range_p", res, name, r);
-}
-
-bool
-trace_gori_compute::compute_operand_range (irange &r, gimple *stmt,
- const irange &lhs,
- tree name,
- const irange *name_range)
-{
- unsigned idx = ++trace_count;
- if (dumping (idx))
- {
- fprintf (dump_file, "compute_operand_range (");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, ") with range ");
- if (name_range)
- name_range->dump (dump_file);
- else
- fputs ("NULL", dump_file);
- fprintf (dump_file, " at stmt:\n");
- dumping (idx, true);
- fputs (" ", dump_file);
- lhs.dump (dump_file);
- fprintf (dump_file, " <==> ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- indent += bump;
- }
- bool res = super::compute_operand_range (r, stmt, lhs, name, name_range);
- return trailer (idx, "compute_operand_range", res, name, r);
-}
-
-bool
-trace_gori_compute::compute_logical_operands (irange &r, gimple *stmt,
- const irange &lhs,
- tree name,
- const irange *name_range)
-{
- unsigned idx = ++trace_count;
- if (dumping (idx))
- {
- fprintf (dump_file, "compute_logical_operands (");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, ") with range ");
- if (name_range)
- name_range->dump (dump_file);
- else
- fputs ("NULL", dump_file);
- fprintf (dump_file, " at stmt:\n");
- dumping (idx, true);
- fputs (" ", dump_file);
- lhs.dump (dump_file);
- fprintf (dump_file, " <==> ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- indent += bump;
- }
- bool res = super::compute_logical_operands (r, stmt, lhs, name, name_range);
- return trailer (idx, "compute_logical_operands", res, name, r);
-}
class logical_stmt_cache
{
@@ -1511,8 +1380,7 @@ gori_compute_cache::~gori_compute_cache ()
bool
gori_compute_cache::compute_operand_range (irange &r, gimple *stmt,
const irange &lhs,
- tree name,
- const irange *name_range)
+ tree name)
{
bool cacheable = m_cache->cacheable_p (stmt, &lhs);
if (cacheable)
@@ -1525,12 +1393,10 @@ gori_compute_cache::compute_operand_range (irange &r, gimple *stmt,
r = range.false_range;
else
r = range.true_range;
- if (name_range)
- r.intersect (*name_range);
return true;
}
}
- if (super::compute_operand_range (r, stmt, lhs, name, name_range))
+ if (super::compute_operand_range (r, stmt, lhs, name))
{
if (cacheable)
cache_comparison (stmt);
@@ -1563,7 +1429,7 @@ gori_compute_cache::cache_comparison_with_int (gimple *stmt,
tree lhs = gimple_assign_lhs (stmt);
range_operator *handler = range_op_handler (code, TREE_TYPE (lhs));
widest_irange op2_range;
- gcc_assert (range_of_expr (op2_range, op2));
+ expr_range_in_bb (op2_range, op2, gimple_bb (stmt));
tree type = TREE_TYPE (op1);
handler->op1_range (r_true_side, type, m_bool_one, op2_range);
handler->op1_range (r_false_side, type, m_bool_zero, op2_range);