From 9fedc3c010ff81f290e4e97cbcd0847ca803dcc4 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 1 Aug 2023 14:33:09 -0400 Subject: Add operand ranges to op1_op2_relation API. With additional floating point relations in the pipeline, we can no longer tell based on the LHS what the relation of X < Y is without knowing the type of X and Y. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Add ranges to the call to relation_fold_and_or. (fold_using_range::relation_fold_and_or): Add op1 and op2 ranges. (fur_source::register_outgoing_edges): Add op1 and op2 ranges. * gimple-range-fold.h (relation_fold_and_or): Adjust params. * gimple-range-gori.cc (gori_compute::compute_operand_range): Add a varying op1 and op2 to call. * range-op-float.cc (range_operator::op1_op2_relation): New dafaults. (operator_equal::op1_op2_relation): New float version. (operator_not_equal::op1_op2_relation): Ditto. (operator_lt::op1_op2_relation): Ditto. (operator_le::op1_op2_relation): Ditto. (operator_gt::op1_op2_relation): Ditto. (operator_ge::op1_op2_relation) Ditto. * range-op-mixed.h (operator_equal::op1_op2_relation): New float prototype. (operator_not_equal::op1_op2_relation): Ditto. (operator_lt::op1_op2_relation): Ditto. (operator_le::op1_op2_relation): Ditto. (operator_gt::op1_op2_relation): Ditto. (operator_ge::op1_op2_relation): Ditto. * range-op.cc (range_op_handler::op1_op2_relation): Dispatch new variations. (range_operator::op1_op2_relation): Add extra params. (operator_equal::op1_op2_relation): Ditto. (operator_not_equal::op1_op2_relation): Ditto. (operator_lt::op1_op2_relation): Ditto. (operator_le::op1_op2_relation): Ditto. (operator_gt::op1_op2_relation): Ditto. (operator_ge::op1_op2_relation): Ditto. * range-op.h (range_operator): New prototypes. (range_op_handler): Ditto. --- gcc/gimple-range-fold.cc | 26 ++++++---- gcc/gimple-range-fold.h | 3 +- gcc/gimple-range-gori.cc | 5 +- gcc/range-op-float.cc | 129 ++++++++++++++++++++++++++++++++++++++++++++++- gcc/range-op-mixed.h | 30 ++++++++--- gcc/range-op.cc | 41 +++++++++++---- gcc/range-op.h | 15 ++++-- 7 files changed, 216 insertions(+), 33 deletions(-) (limited to 'gcc') diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index ab2d996..7fa5a27 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -700,7 +700,7 @@ fold_using_range::range_of_range_op (vrange &r, relation_trio::op1_op2 (rel))) r.set_varying (type); if (irange::supports_p (type)) - relation_fold_and_or (as_a (r), s, src); + relation_fold_and_or (as_a (r), s, src, range1, range2); if (lhs) { if (src.gori ()) @@ -1103,7 +1103,8 @@ fold_using_range::range_of_ssa_name_with_loop_info (vrange &r, tree name, void fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, - fur_source &src) + fur_source &src, vrange &op1, + vrange &op2) { // No queries or already folded. if (!src.gori () || !src.query ()->oracle () || lhs_range.singleton_p ()) @@ -1164,9 +1165,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, return; int_range<2> bool_one = range_true (); - - relation_kind relation1 = handler1.op1_op2_relation (bool_one); - relation_kind relation2 = handler2.op1_op2_relation (bool_one); + relation_kind relation1 = handler1.op1_op2_relation (bool_one, op1, op2); + relation_kind relation2 = handler2.op1_op2_relation (bool_one, op1, op2); if (relation1 == VREL_VARYING || relation2 == VREL_VARYING) return; @@ -1201,7 +1201,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, // Register any outgoing edge relations from a conditional branch. void -fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge e1) +fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, + edge e0, edge e1) { int_range<2> e0_range, e1_range; tree name; @@ -1236,17 +1237,20 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge // if (a_2 < b_5) tree ssa1 = gimple_range_ssa_p (handler.operand1 ()); tree ssa2 = gimple_range_ssa_p (handler.operand2 ()); + Value_Range r1,r2; if (ssa1 && ssa2) { + r1.set_varying (TREE_TYPE (ssa1)); + r2.set_varying (TREE_TYPE (ssa2)); if (e0) { - relation_kind relation = handler.op1_op2_relation (e0_range); + relation_kind relation = handler.op1_op2_relation (e0_range, r1, r2); if (relation != VREL_VARYING) register_relation (e0, relation, ssa1, ssa2); } if (e1) { - relation_kind relation = handler.op1_op2_relation (e1_range); + relation_kind relation = handler.op1_op2_relation (e1_range, r1, r2); if (relation != VREL_VARYING) register_relation (e1, relation, ssa1, ssa2); } @@ -1273,17 +1277,19 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge Value_Range r (TREE_TYPE (name)); if (ssa1 && ssa2) { + r1.set_varying (TREE_TYPE (ssa1)); + r2.set_varying (TREE_TYPE (ssa2)); if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query) && r.singleton_p ()) { - relation_kind relation = handler.op1_op2_relation (r); + relation_kind relation = handler.op1_op2_relation (r, r1, r2); if (relation != VREL_VARYING) register_relation (e0, relation, ssa1, ssa2); } if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query) && r.singleton_p ()) { - relation_kind relation = handler.op1_op2_relation (r); + relation_kind relation = handler.op1_op2_relation (r, r1, r2); if (relation != VREL_VARYING) register_relation (e1, relation, ssa1, ssa2); } diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 939b7a7..fcbe162 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -173,6 +173,7 @@ protected: bool range_of_phi (vrange &r, gphi *phi, fur_source &src); void range_of_ssa_name_with_loop_info (vrange &, tree, class loop *, gphi *, fur_source &src); - void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src); + void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src, + vrange &op1, vrange &op2); }; #endif // GCC_GIMPLE_RANGE_FOLD_H diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index c37e54b..51fb542 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -627,7 +627,10 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt, // likely to be more applicable. if (op1 && op2) { - relation_kind k = handler.op1_op2_relation (lhs); + Value_Range r1, r2; + r1.set_varying (TREE_TYPE (op1)); + r2.set_varying (TREE_TYPE (op2)); + relation_kind k = handler.op1_op2_relation (lhs, r1, r2); if (k != VREL_VARYING) { vrel.set_relation (k, op1, op2); diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index a8d39cf..e30b489 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -244,7 +244,18 @@ range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED, } relation_kind -range_operator::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const +range_operator::op1_op2_relation (const irange &, + const frange &, + const frange &) const +{ + return VREL_VARYING; +} + + +relation_kind +range_operator::op1_op2_relation (const frange &, + const frange &, + const frange &) const { return VREL_VARYING; } @@ -705,6 +716,25 @@ operator_equal::op1_range (frange &r, tree type, return true; } +// Check if the LHS range indicates a relation between OP1 and OP2. + +relation_kind +operator_equal::op1_op2_relation (const irange &lhs, const frange &, + const frange &) const +{ + if (lhs.undefined_p ()) + return VREL_UNDEFINED; + + // FALSE = op1 == op2 indicates NE_EXPR. + if (lhs.zero_p ()) + return VREL_NE; + + // TRUE = op1 == op2 indicates EQ_EXPR. + if (lhs.undefined_p () || !contains_zero_p (lhs)) + return VREL_EQ; + return VREL_VARYING; +} + bool operator_not_equal::fold_range (irange &r, tree type, const frange &op1, const frange &op2, @@ -809,6 +839,26 @@ operator_not_equal::op1_range (frange &r, tree type, return true; } + +// Check if the LHS range indicates a relation between OP1 and OP2. + +relation_kind +operator_not_equal::op1_op2_relation (const irange &lhs, const frange &, + const frange &) const +{ + if (lhs.undefined_p ()) + return VREL_UNDEFINED; + + // FALSE = op1 != op2 indicates EQ_EXPR. + if (lhs.zero_p ()) + return VREL_EQ; + + // TRUE = op1 != op2 indicates NE_EXPR. + if (lhs.undefined_p () || !contains_zero_p (lhs)) + return VREL_NE; + return VREL_VARYING; +} + bool operator_lt::fold_range (irange &r, tree type, const frange &op1, const frange &op2, @@ -903,6 +953,26 @@ operator_lt::op2_range (frange &r, return true; } + +// Check if the LHS range indicates a relation between OP1 and OP2. + +relation_kind +operator_lt::op1_op2_relation (const irange &lhs, const frange &, + const frange &) const +{ + if (lhs.undefined_p ()) + return VREL_UNDEFINED; + + // FALSE = op1 < op2 indicates GE_EXPR. + if (lhs.zero_p ()) + return VREL_GE; + + // TRUE = op1 < op2 indicates LT_EXPR. + if (lhs.undefined_p () || !contains_zero_p (lhs)) + return VREL_LT; + return VREL_VARYING; +} + bool operator_le::fold_range (irange &r, tree type, const frange &op1, const frange &op2, @@ -991,6 +1061,25 @@ operator_le::op2_range (frange &r, return true; } +// Check if the LHS range indicates a relation between OP1 and OP2. + +relation_kind +operator_le::op1_op2_relation (const irange &lhs, const frange &, + const frange &) const +{ + if (lhs.undefined_p ()) + return VREL_UNDEFINED; + + // FALSE = op1 <= op2 indicates GT_EXPR. + if (lhs.zero_p ()) + return VREL_GT; + + // TRUE = op1 <= op2 indicates LE_EXPR. + if (lhs.undefined_p () || !contains_zero_p (lhs)) + return VREL_LE; + return VREL_VARYING; +} + bool operator_gt::fold_range (irange &r, tree type, const frange &op1, const frange &op2, @@ -1089,6 +1178,25 @@ operator_gt::op2_range (frange &r, return true; } +// Check if the LHS range indicates a relation between OP1 and OP2. + +relation_kind +operator_gt::op1_op2_relation (const irange &lhs, const frange &, + const frange &) const +{ + if (lhs.undefined_p ()) + return VREL_UNDEFINED; + + // FALSE = op1 > op2 indicates LE_EXPR. + if (lhs.zero_p ()) + return VREL_LE; + + // TRUE = op1 > op2 indicates GT_EXPR. + if (!contains_zero_p (lhs)) + return VREL_GT; + return VREL_VARYING; +} + bool operator_ge::fold_range (irange &r, tree type, const frange &op1, const frange &op2, @@ -1178,6 +1286,25 @@ operator_ge::op2_range (frange &r, tree type, return true; } +// Check if the LHS range indicates a relation between OP1 and OP2. + +relation_kind +operator_ge::op1_op2_relation (const irange &lhs, const frange &, + const frange &) const +{ + if (lhs.undefined_p ()) + return VREL_UNDEFINED; + + // FALSE = op1 >= op2 indicates LT_EXPR. + if (lhs.zero_p ()) + return VREL_LT; + + // TRUE = op1 >= op2 indicates GE_EXPR. + if (!contains_zero_p (lhs)) + return VREL_GE; + return VREL_VARYING; +} + // UNORDERED_EXPR comparison. class foperator_unordered : public range_operator diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h index b623a88..825f934 100644 --- a/gcc/range-op-mixed.h +++ b/gcc/range-op-mixed.h @@ -132,7 +132,10 @@ public: const irange &lhs, const frange &op1, relation_trio rel = TRIO_VARYING) const final override; - relation_kind op1_op2_relation (const irange &lhs) const final override; + relation_kind op1_op2_relation (const irange &lhs, const irange &, + const irange &) const final override; + relation_kind op1_op2_relation (const irange &lhs, const frange &, + const frange &) const final override; void update_bitmask (irange &r, const irange &lh, const irange &rh) const final override; }; @@ -162,7 +165,10 @@ public: const irange &lhs, const irange &op1, relation_trio = TRIO_VARYING) const final override; - relation_kind op1_op2_relation (const irange &lhs) const final override; + relation_kind op1_op2_relation (const irange &lhs, const irange &, + const irange &) const final override; + relation_kind op1_op2_relation (const irange &lhs, const frange &, + const frange &) const final override; void update_bitmask (irange &r, const irange &lh, const irange &rh) const final override; }; @@ -192,7 +198,10 @@ public: bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, relation_trio = TRIO_VARYING) const final override; - relation_kind op1_op2_relation (const irange &lhs) const final override; + relation_kind op1_op2_relation (const irange &lhs, const irange &, + const irange &) const final override; + relation_kind op1_op2_relation (const irange &lhs, const frange &, + const frange &) const final override; void update_bitmask (irange &r, const irange &lh, const irange &rh) const final override; }; @@ -225,7 +234,10 @@ public: const irange &lhs, const frange &op1, relation_trio rel = TRIO_VARYING) const final override; - relation_kind op1_op2_relation (const irange &lhs) const final override; + relation_kind op1_op2_relation (const irange &lhs, const irange &, + const irange &) const final override; + relation_kind op1_op2_relation (const irange &lhs, const frange &, + const frange &) const final override; void update_bitmask (irange &r, const irange &lh, const irange &rh) const final override; }; @@ -257,7 +269,10 @@ public: bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, relation_trio = TRIO_VARYING) const final override; - relation_kind op1_op2_relation (const irange &lhs) const final override; + relation_kind op1_op2_relation (const irange &lhs, const irange &, + const irange &) const final override; + relation_kind op1_op2_relation (const irange &lhs, const frange &, + const frange &) const final override; void update_bitmask (irange &r, const irange &lh, const irange &rh) const final override; }; @@ -290,7 +305,10 @@ public: const irange &lhs, const frange &op1, relation_trio = TRIO_VARYING) const final override; - relation_kind op1_op2_relation (const irange &lhs) const final override; + relation_kind op1_op2_relation (const irange &lhs, const irange &, + const irange &) const final override; + relation_kind op1_op2_relation (const irange &lhs, const frange &, + const frange &) const final override; void update_bitmask (irange &r, const irange &lh, const irange &rh) const final override; }; diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 19fdff0..086c6c1 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -350,16 +350,27 @@ range_op_handler::lhs_op2_relation (const vrange &lhs, // Dispatch a call to op1_op2_relation based on the type of LHS. relation_kind -range_op_handler::op1_op2_relation (const vrange &lhs) const +range_op_handler::op1_op2_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2) const { gcc_checking_assert (m_operator); - switch (dispatch_kind (lhs, lhs, lhs)) + switch (dispatch_kind (lhs, op1, op2)) { case RO_III: - return m_operator->op1_op2_relation (as_a (lhs)); + return m_operator->op1_op2_relation (as_a (lhs), + as_a (op1), + as_a (op2)); + + case RO_IFF: + return m_operator->op1_op2_relation (as_a (lhs), + as_a (op1), + as_a (op2)); case RO_FFF: - return m_operator->op1_op2_relation (as_a (lhs)); + return m_operator->op1_op2_relation (as_a (lhs), + as_a (op1), + as_a (op2)); default: return VREL_VARYING; @@ -676,7 +687,9 @@ range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED, } relation_kind -range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const +range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED, + const irange &op1 ATTRIBUTE_UNUSED, + const irange &op2 ATTRIBUTE_UNUSED) const { return VREL_VARYING; } @@ -868,7 +881,8 @@ operator_equal::update_bitmask (irange &r, const irange &lh, // Check if the LHS range indicates a relation between OP1 and OP2. relation_kind -operator_equal::op1_op2_relation (const irange &lhs) const +operator_equal::op1_op2_relation (const irange &lhs, const irange &, + const irange &) const { if (lhs.undefined_p ()) return VREL_UNDEFINED; @@ -969,7 +983,8 @@ operator_not_equal::update_bitmask (irange &r, const irange &lh, // Check if the LHS range indicates a relation between OP1 and OP2. relation_kind -operator_not_equal::op1_op2_relation (const irange &lhs) const +operator_not_equal::op1_op2_relation (const irange &lhs, const irange &, + const irange &) const { if (lhs.undefined_p ()) return VREL_UNDEFINED; @@ -1129,7 +1144,8 @@ operator_lt::update_bitmask (irange &r, const irange &lh, // Check if the LHS range indicates a relation between OP1 and OP2. relation_kind -operator_lt::op1_op2_relation (const irange &lhs) const +operator_lt::op1_op2_relation (const irange &lhs, const irange &, + const irange &) const { if (lhs.undefined_p ()) return VREL_UNDEFINED; @@ -1229,7 +1245,8 @@ operator_le::update_bitmask (irange &r, const irange &lh, // Check if the LHS range indicates a relation between OP1 and OP2. relation_kind -operator_le::op1_op2_relation (const irange &lhs) const +operator_le::op1_op2_relation (const irange &lhs, const irange &, + const irange &) const { if (lhs.undefined_p ()) return VREL_UNDEFINED; @@ -1326,7 +1343,8 @@ operator_gt::update_bitmask (irange &r, const irange &lh, // Check if the LHS range indicates a relation between OP1 and OP2. relation_kind -operator_gt::op1_op2_relation (const irange &lhs) const +operator_gt::op1_op2_relation (const irange &lhs, const irange &, + const irange &) const { if (lhs.undefined_p ()) return VREL_UNDEFINED; @@ -1421,7 +1439,8 @@ operator_ge::update_bitmask (irange &r, const irange &lh, // Check if the LHS range indicates a relation between OP1 and OP2. relation_kind -operator_ge::op1_op2_relation (const irange &lhs) const +operator_ge::op1_op2_relation (const irange &lhs, const irange &, + const irange &) const { if (lhs.undefined_p ()) return VREL_UNDEFINED; diff --git a/gcc/range-op.h b/gcc/range-op.h index af94c27..5112141 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -145,8 +145,15 @@ public: const frange &op2, relation_kind = VREL_VARYING) const; - virtual relation_kind op1_op2_relation (const irange &lhs) const; - virtual relation_kind op1_op2_relation (const frange &lhs) const; + virtual relation_kind op1_op2_relation (const irange &lhs, + const irange &op1, + const irange &op2) const; + virtual relation_kind op1_op2_relation (const irange &lhs, + const frange &op1, + const frange &op2) const; + virtual relation_kind op1_op2_relation (const frange &lhs, + const frange &op1, + const frange &op2) const; protected: // Perform an integral operation between 2 sub-ranges and return it. virtual void wi_fold (irange &r, tree type, @@ -213,7 +220,9 @@ public: const vrange &op1, const vrange &op2, relation_kind = VREL_VARYING) const; - relation_kind op1_op2_relation (const vrange &lhs) const; + relation_kind op1_op2_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2) const; protected: unsigned dispatch_kind (const vrange &lhs, const vrange &op1, const vrange& op2) const; -- cgit v1.1