From e925119d520ac10674ed42faf14955aaf130c03b Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 31 May 2023 12:31:53 -0400
Subject: [PATCH 3/4] Unify range_operators to one class.

Range_operator and range_operator_float are 2 different classes, making
generalized dispatch difficult.  The distinction between what is a float
operator and what is an integral operator also blurs when some methods
have multiple types.  ie, casts : INT = FLOAT and FLOAT = INT

This patch unifies all possible invocation patterns in one class, and
switches the float table to use the general range_op_table.

	* gimple-range-op.cc (cfn_constant_float_p): Change base class.
	(cfn_pass_through_arg1): Adjust using statemenmt.
	(cfn_signbit): Change base class, adjust using statement.
	(cfn_copysign): Ditto.
	(cfn_sqrt): Ditto.
	(cfn_sincos): Ditto.
	* range-op-float.cc (fold_range): Change class to range_operator.
	(rv_fold): Ditto.
	(op1_range): Ditto
	(op2_range): Ditto
	(lhs_op1_relation): Ditto.
	(lhs_op2_relation): Ditto.
	(op1_op2_relation): Ditto.
	(foperator_*): Ditto.
	(class float_table): New.  Inherit from range_op_table.
	(floating_tree_table) Change to range_op_table pointer.
	(class floating_op_table): Delete.
	* range-op.cc (operator_equal): Adjust using statement.
	(operator_not_equal): Ditto.
	(operator_lt, operator_le, operator_gt, operator_ge): Ditto.
	(operator_minus, operator_cast): Ditto.
	(operator_bitwise_and, pointer_plus_operator): Ditto.
	(get_float_handle): Change return type.
	* range-op.h (range_operator_float): Delete.  Relocate all methods
	into class range_operator.
	(range_op_handler::m_float): Change type to range_operator.
	(floating_op_table): Delete.
	(floating_tree_table): Change type.
---
 gcc/gimple-range-op.cc |  27 ++---
 gcc/range-op-float.cc  | 222 +++++++++++++++++++----------------------
 gcc/range-op.cc        |  12 ++-
 gcc/range-op.h         | 124 +++++++++++------------
 4 files changed, 183 insertions(+), 202 deletions(-)

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 59c47e2074d..293d76402e1 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -268,10 +268,10 @@ gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
 // --------------------------------------------------------------------
 
 // Implement range operator for float CFN_BUILT_IN_CONSTANT_P.
-class cfn_constant_float_p : public range_operator_float
+class cfn_constant_float_p : public range_operator
 {
 public:
-  using range_operator_float::fold_range;
+  using range_operator::fold_range;
   virtual bool fold_range (irange &r, tree type, const frange &lh,
 			   const irange &, relation_trio) const
   {
@@ -319,6 +319,7 @@ class cfn_pass_through_arg1 : public range_operator
 {
 public:
   using range_operator::fold_range;
+  using range_operator::op1_range;
   virtual bool fold_range (irange &r, tree, const irange &lh,
 			   const irange &, relation_trio) const
   {
@@ -334,11 +335,11 @@ public:
 } op_cfn_pass_through_arg1;
 
 // Implement range operator for CFN_BUILT_IN_SIGNBIT.
-class cfn_signbit : public range_operator_float
+class cfn_signbit : public range_operator
 {
 public:
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
   virtual bool fold_range (irange &r, tree type, const frange &lh,
 			   const irange &, relation_trio) const override
   {
@@ -373,10 +374,10 @@ public:
 } op_cfn_signbit;
 
 // Implement range operator for CFN_BUILT_IN_COPYSIGN
-class cfn_copysign : public range_operator_float
+class cfn_copysign : public range_operator
 {
 public:
-  using range_operator_float::fold_range;
+  using range_operator::fold_range;
   virtual bool fold_range (frange &r, tree type, const frange &lh,
 			   const frange &rh, relation_trio) const override
   {
@@ -464,11 +465,11 @@ frange_mpfr_arg1 (REAL_VALUE_TYPE *res_low, REAL_VALUE_TYPE *res_high,
   return true;
 }
 
-class cfn_sqrt : public range_operator_float
+class cfn_sqrt : public range_operator
 {
 public:
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
   virtual bool fold_range (frange &r, tree type,
 			   const frange &lh, const frange &,
 			   relation_trio) const final override
@@ -599,11 +600,11 @@ public:
   }
 } op_cfn_sqrt;
 
-class cfn_sincos : public range_operator_float
+class cfn_sincos : public range_operator
 {
 public:
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
   cfn_sincos (combined_fn cfn) { m_cfn = cfn; }
   virtual bool fold_range (frange &r, tree type,
 			   const frange &lh, const frange &,
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index af598b60a79..bb10accd78f 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -49,7 +49,7 @@ along with GCC; see the file COPYING3.  If not see
 // Default definitions for floating point operators.
 
 bool
-range_operator_float::fold_range (frange &r, tree type,
+range_operator::fold_range (frange &r, tree type,
 				  const frange &op1, const frange &op2,
 				  relation_trio trio) const
 {
@@ -121,7 +121,7 @@ range_operator_float::fold_range (frange &r, tree type,
 // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
 // UB, the final range has the possibility of a NAN.
 void
-range_operator_float::rv_fold (REAL_VALUE_TYPE &lb,
+range_operator::rv_fold (REAL_VALUE_TYPE &lb,
 			       REAL_VALUE_TYPE &ub,
 			       bool &maybe_nan,
 			       tree type ATTRIBUTE_UNUSED,
@@ -137,7 +137,7 @@ range_operator_float::rv_fold (REAL_VALUE_TYPE &lb,
 }
 
 bool
-range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
+range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
 				  tree type ATTRIBUTE_UNUSED,
 				  const frange &lh ATTRIBUTE_UNUSED,
 				  const irange &rh ATTRIBUTE_UNUSED,
@@ -147,7 +147,7 @@ range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
+range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
 				  tree type ATTRIBUTE_UNUSED,
 				  const frange &lh ATTRIBUTE_UNUSED,
 				  const frange &rh ATTRIBUTE_UNUSED,
@@ -157,7 +157,7 @@ range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
 				 tree type ATTRIBUTE_UNUSED,
 				 const frange &lhs ATTRIBUTE_UNUSED,
 				 const frange &op2 ATTRIBUTE_UNUSED,
@@ -167,7 +167,7 @@ range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
 				 tree type ATTRIBUTE_UNUSED,
 				 const irange &lhs ATTRIBUTE_UNUSED,
 				 const frange &op2 ATTRIBUTE_UNUSED,
@@ -177,7 +177,7 @@ range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
 				 tree type ATTRIBUTE_UNUSED,
 				 const frange &lhs ATTRIBUTE_UNUSED,
 				 const frange &op1 ATTRIBUTE_UNUSED,
@@ -187,7 +187,7 @@ range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
 				 tree type ATTRIBUTE_UNUSED,
 				 const irange &lhs ATTRIBUTE_UNUSED,
 				 const frange &op1 ATTRIBUTE_UNUSED,
@@ -197,7 +197,7 @@ range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
 					const frange &op1 ATTRIBUTE_UNUSED,
 					const frange &op2 ATTRIBUTE_UNUSED,
 					relation_kind) const
@@ -206,7 +206,7 @@ range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
 					const frange &op1 ATTRIBUTE_UNUSED,
 					const frange &op2 ATTRIBUTE_UNUSED,
 					relation_kind) const
@@ -215,7 +215,7 @@ range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
 					const frange &op1 ATTRIBUTE_UNUSED,
 					const frange &op2 ATTRIBUTE_UNUSED,
 					relation_kind) const
@@ -224,7 +224,7 @@ range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
 					const frange &op1 ATTRIBUTE_UNUSED,
 					const frange &op2 ATTRIBUTE_UNUSED,
 					relation_kind) const
@@ -233,13 +233,7 @@ range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
 }
 
 relation_kind
-range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
-{
-  return VREL_VARYING;
-}
-
-relation_kind
-range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
+range_operator::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
 {
   return VREL_VARYING;
 }
@@ -546,10 +540,10 @@ build_gt (frange &r, tree type, const frange &val)
 }
 
 
-class foperator_identity : public range_operator_float
+class foperator_identity : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
 public:
   bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
 		   const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
@@ -568,12 +562,12 @@ public:
 public:
 } fop_identity;
 
-class foperator_equal : public range_operator_float
+class foperator_equal : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
-  using range_operator_float::op1_op2_relation;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -697,11 +691,11 @@ foperator_equal::op1_range (frange &r, tree type,
   return true;
 }
 
-class foperator_not_equal : public range_operator_float
+class foperator_not_equal : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op1_op2_relation;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -819,12 +813,12 @@ foperator_not_equal::op1_range (frange &r, tree type,
   return true;
 }
 
-class foperator_lt : public range_operator_float
+class foperator_lt : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
-  using range_operator_float::op1_op2_relation;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -935,12 +929,12 @@ foperator_lt::op2_range (frange &r,
   return true;
 }
 
-class foperator_le : public range_operator_float
+class foperator_le : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
-  using range_operator_float::op1_op2_relation;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1045,12 +1039,12 @@ foperator_le::op2_range (frange &r,
   return true;
 }
 
-class foperator_gt : public range_operator_float
+class foperator_gt : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
-  using range_operator_float::op1_op2_relation;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1165,12 +1159,12 @@ foperator_gt::op2_range (frange &r,
   return true;
 }
 
-class foperator_ge : public range_operator_float
+class foperator_ge : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
-  using range_operator_float::op1_op2_relation;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1278,11 +1272,11 @@ foperator_ge::op2_range (frange &r, tree type,
 
 // UNORDERED_EXPR comparison.
 
-class foperator_unordered : public range_operator_float
+class foperator_unordered : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1352,11 +1346,11 @@ foperator_unordered::op1_range (frange &r, tree type,
 
 // ORDERED_EXPR comparison.
 
-class foperator_ordered : public range_operator_float
+class foperator_ordered : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1421,10 +1415,10 @@ foperator_ordered::op1_range (frange &r, tree type,
   return true;
 }
 
-class foperator_negate : public range_operator_float
+class foperator_negate : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
 public:
   bool fold_range (frange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1467,10 +1461,10 @@ public:
   }
 } fop_negate;
 
-class foperator_abs : public range_operator_float
+class foperator_abs : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
 public:
   bool fold_range (frange &r, tree type,
 		   const frange &op1, const frange &,
@@ -1566,11 +1560,11 @@ foperator_abs::op1_range (frange &r, tree type,
   return true;
 }
 
-class foperator_unordered_lt : public range_operator_float
+class foperator_unordered_lt : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1677,11 +1671,11 @@ foperator_unordered_lt::op2_range (frange &r, tree type,
   return true;
 }
 
-class foperator_unordered_le : public range_operator_float
+class foperator_unordered_le : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1784,11 +1778,11 @@ foperator_unordered_le::op2_range (frange &r,
   return true;
 }
 
-class foperator_unordered_gt : public range_operator_float
+class foperator_unordered_gt : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -1895,11 +1889,11 @@ foperator_unordered_gt::op2_range (frange &r,
   return true;
 }
 
-class foperator_unordered_ge : public range_operator_float
+class foperator_unordered_ge : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -2005,11 +1999,11 @@ foperator_unordered_ge::op2_range (frange &r, tree type,
   return true;
 }
 
-class foperator_unordered_equal : public range_operator_float
+class foperator_unordered_equal : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -2086,11 +2080,11 @@ foperator_unordered_equal::op1_range (frange &r, tree type,
   return true;
 }
 
-class foperator_ltgt : public range_operator_float
+class foperator_ltgt : public range_operator
 {
-  using range_operator_float::fold_range;
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::fold_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   bool fold_range (irange &r, tree type,
 		   const frange &op1, const frange &op2,
@@ -2374,10 +2368,10 @@ float_widen_lhs_range (tree type, const frange &lhs)
   return ret;
 }
 
-class foperator_plus : public range_operator_float
+class foperator_plus : public range_operator
 {
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   virtual bool op1_range (frange &r, tree type,
 			  const frange &lhs,
@@ -2424,10 +2418,10 @@ private:
 } fop_plus;
 
 
-class foperator_minus : public range_operator_float
+class foperator_minus : public range_operator
 {
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   virtual bool op1_range (frange &r, tree type,
 			  const frange &lhs,
@@ -2476,7 +2470,7 @@ private:
 } fop_minus;
 
 
-class foperator_mult_div_base : public range_operator_float
+class foperator_mult_div_base : public range_operator
 {
 protected:
   // Given CP[0] to CP[3] floating point values rounded to -INF,
@@ -2503,8 +2497,8 @@ protected:
 
 class foperator_mult : public foperator_mult_div_base
 {
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   virtual bool op1_range (frange &r, tree type,
 			  const frange &lhs,
@@ -2659,8 +2653,8 @@ private:
 
 class foperator_div : public foperator_mult_div_base
 {
-  using range_operator_float::op1_range;
-  using range_operator_float::op2_range;
+  using range_operator::op1_range;
+  using range_operator::op2_range;
 public:
   virtual bool op1_range (frange &r, tree type,
 			  const frange &lhs,
@@ -2814,12 +2808,16 @@ private:
 } fop_div;
 
 // Instantiate a range_op_table for floating point operations.
-static floating_op_table global_floating_table;
+class float_table : public range_op_table
+{
+  public:
+    float_table ();
+} global_floating_table;
 
 // Pointer to the float table so the dispatch code can access it.
-floating_op_table *floating_tree_table = &global_floating_table;
+range_op_table *floating_tree_table = &global_floating_table;
 
-floating_op_table::floating_op_table ()
+float_table::float_table ()
 {
   set (SSA_NAME, fop_identity);
   set (PAREN_EXPR, fop_identity);
@@ -2852,24 +2850,6 @@ floating_op_table::floating_op_table ()
   set (RDIV_EXPR, fop_div);
 }
 
-// Return a pointer to the range_operator_float instance, if there is
-// one associated with tree_code CODE.
-
-range_operator_float *
-floating_op_table::operator[] (enum tree_code code)
-{
-  return m_range_tree[code];
-}
-
-// Add OP to the handler table for CODE.
-
-void
-floating_op_table::set (enum tree_code code, range_operator_float &op)
-{
-  gcc_checking_assert (m_range_tree[code] == NULL);
-  m_range_tree[code] = &op;
-}
-
 #if CHECKING_P
 #include "selftest.h"
 
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 2deca3bac93..203c30f6e94 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -556,6 +556,7 @@ class operator_equal : public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -678,6 +679,7 @@ class operator_not_equal : public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -860,6 +862,7 @@ class operator_lt :  public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -982,6 +985,7 @@ class operator_le :  public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -1101,6 +1105,7 @@ class operator_gt :  public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -1219,6 +1224,7 @@ class operator_ge :  public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -1647,6 +1653,7 @@ class operator_minus : public range_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::lhs_op1_relation;
 public:
   virtual bool op1_range (irange &r, tree type,
 			  const irange &lhs,
@@ -2710,6 +2717,7 @@ class operator_cast: public range_operator
 {
   using range_operator::fold_range;
   using range_operator::op1_range;
+  using range_operator::lhs_op1_relation;
 public:
   virtual bool fold_range (irange &r, tree type,
 			   const irange &op1,
@@ -3055,6 +3063,7 @@ class operator_bitwise_and : public range_operator
 {
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::lhs_op1_relation;
 public:
   virtual bool op1_range (irange &r, tree type,
 			  const irange &lhs,
@@ -4410,6 +4419,7 @@ operator_addr_expr::op1_range (irange &r, tree type,
 
 class pointer_plus_operator : public range_operator
 {
+  using range_operator::op2_range;
 public:
   virtual void wi_fold (irange &r, tree type,
 		        const wide_int &lh_lb,
@@ -4719,7 +4729,7 @@ get_handler (enum tree_code code, tree type)
 
 // Return the floating point operator for CODE or NULL if none available.
 
-static inline range_operator_float *
+static inline range_operator *
 get_float_handler (enum tree_code code, tree)
 {
   return (*floating_tree_table)[code];
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 5bfbc89df52..cad16f4cd20 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -45,6 +45,11 @@ along with GCC; see the file COPYING3.  If not see
 //     non-zero.  This is mostly for logical true false, but can serve other
 //     purposes.
 //       ie   0 = op1 - op2 implies op2 has the same range as op1.
+//
+// 4 - All supported range combinations are explicitly specified.
+//     Any desired combinations should be implemented for each operator.
+//     When new range classes are added, new matching prototypes should be
+//     added.
 
 class range_operator
 {
@@ -55,6 +60,18 @@ public:
 			   const irange &lh,
 			   const irange &rh,
 			   relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (frange &r, tree type,
+			   const frange &lh,
+			   const frange &rh,
+			   relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (irange &r, tree type,
+			   const frange &lh,
+			   const irange &rh,
+			   relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (irange &r, tree type,
+			   const frange &lh,
+			   const frange &rh,
+			   relation_trio = TRIO_VARYING) const;
 
   // Return the range for op[12] in the general case.  LHS is the range for
   // the LHS of the expression, OP[12]is the range for the other
@@ -71,10 +88,28 @@ public:
 			  const irange &lhs,
 			  const irange &op2,
 			  relation_trio = TRIO_VARYING) const;
+  virtual bool op1_range (frange &r, tree type,
+			  const frange &lhs,
+			  const frange &op2,
+			  relation_trio = TRIO_VARYING) const;
+  virtual bool op1_range (frange &r, tree type,
+			  const irange &lhs,
+			  const frange &op2,
+			  relation_trio = TRIO_VARYING) const;
+
+
   virtual bool op2_range (irange &r, tree type,
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
+  virtual bool op2_range (frange &r, tree type,
+			  const frange &lhs,
+			  const frange &op1,
+			  relation_trio = TRIO_VARYING) const;
+  virtual bool op2_range (frange &r, tree type,
+			  const irange &lhs,
+			  const frange &op1,
+			  relation_trio = TRIO_VARYING) const;
 
   // The following routines are used to represent relations between the
   // various operations.  If the caller knows where the symbolics are,
@@ -84,11 +119,30 @@ public:
 					  const irange &op1,
 					  const irange &op2,
 					  relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op1_relation (const frange &lhs,
+					  const frange &op1,
+					  const frange &op2,
+					  relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op1_relation (const irange &lhs,
+					  const frange &op1,
+					  const frange &op2,
+					  relation_kind = VREL_VARYING) const;
+
   virtual relation_kind lhs_op2_relation (const irange &lhs,
 					  const irange &op1,
 					  const irange &op2,
 					  relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op2_relation (const frange &lhs,
+					  const frange &op1,
+					  const frange &op2,
+					  relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op2_relation (const irange &lhs,
+					  const frange &op1,
+					  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;
 protected:
   // Perform an integral operation between 2 sub-ranges and return it.
   virtual void wi_fold (irange &r, tree type,
@@ -115,17 +169,8 @@ protected:
 			       unsigned limit) const;
   // Apply any bitmasks implied by these ranges.
   virtual void update_bitmask (irange &, const irange &, const irange &) const;
-};
-
-// Like range_operator above, but for floating point operators.
 
-class range_operator_float
-{
-public:
-  virtual bool fold_range (frange &r, tree type,
-			   const frange &lh,
-			   const frange &rh,
-			   relation_trio = TRIO_VARYING) const;
+  // Perform an float operation between 2 ranges and return it.
   virtual void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
 			bool &maybe_nan,
 			tree type,
@@ -134,50 +179,6 @@ public:
 			const REAL_VALUE_TYPE &rh_lb,
 			const REAL_VALUE_TYPE &rh_ub,
 			relation_kind) const;
-  // Unary operations have the range of the LHS as op2.
-  virtual bool fold_range (irange &r, tree type,
-			   const frange &lh,
-			   const irange &rh,
-			   relation_trio = TRIO_VARYING) const;
-  virtual bool fold_range (irange &r, tree type,
-			   const frange &lh,
-			   const frange &rh,
-			   relation_trio = TRIO_VARYING) const;
-  virtual bool op1_range (frange &r, tree type,
-			  const frange &lhs,
-			  const frange &op2,
-			  relation_trio = TRIO_VARYING) const;
-  virtual bool op1_range (frange &r, tree type,
-			  const irange &lhs,
-			  const frange &op2,
-			  relation_trio = TRIO_VARYING) const;
-  virtual bool op2_range (frange &r, tree type,
-			  const frange &lhs,
-			  const frange &op1,
-			  relation_trio = TRIO_VARYING) const;
-  virtual bool op2_range (frange &r, tree type,
-			  const irange &lhs,
-			  const frange &op1,
-			  relation_trio = TRIO_VARYING) const;
-
-  virtual relation_kind lhs_op1_relation (const frange &lhs,
-					  const frange &op1,
-					  const frange &op2,
-					  relation_kind = VREL_VARYING) const;
-  virtual relation_kind lhs_op1_relation (const irange &lhs,
-					  const frange &op1,
-					  const frange &op2,
-					  relation_kind = VREL_VARYING) const;
-  virtual relation_kind lhs_op2_relation (const frange &lhs,
-					  const frange &op1,
-					  const frange &op2,
-					  relation_kind = VREL_VARYING) const;
-  virtual relation_kind lhs_op2_relation (const irange &lhs,
-					  const frange &op1,
-					  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;
 };
 
 class range_op_handler
@@ -212,7 +213,7 @@ protected:
   void set_op_handler (enum tree_code code, tree type);
   bool m_valid;
   range_operator *m_int;
-  range_operator_float *m_float;
+  range_operator *m_float;
 };
 
 extern bool range_cast (vrange &, tree type);
@@ -294,20 +295,9 @@ private:
   range_operator *m_range_tree[MAX_TREE_CODES];
 };
 
-// Like above, but for floating point operators.
-
-class floating_op_table
-{
-public:
-  floating_op_table ();
-  range_operator_float *operator[] (enum tree_code code);
-private:
-  void set (enum tree_code code, range_operator_float &op);
-  range_operator_float *m_range_tree[MAX_TREE_CODES];
-};
 
 // This holds the range op table for floating point operations.
-extern floating_op_table *floating_tree_table;
+extern range_op_table *floating_tree_table;
 
 extern range_operator *ptr_op_widen_mult_signed;
 extern range_operator *ptr_op_widen_mult_unsigned;
-- 
2.40.1

