Certain components of GORI were needed in order to process a COND_EXPR
expression and calculate the 2 operands as if they were true and false edges
based on the condition. With GORI available from the range_query
object now, this can be moved into the fold_using_range code where it
really belongs.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
From eb66da78b896ad5e7f6a315413ed68273c83662f Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Tue, 21 May 2024 12:41:49 -0400
Subject: [PATCH 12/12] Move condexpr_adjust into gimple-range-fold
Certain components of GORI were needed in order to process a COND_EXPR
expression and calculate the 2 operands as if they were true and false edges
based on the condition. With GORI available from the range_query
objcet now, this can be moved into the fold_using_range code where it
really belongs.
* gimple-range-edge.h (range_query::condexpr_adjust): Delete.
* gimpe-range-fold.cc (fold_using_range::range_of_range_op): Use
gori_ssa routine.
(fold_using_range::range_of_address): Likewise.
(fold_using_range::range_of_phi): Likewise.
(fold_using_range::condexpr_adjust): Relocated from gori_compute.
(fold_using_range::range_of_cond_expr): Use local condexpr_adjust.
(fur_source::register_outgoing_edges): Use gori_ssa routine.
* gimple-range-fold.h (gori_ssa): Rename from gori_bb.
(fold_using_range::condexpr_adjust): Add prototype.
* gimple-range-gori.cc (gori_compute::condexpr_adjust): Relocate.
* gimple-range-gori.h (gori_compute::condexpr_adjust): Delete.
---
gcc/gimple-range-edge.h | 4 +-
gcc/gimple-range-fold.cc | 130 ++++++++++++++++++++++++++++++++-------
gcc/gimple-range-fold.h | 4 +-
gcc/gimple-range-gori.cc | 103 -------------------------------
gcc/gimple-range-gori.h | 2 -
5 files changed, 113 insertions(+), 130 deletions(-)
diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
index 0096c02faf4..0de1cca4294 100644
--- a/gcc/gimple-range-edge.h
+++ b/gcc/gimple-range-edge.h
@@ -54,13 +54,11 @@ public:
virtual bool edge_range_p (vrange &, edge, tree, range_query &)
{ return false; }
- virtual bool condexpr_adjust (vrange &, vrange &, gimple *, tree, tree, tree,
- class fur_source &) { return false; }
virtual bool has_edge_range_p (tree, basic_block = NULL) { return false; }
virtual bool has_edge_range_p (tree, edge ) { return false; }
virtual void dump (FILE *) { }
virtual bool compute_operand_range (vrange &, gimple *, const vrange &, tree,
- fur_source &,
+ class fur_source &,
class value_relation * = NULL)
{ return false; }
private:
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index a0ff7f2b98b..b3965b5ee50 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -745,8 +745,8 @@ fold_using_range::range_of_range_op (vrange &r,
r.set_varying (type);
if (lhs && gimple_range_ssa_p (op1))
{
- if (src.gori_bb ())
- src.gori_bb ()->register_dependency (lhs, op1);
+ if (src.gori_ssa ())
+ src.gori_ssa ()->register_dependency (lhs, op1);
relation_kind rel;
rel = handler.lhs_op1_relation (r, range1, range1);
if (rel != VREL_VARYING)
@@ -772,10 +772,10 @@ fold_using_range::range_of_range_op (vrange &r,
relation_fold_and_or (as_a <irange> (r), s, src, range1, range2);
if (lhs)
{
- if (src.gori_bb ())
+ if (src.gori_ssa ())
{
- src.gori_bb ()->register_dependency (lhs, op1);
- src.gori_bb ()->register_dependency (lhs, op2);
+ src.gori_ssa ()->register_dependency (lhs, op1);
+ src.gori_ssa ()->register_dependency (lhs, op2);
}
if (gimple_range_ssa_p (op1))
{
@@ -843,8 +843,8 @@ fold_using_range::range_of_address (prange &r, gimple *stmt, fur_source &src)
{
tree ssa = TREE_OPERAND (base, 0);
tree lhs = gimple_get_lhs (stmt);
- if (lhs && gimple_range_ssa_p (ssa) && src.gori_bb ())
- src.gori_bb ()->register_dependency (lhs, ssa);
+ if (lhs && gimple_range_ssa_p (ssa) && src.gori_ssa ())
+ src.gori_ssa ()->register_dependency (lhs, ssa);
src.get_operand (r, ssa);
range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt)));
@@ -950,8 +950,8 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
else
r.union_ (arg_range);
- if (gimple_range_ssa_p (arg) && src.gori_bb ())
- src.gori_bb ()->register_dependency (phi_def, arg);
+ if (gimple_range_ssa_p (arg) && src.gori_ssa ())
+ src.gori_ssa ()->register_dependency (phi_def, arg);
}
// Track if all arguments are the same.
@@ -1114,6 +1114,95 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &)
return true;
}
+// Given COND ? OP1 : OP2 with ranges R1 for OP1 and R2 for OP2, Use gori
+// to further resolve R1 and R2 if there are any dependencies between
+// OP1 and COND or OP2 and COND. All values can are to be calculated using SRC
+// as the origination source location for operands..
+// Effectively, use COND an the edge condition and solve for OP1 on the true
+// edge and OP2 on the false edge.
+
+bool
+fold_using_range::condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond,
+ tree op1, tree op2, fur_source &src)
+{
+ if (!src.gori () || !src.gori_ssa ())
+ return false;
+
+ tree ssa1 = gimple_range_ssa_p (op1);
+ tree ssa2 = gimple_range_ssa_p (op2);
+ if (!ssa1 && !ssa2)
+ return false;
+ if (TREE_CODE (cond) != SSA_NAME)
+ return false;
+ gassign *cond_def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (cond));
+ if (!cond_def
+ || TREE_CODE_CLASS (gimple_assign_rhs_code (cond_def)) != tcc_comparison)
+ return false;
+ tree type = TREE_TYPE (gimple_assign_rhs1 (cond_def));
+ if (!range_compatible_p (type, TREE_TYPE (gimple_assign_rhs2 (cond_def))))
+ return false;
+ range_op_handler hand (gimple_assign_rhs_code (cond_def));
+ if (!hand)
+ return false;
+
+ tree c1 = gimple_range_ssa_p (gimple_assign_rhs1 (cond_def));
+ tree c2 = gimple_range_ssa_p (gimple_assign_rhs2 (cond_def));
+
+ // Only solve if there is one SSA name in the condition.
+ if ((!c1 && !c2) || (c1 && c2))
+ return false;
+
+ // Pick up the current values of each part of the condition.
+ tree rhs1 = gimple_assign_rhs1 (cond_def);
+ tree rhs2 = gimple_assign_rhs2 (cond_def);
+ Value_Range cl (TREE_TYPE (rhs1));
+ Value_Range cr (TREE_TYPE (rhs2));
+ src.get_operand (cl, rhs1);
+ src.get_operand (cr, rhs2);
+
+ tree cond_name = c1 ? c1 : c2;
+ gimple *def_stmt = SSA_NAME_DEF_STMT (cond_name);
+
+ // Evaluate the value of COND_NAME on the true and false edges, using either
+ // the op1 or op2 routines based on its location.
+ Value_Range cond_true (type), cond_false (type);
+ if (c1)
+ {
+ if (!hand.op1_range (cond_false, type, range_false (), cr))
+ return false;
+ if (!hand.op1_range (cond_true, type, range_true (), cr))
+ return false;
+ cond_false.intersect (cl);
+ cond_true.intersect (cl);
+ }
+ else
+ {
+ if (!hand.op2_range (cond_false, type, range_false (), cl))
+ return false;
+ if (!hand.op2_range (cond_true, type, range_true (), cl))
+ return false;
+ cond_false.intersect (cr);
+ cond_true.intersect (cr);
+ }
+
+ // Now solve for SSA1 or SSA2 if they are in the dependency chain.
+ if (ssa1 && src.gori_ssa()->in_chain_p (ssa1, cond_name))
+ {
+ Value_Range tmp1 (TREE_TYPE (ssa1));
+ if (src.gori ()->compute_operand_range (tmp1, def_stmt, cond_true,
+ ssa1, src))
+ r1.intersect (tmp1);
+ }
+ if (ssa2 && src.gori_ssa ()->in_chain_p (ssa2, cond_name))
+ {
+ Value_Range tmp2 (TREE_TYPE (ssa2));
+ if (src.gori ()->compute_operand_range (tmp2, def_stmt, cond_false,
+ ssa2, src))
+ r2.intersect (tmp2);
+ }
+ return true;
+}
+
// Calculate a range for COND_EXPR statement S and return it in R.
// If a range cannot be calculated, return false.
@@ -1138,16 +1227,15 @@ fold_using_range::range_of_cond_expr (vrange &r, gassign *s, fur_source &src)
src.get_operand (range2, op2);
// Try to see if there is a dependence between the COND and either operand
- if (src.gori ())
- if (src.gori ()->condexpr_adjust (range1, range2, s, cond, op1, op2, src))
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Possible COND_EXPR adjustment. Range op1 : ");
- range1.dump(dump_file);
- fprintf (dump_file, " and Range op2: ");
- range2.dump(dump_file);
- fprintf (dump_file, "\n");
- }
+ if (condexpr_adjust (range1, range2, s, cond, op1, op2, src))
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Possible COND_EXPR adjustment. Range op1 : ");
+ range1.dump(dump_file);
+ fprintf (dump_file, " and Range op2: ");
+ range2.dump(dump_file);
+ fprintf (dump_file, "\n");
+ }
// If the condition is known, choose the appropriate expression.
if (cond_range.singleton_p ())
@@ -1345,14 +1433,14 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range,
}
// Outgoing relations of GORI exports require a gori engine.
- if (!gori_bb ())
+ if (!gori_ssa ())
return;
// Now look for other relations in the exports. This will find stmts
// leading to the condition such as:
// c_2 = a_4 < b_7
// if (c_2)
- FOR_EACH_GORI_EXPORT_NAME (gori_bb (), bb, name)
+ FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb, name)
{
if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE)
continue;
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index b240a6e4c61..491d57386f3 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -106,7 +106,7 @@ class fur_source
public:
fur_source (range_query *q = NULL);
inline range_query *query () const { return m_query; }
- inline gori_map *gori_bb () const
+ inline gori_map *gori_ssa () const
{ return (m_depend_p && m_query) ? m_query->gori_ssa () : NULL; }
inline class gimple_outgoing_range *gori ()
{ return m_depend_p ? &(m_query->gori ()) : NULL; }
@@ -171,5 +171,7 @@ protected:
fur_source &src);
void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src,
vrange &op1, vrange &op2);
+ bool condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond, tree op1,
+ tree op2, fur_source &src);
};
#endif // GCC_GIMPLE_RANGE_FOLD_H
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index a3fe67ede4e..0d471b46903 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -1452,109 +1452,6 @@ gori_compute::edge_range_p (vrange &r, edge e, tree name, range_query &q)
return false;
}
-// Given COND ? OP1 : OP2 with ranges R1 for OP1 and R2 for OP2, Use gori
-// to further resolve R1 and R2 if there are any dependencies between
-// OP1 and COND or OP2 and COND. All values can are to be calculated using SRC
-// as the origination source location for operands..
-// Effectively, use COND an the edge condition and solve for OP1 on the true
-// edge and OP2 on the false edge.
-
-bool
-gori_compute::condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond,
- tree op1, tree op2, fur_source &src)
-{
- tree ssa1 = gimple_range_ssa_p (op1);
- tree ssa2 = gimple_range_ssa_p (op2);
- if (!ssa1 && !ssa2)
- return false;
- if (TREE_CODE (cond) != SSA_NAME)
- return false;
- gassign *cond_def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (cond));
- if (!cond_def
- || TREE_CODE_CLASS (gimple_assign_rhs_code (cond_def)) != tcc_comparison)
- return false;
- tree type = TREE_TYPE (gimple_assign_rhs1 (cond_def));
- if (!range_compatible_p (type, TREE_TYPE (gimple_assign_rhs2 (cond_def))))
- return false;
- range_op_handler hand (gimple_assign_rhs_code (cond_def));
- if (!hand)
- return false;
-
- tree c1 = gimple_range_ssa_p (gimple_assign_rhs1 (cond_def));
- tree c2 = gimple_range_ssa_p (gimple_assign_rhs2 (cond_def));
-
- // Only solve if there is one SSA name in the condition.
- if ((!c1 && !c2) || (c1 && c2))
- return false;
-
- // Pick up the current values of each part of the condition.
- tree rhs1 = gimple_assign_rhs1 (cond_def);
- tree rhs2 = gimple_assign_rhs2 (cond_def);
- Value_Range cl (TREE_TYPE (rhs1));
- Value_Range cr (TREE_TYPE (rhs2));
- src.get_operand (cl, rhs1);
- src.get_operand (cr, rhs2);
-
- tree cond_name = c1 ? c1 : c2;
- gimple *def_stmt = SSA_NAME_DEF_STMT (cond_name);
-
- // Evaluate the value of COND_NAME on the true and false edges, using either
- // the op1 or op2 routines based on its location.
- Value_Range cond_true (type), cond_false (type);
- if (c1)
- {
- if (!hand.op1_range (cond_false, type, m_bool_zero, cr))
- return false;
- if (!hand.op1_range (cond_true, type, m_bool_one, cr))
- return false;
- cond_false.intersect (cl);
- cond_true.intersect (cl);
- }
- else
- {
- if (!hand.op2_range (cond_false, type, m_bool_zero, cl))
- return false;
- if (!hand.op2_range (cond_true, type, m_bool_one, cl))
- return false;
- cond_false.intersect (cr);
- cond_true.intersect (cr);
- }
-
- unsigned idx;
- if ((idx = tracer.header ("cond_expr evaluation : ")))
- {
- fprintf (dump_file, " range1 = ");
- r1.dump (dump_file);
- fprintf (dump_file, ", range2 = ");
- r1.dump (dump_file);
- fprintf (dump_file, "\n");
- }
-
- // Now solve for SSA1 or SSA2 if they are in the dependency chain.
- if (ssa1 && m_map.in_chain_p (ssa1, cond_name))
- {
- Value_Range tmp1 (TREE_TYPE (ssa1));
- if (compute_operand_range (tmp1, def_stmt, cond_true, ssa1, src))
- r1.intersect (tmp1);
- }
- if (ssa2 && m_map.in_chain_p (ssa2, cond_name))
- {
- Value_Range tmp2 (TREE_TYPE (ssa2));
- if (compute_operand_range (tmp2, def_stmt, cond_false, ssa2, src))
- r2.intersect (tmp2);
- }
- if (idx)
- {
- tracer.print (idx, "outgoing: range1 = ");
- r1.dump (dump_file);
- fprintf (dump_file, ", range2 = ");
- r1.dump (dump_file);
- fprintf (dump_file, "\n");
- tracer.trailer (idx, "cond_expr", true, cond_name, cond_true);
- }
- return true;
-}
-
// Dump what is known to GORI computes to listing file F.
void
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index aa8369a6823..9b4bcd919f5 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -168,8 +168,6 @@ public:
int max_sw_edges = 0);
virtual ~gori_compute ();
bool edge_range_p (vrange &r, edge e, tree name, range_query &q);
- bool condexpr_adjust (vrange &r1, vrange &r2, gimple *s, tree cond, tree op1,
- tree op2, fur_source &src);
bool has_edge_range_p (tree name, basic_block bb = NULL);
bool has_edge_range_p (tree name, edge e);
void dump (FILE *f);
--
2.41.0