This tweaks someof the fold_stmt routines and helpers.. in particular
the ones which you provide a vector of ranges to to satisfy any ssa-names.
Previously, once the vector was depleted, any remaining values were
picked up from the default get_global_range_query() query. It is useful
to be able to speiocyf your own range_query to these routines, as most
fo the other fold_stmt routines allow.
This patch changes it so the default doesnt change, but you can
optionally specify your own range_query to the routines.
It also provides a new routine:
relation_trio fold_relations (gimple *s, range_query *q)
Which instead of folding a stmt, will return a relation trio based on
folding the stmt with the range_query. The relation trio will let you
know if the statement causes a relation between LHS-OP1, LHS_OP2, or
OP1_OP2... so for something like
a_3 = b_4 + 6
based on known ranges and types, we might get back (LHS > OP1)
It just provides a generic interface into what relations a statement
may provide based on what a range_query returns for values and the stmt
itself.
There is no performance impact.
Bootstraps on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
From 933e14dc613269641ffe3613bf4792ac50590275 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Wed, 24 May 2023 09:17:32 -0400
Subject: [PATCH 3/4] Provide relation queries for a stmt.
Allow fur_list and fold_stmt to be provided a range_query rather than
always defaultsing to NULL (which becomes a global query).
Also provide a fold_relations () routine which can provide a range_trio
for an arbitrary statement using any range_query
* gimple-range-fold.cc (fur_list::fur_list): Add range_query param
to contructors.
(fold_range): Add range_query parameter.
(fur_relation::fur_relation): New.
(fur_relation::trio): New.
(fur_relation::register_relation): New.
(fold_relations): New.
* gimple-range-fold.h (fold_range): Adjust prototypes.
(fold_relations): New.
---
gcc/gimple-range-fold.cc | 128 +++++++++++++++++++++++++++++++++++----
gcc/gimple-range-fold.h | 11 +++-
2 files changed, 124 insertions(+), 15 deletions(-)
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 96cbd799488..4df065c8a6e 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -214,9 +214,9 @@ fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
class fur_list : public fur_source
{
public:
- fur_list (vrange &r1);
- fur_list (vrange &r1, vrange &r2);
- fur_list (unsigned num, vrange **list);
+ fur_list (vrange &r1, range_query *q = NULL);
+ fur_list (vrange &r1, vrange &r2, range_query *q = NULL);
+ fur_list (unsigned num, vrange **list, range_query *q = NULL);
virtual bool get_operand (vrange &r, tree expr) override;
virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
private:
@@ -228,7 +228,7 @@ private:
// One range supplied for unary operations.
-fur_list::fur_list (vrange &r1) : fur_source (NULL)
+fur_list::fur_list (vrange &r1, range_query *q) : fur_source (q)
{
m_list = m_local;
m_index = 0;
@@ -238,7 +238,7 @@ fur_list::fur_list (vrange &r1) : fur_source (NULL)
// Two ranges supplied for binary operations.
-fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL)
+fur_list::fur_list (vrange &r1, vrange &r2, range_query *q) : fur_source (q)
{
m_list = m_local;
m_index = 0;
@@ -249,7 +249,8 @@ fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL)
// Arbitrary number of ranges in a vector.
-fur_list::fur_list (unsigned num, vrange **list) : fur_source (NULL)
+fur_list::fur_list (unsigned num, vrange **list, range_query *q)
+ : fur_source (q)
{
m_list = list;
m_index = 0;
@@ -278,20 +279,20 @@ fur_list::get_phi_operand (vrange &r, tree expr, edge e ATTRIBUTE_UNUSED)
// Fold stmt S into range R using R1 as the first operand.
bool
-fold_range (vrange &r, gimple *s, vrange &r1)
+fold_range (vrange &r, gimple *s, vrange &r1, range_query *q)
{
fold_using_range f;
- fur_list src (r1);
+ fur_list src (r1, q);
return f.fold_stmt (r, s, src);
}
// Fold stmt S into range R using R1 and R2 as the first two operands.
bool
-fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2)
+fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2, range_query *q)
{
fold_using_range f;
- fur_list src (r1, r2);
+ fur_list src (r1, r2, q);
return f.fold_stmt (r, s, src);
}
@@ -299,10 +300,11 @@ fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2)
// operands encountered.
bool
-fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector)
+fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector,
+ range_query *q)
{
fold_using_range f;
- fur_list src (num_elements, vector);
+ fur_list src (num_elements, vector, q);
return f.fold_stmt (r, s, src);
}
@@ -326,6 +328,108 @@ fold_range (vrange &r, gimple *s, edge on_edge, range_query *q)
return f.fold_stmt (r, s, src);
}
+// Provide a fur_source which can be used to determine any relations on
+// a statement. It manages the callback from fold_using_ranges to determine
+// a relation_trio for a statement.
+
+class fur_relation : public fur_stmt
+{
+public:
+ fur_relation (gimple *s, range_query *q = NULL);
+ virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
+ tree op2);
+ virtual void register_relation (edge e, relation_kind k, tree op1,
+ tree op2);
+ relation_trio trio() const;
+private:
+ relation_kind def_op1, def_op2, op1_op2;
+};
+
+fur_relation::fur_relation (gimple *s, range_query *q) : fur_stmt (s, q)
+{
+ def_op1 = def_op2 = op1_op2 = VREL_VARYING;
+}
+
+// Construct a trio from what is known.
+
+relation_trio
+fur_relation::trio () const
+{
+ return relation_trio (def_op1, def_op2, op1_op2);
+}
+
+// Don't support edges, but avoid a compiler warning by providing the routine.
+
+void
+fur_relation::register_relation (edge, relation_kind, tree, tree)
+{
+}
+
+// Register relation K between OP1 and OP2 on STMT.
+
+void
+fur_relation::register_relation (gimple *stmt, relation_kind k, tree op1,
+ tree op2)
+{
+ tree lhs = gimple_get_lhs (stmt);
+ tree a1 = NULL_TREE;
+ tree a2 = NULL_TREE;
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_COND:
+ a1 = gimple_cond_lhs (stmt);
+ a2 = gimple_cond_rhs (stmt);
+ break;
+ case GIMPLE_ASSIGN:
+ a1 = gimple_assign_rhs1 (stmt);
+ if (gimple_num_ops (stmt) >= 3)
+ a2 = gimple_assign_rhs2 (stmt);
+ break;
+ default:
+ break;
+ }
+ // STMT is of the form LHS = A1 op A2, now map the relation to these
+ // operands, if possible.
+ if (op1 == lhs)
+ {
+ if (op2 == a1)
+ def_op1 = k;
+ else if (op2 == a2)
+ def_op2 = k;
+ }
+ else if (op2 == lhs)
+ {
+ if (op1 == a1)
+ def_op1 = relation_swap (k);
+ else if (op1 == a2)
+ def_op2 = relation_swap (k);
+ }
+ else
+ {
+ if (op1 == a1 && op2 == a2)
+ op1_op2 = k;
+ else if (op2 == a1 && op1 == a2)
+ op1_op2 = relation_swap (k);
+ }
+}
+
+// Return the relation trio for stmt S using query Q.
+
+relation_trio
+fold_relations (gimple *s, range_query *q)
+{
+ fold_using_range f;
+ fur_relation src (s, q);
+ tree lhs = gimple_range_ssa_p (gimple_get_lhs (s));
+ if (lhs)
+ {
+ Value_Range vr(TREE_TYPE (lhs));
+ if (f.fold_stmt (vr, s, src))
+ return src.trio ();
+ }
+ return TRIO_VARYING;
+}
+
// -------------------------------------------------------------------------
// Adjust the range for a pointer difference where the operands came
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index 68c6d7743e9..939b7a76f0e 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -37,9 +37,14 @@ bool fold_range (vrange &v, gimple *s, edge on_edge, range_query *q = NULL);
// These routines the operands to be specified when manually folding.
// Any excess queries will be drawn from the current range_query.
-bool fold_range (vrange &r, gimple *s, vrange &r1);
-bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2);
-bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector);
+bool fold_range (vrange &r, gimple *s, vrange &r1, range_query *q = NULL);
+bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2,
+ range_query *q = NULL);
+bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector,
+ range_query *q = NULL);
+
+// This routine will return a relation trio for stmt S.
+relation_trio fold_relations (gimple *s, range_query *q = NULL);
// Return the type of range which statement S calculates. If the type is
// unsupported or no type can be determined, return NULL_TREE.
--
2.40.1