From c5065669a36ba0c26841cb108d32f03058757e85 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 31 May 2023 10:55:28 -0400
Subject: [PATCH 2/4] Remove tree_code from range-operator.

Range_operator had a tree code added last release to facilitate
bitmask operations.  This removes the tree_code and replaces it with a
virtual routine to peform the masking.  Remove any duplicate instances
which are no longer needed.

	* range-op.cc (range_operator::fold_range): Call virtual routine.
	(range_operator::update_bitmask): New.
	(operator_equal::update_bitmask): New.
	(operator_not_equal::update_bitmask): New.
	(operator_lt::update_bitmask): New.
	(operator_le::update_bitmask): New.
	(operator_gt::update_bitmask): New.
	(operator_ge::update_bitmask): New.
	(operator_ge::update_bitmask): New.
	(operator_plus::update_bitmask): New.
	(operator_minus::update_bitmask): New.
	(operator_pointer_diff::update_bitmask): New.
	(operator_min::update_bitmask): New.
	(operator_max::update_bitmask): New.
	(operator_mult::update_bitmask): New.
	(operator_div:operator_div):New.
	(operator_div::update_bitmask): New.
	(operator_div::m_code): New member.
	(operator_exact_divide::operator_exact_divide): New constructor.
	(operator_lshift::update_bitmask): New.
	(operator_rshift::update_bitmask): New.
	(operator_bitwise_and::update_bitmask): New.
	(operator_bitwise_or::update_bitmask): New.
	(operator_bitwise_xor::update_bitmask): New.
	(operator_trunc_mod::update_bitmask): New.
	(op_ident, op_unknown, op_ptr_min_max): New.
	(op_nop, op_convert): Delete.
	(op_ssa, op_paren, op_obj_type): Delete.
	(op_realpart, op_imagpart): Delete.
	(op_ptr_min, op_ptr_max): Delete.
	(pointer_plus_operator:update_bitmask): New.
	(range_op_table::set): Do not use m_code.
	(integral_table::integral_table): Adjust to single instances.
	* range-op.h (range_operator::range_operator): Delete.
	(range_operator::m_code): Delete.
	(range_operator::update_bitmask): New.
---
 gcc/range-op.cc | 110 +++++++++++++++++++++++++++++++++---------------
 gcc/range-op.h  |   6 +--
 2 files changed, 79 insertions(+), 37 deletions(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 3ab2c665901..2deca3bac93 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -286,7 +286,7 @@ range_operator::fold_range (irange &r, tree type,
 	    break;
 	}
       op1_op2_relation_effect (r, type, lh, rh, rel);
-      update_known_bitmask (r, m_code, lh, rh);
+      update_bitmask (r, lh, rh);
       return true;
     }
 
@@ -298,7 +298,7 @@ range_operator::fold_range (irange &r, tree type,
       wi_fold_in_parts (r, type, lh.lower_bound (), lh.upper_bound (),
 			rh.lower_bound (), rh.upper_bound ());
       op1_op2_relation_effect (r, type, lh, rh, rel);
-      update_known_bitmask (r, m_code, lh, rh);
+      update_bitmask (r, lh, rh);
       return true;
     }
 
@@ -316,12 +316,12 @@ range_operator::fold_range (irange &r, tree type,
 	if (r.varying_p ())
 	  {
 	    op1_op2_relation_effect (r, type, lh, rh, rel);
-	    update_known_bitmask (r, m_code, lh, rh);
+	    update_bitmask (r, lh, rh);
 	    return true;
 	  }
       }
   op1_op2_relation_effect (r, type, lh, rh, rel);
-  update_known_bitmask (r, m_code, lh, rh);
+  update_bitmask (r, lh, rh);
   return true;
 }
 
@@ -387,6 +387,14 @@ range_operator::op1_op2_relation_effect (irange &lhs_range ATTRIBUTE_UNUSED,
   return false;
 }
 
+// Apply any known bitmask updates based on this operator.
+
+void
+range_operator::update_bitmask (irange &, const irange &,
+				       const irange &) const
+{
+}
+
 // Create and return a range from a pair of wide-ints that are known
 // to have overflowed (or underflowed).
 
@@ -562,6 +570,8 @@ public:
 			  const irange &val,
 			  relation_trio = TRIO_VARYING) const;
   virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, EQ_EXPR, lh, rh); }
 } op_equal;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -682,6 +692,8 @@ public:
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
   virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, NE_EXPR, lh, rh); }
 } op_not_equal;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -862,6 +874,8 @@ public:
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
   virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, LT_EXPR, lh, rh); }
 } op_lt;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -982,6 +996,8 @@ public:
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
   virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, LE_EXPR, lh, rh); }
 } op_le;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -1099,6 +1115,8 @@ public:
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
   virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, GT_EXPR, lh, rh); }
 } op_gt;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -1215,6 +1233,8 @@ public:
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
   virtual relation_kind op1_op2_relation (const irange &lhs) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, GE_EXPR, lh, rh); }
 } op_ge;
 
 // Check if the LHS range indicates a relation between OP1 and OP2.
@@ -1339,6 +1359,8 @@ public:
   virtual relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
 					  const irange &op2,
 					  relation_kind rel) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, PLUS_EXPR, lh, rh); }
 } op_plus;
 
 // Check to see if the range of OP2 indicates anything about the relation
@@ -1648,6 +1670,8 @@ public:
 					const irange &op1_range,
 					const irange &op2_range,
 					relation_kind rel) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, MINUS_EXPR, lh, rh); }
 } op_minus;
 
 void 
@@ -1801,6 +1825,8 @@ class operator_pointer_diff : public range_operator
 					const irange &op1_range,
 					const irange &op2_range,
 					relation_kind rel) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, POINTER_DIFF_EXPR, lh, rh); }
 } op_pointer_diff;
 
 bool
@@ -1822,6 +1848,8 @@ public:
 		        const wide_int &lh_ub,
 		        const wide_int &rh_lb,
 		        const wide_int &rh_ub) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, MIN_EXPR, lh, rh); }
 } op_min;
 
 void
@@ -1844,6 +1872,8 @@ public:
 		        const wide_int &lh_ub,
 		        const wide_int &rh_lb,
 		        const wide_int &rh_ub) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, MAX_EXPR, lh, rh); }
 } op_max;
 
 void
@@ -1952,6 +1982,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio) const final override;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, MULT_EXPR, lh, rh); }
 } op_mult;
 
 bool
@@ -2162,6 +2194,7 @@ operator_widen_mult_unsigned::wi_fold (irange &r, tree type,
 class operator_div : public cross_product_operator
 {
 public:
+  operator_div (tree_code div_kind) { m_code = div_kind; }
   virtual void wi_fold (irange &r, tree type,
 		        const wide_int &lh_lb,
 		        const wide_int &lh_ub,
@@ -2170,8 +2203,17 @@ public:
   virtual bool wi_op_overflows (wide_int &res, tree type,
 				const wide_int &, const wide_int &)
     const final override;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, m_code, lh, rh); }
+protected:
+  tree_code m_code;
 };
 
+static operator_div op_trunc_div (TRUNC_DIV_EXPR);
+static operator_div op_floor_div (FLOOR_DIV_EXPR);
+static operator_div op_round_div (ROUND_DIV_EXPR);
+static operator_div op_ceil_div (CEIL_DIV_EXPR);
+
 bool
 operator_div::wi_op_overflows (wide_int &res, tree type,
 			       const wide_int &w0, const wide_int &w1) const
@@ -2265,6 +2307,7 @@ class operator_exact_divide : public operator_div
 {
   using range_operator::op1_range;
 public:
+  operator_exact_divide () : operator_div (EXACT_DIV_EXPR) { }
   virtual bool op1_range (irange &r, tree type,
 			  const irange &lhs,
 			  const irange &op2,
@@ -2314,6 +2357,8 @@ public:
 				tree type,
 				const wide_int &,
 				const wide_int &) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, LSHIFT_EXPR, lh, rh); }
 } op_lshift;
 
 class operator_rshift : public cross_product_operator
@@ -2343,6 +2388,8 @@ public:
 					   const irange &op1,
 					   const irange &op2,
 					   relation_kind rel) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, RSHIFT_EXPR, lh, rh); }
 } op_rshift;
 
 
@@ -2682,7 +2729,7 @@ private:
 			const irange &outer) const;
   void fold_pair (irange &r, unsigned index, const irange &inner,
 			   const irange &outer) const;
-};
+} op_cast;
 
 // Add a partial equivalence between the LHS and op1 for casts.
 
@@ -3026,6 +3073,8 @@ public:
 					  const irange &op1,
 					  const irange &op2,
 					  relation_kind) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, BIT_AND_EXPR, lh, rh); }
 private:
   void simple_op1_range_solver (irange &r, tree type,
 				const irange &lhs,
@@ -3524,6 +3573,8 @@ public:
 		        const wide_int &lh_ub,
 		        const wide_int &rh_lb,
 		        const wide_int &rh_ub) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, BIT_IOR_EXPR, lh, rh); }
 } op_bitwise_or;
 
 void
@@ -3636,6 +3687,8 @@ public:
 					const irange &op1_range,
 					const irange &op2_range,
 					relation_kind rel) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, BIT_XOR_EXPR, lh, rh); }
 } op_bitwise_xor;
 
 void
@@ -3777,6 +3830,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, TRUNC_MOD_EXPR, lh, rh); }
 } op_trunc_mod;
 
 void
@@ -4046,7 +4101,7 @@ public:
 					   const irange &op1,
 					   const irange &op2,
 					   relation_kind rel) const;
-};
+} op_ident;
 
 // Determine if there is a relationship between LHS and OP1.
 
@@ -4091,7 +4146,7 @@ public:
 			   const irange &op1,
 			   const irange &op2,
 			   relation_trio rel = TRIO_VARYING) const;
-};
+} op_unknown;
 
 bool
 operator_unknown::fold_range (irange &r, tree type,
@@ -4365,6 +4420,8 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
+  void update_bitmask (irange &r, const irange &lh, const irange &rh) const
+    { update_known_bitmask (r, POINTER_PLUS_EXPR, lh, rh); }
 } op_pointer_plus;
 
 void
@@ -4436,7 +4493,7 @@ public:
   virtual void wi_fold (irange & r, tree type,
 			const wide_int &lh_lb, const wide_int &lh_ub,
 			const wide_int &rh_lb, const wide_int &rh_ub) const;
-};
+} op_ptr_min_max;
 
 void
 pointer_min_max_operator::wi_fold (irange &r, tree type,
@@ -4562,21 +4619,8 @@ range_op_table::set (enum tree_code code, range_operator &op)
 {
   gcc_checking_assert (m_range_tree[code] == NULL);
   m_range_tree[code] = &op;
-  gcc_checking_assert (op.m_code == ERROR_MARK || op.m_code == code);
-  op.m_code = code;
 }
 
-// Shared operators that require separate instantiations because they
-// do not share a common tree code.
-static operator_cast op_nop, op_convert;
-static operator_identity op_ssa, op_paren, op_obj_type;
-static operator_unknown op_realpart, op_imagpart;
-static pointer_min_max_operator op_ptr_min, op_ptr_max;
-static operator_div op_trunc_div;
-static operator_div op_floor_div;
-static operator_div op_round_div;
-static operator_div op_ceil_div;
-
 // Instantiate a range op table for integral operations.
 
 class integral_table : public range_op_table
@@ -4605,8 +4649,8 @@ integral_table::integral_table ()
   set (EXACT_DIV_EXPR, op_exact_div);
   set (LSHIFT_EXPR, op_lshift);
   set (RSHIFT_EXPR, op_rshift);
-  set (NOP_EXPR, op_nop);
-  set (CONVERT_EXPR, op_convert);
+  set (NOP_EXPR, op_cast);
+  set (CONVERT_EXPR, op_cast);
   set (TRUTH_AND_EXPR, op_logical_and);
   set (BIT_AND_EXPR, op_bitwise_and);
   set (TRUTH_OR_EXPR, op_logical_or);
@@ -4616,11 +4660,11 @@ integral_table::integral_table ()
   set (TRUTH_NOT_EXPR, op_logical_not);
   set (BIT_NOT_EXPR, op_bitwise_not);
   set (INTEGER_CST, op_integer_cst);
-  set (SSA_NAME, op_ssa);
-  set (PAREN_EXPR, op_paren);
-  set (OBJ_TYPE_REF, op_obj_type);
-  set (IMAGPART_EXPR, op_imagpart);
-  set (REALPART_EXPR, op_realpart);
+  set (SSA_NAME, op_ident);
+  set (PAREN_EXPR, op_ident);
+  set (OBJ_TYPE_REF, op_ident);
+  set (IMAGPART_EXPR, op_unknown);
+  set (REALPART_EXPR, op_unknown);
   set (POINTER_DIFF_EXPR, op_pointer_diff);
   set (ABS_EXPR, op_abs);
   set (ABSU_EXPR, op_absu);
@@ -4640,8 +4684,8 @@ pointer_table::pointer_table ()
 {
   set (BIT_AND_EXPR, op_pointer_and);
   set (BIT_IOR_EXPR, op_pointer_or);
-  set (MIN_EXPR, op_ptr_min);
-  set (MAX_EXPR, op_ptr_max);
+  set (MIN_EXPR, op_ptr_min_max);
+  set (MAX_EXPR, op_ptr_min_max);
   set (POINTER_PLUS_EXPR, op_pointer_plus);
 
   set (EQ_EXPR, op_equal);
@@ -4650,11 +4694,11 @@ pointer_table::pointer_table ()
   set (LE_EXPR, op_le);
   set (GT_EXPR, op_gt);
   set (GE_EXPR, op_ge);
-  set (SSA_NAME, op_ssa);
+  set (SSA_NAME, op_ident);
   set (INTEGER_CST, op_integer_cst);
   set (ADDR_EXPR, op_addr);
-  set (NOP_EXPR, op_nop);
-  set (CONVERT_EXPR, op_convert);
+  set (NOP_EXPR, op_cast);
+  set (CONVERT_EXPR, op_cast);
 
   set (BIT_NOT_EXPR, op_bitwise_not);
   set (BIT_XOR_EXPR, op_bitwise_xor);
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 03ef6b98542..5bfbc89df52 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -50,7 +50,6 @@ class range_operator
 {
   friend class range_op_table;
 public:
-  range_operator () : m_code (ERROR_MARK) { }
   // Perform an operation between 2 ranges and return it.
   virtual bool fold_range (irange &r, tree type,
 			   const irange &lh,
@@ -114,9 +113,8 @@ protected:
 			       const wide_int &lb,
 			       const wide_int &ub,
 			       unsigned limit) const;
-
-  // Tree code of the range operator or ERROR_MARK if unknown.
-  tree_code m_code;
+  // 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.
-- 
2.40.1

