public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-2974] Refine ranges using relations in GORI.
@ 2022-09-29 22:34 Andrew Macleod
0 siblings, 0 replies; only message in thread
From: Andrew Macleod @ 2022-09-29 22:34 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:67166c9ec35d58efd0225b74730983aa480a88f1
commit r13-2974-g67166c9ec35d58efd0225b74730983aa480a88f1
Author: Andrew MacLeod <amacleod@redhat.com>
Date: Thu Sep 22 18:17:20 2022 -0400
Refine ranges using relations in GORI.
This allows GORI to recognize when a relation passed in applies to the
2 operands of the current statement. Check to see if further range
refinement is possible before proceeding.
* gimple-range-gori.cc (gori_compute::refine_using_relation): New.
(gori_compute::compute_operand1_range): Invoke
refine_using_relation when applicable.
(gori_compute::compute_operand2_range): Ditto.
* gimple-range-gori.h (class gori_compute): Adjust prototypes.
Diff:
---
gcc/gimple-range-gori.cc | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
gcc/gimple-range-gori.h | 3 +
2 files changed, 146 insertions(+), 3 deletions(-)
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 57a7e820749..b37d03cddda 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -934,6 +934,115 @@ gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range,
src.get_operand (false_range, name);
}
+
+// This routine will try to refine the ranges of OP1 and OP2 given a relation
+// K between them. In order to perform this refinement, one of the operands
+// must be in the definition chain of the other. The use is refined using
+// op1/op2_range on the statement, and the defintion is then recalculated
+// using the relation.
+
+bool
+gori_compute::refine_using_relation (tree op1, vrange &op1_range,
+ tree op2, vrange &op2_range,
+ fur_source &src, relation_kind k)
+{
+ gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
+ gcc_checking_assert (TREE_CODE (op2) == SSA_NAME);
+ gcc_checking_assert (k != VREL_VARYING && k != VREL_UNDEFINED);
+
+ bool change = false;
+ bool op1_def_p = in_chain_p (op2, op1);
+ if (!op1_def_p)
+ if (!in_chain_p (op1, op2))
+ return false;
+
+ tree def_op = op1_def_p ? op1 : op2;
+ tree use_op = op1_def_p ? op2 : op1;
+
+ if (!op1_def_p)
+ k = relation_swap (k);
+
+ // op1_def is true if we want to look up op1, otherwise we want op2.
+ // if neither is the case, we returned in the above check.
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (def_op);
+ gimple_range_op_handler op_handler (def_stmt);
+ if (!op_handler)
+ return false;
+ tree def_op1 = op_handler.operand1 ();
+ tree def_op2 = op_handler.operand2 ();
+ // if the def isn't binary, the relation will not be useful.
+ if (!def_op2)
+ return false;
+
+ // Determine if op2 is directly referenced as an operand.
+ if (def_op1 == use_op)
+ {
+ // def_stmt has op1 in the 1st operand position.
+ Value_Range other_op (TREE_TYPE (def_op2));
+ src.get_operand (other_op, def_op2);
+
+ // Using op1_range as the LHS, and relation REL, evaluate op2.
+ tree type = TREE_TYPE (def_op1);
+ Value_Range new_result (type);
+ if (!op_handler.op1_range (new_result, type,
+ op1_def_p ? op1_range : op2_range,
+ other_op, k))
+ return false;
+ if (op1_def_p)
+ {
+ change |= op2_range.intersect (new_result);
+ // Recalculate op2.
+ if (op_handler.fold_range (new_result, type, op2_range, other_op))
+ {
+ change |= op1_range.intersect (new_result);
+ }
+ }
+ else
+ {
+ change |= op1_range.intersect (new_result);
+ // Recalculate op1.
+ if (op_handler.fold_range (new_result, type, op1_range, other_op))
+ {
+ change |= op2_range.intersect (new_result);
+ }
+ }
+ }
+ else if (def_op2 == use_op)
+ {
+ // def_stmt has op1 in the 1st operand position.
+ Value_Range other_op (TREE_TYPE (def_op1));
+ src.get_operand (other_op, def_op1);
+
+ // Using op1_range as the LHS, and relation REL, evaluate op2.
+ tree type = TREE_TYPE (def_op2);
+ Value_Range new_result (type);
+ if (!op_handler.op2_range (new_result, type,
+ op1_def_p ? op1_range : op2_range,
+ other_op, k))
+ return false;
+ if (op1_def_p)
+ {
+ change |= op2_range.intersect (new_result);
+ // Recalculate op1.
+ if (op_handler.fold_range (new_result, type, other_op, op2_range))
+ {
+ change |= op1_range.intersect (new_result);
+ }
+ }
+ else
+ {
+ change |= op1_range.intersect (new_result);
+ // Recalculate op2.
+ if (op_handler.fold_range (new_result, type, other_op, op1_range))
+ {
+ change |= op2_range.intersect (new_result);
+ }
+ }
+ }
+ return change;
+}
+
// Calculate a range for NAME from the operand 1 position of STMT
// assuming the result of the statement is LHS. Return the range in
// R, or false if no range could be calculated.
@@ -947,6 +1056,7 @@ gori_compute::compute_operand1_range (vrange &r,
gimple *stmt = handler.stmt ();
tree op1 = handler.operand1 ();
tree op2 = handler.operand2 ();
+ tree lhs_name = gimple_get_lhs (stmt);
Value_Range op1_range (TREE_TYPE (op1));
Value_Range tmp (TREE_TYPE (op1));
@@ -959,7 +1069,21 @@ gori_compute::compute_operand1_range (vrange &r,
if (op2)
{
src.get_operand (op2_range, op2);
- if (!handler.calc_op1 (tmp, lhs, op2_range))
+ relation_kind k = VREL_VARYING;
+ if (rel)
+ {
+ if (lhs_name == rel->op1 () && op1 == rel->op2 ())
+ k = rel->kind ();
+ else if (lhs_name == rel->op2 () && op1 == rel->op1 ())
+ k = relation_swap (rel->kind ());
+ else if (op1 == rel->op1 () && op2 == rel->op2 ())
+ refine_using_relation (op1, op1_range, op2, op2_range, src,
+ rel->kind ());
+ else if (op1 == rel->op2 () && op2 == rel->op1 ())
+ refine_using_relation (op1, op1_range, op2, op2_range, src,
+ relation_swap (rel->kind ()));
+ }
+ if (!handler.calc_op1 (tmp, lhs, op2_range, k))
return false;
}
else
@@ -967,7 +1091,7 @@ gori_compute::compute_operand1_range (vrange &r,
// 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 (!handler.calc_op1 (tmp, lhs, op1_range))
+ if (!handler.calc_op1 (tmp, lhs, op1_range, VREL_VARYING))
return false;
}
@@ -1030,6 +1154,7 @@ gori_compute::compute_operand2_range (vrange &r,
gimple *stmt = handler.stmt ();
tree op1 = handler.operand1 ();
tree op2 = handler.operand2 ();
+ tree lhs_name = gimple_get_lhs (stmt);
Value_Range op1_range (TREE_TYPE (op1));
Value_Range op2_range (TREE_TYPE (op2));
@@ -1037,9 +1162,24 @@ gori_compute::compute_operand2_range (vrange &r,
src.get_operand (op1_range, op1);
src.get_operand (op2_range, op2);
+ relation_kind k = VREL_VARYING;
+ if (rel)
+ {
+ if (lhs_name == rel->op1 () && op2 == rel->op2 ())
+ k = rel->kind ();
+ else if (lhs_name == rel->op2 () && op2 == rel->op1 ())
+ k = relation_swap (rel->kind ());
+ else if (op1 == rel->op1 () && op2 == rel->op2 ())
+ refine_using_relation (op1, op1_range, op2, op2_range, src,
+ rel->kind ());
+ else if (op1 == rel->op2 () && op2 == rel->op1 ())
+ refine_using_relation (op1, op1_range, op2, op2_range, src,
+ relation_swap (rel->kind ()));
+ }
+
// Intersect with range for op2 based on lhs and op1.
- if (!handler.calc_op2 (tmp, lhs, op1_range))
+ if (!handler.calc_op2 (tmp, lhs, op1_range, k))
return false;
unsigned idx;
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 1fff3e6255a..c7a32162a1b 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -166,6 +166,9 @@ public:
bool has_edge_range_p (tree name, edge e);
void dump (FILE *f);
private:
+ bool refine_using_relation (tree op1, vrange &op1_range,
+ tree op2, vrange &op2_range,
+ fur_source &src, relation_kind k);
bool may_recompute_p (tree name, edge e);
bool may_recompute_p (tree name, basic_block bb = NULL);
bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs,
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-09-29 22:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-29 22:34 [gcc r13-2974] Refine ranges using relations in GORI 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).