]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add operand ranges to op1_op2_relation API.
authorAndrew MacLeod <amacleod@redhat.com>
Tue, 1 Aug 2023 18:33:09 +0000 (14:33 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Thu, 3 Aug 2023 18:19:54 +0000 (14:19 -0400)
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
gcc/gimple-range-fold.h
gcc/gimple-range-gori.cc
gcc/range-op-float.cc
gcc/range-op-mixed.h
gcc/range-op.cc
gcc/range-op.h

index ab2d996c4ebfb38acd1f00075cfcd151df75841e..7fa5a27cb12b2e34e7f7973022ee407d293852ef 100644 (file)
@@ -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 <irange> (r), s, src);
+           relation_fold_and_or (as_a <irange> (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);
            }
index 939b7a76f0e341491f9212d8e6b55f4a0d5d784c..fcbe162679032f66eb433b2dbc74052195490898 100644 (file)
@@ -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
index c37e54bcf842a596b3b18ed88a7dbb573c6e911f..51fb542a19cbcfe5696a68ab632291ec63cd1fe8 100644 (file)
@@ -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);
index a8d39cff27f559b885b47a2f7236ce1e9655f76a..e30b489c410eb30aa88cad415f375cf789195e51 100644 (file)
@@ -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
index b623a88cc719c785728a2f59aee0dcd3e969bf72..825f934cf603488b99146e20d3e5111972cf73d0 100644 (file)
@@ -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;
 };
index 19fdff0eb6479b596b7ebe7a34555744d0565cb8..086c6c19735831aea513f03179d4535202b6df69 100644 (file)
@@ -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 <irange> (lhs));
+       return m_operator->op1_op2_relation (as_a <irange> (lhs),
+                                            as_a <irange> (op1),
+                                            as_a <irange> (op2));
+
+      case RO_IFF:
+       return m_operator->op1_op2_relation (as_a <irange> (lhs),
+                                            as_a <frange> (op1),
+                                            as_a <frange> (op2));
 
       case RO_FFF:
-       return m_operator->op1_op2_relation (as_a <frange> (lhs));
+       return m_operator->op1_op2_relation (as_a <frange> (lhs),
+                                            as_a <frange> (op1),
+                                            as_a <frange> (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;
index af94c2756a74f710aa50aec1ac3b3de5eeb43a8e..51121410233f73ad715ae38296f186d672c77eee 100644 (file)
@@ -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;