summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Macleod <amacleod@gcc.gnu.org>2018-04-10 22:55:44 +0000
committerAndrew Macleod <amacleod@gcc.gnu.org>2018-04-10 22:55:44 +0000
commit57e7640ca39e7a63b5bca0bb890f127f5e3c058d (patch)
treee8023b358b6f28a479dbae239c6f176e39ca9ecf
parentd739eb8b490b481c9b75a12274f08afd695c8041 (diff)
downloadgcc-57e7640ca39e7a63b5bca0bb890f127f5e3c058d.tar.gz
Reduce range_stmt to a single gimple stmt for efficiency
From-SVN: r259304
-rw-r--r--gcc/ssa-range-bb.c221
-rw-r--r--gcc/ssa-range-bb.h11
-rw-r--r--gcc/ssa-range-stmt.c281
-rw-r--r--gcc/ssa-range-stmt.h66
-rw-r--r--gcc/ssa-range.c14
5 files changed, 280 insertions, 313 deletions
diff --git a/gcc/ssa-range-bb.c b/gcc/ssa-range-bb.c
index a288037b170..bafee0f817b 100644
--- a/gcc/ssa-range-bb.c
+++ b/gcc/ssa-range-bb.c
@@ -208,13 +208,14 @@ void
gori_map::process_stmt (gimple *stmt, bitmap result, basic_block bb)
{
range_stmt rn (stmt);
- tree ssa1 = rn.ssa_operand1 ();
- tree ssa2 = rn.ssa_operand2 ();
bitmap b;
if (!rn.valid ())
return;
+ tree ssa1 = rn.ssa_operand1 ();
+ tree ssa2 = rn.ssa_operand2 ();
+
if (ssa1)
{
b = calc_def_chain (ssa1, bb);
@@ -348,125 +349,36 @@ block_ranger::~block_ranger ()
delete gori;
}
-/* Return TRUE if CODE with operands of type TYPE is a boolean
- evaluation. These are important to identify as both sides of a logical
- binary expression must be evaluated in order to calculate a range. */
+/* This routine will return what is globally known about the range for an
+ operand of any kind. */
bool
-block_ranger::logical_expr_p (tree_code code, tree type) const
+block_ranger::get_operand_range (irange& r, tree op)
{
+ /* This check allows unary operations to be handled without having to
+ make an explicit check for the existence of a second operand. */
+ if (!op)
+ return false;
- /* Look for boolean and/or condition. */
- switch (code)
- {
- case TRUTH_AND_EXPR:
- case TRUTH_OR_EXPR:
- return true;
-
- case BIT_AND_EXPR:
- case BIT_IOR_EXPR:
- if (types_compatible_p (type, boolean_type_node))
- return true;
- break;
-
- default:
- break;
- }
- return false;
-}
-
-/* Evaluate a binary logical expression given true and false ranges for each
- of the operands. Base the result on the value in the LHS. */
-bool
-block_ranger::eval_logical (irange& r, range_stmt &stmt, const irange& lhs,
- const irange& op1_true, const irange& op1_false,
- const irange& op2_true,
- const irange& op2_false) const
-{
- gcc_checking_assert (logical_expr_p (stmt.get_code (),
- TREE_TYPE (stmt.operand1 ())));
-
- /* If the LHS can be TRUE OR FALSE, then both need to be evalauted and
- combined, otherwise any range restrictions that have been determined
- leading up to this point would be lost. */
- if (!wi::eq_p (lhs.lower_bound(), lhs.upper_bound()))
- {
- irange r1;
- if (eval_logical (r1, stmt, bool_zero, op1_true, op1_false, op2_true,
- op2_false) &&
- eval_logical (r, stmt, bool_one, op1_true, op1_false, op2_true,
- op2_false))
- {
- r.union_ (r1);
- return true;
- }
- return false;
-
- }
-
- /* Now combine based on whether the result is TRUE or FALSE. */
- switch (stmt.get_code ())
- {
-
- /* A logical operation on two ranges is executed with operand ranges that
- have been determined for both a TRUE and FALSE result..
- Assuming x_8 is an unsigned char:
- b_1 = x_8 < 20
- b_2 = x_8 > 5
- if we are looking for the range of x_8, the operand ranges will be:
- will be:
- b_1 TRUE x_8 = [0, 19]
- b_1 FALSE x_8 = [20, 255]
- b_2 TRUE x_8 = [6, 255]
- b_2 FALSE x_8 = [0,5]. */
-
- /* c_2 = b_1 && b_2
- The result of an AND operation with a TRUE result is the intersection
- of the 2 TRUE ranges, [0,19] intersect [6,255] -> [6, 19]. */
- case TRUTH_AND_EXPR:
- case BIT_AND_EXPR:
- if (!lhs.zero_p ())
- r = irange_intersect (op1_true, op2_true);
- else
- {
- /* The FALSE side is the union of the other 3 cases. */
- irange ff = irange_intersect (op1_false, op2_false);
- irange tf = irange_intersect (op1_true, op2_false);
- irange ft = irange_intersect (op1_false, op2_true);
- r = irange_union (ff, tf);
- r.union_ (ft);
- }
- break;
-
- /* c_2 = b_1 || b_2
- An OR operation will only take the FALSE path if both operands are
- false, so [20, 255] intersect [0, 5] is the union: [0,5][20,255]. */
- case TRUTH_OR_EXPR:
- case BIT_IOR_EXPR:
- if (lhs.zero_p ())
- r = irange_intersect (op1_false, op2_false);
- else
- {
- /* The TRUE side of the OR operation will be the union of the other
- three combinations. */
- irange tt = irange_intersect (op1_true, op2_true);
- irange tf = irange_intersect (op1_true, op2_false);
- irange ft = irange_intersect (op1_false, op2_true);
- r = irange_union (tt, tf);
- r.union_ (ft);
- }
- break;
-
- default:
- gcc_unreachable ();
- }
+ if (TREE_CODE (op) == INTEGER_CST)
+ r.set_range (TREE_TYPE (op), op, op);
+ else
+ if (TREE_CODE (op) == SSA_NAME)
+ r = op;
+ else
+ if (TYPE_P (op))
+ r.set_range_for_type (op);
+ else
+ /* Default to range for the type of the expression. */
+ r.set_range_for_type (TREE_TYPE (op));
return true;
}
+
/* Given a logical STMT, calculate true and false for each potential path
using NAME and resolve the outcome based on the logical operator. */
bool
-block_ranger::process_logical (range_stmt& stmt, irange& r, tree name,
+block_ranger::process_logical (range_stmt stmt, irange& r, tree name,
const irange& lhs)
{
range_stmt op_stmt;
@@ -521,8 +433,8 @@ block_ranger::process_logical (range_stmt& stmt, irange& r, tree name,
}
}
- if (!ret || !eval_logical (r, stmt, lhs, op1_true, op1_false, op2_true,
- op2_false))
+ if (!ret || !stmt.fold_logical (r, lhs, op1_true, op1_false, op2_true,
+ op2_false))
r.set_range_for_type (TREE_TYPE (name));
return true;
}
@@ -531,14 +443,22 @@ block_ranger::process_logical (range_stmt& stmt, irange& r, tree name,
/* Given the expression in STMT, return an evaluation in R for NAME.
Returning false means the name being looked for was NOT resolvable. */
bool
-block_ranger::get_range (range_stmt& stmt, irange& r, tree name,
- const irange& lhs)
+block_ranger::get_range_from_stmt (range_stmt stmt, irange& r, tree name,
+ const irange& lhs)
{
- range_stmt op_stmt;
irange op1_range, op2_range;
tree op1, op2;
bool op1_in_chain, op2_in_chain;
+ if (!stmt.valid ())
+ return false;
+
+ if (lhs.empty_p ())
+ {
+ r.clear (TREE_TYPE (name));
+ return true;
+ }
+
op1 = stmt.operand1 ();
op2 = stmt.operand2 ();
@@ -561,7 +481,7 @@ block_ranger::get_range (range_stmt& stmt, irange& r, tree name,
}
/* Check for boolean cases which require developing ranges and combining. */
- if (logical_expr_p (stmt.get_code (), TREE_TYPE (op1)))
+ if (stmt.logical_expr_p ())
return process_logical (stmt, r, name, lhs);
/* Reaching this point means NAME is not in this stmt, but one of the
@@ -621,29 +541,6 @@ block_ranger::get_range (range_stmt& stmt, irange& r, tree name,
return get_range_from_stmt (SSA_NAME_DEF_STMT (op2), r, name, op2_range);
}
-/* Given the expression in STMT, return an evaluation in R for NAME. */
-bool
-block_ranger::get_range_from_stmt (gimple *stmt, irange& r, tree name,
- const irange& lhs)
-{
- range_stmt rn;
- rn = stmt;
-
- /* If it isnt an expression that is understood, we know nothing. */
- if (!rn.valid())
- return false;
-
- /* If the lhs has no range, ie , it cannot be executed, then the query
- has no range either. */
- if (lhs.empty_p ())
- {
- r.clear (TREE_TYPE (name));
- return true;
- }
-
- return get_range (rn, r, name, lhs);
-}
-
void
block_ranger::dump (FILE *f)
{
@@ -812,28 +709,45 @@ block_ranger::range_on_stmt (irange& r, tree name, gimple *g)
if (rn.operand1 () != name && rn.operand2 () != name)
return false;
- /* So far only understand LHS if its an assignment. */
- if (gimple_code (g) != GIMPLE_ASSIGN)
+ /* Only works if there is a LHS. */
+ if (!gimple_get_lhs (g))
return false;
if (get_operand_range (lhs, gimple_get_lhs (g)))
- return get_range (rn, r, name, lhs);
+ return get_range_from_stmt (rn, r, name, lhs);
return false;
}
+
+/* Attempt to evaluate the epression using whatever is globally known about
+ the operands. If it can be evaluated, TRUE is returned
+ and the range is returned in R. */
+
bool
block_ranger::range_of_def (irange& r, gimple *g)
{
range_stmt rn (g);
+ irange r1, r2;
/* If we don't understand the stmt... */
if (!rn.valid())
return false;
- return rn.fold (r);
+ tree op1 = rn.operand1 ();
+ tree op2 = rn.operand2 ();
+
+ get_operand_range (r1, op1);
+ if (op2)
+ return rn.fold (r, r1);
+
+ get_operand_range (r2, op2);
+ return rn.fold (r, r1, r2);
}
+/* This method will attempt to evaluate the expression by replacing any
+ occurrence of ssa_name NAME with the range NAME_RANGE. If it can be
+ evaluated, TRUE is returned and the resulting range returned in R. */
bool
block_ranger::range_of_def (irange& r, gimple *g, tree name,
const irange& range_of_name)
@@ -844,6 +758,23 @@ block_ranger::range_of_def (irange& r, gimple *g, tree name,
if (!rn.valid())
return false;
- return rn.fold (r, name, range_of_name);
+ irange r1, r2;
+ tree op1 = rn.operand1 ();
+ tree op2 = rn.operand2 ();
+
+ if (op1 == name)
+ r1 = range_of_name;
+ else
+ get_operand_range (r1, op1);
+
+ if (!op2)
+ return rn.fold (r, r1);
+
+ if (op2 == name)
+ r2 = range_of_name;
+ else
+ get_operand_range (r2, op2);
+
+ return rn.fold (r, r1, r2);
}
diff --git a/gcc/ssa-range-bb.h b/gcc/ssa-range-bb.h
index ce42d432bb2..e4895566f78 100644
--- a/gcc/ssa-range-bb.h
+++ b/gcc/ssa-range-bb.h
@@ -34,15 +34,12 @@ class block_ranger
class gori_map *gori; /* Generates Outgoing Range Info. */
irange bool_zero;
irange bool_one;
- bool logical_expr_p (tree_code code, tree type) const;
- bool eval_logical (irange& r, range_stmt &stmt, const irange& lhs,
- const irange& op1_true, const irange& op1_false,
- const irange& op2_true, const irange& op2_false) const;
- bool process_logical (range_stmt& stmt, irange& r, tree name,
+ bool process_logical (range_stmt stmt, irange& r, tree name,
const irange& lhs);
- bool get_range (range_stmt& stmt, irange& r, tree name, const irange& lhs);
- bool get_range_from_stmt (gimple *stmt, irange& r, tree name,
+ bool get_range_from_stmt (range_stmt stmt, irange& r, tree name,
const irange& lhs);
+protected:
+ bool get_operand_range (irange& r, tree op);
public:
block_ranger ();
~block_ranger ();
diff --git a/gcc/ssa-range-stmt.c b/gcc/ssa-range-stmt.c
index 4cf6e0fcf8f..3e6eccf2947 100644
--- a/gcc/ssa-range-stmt.c
+++ b/gcc/ssa-range-stmt.c
@@ -46,94 +46,156 @@ along with GCC; see the file COPYING3. If not see
#include "ssa-range-stmt.h"
-/* This routine will return what is globally known about the range for an
- operand of any kind. */
-bool
-get_operand_range (irange& r, tree op)
+/* Validate that the statement and all operands of this expression are
+ operable on iranges. If it is valid, set the stmt pointer. */
+void
+range_stmt::validate_stmt (gimple *s)
{
- /* This check allows unary operations to be handled without having to
- make an explicit check for the existence of a second operand. */
- if (!op)
- return false;
+ // Check for supported statements
+ switch (gimple_code (s))
+ {
+ case GIMPLE_COND:
+ case GIMPLE_ASSIGN:
+ g = s;
+ break;
- if (TREE_CODE (op) == INTEGER_CST)
- r.set_range (TREE_TYPE (op), op, op);
- else
- if (TREE_CODE (op) == SSA_NAME)
- r = op;
- else
- if (TYPE_P (op))
- r.set_range_for_type (op);
- else
- /* Default to range for the type of the expression. */
- r.set_range_for_type (TREE_TYPE (op));
+ default:
+ g = NULL;
+ }
- return true;
+ // Must have a ranger operation handler as well.
+ if (g && handler ())
+ {
+ // Now verify all the operanmds are compatible
+ tree op1 = operand1 ();
+ tree op2 = operand2 ();
+ tree ssa1 = valid_irange_ssa (op1);
+ tree ssa2 = valid_irange_ssa (op2);
+
+ if (ssa1 || (TREE_CODE (op1) == INTEGER_CST && !TREE_OVERFLOW (op1)))
+ {
+ if (!op2)
+ return;
+ if (ssa2 || (TREE_CODE (op2) == INTEGER_CST && !TREE_OVERFLOW (op2)))
+ return;
+ }
+ }
+ g = NULL;
}
-/* Initialize the SSA operands and validate that all operands of this
- expression are operable on iranges.
- Return ERROR_MARK if they are not, otherwise the current tree code. */
-tree_code
-range_stmt::validate_operands ()
+/* Return TRUE if CODE with operands of type TYPE is a boolean
+ evaluation. These are important to identify as both sides of a logical
+ binary expression must be evaluated in order to calculate a range. */
+bool
+range_stmt::logical_expr_p () const
{
- ssa1 = valid_irange_ssa (op1);
- ssa2 = valid_irange_ssa (op2);
-
- if (ssa1 || (TREE_CODE (op1) == INTEGER_CST && !TREE_OVERFLOW (op1)))
- {
- if (!op2)
- return code;
- if (ssa2 || (TREE_CODE (op2) == INTEGER_CST && !TREE_OVERFLOW (op2)))
- return code;
- }
- return ERROR_MARK;
+ /* Look for boolean and/or condition. */
+ switch (get_code ())
+ {
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ return true;
+
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ if (types_compatible_p (TREE_TYPE (operand1 ()), boolean_type_node))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ return false;
}
-/* Build a range node from a stmt, if it possible. */
-void
-range_stmt::from_stmt (gimple *s)
+
+/* Evaluate a binary logical expression given true and false ranges for each
+ of the operands. Base the result on the value in the LHS. */
+bool
+range_stmt::fold_logical (irange& r, const irange& lhs, const irange& op1_true,
+ const irange& op1_false, const irange& op2_true,
+ const irange& op2_false) const
{
- switch (gimple_code (s))
+ gcc_checking_assert (logical_expr_p ());
+
+ /* If the LHS can be TRUE OR FALSE, then both need to be evaluated and
+ combined, otherwise any range restrictions that have been determined
+ leading up to this point would be lost. */
+ if (!wi::eq_p (lhs.lower_bound(), lhs.upper_bound()))
{
- case GIMPLE_COND:
- {
- gcond *gc = as_a <gcond *> (s);
- code = gimple_cond_code (gc);
- if (irange_op_handler (code))
- {
- lhs = gimple_get_lhs (s);
- op1 = gimple_cond_lhs (gc);
- op2 = gimple_cond_rhs (gc);
- code = validate_operands ();
- return;
- }
- break;
- }
- case GIMPLE_ASSIGN:
+ irange r1;
+ irange bool_zero (boolean_type_node, 0, 0);
+ irange bool_one (boolean_type_node, 1, 1);
+ if (fold_logical (r1, bool_zero, op1_true, op1_false, op2_true,
+ op2_false) &&
+ fold_logical (r, bool_one, op1_true, op1_false, op2_true, op2_false))
{
- gassign *ga = as_a <gassign *> (s);
- code = gimple_assign_rhs_code (ga);
- if (irange_op_handler (code))
- {
- lhs = gimple_get_lhs (s);
- op1 = gimple_assign_rhs1 (ga);
- if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
- op2 = gimple_assign_rhs2 (ga);
- else
- op2 = NULL;
- code = validate_operands ();
- return;
- }
- break;
+ r.union_ (r1);
+ return true;
}
+ return false;
- default:
+ }
+
+ /* Now combine based on whether the result is TRUE or FALSE. */
+ switch (get_code ())
+ {
+
+ /* A logical operation on two ranges is executed with operand ranges that
+ have been determined for both a TRUE and FALSE result..
+ Assuming x_8 is an unsigned char:
+ b_1 = x_8 < 20
+ b_2 = x_8 > 5
+ if we are looking for the range of x_8, the operand ranges will be:
+ will be:
+ b_1 TRUE x_8 = [0, 19]
+ b_1 FALSE x_8 = [20, 255]
+ b_2 TRUE x_8 = [6, 255]
+ b_2 FALSE x_8 = [0,5]. */
+
+ /* c_2 = b_1 && b_2
+ The result of an AND operation with a TRUE result is the intersection
+ of the 2 TRUE ranges, [0,19] intersect [6,255] -> [6, 19]. */
+ case TRUTH_AND_EXPR:
+ case BIT_AND_EXPR:
+ if (!lhs.zero_p ())
+ r = irange_intersect (op1_true, op2_true);
+ else
+ {
+ /* The FALSE side is the union of the other 3 cases. */
+ irange ff = irange_intersect (op1_false, op2_false);
+ irange tf = irange_intersect (op1_true, op2_false);
+ irange ft = irange_intersect (op1_false, op2_true);
+ r = irange_union (ff, tf);
+ r.union_ (ft);
+ }
break;
+
+ /* c_2 = b_1 || b_2
+ An OR operation will only take the FALSE path if both operands are
+ false, so [20, 255] intersect [0, 5] is the union: [0,5][20,255]. */
+ case TRUTH_OR_EXPR:
+ case BIT_IOR_EXPR:
+ if (lhs.zero_p ())
+ r = irange_intersect (op1_false, op2_false);
+ else
+ {
+ /* The TRUE side of the OR operation will be the union of the other
+ three combinations. */
+ irange tt = irange_intersect (op1_true, op2_true);
+ irange tf = irange_intersect (op1_true, op2_false);
+ irange ft = irange_intersect (op1_false, op2_true);
+ r = irange_union (tt, tf);
+ r.union_ (ft);
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
}
- code = ERROR_MARK;
- return;
+
+ return true;
}
/* This method will attempt to resolve a unary expression with value R1 to
@@ -144,16 +206,14 @@ bool
range_stmt::fold (irange &res, const irange& r1) const
{
irange r2;
- irange_operator *handler = irange_op_handler (code);
- gcc_assert (handler != NULL);
-
+ tree lhs = gimple_get_lhs (g);
/* Single ssa operations require the LHS type as the second range. */
if (lhs)
r2.set_range_for_type (TREE_TYPE (lhs));
else
r2.clear (r1.get_type ());
- return handler->fold_range (res, r1, r2);
+ return handler()->fold_range (res, r1, r2);
}
/* This method will attempt to resolve a binary expression with operand
@@ -163,62 +223,9 @@ range_stmt::fold (irange &res, const irange& r1) const
bool
range_stmt::fold (irange &res, const irange& r1, const irange& r2) const
{
- irange_operator *handler = irange_op_handler (code);
- gcc_assert (handler != NULL);
-
// Make sure this isnt a unary operation being passed a second range.
- gcc_assert (op2);
- return handler->fold_range (res, r1, r2);
-}
-
-/* This method will attempt to evaluate the epression using whatever is
- globally known about the operands. If it can be evaluated, TRUE is returned
- and the range is returned in RES. */
-
-bool
-range_stmt::fold (irange &res) const
-{
- irange r1, r2;
-
- if (!op2)
- {
- get_operand_range (r1, op1);
- return fold (res, r1);
- }
-
- get_operand_range (r1, op1);
- get_operand_range (r2, op2);
- return fold (res, r1, r2);
-}
-
-/* This method will attempt to evaluate the expression by replacing any
- occurrence of ssa_name NAME with the range NAME_RANGE. If it can be
- evaluated, TRUE is returned and the resulting range returned in RES. */
-bool
-range_stmt::fold (irange& res, tree name, const irange& name_range) const
-{
- irange r1, r2;
-
- if (!op2)
- {
- if (ssa1 == name)
- r1 = name_range;
- else
- get_operand_range (r1, op1);
- return fold (res, r1);
- }
-
- if (ssa1 == name)
- r1 = name_range;
- else
- get_operand_range (r1, op1);
-
- if (ssa2 == name)
- r2 = name_range;
- else
- get_operand_range (r2, op2);
-
- return fold (res, r1, r2);
+ gcc_assert (operand2 ());
+ return handler() ->fold_range (res, r1, r2);
}
/* This method will evaluate a range for the operand of a unary expression
@@ -228,7 +235,7 @@ bool
range_stmt::op1_irange (irange& r, const irange& lhs_range) const
{
irange type_range;
- type_range.set_range_for_type (TREE_TYPE (op1));
+ type_range.set_range_for_type (TREE_TYPE (operand1 ()));
return handler ()->op1_irange (r, lhs_range, type_range);
}
@@ -240,7 +247,7 @@ bool
range_stmt::op1_irange (irange& r, const irange& lhs_range,
const irange& op2_range) const
{
- gcc_assert (op2 != NULL);
+ gcc_assert (operand2 () != NULL);
return handler ()->op1_irange (r, lhs_range, op2_range);
}
@@ -259,6 +266,10 @@ range_stmt::op2_irange (irange& r, const irange& lhs_range,
void
range_stmt::dump (FILE *f) const
{
+ tree lhs = gimple_get_lhs (g);
+ tree op1 = operand1 ();
+ tree op2 = operand2 ();
+
if (lhs)
{
print_generic_expr (f, lhs, TDF_SLIM);
@@ -266,13 +277,13 @@ range_stmt::dump (FILE *f) const
}
if (!op2)
- irange_op_handler (code)->dump (f);
+ handler ()->dump (f);
print_generic_expr (f, op1, TDF_SLIM);
if (op2)
{
- irange_op_handler (code)->dump (f);
+ handler ()->dump (f);
print_generic_expr (f, op2, TDF_SLIM);
}
diff --git a/gcc/ssa-range-stmt.h b/gcc/ssa-range-stmt.h
index fe685b010f5..e0d9bf78906 100644
--- a/gcc/ssa-range-stmt.h
+++ b/gcc/ssa-range-stmt.h
@@ -24,9 +24,6 @@ along with GCC; see the file COPYING3. If not see
#include "range.h"
#include "range-op.h"
-/* Return a the range for a single tree object. */
-bool get_operand_range (irange& r, tree op);
-
/* This class is used summarize expressions that are supported by the
irange_operator class, and provide an interface to the operators on
the expression.
@@ -43,12 +40,8 @@ bool get_operand_range (irange& r, tree op);
class range_stmt
{
private:
- tree_code code;
- tree lhs;
- tree op1, op2;
- tree ssa1, ssa2;
- tree_code validate_operands ();
- void from_stmt (gimple *s);
+ gimple *g;
+ void validate_stmt (gimple *s);
class irange_operator *handler() const;
public:
range_stmt ();
@@ -64,8 +57,8 @@ public:
tree ssa_operand1 () const;
tree ssa_operand2 () const;
- bool fold (irange& res) const;
- bool fold (irange& res, tree name, const irange& name_range) const;
+ bool logical_expr_p () const;
+
bool fold (irange& res, const irange& r1) const;
bool fold (irange& res, const irange& r1, const irange& r2) const;
bool op1_irange (irange& r, const irange& lhs_range) const;
@@ -74,6 +67,10 @@ public:
bool op2_irange (irange& r, const irange& lhs_range,
const irange& op1_range) const;
+ bool fold_logical (irange& r, const irange& lhs, const irange& op1_true,
+ const irange& op1_false, const irange& op2_true,
+ const irange& op2_false) const;
+
void dump (FILE *f) const;
};
@@ -82,21 +79,21 @@ public:
inline
range_stmt::range_stmt ()
{
- code = ERROR_MARK;
+ g = NULL;
}
/* Initialize a range statement from gimple statement S. */
inline
range_stmt::range_stmt (gimple *s)
{
- from_stmt (s);
+ validate_stmt (s);
}
/* Initialize a range statement from gimple statement S. */
inline range_stmt&
range_stmt::operator= (gimple *s)
{
- from_stmt (s);
+ validate_stmt (s);
return *this;
}
@@ -104,43 +101,70 @@ range_stmt::operator= (gimple *s)
inline bool
range_stmt::valid () const
{
- return code != ERROR_MARK;
+ return g != NULL;
}
inline tree_code
range_stmt::get_code () const
{
- return code;
+ return gimple_expr_code (g);
}
inline tree
range_stmt::operand1 () const
{
- return op1;
+ switch (gimple_code (g))
+ {
+ case GIMPLE_COND:
+ return gimple_cond_lhs (g);
+ case GIMPLE_ASSIGN:
+ return gimple_assign_rhs1 (g);
+ default:
+ break;
+ }
+ return NULL;
}
inline tree
range_stmt::operand2 () const
{
- return op2;
+ switch (gimple_code (g))
+ {
+ case GIMPLE_COND:
+ return gimple_cond_rhs (g);
+ case GIMPLE_ASSIGN:
+ if (gimple_num_ops (g) >= 3)
+ return gimple_assign_rhs2 (g);
+ else
+ return NULL;
+ default:
+ break;
+ }
+ return NULL;
}
inline tree
range_stmt::ssa_operand1() const
{
- return ssa1;
+ tree op1 = operand1 ();
+ if (op1 && TREE_CODE (op1) == SSA_NAME)
+ return op1;
+ return NULL_TREE;
}
inline tree
range_stmt::ssa_operand2 () const
{
- return ssa2;
+ tree op2 = operand2 ();
+ if (op2 && TREE_CODE (op2) == SSA_NAME)
+ return op2;
+ return NULL_TREE;
}
inline irange_operator *
range_stmt::handler () const
{
- return irange_op_handler (code);
+ return irange_op_handler (get_code ());
}
#endif /* GCC_SSA_RANGE_STMT_H */
diff --git a/gcc/ssa-range.c b/gcc/ssa-range.c
index 58595e419bb..7a63089d0d3 100644
--- a/gcc/ssa-range.c
+++ b/gcc/ssa-range.c
@@ -430,6 +430,7 @@ path_ranger::path_range_stmt (irange& r, gimple *g)
irange range_op1, range_op2;
range_stmt rn;
basic_block bb = gimple_bb (g);
+ bool res;
if (is_a <gphi *> (g))
{
@@ -458,13 +459,16 @@ path_ranger::path_range_stmt (irange& r, gimple *g)
// If this is a unary operation, call fold now.
if (!rn.operand2 ())
- return rn.fold (r, range_op1);
+ res = rn.fold (r, range_op1);
+ else
+ {
- if (!path_get_operand (range_op2, rn.operand2 (), bb))
- return false;
+ if (!path_get_operand (range_op2, rn.operand2 (), bb))
+ return false;
- normalize_bool_type (range_op1, range_op2);
- bool res = rn.fold (r, range_op1, range_op2);
+ normalize_bool_type (range_op1, range_op2);
+ res = rn.fold (r, range_op1, range_op2);
+ }
if (name)
{