https://gcc.gnu.org/g:83bb9ad465f0c92c24658702804ee003183a9028
commit r15-808-g83bb9ad465f0c92c24658702804ee003183a9028 Author: Andrew MacLeod <amacl...@redhat.com> Date: Tue May 21 12:41:49 2024 -0400 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. * gimple-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. Diff: --- 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);