[gcc r15-992] Remove value_range typedef.

2024-06-03 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:6fb43d1b90e2683f6f41f04a65341fc2dab4b495

commit r15-992-g6fb43d1b90e2683f6f41f04a65341fc2dab4b495
Author: Aldy Hernandez 
Date:   Fri May 31 15:49:26 2024 +0200

Remove value_range typedef.

Now that pointers and integers have been disambiguated from irange,
and all the pointer range temporaries use prange, we can reclaim
value_range as a general purpose range container.

This patch removes the typedef, in favor of int_range_max, thus
providing slightly better ranges in places.  I have also used
int_range<1> or <2> when it's known ahead of time how big the range will
be, thus saving a few words.

In a follow-up patch I will rename the Value_Range temporary to
value_range.

No change in performance.

gcc/ChangeLog:

* builtins.cc (expand_builtin_strnlen): Replace value_range use
with int_range_max or irange when appropriate.
(determine_block_size): Same.
* fold-const.cc (minmax_from_comparison): Same.
* gimple-array-bounds.cc (check_out_of_bounds_and_warn): Same.
(array_bounds_checker::check_array_ref): Same.
* gimple-fold.cc (size_must_be_zero_p): Same.
* gimple-predicate-analysis.cc (find_var_cmp_const): Same.
* gimple-ssa-sprintf.cc (get_int_range): Same.
(format_integer): Same.
(try_substitute_return_value): Same.
(handle_printf_call): Same.
* gimple-ssa-warn-restrict.cc
(builtin_memref::extend_offset_range): Same.
* graphite-sese-to-poly.cc (add_param_constraints): Same.
* internal-fn.cc (get_min_precision): Same.
* match.pd: Same.
* pointer-query.cc (get_size_range): Same.
* range-op.cc (get_shift_range): Same.
(operator_trunc_mod::op1_range): Same.
(operator_trunc_mod::op2_range): Same.
* range.cc (range_negatives): Same.
* range.h (range_positives): Same.
(range_negatives): Same.
* tree-affine.cc (expr_to_aff_combination): Same.
* tree-data-ref.cc (compute_distributive_range): Same.
(nop_conversion_for_offset_p): Same.
(split_constant_offset): Same.
(split_constant_offset_1): Same.
(dr_step_indicator): Same.
* tree-dfa.cc (get_ref_base_and_extent): Same.
* tree-scalar-evolution.cc (iv_can_overflow_p): Same.
* tree-ssa-math-opts.cc (optimize_spaceship): Same.
* tree-ssa-pre.cc (insert_into_preds_of_block): Same.
* tree-ssa-reassoc.cc (optimize_range_tests_to_bit_test): Same.
* tree-ssa-strlen.cc (compare_nonzero_chars): Same.
(dump_strlen_info): Same.
(get_range_strlen_dynamic): Same.
(set_strlen_range): Same.
(maybe_diag_stxncpy_trunc): Same.
(strlen_pass::get_len_or_size): Same.
(strlen_pass::handle_builtin_string_cmp): Same.
(strlen_pass::count_nonzero_bytes_addr): Same.
(strlen_pass::handle_integral_assign): Same.
* tree-switch-conversion.cc (bit_test_cluster::emit): Same.
* tree-vect-loop-manip.cc (vect_gen_vector_loop_niters): Same.
(vect_do_peeling): Same.
* tree-vect-patterns.cc (vect_get_range_info): Same.
(vect_recog_divmod_pattern): Same.
* tree.cc (get_range_pos_neg): Same.
* value-range.cc (debug): Remove value_range variants.
* value-range.h (value_range): Remove typedef.
* vr-values.cc
(simplify_using_ranges::op_with_boolean_value_range_p): Replace
value_range use with int_range_max or irange when appropriate.
(check_for_binary_op_overflow): Same.
(simplify_using_ranges::legacy_fold_cond_overflow): Same.
(find_case_label_ranges): Same.
(simplify_using_ranges::simplify_abs_using_ranges): Same.
(test_for_singularity): Same.
(simplify_using_ranges::simplify_compare_using_ranges_1): Same.
(simplify_using_ranges::simplify_casted_compare): Same.
(simplify_using_ranges::simplify_switch_using_ranges): Same.
(simplify_conversion_using_ranges): Same.
(simplify_using_ranges::two_valued_val_range_p): Same.

Diff:
---
 gcc/builtins.cc  |  4 ++--
 gcc/fold-const.cc|  4 ++--
 gcc/gimple-array-bounds.cc   |  4 ++--
 gcc/gimple-fold.cc   |  4 ++--
 gcc/gimple-predicate-analysis.cc |  2 +-
 gcc/gimple-ssa-sprintf.cc|  8 
 gcc/gimple-ssa-warn-restrict.cc  |  2 +-
 gcc/graphite-sese-to-poly.cc |  2 +-
 gcc/internal-fn.cc   |  2 +-
 gcc/match.pd | 22 +++---
 gcc/pointer-query.cc |  2 +-
 gcc/range-op.cc  | 

[gcc r15-785] [prange] Use type agnostic range in phiopt [PR115191]

2024-05-23 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:35a293a6454ac0cd88735036f536d8f4ec65951a

commit r15-785-g35a293a6454ac0cd88735036f536d8f4ec65951a
Author: Aldy Hernandez 
Date:   Wed May 22 22:32:57 2024 +0200

[prange] Use type agnostic range in phiopt [PR115191]

Fix a use of int_range_max in phiopt that should be a type agnostic
range, because it could be either a pointer or an int.

PR tree-optimization/115191

gcc/ChangeLog:

* tree-ssa-phiopt.cc (value_replacement): Use Value_Range instead
of int_range_max.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/pr115191.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/pr115191.c | 10 ++
 gcc/tree-ssa-phiopt.cc   |  5 ++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr115191.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr115191.c
new file mode 100644
index 000..43f780aa3b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr115191.c
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-O1 -w" }
+
+typedef void *SCM;
+void set_socket_io_ports();
+void STk_socket_accept(SCM line_buffered) {
+  if (!line_buffered)
+line_buffered = (SCM)3;
+  set_socket_io_ports(line_buffered != 1);
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 918cf50b589..65f63eb0652 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -1326,12 +1326,11 @@ value_replacement (basic_block cond_bb, basic_block 
middle_bb,
{
  /* After the optimization PHI result can have value
 which it couldn't have previously.  */
- int_range_max r;
+ Value_Range r (TREE_TYPE (phires));
  if (get_global_range_query ()->range_of_expr (r, phires,
phi))
{
- wide_int warg = wi::to_wide (carg);
- int_range<2> tmp (TREE_TYPE (carg), warg, warg);
+ Value_Range tmp (carg, carg);
  r.union_ (tmp);
  reset_flow_sensitive_info (phires);
  set_range_info (phires, r);


[gcc r15-632] [prange] Drop range to VARYING if the bitmask intersection made it so [PR115131]

2024-05-17 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:1accf4454a2ab57c4d681d1f6db332c46c61c058

commit r15-632-g1accf4454a2ab57c4d681d1f6db332c46c61c058
Author: Aldy Hernandez 
Date:   Fri May 17 13:44:08 2024 +0200

[prange] Drop range to VARYING if the bitmask intersection made it so 
[PR115131]

If the intersection of the bitmasks made the range span the entire
domain, normalize the range to VARYING.

gcc/ChangeLog:

PR middle-end/115131
* value-range.cc (prange::intersect): Set VARYING if intersection
of bitmasks made the range span the entire domain.
(range_tests_misc): New test.

Diff:
---
 gcc/value-range.cc | 21 +
 1 file changed, 21 insertions(+)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 334ffb70fbc2..b38d6159a856 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -589,6 +589,11 @@ prange::intersect (const vrange )
   irange_bitmask new_bitmask = get_bitmask_from_range (m_type, m_min, m_max);
   m_bitmask.intersect (new_bitmask);
   m_bitmask.intersect (r.m_bitmask);
+  if (varying_compatible_p ())
+{
+  set_varying (type ());
+  return true;
+}
 
   if (flag_checking)
 verify_range ();
@@ -2889,6 +2894,22 @@ range_tests_misc ()
   p0.invert ();
   ASSERT_TRUE (p0 == p1);
 
+  // The intersection of:
+  //[0, +INF] MASK 0xff..00 VALUE 0xf8
+  //[0, +INF] MASK 0xff..00 VALUE 0x00
+  // is [0, +INF] MASK 0xff..ff VALUE 0x00, which is VARYING.
+  // Test that we normalized to VARYING.
+  unsigned prec = TYPE_PRECISION (voidp);
+  p0.set_varying (voidp);
+  wide_int mask = wi::mask (8, true, prec);
+  wide_int value = wi::uhwi (0xf8, prec);
+  irange_bitmask bm (wi::uhwi (0xf8, prec), mask);
+  p0.update_bitmask (bm);
+  p1.set_varying (voidp);
+  bm = irange_bitmask (wi::zero (prec), mask);
+  p1.update_bitmask (bm);
+  p0.intersect (p1);
+
   // [10,20] U [15, 30] => [10, 30].
   r0 = range_int (10, 20);
   r1 = range_int (15, 30);


[gcc r15-627] [prange] Avoid looking at type() for undefined ranges

2024-05-17 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:bc6e336cb7c85094ddc77757be97c3d8588f35ca

commit r15-627-gbc6e336cb7c85094ddc77757be97c3d8588f35ca
Author: Aldy Hernandez 
Date:   Fri May 17 10:30:03 2024 +0200

[prange] Avoid looking at type() for undefined ranges

Undefined ranges have no type.  This patch fixes the thinko.

gcc/ChangeLog:

PR middle-end/115128
* ipa-cp.cc (ipa_value_range_from_jfunc): Check for undefined_p
before looking at type.
(propagate_vr_across_jump_function): Same.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/pr115128.c: New test.

Diff:
---
 gcc/ipa-cp.cc|  4 
 gcc/testsuite/gcc.dg/tree-ssa/pr115128.c | 31 +++
 2 files changed, 35 insertions(+)

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 09cab7618226..408166b8044b 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1744,6 +1744,8 @@ ipa_value_range_from_jfunc (vrange ,
 pointer type to hold the result instead of a boolean
 type.  Avoid trapping in the sanity check in
 fold_range until this is fixed.  */
+ || srcvr.undefined_p ()
+ || op_vr.undefined_p ()
  || !handler.operand_check_p (vr_type, srcvr.type (), op_vr.type 
())
  || !handler.fold_range (op_res, vr_type, srcvr, op_vr))
op_res.set_varying (vr_type);
@@ -2556,6 +2558,8 @@ propagate_vr_across_jump_function (cgraph_edge *cs, 
ipa_jump_func *jfunc,
 pointer type to hold the result instead of a boolean
 type.  Avoid trapping in the sanity check in
 fold_range until this is fixed.  */
+ || src_lats->m_value_range.m_vr.undefined_p ()
+ || op_vr.undefined_p ()
  || !handler.operand_check_p (operand_type,
   src_lats->m_value_range.m_vr.type (),
   op_vr.type ())
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr115128.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr115128.c
new file mode 100644
index ..14bd4dbd6e51
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr115128.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -w" } */
+
+long XXH3_len_4to8_64b_len, XXH3_len_0to16_64b___trans_tmp_3, 
XXH3_mix2Accs_acc,
+XXH3_64bits_internal___trans_tmp_8;
+typedef unsigned long XXH3_hashLong64_f();
+void *XXH3_64bits_internal_input;
+int XXH3_64bits_internal___trans_tmp_1;
+void XXH3_mul128_fold64();
+static void XXH3_mergeAccs(unsigned long) {
+  for (;;)
+XXH3_mul128_fold64(XXH3_mix2Accs_acc);
+}
+static __attribute__((noinline)) unsigned long
+XXH3_hashLong_64b_default(void *, unsigned long len) {
+  XXH3_mergeAccs(len * 7);
+}
+__attribute__((always_inline)) long
+XXH3_64bits_internal(unsigned long len, XXH3_hashLong64_f f_hashLong) {
+  if (len <= 16) {
+long keyed =
+XXH3_64bits_internal___trans_tmp_1 ^ XXH3_len_0to16_64b___trans_tmp_3;
+XXH3_mul128_fold64(keyed, XXH3_len_4to8_64b_len);
+return XXH3_64bits_internal___trans_tmp_8;
+  }
+  f_hashLong(XXH3_64bits_internal_input, len);
+}
+static void XXH_INLINE_XXH3_64bits(unsigned long len) {
+  XXH3_64bits_internal(len, XXH3_hashLong_64b_default);
+}
+void __cmplog_rtn_hook() { XXH_INLINE_XXH3_64bits(sizeof(long)); }


[gcc r15-575] Revert "Revert: "Enable prange support.""

2024-05-16 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:da73261ce7731be7f2b164f1db796878cdc23365

commit r15-575-gda73261ce7731be7f2b164f1db796878cdc23365
Author: Aldy Hernandez 
Date:   Fri May 10 00:38:51 2024 +0200

Revert "Revert: "Enable prange support.""

This reverts commit d7bb8eaade3cd3aa70715c8567b4d7b08098e699 and enables 
prange
support again.

Diff:
---
 gcc/gimple-range-cache.cc |  4 ++--
 gcc/gimple-range-fold.cc  |  4 ++--
 gcc/gimple-range-fold.h   |  2 +-
 gcc/gimple-range-infer.cc |  2 +-
 gcc/gimple-range-op.cc|  2 +-
 gcc/gimple-range-path.cc  |  2 +-
 gcc/gimple-ssa-warn-access.cc |  2 +-
 gcc/ipa-cp.h  |  2 +-
 gcc/range-op-ptr.cc   |  4 
 gcc/range-op.cc   | 18 --
 gcc/tree-ssa-structalias.cc   |  2 +-
 gcc/value-range.cc|  1 +
 gcc/value-range.h |  4 ++--
 13 files changed, 18 insertions(+), 31 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 72ac25523117..bdd2832873aa 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -274,10 +274,10 @@ sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, 
vrange_allocator *allocator,
   // Pre-cache zero and non-zero values for pointers.
   if (POINTER_TYPE_P (t))
 {
-  int_range<2> nonzero;
+  prange nonzero;
   nonzero.set_nonzero (t);
   m_range[1] = m_range_allocator->clone (nonzero);
-  int_range<2> zero;
+  prange zero;
   zero.set_zero (t);
   m_range[2] = m_range_allocator->clone (zero);
 }
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 9c4ad1ee7b91..a9c8c4d03e63 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -597,7 +597,7 @@ fold_using_range::fold_stmt (vrange , gimple *s, 
fur_source , tree name)
   // Process addresses.
   if (gimple_code (s) == GIMPLE_ASSIGN
   && gimple_assign_rhs_code (s) == ADDR_EXPR)
-return range_of_address (as_a  (r), s, src);
+return range_of_address (as_a  (r), s, src);
 
   gimple_range_op_handler handler (s);
   if (handler)
@@ -757,7 +757,7 @@ fold_using_range::range_of_range_op (vrange ,
 // If a range cannot be calculated, set it to VARYING and return true.
 
 bool
-fold_using_range::range_of_address (irange , gimple *stmt, fur_source )
+fold_using_range::range_of_address (prange , gimple *stmt, fur_source )
 {
   gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
   gcc_checking_assert (gimple_assign_rhs_code (stmt) == ADDR_EXPR);
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index 7cbe15d05e53..c7c599bfc939 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -157,7 +157,7 @@ protected:
  fur_source );
   bool range_of_call (vrange , gcall *call, fur_source );
   bool range_of_cond_expr (vrange , gassign* cond, fur_source );
-  bool range_of_address (irange , gimple *s, fur_source );
+  bool range_of_address (prange , gimple *s, fur_source );
   bool range_of_phi (vrange , gphi *phi, fur_source );
   void range_of_ssa_name_with_loop_info (vrange &, tree, class loop *, gphi *,
 fur_source );
diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc
index c8e8b9b60ac1..d5e1aa142758 100644
--- a/gcc/gimple-range-infer.cc
+++ b/gcc/gimple-range-infer.cc
@@ -123,7 +123,7 @@ gimple_infer_range::add_nonzero (tree name)
 {
   if (!gimple_range_ssa_p (name))
 return;
-  int_range<2> nz;
+  prange nz;
   nz.set_nonzero (TREE_TYPE (name));
   add_range (name, nz);
 }
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 7321342b00de..aec3f39ec0e8 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -1107,7 +1107,7 @@ class cfn_strlen : public range_operator
 {
 public:
   using range_operator::fold_range;
-  virtual bool fold_range (irange , tree type, const irange &,
+  virtual bool fold_range (irange , tree type, const prange &,
   const irange &, relation_trio) const
   {
 wide_int max = irange_val_max (ptrdiff_type_node);
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index 96c6ac6b6a50..f1a12f76144c 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -443,7 +443,7 @@ path_range_query::compute_ranges_in_block (basic_block bb)
 void
 path_range_query::adjust_for_non_null_uses (basic_block bb)
 {
-  int_range_max r;
+  prange r;
   bitmap_iterator bi;
   unsigned i;
 
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 2c10d19e7f36..0cd5b6d6ef48 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -4213,7 +4213,7 @@ pass_waccess::check_pointer_uses (gimple *stmt, tree ptr,
 where the realloc call is known to have failed are valid.
 Ignore pointers that nothing is known about.  Those could
 have escaped along with their nullness.  */
- value_range 

[gcc r15-574] Cleanup prange sanity checks.

2024-05-16 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:b8e3574e68310f68116f157a35d5650600d13718

commit r15-574-gb8e3574e68310f68116f157a35d5650600d13718
Author: Aldy Hernandez 
Date:   Thu May 16 09:47:56 2024 +0200

Cleanup prange sanity checks.

The pointers_handled_p() code was a temporary sanity check, and not
even a good one, since we have a cleaner way of checking type
mismatches with operand_check_p.  This patch removes all the code, and
adds an explicit type check for relational operators, which are the
main problem in PR114985.

Adding this check makes it clear where the type mismatch is happening
in IPA, even without prange.  I've added code to skip the range
folding if the types don't match what the operator expects.  In order
to reproduce the latent bug, just remove the operand_check_p calls.

Tested on x86-64 and ppc64le with and without prange support.

gcc/ChangeLog:

PR tree-optimization/114985
* gimple-range-op.cc: Remove pointers_handled_p.
* ipa-cp.cc (ipa_value_range_from_jfunc): Skip range folding if
operands don't match.
(propagate_vr_across_jump_function): Same.
* range-op-mixed.h: Remove pointers_handled_p and tweak
operand_check_p.
* range-op-ptr.cc (range_operator::pointers_handled_p): Remove.
(pointer_plus_operator::pointers_handled_p): Remove.
(class operator_pointer_diff): Remove pointers_handled_p.
(operator_pointer_diff::pointers_handled_p): Remove.
(operator_identity::pointers_handled_p): Remove.
(operator_cst::pointers_handled_p): Remove.
(operator_cast::pointers_handled_p): Remove.
(operator_min::pointers_handled_p): Remove.
(operator_max::pointers_handled_p): Remove.
(operator_addr_expr::pointers_handled_p): Remove.
(operator_bitwise_and::pointers_handled_p): Remove.
(operator_bitwise_or::pointers_handled_p): Remove.
(operator_equal::pointers_handled_p): Remove.
(operator_not_equal::pointers_handled_p): Remove.
(operator_lt::pointers_handled_p): Remove.
(operator_le::pointers_handled_p): Remove.
(operator_gt::pointers_handled_p): Remove.
(operator_ge::pointers_handled_p): Remove.
* range-op.cc (TRAP_ON_UNHANDLED_POINTER_OPERATORS): Remove.
(range_op_handler::lhs_op1_relation): Remove pointers_handled_p 
checks.
(range_op_handler::lhs_op2_relation): Same.
(range_op_handler::op1_op2_relation): Same.
* range-op.h: Remove RO_* declarations.

Diff:
---
 gcc/gimple-range-op.cc |  24 -
 gcc/ipa-cp.cc  |  12 +++
 gcc/range-op-mixed.h   |  38 +++-
 gcc/range-op-ptr.cc| 259 -
 gcc/range-op.cc|  43 +---
 gcc/range-op.h |  17 
 6 files changed, 25 insertions(+), 368 deletions(-)

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 55dfbb23ce22..7321342b00de 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -329,19 +329,6 @@ public:
 r = lhs;
 return true;
   }
-  virtual bool pointers_handled_p (range_op_dispatch_type type,
-  unsigned dispatch) const
-  {
-switch (type)
-  {
-  case DISPATCH_FOLD_RANGE:
-   return dispatch == RO_PPP;
-  case DISPATCH_OP1_RANGE:
-   return dispatch == RO_PPP;
-  default:
-   return true;
-  }
-  }
 } op_cfn_pass_through_arg1;
 
 // Implement range operator for CFN_BUILT_IN_SIGNBIT.
@@ -1132,17 +1119,6 @@ public:
 r.set (type, wi::zero (TYPE_PRECISION (type)), max - 2);
 return true;
   }
-  virtual bool pointers_handled_p (range_op_dispatch_type type,
-  unsigned dispatch) const
-  {
-switch (type)
-  {
-  case DISPATCH_FOLD_RANGE:
-   return dispatch == RO_IPI;
-  default:
-   return true;
-  }
-  }
 } op_cfn_strlen;
 
 
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 5781f50c8546..09cab7618226 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1740,6 +1740,11 @@ ipa_value_range_from_jfunc (vrange ,
 
  if (!handler
  || !op_res.supports_type_p (vr_type)
+ /* Sometimes we try to fold comparison operators using a
+pointer type to hold the result instead of a boolean
+type.  Avoid trapping in the sanity check in
+fold_range until this is fixed.  */
+ || !handler.operand_check_p (vr_type, srcvr.type (), op_vr.type 
())
  || !handler.fold_range (op_res, vr_type, srcvr, op_vr))
op_res.set_varying (vr_type);
 
@@ -2547,6 +2552,13 @@ propagate_vr_across_jump_function (cgraph_edge *cs, 
ipa_jump_func *jfunc,
 
  if (!handler
  || !ipa_supports_p (operand_type)
+ 

[gcc r15-573] Use a boolean type when folding conditionals in simplify_using_ranges.

2024-05-16 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:f6bed6d3fcc13880ffa786b6c616e2306efe2bf3

commit r15-573-gf6bed6d3fcc13880ffa786b6c616e2306efe2bf3
Author: Aldy Hernandez 
Date:   Thu May 16 09:22:55 2024 +0200

Use a boolean type when folding conditionals in simplify_using_ranges.

In adding some traps for PR114985 I noticed that the conditional
folding code in simplify_using_ranges was using the wrong type.  This
cleans up the oversight.

gcc/ChangeLog:

PR tree-optimization/114985
* vr-values.cc (simplify_using_ranges::fold_cond_with_ops): Use
boolean type when folding conditionals.

Diff:
---
 gcc/vr-values.cc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index 0572bf6c8c73..e6ea9592574f 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -316,10 +316,9 @@ simplify_using_ranges::fold_cond_with_ops (enum tree_code 
code,
   || !query->range_of_expr (r1, op1, s))
 return NULL_TREE;
 
-  tree type = TREE_TYPE (op0);
   int_range<1> res;
   range_op_handler handler (code);
-  if (handler && handler.fold_range (res, type, r0, r1))
+  if (handler && handler.fold_range (res, boolean_type_node, r0, r1))
 {
   if (res == range_true ())
return boolean_true_node;


[gcc r15-504] [prange] Default pointers_handled_p() to false.

2024-05-15 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:c400b2100719d0a9e5989c63e0827b9e98919df3

commit r15-504-gc400b2100719d0a9e5989c63e0827b9e98919df3
Author: Aldy Hernandez 
Date:   Tue May 14 16:21:50 2024 +0200

[prange] Default pointers_handled_p() to false.

The pointers_handled_p() method is an internal range-op helper to help
catch dispatch type mismatches for pointer operands.  This is what
caught the IPA mismatch in PR114985.

This method is only a temporary measure to catch any incompatibilities
in the current pointer range-op entries.  This patch returns true for
any *new* entries in the range-op table, as the current ones are
already fleshed out.  This keeps us from having to implement this
boilerplate function for any new range-op entries.

PR tree-optimization/114995
* range-op-ptr.cc (range_operator::pointers_handled_p): Default to 
true.

Diff:
---
 gcc/range-op-ptr.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 65cca65103af..2f47f3354ed7 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -58,7 +58,7 @@ bool
 range_operator::pointers_handled_p (range_op_dispatch_type ATTRIBUTE_UNUSED,
unsigned dispatch ATTRIBUTE_UNUSED) const
 {
-  return false;
+  return true;
 }
 
 bool


[gcc r15-379] [prange] Default unimplemented prange operators to false.

2024-05-11 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:18c93c65a9fbaaf3762198e78fb3c24b9b6fd9fc

commit r15-379-g18c93c65a9fbaaf3762198e78fb3c24b9b6fd9fc
Author: Aldy Hernandez 
Date:   Fri May 10 18:55:34 2024 +0200

[prange] Default unimplemented prange operators to false.

The canonical way to indicate that a range operator is unsupported is
to return false, which has the sematic meaning of VARYING.  This patch
cleans up a few default virtuals that were trying harder to set
VARYING manually.

gcc/ChangeLog:

* range-op-ptr.cc (range_operator::fold_range): Return false.

Diff:
---
 gcc/range-op-ptr.cc | 55 +++--
 1 file changed, 15 insertions(+), 40 deletions(-)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 466edc6bf746..65cca65103af 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -62,63 +62,38 @@ range_operator::pointers_handled_p (range_op_dispatch_type 
ATTRIBUTE_UNUSED,
 }
 
 bool
-range_operator::fold_range (prange , tree type,
-   const prange ,
-   const prange ,
-   relation_trio trio) const
+range_operator::fold_range (prange &, tree, const prange &, const prange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (prange , tree type,
-   const prange ,
-   const irange ,
-   relation_trio trio) const
+range_operator::fold_range (prange &, tree, const prange &, const irange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (irange , tree type,
-   const prange ,
-   const prange ,
-   relation_trio trio) const
+range_operator::fold_range (irange &, tree, const prange &, const prange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (prange , tree type,
-   const irange ,
-   const prange ,
-   relation_trio trio) const
+range_operator::fold_range (prange &, tree, const irange &, const prange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool
-range_operator::fold_range (irange , tree type,
-   const prange ,
-   const irange ,
-   relation_trio trio) const
+range_operator::fold_range (irange &, tree, const prange &, const irange &,
+   relation_trio) const
 {
-  relation_kind rel = trio.op1_op2 ();
-  r.set_varying (type);
-  op1_op2_relation_effect (r, type, op1, op2, rel);
-  return true;
+  return false;
 }
 
 bool


[gcc r15-378] [prange] Do not trap by default on range dispatch mismatches.

2024-05-11 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:45ef24f2702dac4f8707ca682ed364019ee90c44

commit r15-378-g45ef24f2702dac4f8707ca682ed364019ee90c44
Author: Aldy Hernandez 
Date:   Fri May 10 23:21:29 2024 +0200

[prange] Do not trap by default on range dispatch mismatches.

The trap in the range-op dispatch code is really an internal debugging
aid, and only a temporary one for a few weeks while the dust settles.
This patch turns it off by default, allowing problematic passes to
turn it on for analysis.

gcc/ChangeLog:

* range-op.cc (TRAP_ON_UNHANDLED_POINTER_OPERATORS): New
(range_op_handler::fold_range): Use it.
(range_op_handler::op1_range): Same.
(range_op_handler::op2_range): Same.
(range_op_handler::lhs_op1_relation): Same.
(range_op_handler::lhs_op2_relation): Same.
(range_op_handler::op1_op2_relation): Same.

Diff:
---
 gcc/range-op.cc | 23 +--
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index a134af68141e..6a410ff656c5 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -49,6 +49,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-ccp.h"
 #include "range-op-mixed.h"
 
+// Set to 1 to trap on range-op entries that cannot handle the pointer
+// combination being requested.  This is a temporary sanity check to
+// aid in debugging, and will be removed later in the release cycle.
+#define TRAP_ON_UNHANDLED_POINTER_OPERATORS 0
+
 // Instantiate the operators which apply to multiple types here.
 
 operator_equal op_equal;
@@ -233,7 +238,8 @@ range_op_handler::fold_range (vrange , tree type,
 #if CHECKING_P
   if (!lh.undefined_p () && !rh.undefined_p ())
 gcc_assert (m_operator->operand_check_p (type, lh.type (), rh.type ()));
-  if (has_pointer_operand_p (r, lh, rh)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (r, lh, rh)
   && !m_operator->pointers_handled_p (DISPATCH_FOLD_RANGE,
  dispatch_kind (r, lh, rh)))
 discriminator_fail (r, lh, rh);
@@ -299,7 +305,8 @@ range_op_handler::op1_range (vrange , tree type,
 #if CHECKING_P
   if (!op2.undefined_p ())
 gcc_assert (m_operator->operand_check_p (lhs.type (), type, op2.type ()));
-  if (has_pointer_operand_p (r, lhs, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (r, lhs, op2)
   && !m_operator->pointers_handled_p (DISPATCH_OP1_RANGE,
  dispatch_kind (r, lhs, op2)))
 discriminator_fail (r, lhs, op2);
@@ -353,7 +360,8 @@ range_op_handler::op2_range (vrange , tree type,
 #if CHECKING_P
   if (!op1.undefined_p ())
 gcc_assert (m_operator->operand_check_p (lhs.type (), op1.type (), type));
-  if (has_pointer_operand_p (r, lhs, op1)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (r, lhs, op1)
   && !m_operator->pointers_handled_p (DISPATCH_OP2_RANGE,
  dispatch_kind (r, lhs, op1)))
 discriminator_fail (r, lhs, op1);
@@ -395,7 +403,8 @@ range_op_handler::lhs_op1_relation (const vrange ,
 {
   gcc_checking_assert (m_operator);
 #if CHECKING_P
-  if (has_pointer_operand_p (lhs, op1, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (lhs, op1, op2)
   && !m_operator->pointers_handled_p (DISPATCH_LHS_OP1_RELATION,
  dispatch_kind (lhs, op1, op2)))
 discriminator_fail (lhs, op1, op2);
@@ -442,7 +451,8 @@ range_op_handler::lhs_op2_relation (const vrange ,
 {
   gcc_checking_assert (m_operator);
 #if CHECKING_P
-  if (has_pointer_operand_p (lhs, op1, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (lhs, op1, op2)
   && !m_operator->pointers_handled_p (DISPATCH_LHS_OP2_RELATION,
  dispatch_kind (lhs, op1, op2)))
 discriminator_fail (lhs, op1, op2);
@@ -475,7 +485,8 @@ range_op_handler::op1_op2_relation (const vrange ,
 {
   gcc_checking_assert (m_operator);
 #if CHECKING_P
-  if (has_pointer_operand_p (lhs, op1, op2)
+  if (TRAP_ON_UNHANDLED_POINTER_OPERATORS
+  && has_pointer_operand_p (lhs, op1, op2)
   && !m_operator->pointers_handled_p (DISPATCH_OP1_OP2_RELATION,
  dispatch_kind (lhs, op1, op2)))
 discriminator_fail (lhs, op1, op2);


[gcc r15-363] [prange] Fix thinko in prange::update_bitmask() [PR115026]

2024-05-10 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:cbd420a1c3e2bb549dc83b53cc9a31aa6b23952c

commit r15-363-gcbd420a1c3e2bb549dc83b53cc9a31aa6b23952c
Author: Aldy Hernandez 
Date:   Fri May 10 12:26:49 2024 +0200

[prange] Fix thinko in prange::update_bitmask() [PR115026]

gcc/ChangeLog:

PR tree-optimization/115026
* value-range.cc (prange::update_bitmask): Use operand bitmask.

Diff:
---
 gcc/value-range.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 3e1ecf69517c..5bcb2c3f650b 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -686,7 +686,7 @@ prange::update_bitmask (const irange_bitmask )
   // If all the bits are known, this is a singleton.
   if (bm.mask () == 0)
 {
-  set (type (), m_bitmask.value (), m_bitmask.value ());
+  set (type (), bm.value (), bm.value ());
   return;
 }


[gcc r15-357] [prange] Do not assume all pointers are the same size [PR115009]

2024-05-10 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:ac255c7afeb8a558bd6224ff77277eebcd849d6e

commit r15-357-gac255c7afeb8a558bd6224ff77277eebcd849d6e
Author: Aldy Hernandez 
Date:   Thu May 9 23:37:30 2024 +0200

[prange] Do not assume all pointers are the same size [PR115009]

In a world with same sized pointers we can always reuse the storage
slots, but since this is not always the case, we need to be more
careful.  However, we can always store an undefined, because that
requires no extra storage.

gcc/ChangeLog:

PR tree-optimization/115009
* value-range-storage.cc (prange_storage::alloc): Do not assume
all pointers are the same size.
(prange_storage::prange_storage): Same.
(prange_storage::fits_p): Same.

Diff:
---
 gcc/value-range-storage.cc | 30 +++---
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index bbae0da4772d..8e8d61d59350 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -593,12 +593,12 @@ frange_storage::fits_p (const frange &) const
 prange_storage *
 prange_storage::alloc (vrange_internal_alloc , const prange )
 {
-  // Assume all pointers are the same size.
-  unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
-  gcc_checking_assert (r.undefined_p () || TYPE_PRECISION (r.type ()) == prec);
-
-  typedef trailing_wide_ints twi;
-  size_t size = sizeof (prange_storage) + twi::extra_size (prec);
+  size_t size = sizeof (prange_storage);
+  if (!r.undefined_p ())
+{
+  unsigned prec = TYPE_PRECISION (r.type ());
+  size += trailing_wide_ints::extra_size (prec);
+}
   prange_storage *p = static_cast  (allocator.alloc (size));
   new (p) prange_storage (r);
   return p;
@@ -610,8 +610,12 @@ prange_storage::prange_storage (const prange )
 {
   // It is the caller's responsibility to allocate enough space such
   // that the precision fits.
-  unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
-  m_trailing_ints.set_precision (prec);
+  if (r.undefined_p ())
+// Undefined ranges do not require any extra space for trailing
+// wide ints.
+m_trailing_ints.set_precision (0);
+  else
+m_trailing_ints.set_precision (TYPE_PRECISION (r.type ()));
 
   set_prange (r);
 }
@@ -669,10 +673,14 @@ prange_storage::equal_p (const prange ) const
 }
 
 bool
-prange_storage::fits_p (const prange &) const
+prange_storage::fits_p (const prange ) const
 {
-  // All pointers are the same size.
-  return true;
+  // Undefined ranges always fit, because they don't store anything in
+  // the trailing wide ints.
+  if (r.undefined_p ())
+return true;
+
+  return TYPE_PRECISION (r.type ()) <= m_trailing_ints.get_precision ();
 }


[gcc r15-353] Revert: "Enable prange support." [PR114985]

2024-05-09 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:d7bb8eaade3cd3aa70715c8567b4d7b08098e699

commit r15-353-gd7bb8eaade3cd3aa70715c8567b4d7b08098e699
Author: Aldy Hernandez 
Date:   Fri May 10 00:29:13 2024 +0200

Revert: "Enable prange support." [PR114985]

This reverts commit 36e877996936abd8bd08f8b1d983c8d1023a5842 until the IPA
pass is fixed with regards to POINTER = POINTER  POINTER.

Diff:
---
 gcc/gimple-range-cache.cc |  4 ++--
 gcc/gimple-range-fold.cc  |  4 ++--
 gcc/gimple-range-fold.h   |  2 +-
 gcc/gimple-range-infer.cc |  2 +-
 gcc/gimple-range-op.cc|  2 +-
 gcc/gimple-range-path.cc  |  2 +-
 gcc/gimple-ssa-warn-access.cc |  2 +-
 gcc/ipa-cp.h  |  2 +-
 gcc/range-op-ptr.cc   |  4 
 gcc/range-op.cc   | 18 ++
 gcc/tree-ssa-structalias.cc   |  2 +-
 gcc/value-range.cc|  1 -
 gcc/value-range.h |  4 ++--
 13 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index bdd2832873aa..72ac25523117 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -274,10 +274,10 @@ sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, 
vrange_allocator *allocator,
   // Pre-cache zero and non-zero values for pointers.
   if (POINTER_TYPE_P (t))
 {
-  prange nonzero;
+  int_range<2> nonzero;
   nonzero.set_nonzero (t);
   m_range[1] = m_range_allocator->clone (nonzero);
-  prange zero;
+  int_range<2> zero;
   zero.set_zero (t);
   m_range[2] = m_range_allocator->clone (zero);
 }
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index a9c8c4d03e63..9c4ad1ee7b91 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -597,7 +597,7 @@ fold_using_range::fold_stmt (vrange , gimple *s, 
fur_source , tree name)
   // Process addresses.
   if (gimple_code (s) == GIMPLE_ASSIGN
   && gimple_assign_rhs_code (s) == ADDR_EXPR)
-return range_of_address (as_a  (r), s, src);
+return range_of_address (as_a  (r), s, src);
 
   gimple_range_op_handler handler (s);
   if (handler)
@@ -757,7 +757,7 @@ fold_using_range::range_of_range_op (vrange ,
 // If a range cannot be calculated, set it to VARYING and return true.
 
 bool
-fold_using_range::range_of_address (prange , gimple *stmt, fur_source )
+fold_using_range::range_of_address (irange , gimple *stmt, fur_source )
 {
   gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
   gcc_checking_assert (gimple_assign_rhs_code (stmt) == ADDR_EXPR);
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index c7c599bfc939..7cbe15d05e53 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -157,7 +157,7 @@ protected:
  fur_source );
   bool range_of_call (vrange , gcall *call, fur_source );
   bool range_of_cond_expr (vrange , gassign* cond, fur_source );
-  bool range_of_address (prange , gimple *s, fur_source );
+  bool range_of_address (irange , gimple *s, fur_source );
   bool range_of_phi (vrange , gphi *phi, fur_source );
   void range_of_ssa_name_with_loop_info (vrange &, tree, class loop *, gphi *,
 fur_source );
diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc
index d5e1aa142758..c8e8b9b60ac1 100644
--- a/gcc/gimple-range-infer.cc
+++ b/gcc/gimple-range-infer.cc
@@ -123,7 +123,7 @@ gimple_infer_range::add_nonzero (tree name)
 {
   if (!gimple_range_ssa_p (name))
 return;
-  prange nz;
+  int_range<2> nz;
   nz.set_nonzero (TREE_TYPE (name));
   add_range (name, nz);
 }
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index ddd13ec55942..55dfbb23ce22 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -1120,7 +1120,7 @@ class cfn_strlen : public range_operator
 {
 public:
   using range_operator::fold_range;
-  virtual bool fold_range (irange , tree type, const prange &,
+  virtual bool fold_range (irange , tree type, const irange &,
   const irange &, relation_trio) const
   {
 wide_int max = irange_val_max (ptrdiff_type_node);
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index f1a12f76144c..96c6ac6b6a50 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -443,7 +443,7 @@ path_range_query::compute_ranges_in_block (basic_block bb)
 void
 path_range_query::adjust_for_non_null_uses (basic_block bb)
 {
-  prange r;
+  int_range_max r;
   bitmap_iterator bi;
   unsigned i;
 
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 0cd5b6d6ef48..2c10d19e7f36 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -4213,7 +4213,7 @@ pass_waccess::check_pointer_uses (gimple *stmt, tree ptr,
 where the realloc call is known to have failed are valid.
 Ignore pointers that nothing is known about.  Those could
 have escaped along with their 

[gcc r15-336] [ranger] Force buffer alignment in Value_Range [PR114912]

2024-05-08 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:d7ff8ae5313bea755f5960786b33a7b151e7b663

commit r15-336-gd7ff8ae5313bea755f5960786b33a7b151e7b663
Author: Aldy Hernandez 
Date:   Fri May 3 11:17:32 2024 +0200

[ranger] Force buffer alignment in Value_Range [PR114912]

gcc/ChangeLog:

PR tree-optimization/114912
* value-range.h (class Value_Range): Use a union.

Diff:
---
 gcc/value-range.h | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/gcc/value-range.h b/gcc/value-range.h
index 6e24874c0a25..44cdbd717f4c 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -800,10 +800,14 @@ private:
   void init (const vrange &);
 
   vrange *m_vrange;
-  // The buffer must be at least the size of the largest range.
-  static_assert (sizeof (int_range_max) > sizeof (frange), "");
-  static_assert (sizeof (int_range_max) > sizeof (prange), "");
-  char m_buffer[sizeof (int_range_max)];
+  union buffer_type {
+int_range_max ints;
+frange floats;
+unsupported_range unsupported;
+prange pointers;
+buffer_type () { }
+~buffer_type () { }
+  } m_buffer;
 };
 
 // The default constructor is uninitialized and must be initialized
@@ -811,6 +815,7 @@ private:
 
 inline
 Value_Range::Value_Range ()
+  : m_buffer ()
 {
   m_vrange = NULL;
 }
@@ -877,13 +882,13 @@ Value_Range::init (tree type)
   gcc_checking_assert (TYPE_P (type));
 
   if (irange::supports_p (type))
-m_vrange = new (_buffer) int_range_max ();
+m_vrange = new (_buffer.ints) int_range_max ();
   else if (prange::supports_p (type))
-m_vrange = new (_buffer) prange ();
+m_vrange = new (_buffer.pointers) prange ();
   else if (frange::supports_p (type))
-m_vrange = new (_buffer) frange ();
+m_vrange = new (_buffer.floats) frange ();
   else
-m_vrange = new (_buffer) unsupported_range ();
+m_vrange = new (_buffer.unsupported) unsupported_range ();
 }
 
 // Initialize object with a copy of R.
@@ -892,13 +897,14 @@ inline void
 Value_Range::init (const vrange )
 {
   if (is_a  (r))
-m_vrange = new (_buffer) int_range_max (as_a  (r));
+m_vrange = new (_buffer.ints) int_range_max (as_a  (r));
   else if (is_a  (r))
-m_vrange = new (_buffer) prange (as_a  (r));
+m_vrange = new (_buffer.pointers) prange (as_a  (r));
   else if (is_a  (r))
-m_vrange = new (_buffer) frange (as_a  (r));
+m_vrange = new (_buffer.floats) frange (as_a  (r));
   else
-m_vrange = new (_buffer) unsupported_range (as_a  
(r));
+m_vrange = new (_buffer.unsupported)
+  unsupported_range (as_a  (r));
 }
 
 // Assignment operator.  Copying incompatible types is allowed.  That


[gcc r15-335] [prange] Reword dispatch error message

2024-05-08 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:be3df704ce7de417682d57bc3e819dfcf0fdd501

commit r15-335-gbe3df704ce7de417682d57bc3e819dfcf0fdd501
Author: Aldy Hernandez 
Date:   Wed May 8 22:50:22 2024 +0200

[prange] Reword dispatch error message

After reading the ICE for the PR, it's obvious the error message is
rather cryptic.  This makes it less so.

gcc/ChangeLog:

* range-op.cc (range_op_handler::discriminator_fail): Reword error
message.

Diff:
---
 gcc/range-op.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 245385fe4876..e00136479a6d 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -197,7 +197,8 @@ range_op_handler::discriminator_fail (const vrange ,
   gcc_checking_assert (r1.m_discriminator < sizeof (name) - 1);
   gcc_checking_assert (r2.m_discriminator < sizeof (name) - 1);
   gcc_checking_assert (r3.m_discriminator < sizeof (name) - 1);
-  fprintf (stderr, "DISCRIMINATOR FAIL.  Dispatch > RO_%c%c%c <\n",
+  fprintf (stderr,
+  "Unsupported operand combination in dispatch: RO_%c%c%c\n",
   name[r1.m_discriminator],
   name[r2.m_discriminator],
   name[r3.m_discriminator]);


[gcc r15-312] Enable prange support.

2024-05-08 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:36e877996936abd8bd08f8b1d983c8d1023a5842

commit r15-312-g36e877996936abd8bd08f8b1d983c8d1023a5842
Author: Aldy Hernandez 
Date:   Tue May 7 14:05:50 2024 +0200

Enable prange support.

This throws the switch on prange.  After this patch, it is no longer
valid to store a pointer in an irange (or vice versa).  Instead, they
must go in prange, which is faster and more memory efficient.

I will push this now, so I have time to do any follow-up bugfixing
before going on paternity leave.

There are various cleanups we plan on doing after this patch (faster
intersect/union, remove range-op-mixed.h, remove value_range in favor
of int_range_max, reclaim the name for the Value_Range temporary,
clean up range-ops, etc etc).  But we will hold off on those for now
to make it easier to revert this patch, if for some reason we need to
do so while I'm away.

Tested on x86-64 Linux.

gcc/ChangeLog:

* gimple-range-cache.cc (sbr_sparse_bitmap::sbr_sparse_bitmap):
Change irange to prange.
* gimple-range-fold.cc (fold_using_range::fold_stmt): Same.
(fold_using_range::range_of_address): Same.
* gimple-range-fold.h (range_of_address): Same.
* gimple-range-infer.cc (gimple_infer_range::add_nonzero): Same.
* gimple-range-op.cc (class cfn_strlen): Same.
* gimple-range-path.cc
(path_range_query::adjust_for_non_null_uses): Same.
* gimple-ssa-warn-access.cc (pass_waccess::check_pointer_uses): 
Same.
* tree-ssa-structalias.cc (find_what_p_points_to): Same.
* range-op-ptr.cc (range_op_table::initialize_pointer_ops): Remove
hybrid entries in table.
* range-op.cc (range_op_table::range_op_table): Add pointer
entries for bitwise and/or and min/max.
* value-range.cc (irange::verify_range): Add assert.
* value-range.h (irange::varying_compatible_p): Remove check for
error_mark_node.
(irange::supports_p): Remove pointer support.
* ipa-cp.h (ipa_supports_p): Add prange support.

Diff:
---
 gcc/gimple-range-cache.cc |  4 ++--
 gcc/gimple-range-fold.cc  |  4 ++--
 gcc/gimple-range-fold.h   |  2 +-
 gcc/gimple-range-infer.cc |  2 +-
 gcc/gimple-range-op.cc|  2 +-
 gcc/gimple-range-path.cc  |  2 +-
 gcc/gimple-ssa-warn-access.cc |  2 +-
 gcc/ipa-cp.h  |  2 +-
 gcc/range-op-ptr.cc   |  4 
 gcc/range-op.cc   | 18 --
 gcc/tree-ssa-structalias.cc   |  2 +-
 gcc/value-range.cc|  1 +
 gcc/value-range.h |  4 ++--
 13 files changed, 18 insertions(+), 31 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 72ac25523117..bdd2832873aa 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -274,10 +274,10 @@ sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, 
vrange_allocator *allocator,
   // Pre-cache zero and non-zero values for pointers.
   if (POINTER_TYPE_P (t))
 {
-  int_range<2> nonzero;
+  prange nonzero;
   nonzero.set_nonzero (t);
   m_range[1] = m_range_allocator->clone (nonzero);
-  int_range<2> zero;
+  prange zero;
   zero.set_zero (t);
   m_range[2] = m_range_allocator->clone (zero);
 }
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 9c4ad1ee7b91..a9c8c4d03e63 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -597,7 +597,7 @@ fold_using_range::fold_stmt (vrange , gimple *s, 
fur_source , tree name)
   // Process addresses.
   if (gimple_code (s) == GIMPLE_ASSIGN
   && gimple_assign_rhs_code (s) == ADDR_EXPR)
-return range_of_address (as_a  (r), s, src);
+return range_of_address (as_a  (r), s, src);
 
   gimple_range_op_handler handler (s);
   if (handler)
@@ -757,7 +757,7 @@ fold_using_range::range_of_range_op (vrange ,
 // If a range cannot be calculated, set it to VARYING and return true.
 
 bool
-fold_using_range::range_of_address (irange , gimple *stmt, fur_source )
+fold_using_range::range_of_address (prange , gimple *stmt, fur_source )
 {
   gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
   gcc_checking_assert (gimple_assign_rhs_code (stmt) == ADDR_EXPR);
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index 7cbe15d05e53..c7c599bfc939 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -157,7 +157,7 @@ protected:
  fur_source );
   bool range_of_call (vrange , gcall *call, fur_source );
   bool range_of_cond_expr (vrange , gassign* cond, fur_source );
-  bool range_of_address (irange , gimple *s, fur_source );
+  bool range_of_address (prange , gimple *s, fur_source );
   bool range_of_phi (vrange , gphi *phi, fur_source );
   void range_of_ssa_name_with_loop_info (vrange &, tree, 

[gcc r15-270] Minor range type fixes for IPA in preparation for prange.

2024-05-07 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:24853cd854eb9b8a5c7b9706ad0908221bf964ce

commit r15-270-g24853cd854eb9b8a5c7b9706ad0908221bf964ce
Author: Aldy Hernandez 
Date:   Tue Mar 19 17:55:58 2024 +0100

Minor range type fixes for IPA in preparation for prange.

The polymorphic Value_Range object takes a tree type at construction
so it can determine what type of range to use (currently irange or
frange).  It seems a few of the types are slightly off.  This isn't a
problem now, because IPA only cares about integers and pointers, which
can both live in an irange.  However, with prange coming about, we
need to get the type right, because you can't store an integer in a
pointer range or vice versa.

Also, in preparation for prange, the irange::supports_p() idiom will become:

  irange::supports_p () || prange::supports_p()

To avoid changing all these places, I've added an inline function we
can later change and change everything at once.

Finally, there's a Value_Range::supports_type_p() &&
irange::supports_p() in the code.  The latter is a subset of the
former, so there's no need to check both.

gcc/ChangeLog:

* ipa-cp.cc (ipa_vr_operation_and_type_effects): Use ipa_supports_p.
(ipa_value_range_from_jfunc): Change Value_Range type.
(propagate_vr_across_jump_function): Same.
* ipa-cp.h (ipa_supports_p): New.
* ipa-fnsummary.cc (evaluate_conditions_for_known_args): Change 
Value_Range type.
* ipa-prop.cc (ipa_compute_jump_functions_for_edge): Use 
ipa_supports_p.
(ipcp_get_parm_bits): Same.

Diff:
---
 gcc/ipa-cp.cc| 14 +++---
 gcc/ipa-cp.h |  8 
 gcc/ipa-fnsummary.cc |  2 +-
 gcc/ipa-prop.cc  |  8 +++-
 4 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index a688dced5c9..5781f50c854 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1649,7 +1649,7 @@ ipa_vr_operation_and_type_effects (vrange _vr,
   enum tree_code operation,
   tree dst_type, tree src_type)
 {
-  if (!irange::supports_p (dst_type) || !irange::supports_p (src_type))
+  if (!ipa_supports_p (dst_type) || !ipa_supports_p (src_type))
 return false;
 
   range_op_handler handler (operation);
@@ -1720,7 +1720,7 @@ ipa_value_range_from_jfunc (vrange ,
 
   if (TREE_CODE_CLASS (operation) == tcc_unary)
{
- Value_Range res (vr_type);
+ Value_Range res (parm_type);
 
  if (ipa_vr_operation_and_type_effects (res,
 srcvr,
@@ -1733,7 +1733,7 @@ ipa_value_range_from_jfunc (vrange ,
  Value_Range op_res (vr_type);
  Value_Range res (vr_type);
  tree op = ipa_get_jf_pass_through_operand (jfunc);
- Value_Range op_vr (vr_type);
+ Value_Range op_vr (TREE_TYPE (op));
  range_op_handler handler (operation);
 
  ipa_range_set_and_normalize (op_vr, op);
@@ -2527,7 +2527,7 @@ propagate_vr_across_jump_function (cgraph_edge *cs, 
ipa_jump_func *jfunc,
   if (src_lats->m_value_range.bottom_p ())
return dest_lat->set_to_bottom ();
 
-  Value_Range vr (operand_type);
+  Value_Range vr (param_type);
   if (TREE_CODE_CLASS (operation) == tcc_unary)
ipa_vr_operation_and_type_effects (vr,
   src_lats->m_value_range.m_vr,
@@ -2540,16 +2540,16 @@ propagate_vr_across_jump_function (cgraph_edge *cs, 
ipa_jump_func *jfunc,
{
  tree op = ipa_get_jf_pass_through_operand (jfunc);
  Value_Range op_vr (TREE_TYPE (op));
- Value_Range op_res (operand_type);
+ Value_Range op_res (param_type);
  range_op_handler handler (operation);
 
  ipa_range_set_and_normalize (op_vr, op);
 
  if (!handler
- || !op_res.supports_type_p (operand_type)
+ || !ipa_supports_p (operand_type)
  || !handler.fold_range (op_res, operand_type,
  src_lats->m_value_range.m_vr, op_vr))
-   op_res.set_varying (operand_type);
+   op_res.set_varying (param_type);
 
  ipa_vr_operation_and_type_effects (vr,
 op_res,
diff --git a/gcc/ipa-cp.h b/gcc/ipa-cp.h
index 7ff74fb5c98..abeaaa4053e 100644
--- a/gcc/ipa-cp.h
+++ b/gcc/ipa-cp.h
@@ -291,4 +291,12 @@ public:
 
 bool values_equal_for_ipcp_p (tree x, tree y);
 
+/* Return TRUE if IPA supports ranges of TYPE.  */
+
+static inline bool
+ipa_supports_p (tree type)
+{
+  return irange::supports_p (type);
+}
+
 #endif /* IPA_CP_H */
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index 668a01ef175..07a853f78e3 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -515,7 +515,7 @@ evaluate_conditions_for_known_args (struct cgraph_node 
*node,

[gcc r15-164] Add prange entries in gimple-range-op.cc.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:6cec31d44a426fa031ca07266fd2723b0038de83

commit r15-164-g6cec31d44a426fa031ca07266fd2723b0038de83
Author: Aldy Hernandez 
Date:   Wed Mar 20 11:27:21 2024 +0100

Add prange entries in gimple-range-op.cc.

gcc/ChangeLog:

* gimple-range-op.cc (class cfn_pass_through_arg1): Add overloads
for prange operations.
(cfn_strlen): Same.

Diff:
---
 gcc/gimple-range-op.cc | 36 
 1 file changed, 36 insertions(+)

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 587de186db2..55dfbb23ce2 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -311,12 +311,37 @@ public:
 r = lh;
 return true;
   }
+  virtual bool fold_range (prange , tree, const prange ,
+  const prange &, relation_trio) const
+  {
+r = lh;
+return true;
+  }
   virtual bool op1_range (irange , tree, const irange ,
  const irange &, relation_trio) const
   {
 r = lhs;
 return true;
   }
+  virtual bool op1_range (prange , tree, const prange ,
+ const prange &, relation_trio) const
+  {
+r = lhs;
+return true;
+  }
+  virtual bool pointers_handled_p (range_op_dispatch_type type,
+  unsigned dispatch) const
+  {
+switch (type)
+  {
+  case DISPATCH_FOLD_RANGE:
+   return dispatch == RO_PPP;
+  case DISPATCH_OP1_RANGE:
+   return dispatch == RO_PPP;
+  default:
+   return true;
+  }
+  }
 } op_cfn_pass_through_arg1;
 
 // Implement range operator for CFN_BUILT_IN_SIGNBIT.
@@ -1107,6 +1132,17 @@ public:
 r.set (type, wi::zero (TYPE_PRECISION (type)), max - 2);
 return true;
   }
+  virtual bool pointers_handled_p (range_op_dispatch_type type,
+  unsigned dispatch) const
+  {
+switch (type)
+  {
+  case DISPATCH_FOLD_RANGE:
+   return dispatch == RO_IPI;
+  default:
+   return true;
+  }
+  }
 } op_cfn_strlen;


[gcc r15-163] Implement operator_ge for prange....

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:ff306c77b7cf5b7b09914f38b7351328835ac4ce

commit r15-163-gff306c77b7cf5b7b09914f38b7351328835ac4ce
Author: Aldy Hernandez 
Date:   Wed Mar 20 11:15:03 2024 +0100

Implement operator_ge for prange

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_ge::fold_range): New.
(operator_ge::op1_range): New.
(operator_ge::op2_range): New.
(operator_ge::op1_op2_relation): New.
(operator_ge::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 ++
 gcc/range-op-ptr.cc  | 108 +++
 2 files changed, 120 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index f7a07b19635..44d51d68655 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -371,6 +371,9 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const prange ,
+  relation_trio = TRIO_VARYING) const final override;
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -378,6 +381,9 @@ public:
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
@@ -385,12 +391,17 @@ public:
   bool op2_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
 
   relation_kind op1_op2_relation (const irange , const irange &,
  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange , const prange &,
+ const prange &) const final override;
   relation_kind op1_op2_relation (const irange , const frange &,
  const frange &) const final override;
   void update_bitmask (irange , const irange ,
@@ -398,6 +409,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
 { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_identity : public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 441a18c08c7..466edc6bf74 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1853,6 +1853,114 @@ operator_gt::pointers_handled_p (range_op_dispatch_type 
type,
 }
 }
 
+bool
+operator_ge::fold_range (irange , tree type,
+const prange ,
+const prange ,
+relation_trio rel) const
+{
+  if (relop_early_resolve (r, type, op1, op2, rel, VREL_GE))
+return true;
+
+  signop sign = TYPE_SIGN (op1.type ());
+  gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
+
+  if (wi::ge_p (op1.lower_bound (), op2.upper_bound (), sign))
+r = range_true ();
+  else if (!wi::ge_p (op1.upper_bound (), op2.lower_bound (), sign))
+r = range_false ();
+  else
+r = range_true_and_false ();
+
+  //update_known_bitmask (r, GE_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_ge::op1_range (prange , tree type,
+   const irange ,
+   const prange ,
+   relation_trio) const
+{
+  if (op2.undefined_p ())
+return false;
+
+  switch (get_bool_state (r, lhs, type))
+{
+case BRS_TRUE:
+  build_ge (r, type, op2);
+  break;
+
+case BRS_FALSE:
+  build_lt (r, type, op2);
+  break;
+
+default:
+  break;
+}
+  return true;
+}
+
+bool
+operator_ge::op2_range (prange , tree type,
+   const irange ,
+   const prange ,
+   relation_trio) const
+{
+  if (op1.undefined_p ())
+return false;
+
+  switch (get_bool_state (r, lhs, type))
+{
+case BRS_TRUE:
+  build_le (r, type, op1);
+  break;
+
+case BRS_FALSE:
+  build_gt (r, type, op1);
+  break;
+
+

[gcc r15-162] Implement operator_gt for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:76fae4051a72b2d417d50f1980dff8ab0c50d0c5

commit r15-162-g76fae4051a72b2d417d50f1980dff8ab0c50d0c5
Author: Aldy Hernandez 
Date:   Wed Mar 20 11:10:03 2024 +0100

Implement operator_gt for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_gt::fold_range): New.
(operator_gt::op1_range): New.
(operator_gt::op2_range): New.
(operator_gt::op1_op2_relation): New.
(operator_gt::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 ++
 gcc/range-op-ptr.cc  | 106 +++
 2 files changed, 118 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 571729e2ab6..f7a07b19635 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -320,6 +320,9 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const prange ,
+  relation_trio = TRIO_VARYING) const final override;
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -327,6 +330,9 @@ public:
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
@@ -334,11 +340,16 @@ public:
   bool op2_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange , const irange &,
  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange , const prange &,
+ const prange &) const final override;
   relation_kind op1_op2_relation (const irange , const frange &,
  const frange &) const final override;
   void update_bitmask (irange , const irange ,
@@ -346,6 +357,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
 { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_ge :  public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index eb28211b583..441a18c08c7 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1747,6 +1747,112 @@ operator_le::pointers_handled_p (range_op_dispatch_type 
type,
 }
 }
 
+bool
+operator_gt::fold_range (irange , tree type,
+const prange , const prange ,
+relation_trio rel) const
+{
+  if (relop_early_resolve (r, type, op1, op2, rel, VREL_GT))
+return true;
+
+  signop sign = TYPE_SIGN (op1.type ());
+  gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
+
+  if (wi::gt_p (op1.lower_bound (), op2.upper_bound (), sign))
+r = range_true ();
+  else if (!wi::gt_p (op1.upper_bound (), op2.lower_bound (), sign))
+r = range_false ();
+  else
+r = range_true_and_false ();
+
+  //update_known_bitmask (r, GT_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_gt::op1_range (prange , tree type,
+   const irange , const prange ,
+   relation_trio) const
+{
+  if (op2.undefined_p ())
+return false;
+
+  switch (get_bool_state (r, lhs, type))
+{
+case BRS_TRUE:
+  build_gt (r, type, op2);
+  break;
+
+case BRS_FALSE:
+  build_le (r, type, op2);
+  break;
+
+default:
+  break;
+}
+  return true;
+}
+
+bool
+operator_gt::op2_range (prange , tree type,
+   const irange ,
+   const prange ,
+   relation_trio) const
+{
+  if (op1.undefined_p ())
+return false;
+
+  switch (get_bool_state (r, lhs, type))
+{
+case BRS_TRUE:
+  build_lt (r, type, op1);
+  break;
+
+case BRS_FALSE:
+  build_ge (r, type, op1);
+  break;
+
+default:
+  break;
+}
+  return true;
+}
+
+relation_kind

[gcc r15-161] Implement operator_le for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:3a4ee6ea8627efe0d34a71d0ea4ce9b70d34df18

commit r15-161-g3a4ee6ea8627efe0d34a71d0ea4ce9b70d34df18
Author: Aldy Hernandez 
Date:   Wed Mar 20 11:07:30 2024 +0100

Implement operator_le for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_le::fold_range): New.
(operator_le::op1_range): New.
(operator_le::op2_range): New.
(operator_le::op1_op2_relation): New.
(operator_le::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 ++
 gcc/range-op-ptr.cc  | 108 +++
 2 files changed, 120 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index b82d06572a7..571729e2ab6 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -268,6 +268,9 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const prange ,
+  relation_trio = TRIO_VARYING) const final override;
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio rel = TRIO_VARYING) const final override;
@@ -275,6 +278,9 @@ public:
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type,
  const irange , const frange ,
  relation_trio rel = TRIO_VARYING) const final override;
@@ -282,12 +288,17 @@ public:
   bool op2_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange , tree type,
  const irange , const frange ,
  relation_trio rel = TRIO_VARYING) const final override;
 
   relation_kind op1_op2_relation (const irange , const irange &,
  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange , const prange &,
+ const prange &) const final override;
   relation_kind op1_op2_relation (const irange , const frange &,
  const frange &) const final override;
   void update_bitmask (irange , const irange ,
@@ -295,6 +306,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
 { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_gt :  public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 11629ba6d8d..eb28211b583 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1639,6 +1639,114 @@ operator_lt::pointers_handled_p (range_op_dispatch_type 
type,
 }
 }
 
+bool
+operator_le::fold_range (irange , tree type,
+const prange ,
+const prange ,
+relation_trio rel) const
+{
+  if (relop_early_resolve (r, type, op1, op2, rel, VREL_LE))
+return true;
+
+  signop sign = TYPE_SIGN (op1.type ());
+  gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
+
+  if (wi::le_p (op1.upper_bound (), op2.lower_bound (), sign))
+r = range_true ();
+  else if (!wi::le_p (op1.lower_bound (), op2.upper_bound (), sign))
+r = range_false ();
+  else
+r = range_true_and_false ();
+
+  //update_known_bitmask (r, LE_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_le::op1_range (prange , tree type,
+   const irange ,
+   const prange ,
+   relation_trio) const
+{
+  if (op2.undefined_p ())
+return false;
+
+  switch (get_bool_state (r, lhs, type))
+{
+case BRS_TRUE:
+  build_le (r, type, op2);
+  break;
+
+case BRS_FALSE:
+  build_gt (r, type, op2);
+  break;
+
+default:
+  break;
+}
+  return true;
+}
+
+bool
+operator_le::op2_range (prange , tree type,
+   const irange ,
+   const prange ,
+   relation_trio) const
+{
+  if (op1.undefined_p ())
+return false;
+
+  switch (get_bool_state (r, lhs, type))
+{
+case BRS_TRUE:
+  build_ge (r, type, op1);
+  break;
+
+case BRS_FALSE:
+  build_lt (r, type, op1);
+  break;
+
+

[gcc r15-160] Implement operator_lt for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:bfa2323d1ddf96a4f40a26aa39b8e1e3bd9b6d98

commit r15-160-gbfa2323d1ddf96a4f40a26aa39b8e1e3bd9b6d98
Author: Aldy Hernandez 
Date:   Wed Mar 20 11:03:24 2024 +0100

Implement operator_lt for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (max_limit): New.
(min_limit): New.
(build_lt): New.
(build_le): New.
(build_gt): New.
(build_ge): New.
(operator_lt::fold_range): New.
(operator_lt::op1_range): New.
(operator_lt::op2_range): New.
(operator_lt::op1_op2_relation): New.
(operator_lt::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 
 gcc/range-op-ptr.cc  | 174 +++
 2 files changed, 186 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index ee8d9dd328f..b82d06572a7 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -219,23 +219,34 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const prange ,
+  relation_trio = TRIO_VARYING) const final override;
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
   bool op2_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
   relation_kind op1_op2_relation (const irange , const irange &,
  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange , const prange &,
+ const prange &) const final override;
   relation_kind op1_op2_relation (const irange , const frange &,
  const frange &) const final override;
   void update_bitmask (irange , const irange ,
@@ -243,6 +254,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
 { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_le :  public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index fb2888bf079..11629ba6d8d 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -262,6 +262,69 @@ range_operator::update_bitmask (irange &,
 {
 }
 
+// Return the upper limit for a type.
+
+static inline wide_int
+max_limit (const_tree type)
+{
+  return wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+}
+
+// Return the lower limit for a type.
+
+static inline wide_int
+min_limit (const_tree type)
+{
+  return wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+}
+
+// Build a range that is < VAL and store it in R.
+
+static void
+build_lt (prange , tree type, const prange )
+{
+  wi::overflow_type ov;
+  wide_int lim = wi::sub (val.upper_bound (), 1, UNSIGNED, );
+
+  // If val - 1 underflows, check if X < MIN, which is an empty range.
+  if (ov)
+r.set_undefined ();
+  else
+r.set (type, min_limit (type), lim);
+}
+
+// Build a range that is <= VAL and store it in R.
+
+static void
+build_le (prange , tree type, const prange )
+{
+  r.set (type, min_limit (type), val.upper_bound ());
+}
+
+// Build a range that is > VAL and store it in R.
+
+static void
+build_gt (prange , tree type, const prange )
+{
+  wi::overflow_type ov;
+  wide_int lim = wi::add (val.lower_bound (), 1, UNSIGNED, );
+
+  // If val + 1 overflows, check is for X > MAX, which is an empty range.
+  if (ov)
+r.set_undefined ();
+  else
+r.set (type, lim, max_limit (type));
+
+}
+
+// Build a range that is >= VAL and store it in R.
+
+static void
+build_ge (prange , tree type, const prange )
+{
+  r.set (type, val.lower_bound (), max_limit (type));
+}
+
 class pointer_plus_operator : public 

[gcc r15-158] Implement operator_not_equal for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:d1be4c907fa47d868d6ef31e8fd7ede0535420ca

commit r15-158-gd1be4c907fa47d868d6ef31e8fd7ede0535420ca
Author: Aldy Hernandez 
Date:   Wed Mar 20 10:49:11 2024 +0100

Implement operator_not_equal for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_not_equal::fold_range): New.
(operator_not_equal::op1_range): New.
(operator_not_equal::op2_range): New.
(operator_not_equal::op1_op2_relation): New.
(operator_not_equal::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 ++
 gcc/range-op-ptr.cc  | 118 +++
 2 files changed, 130 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index c45aed93567..980611dc339 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -155,6 +155,9 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const prange ,
+  relation_trio rel = TRIO_VARYING) const final override;
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio rel = TRIO_VARYING) const final override;
@@ -162,6 +165,9 @@ public:
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
@@ -169,12 +175,17 @@ public:
   bool op2_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
 
   relation_kind op1_op2_relation (const irange , const irange &,
  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange , const prange &,
+ const prange &) const final override;
   relation_kind op1_op2_relation (const irange , const frange &,
  const frange &) const final override;
   void update_bitmask (irange , const irange ,
@@ -182,6 +193,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
 { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_lt :  public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 2f2f4bb2b5d..081e8fdba1f 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1230,6 +1230,124 @@ operator_bitwise_or::pointers_handled_p 
(range_op_dispatch_type,
   return false;
 }
 
+bool
+operator_not_equal::fold_range (irange , tree type,
+   const prange ,
+   const prange ,
+   relation_trio rel) const
+{
+  if (relop_early_resolve (r, type, op1, op2, rel, VREL_NE))
+return true;
+
+  // We can be sure the values are always equal or not if both ranges
+  // consist of a single value, and then compare them.
+  bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+  bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+  if (op1_const && op2_const)
+{
+  if (wi::ne_p (op1.lower_bound (), op2.upper_bound()))
+   r = range_true ();
+  else
+   r = range_false ();
+}
+  else
+{
+  // If ranges do not intersect, we know the range is not equal,
+  // otherwise we don't know anything for sure.
+  prange tmp = op1;
+  tmp.intersect (op2);
+  if (tmp.undefined_p ())
+   r = range_true ();
+  // Check if a constant cannot satisfy the bitmask requirements.
+  else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+r = range_true ();
+  else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+r = range_true ();
+  else
+   r = range_true_and_false ();
+}
+
+  //update_known_bitmask (r, NE_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_not_equal::op1_range (prange , tree type,
+  const 

[gcc r15-159] Implement operator_equal for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:bcb226924f50d9b84ca32b6f39abb63b43e23229

commit r15-159-gbcb226924f50d9b84ca32b6f39abb63b43e23229
Author: Aldy Hernandez 
Date:   Wed Mar 20 10:54:39 2024 +0100

Implement operator_equal for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_equal::fold_range): New.
(operator_equal::op1_range): New.
(operator_equal::op2_range): New.
(operator_equal::op1_op2_relation): New.
(operator_equal::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 ++
 gcc/range-op-ptr.cc  | 117 +++
 2 files changed, 129 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 980611dc339..ee8d9dd328f 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -115,6 +115,9 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const prange ,
+  relation_trio = TRIO_VARYING) const final override;
   bool fold_range (irange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -122,6 +125,9 @@ public:
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type,
  const irange , const frange ,
  relation_trio = TRIO_VARYING) const final override;
@@ -129,12 +135,17 @@ public:
   bool op2_range (irange , tree type,
  const irange , const irange ,
  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange , tree type,
  const irange , const frange ,
  relation_trio rel = TRIO_VARYING) const final override;
 
   relation_kind op1_op2_relation (const irange , const irange &,
  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange , const prange &,
+ const prange &) const final override;
   relation_kind op1_op2_relation (const irange , const frange &,
  const frange &) const final override;
   void update_bitmask (irange , const irange ,
@@ -142,6 +153,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
 { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_not_equal : public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 081e8fdba1f..fb2888bf079 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1230,6 +1230,123 @@ operator_bitwise_or::pointers_handled_p 
(range_op_dispatch_type,
   return false;
 }
 
+bool
+operator_equal::fold_range (irange , tree type,
+   const prange ,
+   const prange ,
+   relation_trio rel) const
+{
+  if (relop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
+return true;
+
+  // We can be sure the values are always equal or not if both ranges
+  // consist of a single value, and then compare them.
+  bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+  bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+  if (op1_const && op2_const)
+{
+  if (wi::eq_p (op1.lower_bound (), op2.upper_bound()))
+   r = range_true ();
+  else
+   r = range_false ();
+}
+  else
+{
+  // If ranges do not intersect, we know the range is not equal,
+  // otherwise we don't know anything for sure.
+  prange tmp = op1;
+  tmp.intersect (op2);
+  if (tmp.undefined_p ())
+   r = range_false ();
+  // Check if a constant cannot satisfy the bitmask requirements.
+  else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+r = range_false ();
+  else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+r = range_false ();
+  else
+   r = range_true_and_false ();
+}
+
+  //update_known_bitmask (r, EQ_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_equal::op1_range (prange , tree type,
+  const irange ,
+  const 

[gcc r15-157] Implement operator_bitwise_or for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:6b9e640d49138183aaeee67f2dcf3de329318d27

commit r15-157-g6b9e640d49138183aaeee67f2dcf3de329318d27
Author: Aldy Hernandez 
Date:   Wed Mar 20 10:29:50 2024 +0100

Implement operator_bitwise_or for prange.

We seem to have a range-op entry for pointer bitwise OR that we've
inherited from the original VRP implementation, but it never gets
used.  If this is not valid gimple, we can safely remove this entry.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_bitwise_or::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  1 +
 gcc/range-op-ptr.cc  | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 6158fc51f8e..c45aed93567 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -762,6 +762,7 @@ public:
   // Check compatibility of all operands.
   bool operand_check_p (tree t1, tree t2, tree t3) const final override
 { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 protected:
   void wi_fold (irange , tree type, const wide_int _lb,
const wide_int _ub, const wide_int _lb,
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 8d5049b1daf..2f2f4bb2b5d 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1219,6 +1219,17 @@ operator_bitwise_and::pointers_handled_p 
(range_op_dispatch_type type,
 }
 }
 
+bool
+operator_bitwise_or::pointers_handled_p (range_op_dispatch_type,
+unsigned) const
+{
+  // NOTE: It looks like we never generate bitwise OR with pointers.
+  // If this is indeed the case, we can move operator_bitwise_or from
+  // range-op-mixed.h to range-op.h.
+  gcc_unreachable ();
+  return false;
+}
+
 // Initialize any pointer operators to the primary table
 
 void


[gcc r15-156] Implement operator_bitwise_and for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:e58f14916954411628eb122da996383b8c996b57

commit r15-156-ge58f14916954411628eb122da996383b8c996b57
Author: Aldy Hernandez 
Date:   Wed Mar 20 10:23:31 2024 +0100

Implement operator_bitwise_and for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_bitwise_and::fold_range): New.
(operator_bitwise_and::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  6 ++
 gcc/range-op-ptr.cc  | 30 ++
 2 files changed, 36 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 0df300781f1..6158fc51f8e 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -712,10 +712,15 @@ private:
 class operator_bitwise_and : public range_operator
 {
 public:
+  using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::lhs_op1_relation;
   using range_operator::update_bitmask;
+  bool fold_range (prange , tree type,
+  const prange ,
+  const prange ,
+  relation_trio) const final override;
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio rel = TRIO_VARYING) const override;
@@ -730,6 +735,7 @@ public:
   // Check compatibility of all operands.
   bool operand_check_p (tree t1, tree t2, tree t3) const final override
 { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 protected:
   void wi_fold (irange , tree type, const wide_int _lb,
const wide_int _ub, const wide_int _lb,
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index b90b8bb9f65..8d5049b1daf 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1189,6 +1189,36 @@ operator_addr_expr::pointers_handled_p 
(range_op_dispatch_type type,
 }
 }
 
+bool
+operator_bitwise_and::fold_range (prange , tree type,
+ const prange ,
+ const prange  ATTRIBUTE_UNUSED,
+ relation_trio) const
+{
+  // For pointer types, we are really only interested in asserting
+  // whether the expression evaluates to non-NULL.
+  if (op1.zero_p () || op2.zero_p ())
+r.set_zero (type);
+  else
+r.set_varying (type);
+
+  update_known_bitmask (r, BIT_AND_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_bitwise_and::pointers_handled_p (range_op_dispatch_type type,
+ unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+  return dispatch == RO_PPP;
+default:
+  return true;
+}
+}
+
 // Initialize any pointer operators to the primary table
 
 void


[gcc r15-155] Implement operator_pointer_diff for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:f803b93feef60c8c2d4f7f7270bfc94650dbc8f5

commit r15-155-gf803b93feef60c8c2d4f7f7270bfc94650dbc8f5
Author: Aldy Hernandez 
Date:   Wed Mar 20 10:12:47 2024 +0100

Implement operator_pointer_diff for prange.

gcc/ChangeLog:

* range-op-ptr.cc
(operator_pointer_diff::op1_op2_relation_effect): New.
(operator_pointer_diff::pointers_handled_p): New.

Diff:
---
 gcc/range-op-ptr.cc | 32 
 1 file changed, 32 insertions(+)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index a4418215613..b90b8bb9f65 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -564,10 +564,42 @@ class operator_pointer_diff : public range_operator
const irange _range,
const irange _range,
relation_kind rel) const;
+  virtual bool op1_op2_relation_effect (irange _range,
+   tree type,
+   const prange _range,
+   const prange _range,
+   relation_kind rel) const final override;
   void update_bitmask (irange , const irange , const irange ) const
 { update_known_bitmask (r, POINTER_DIFF_EXPR, lh, rh); }
+  void update_bitmask (irange ,
+  const prange , const prange ) const final override
+  { update_known_bitmask (r, POINTER_DIFF_EXPR, lh, rh); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 } op_pointer_diff;
 
+bool
+operator_pointer_diff::op1_op2_relation_effect (irange _range, tree type,
+   const prange _range,
+   const prange _range,
+   relation_kind rel) const
+{
+  int_range<2> op1, op2, tmp;
+  range_op_handler cast (CONVERT_EXPR);
+
+  if (!cast.fold_range (op1, type, op1_range, tmp)
+  || !cast.fold_range (op2, type, op2_range, tmp))
+return false;
+
+  return minus_op1_op2_relation_effect (lhs_range, type, op1, op2, rel);
+}
+
+bool
+operator_pointer_diff::pointers_handled_p (range_op_dispatch_type,
+  unsigned) const
+{
+  return true;
+}
+
 bool
 operator_pointer_diff::op1_op2_relation_effect (irange _range, tree type,
const irange _range,


[gcc r15-154] Implement pointer_plus_operator for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:86ff3c45ea82452888244476f26a4f628b148ace

commit r15-154-g86ff3c45ea82452888244476f26a4f628b148ace
Author: Aldy Hernandez 
Date:   Wed Mar 20 10:04:41 2024 +0100

Implement pointer_plus_operator for prange.

gcc/ChangeLog:

* range-op-ptr.cc (class pointer_plus_operator): Add overloaded 
declarations
for pointer variants.
(pointer_plus_operator::fold_range): New.
(pointer_plus_operator::op2_range): New.
(pointer_plus_operator::pointers_handled_p): New.

Diff:
---
 gcc/range-op-ptr.cc | 98 +
 1 file changed, 98 insertions(+)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 38d9f65566f..a4418215613 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -265,8 +265,17 @@ range_operator::update_bitmask (irange &,
 class pointer_plus_operator : public range_operator
 {
   using range_operator::update_bitmask;
+  using range_operator::fold_range;
   using range_operator::op2_range;
 public:
+  virtual bool fold_range (prange , tree type,
+  const prange ,
+  const irange ,
+  relation_trio) const final override;
+  virtual bool op2_range (irange , tree type,
+ const prange ,
+ const prange ,
+ relation_trio = TRIO_VARYING) const final override;
   virtual void wi_fold (irange , tree type,
const wide_int _lb,
const wide_int _ub,
@@ -276,10 +285,99 @@ public:
  const irange ,
  const irange ,
  relation_trio = TRIO_VARYING) const;
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
   void update_bitmask (irange , const irange , const irange ) const
 { update_known_bitmask (r, POINTER_PLUS_EXPR, lh, rh); }
 } op_pointer_plus;
 
+bool
+pointer_plus_operator::fold_range (prange , tree type,
+  const prange ,
+  const irange ,
+  relation_trio) const
+{
+  if (empty_range_varying (r, type, op1, op2))
+return true;
+
+  const wide_int lh_lb = op1.lower_bound ();
+  const wide_int lh_ub = op1.upper_bound ();
+  const wide_int rh_lb = op2.lower_bound ();
+  const wide_int rh_ub = op2.upper_bound ();
+
+  // Check for [0,0] + const, and simply return the const.
+  if (lh_lb == 0 && lh_ub == 0 && rh_lb == rh_ub)
+{
+  r.set (type, rh_lb, rh_lb);
+  return true;
+}
+
+  // For pointer types, we are really only interested in asserting
+  // whether the expression evaluates to non-NULL.
+  //
+  // With -fno-delete-null-pointer-checks we need to be more
+  // conservative.  As some object might reside at address 0,
+  // then some offset could be added to it and the same offset
+  // subtracted again and the result would be NULL.
+  // E.g.
+  // static int a[12]; where [0] is NULL and
+  // ptr = [6];
+  // ptr -= 6;
+  // ptr will be NULL here, even when there is POINTER_PLUS_EXPR
+  // where the first range doesn't include zero and the second one
+  // doesn't either.  As the second operand is sizetype (unsigned),
+  // consider all ranges where the MSB could be set as possible
+  // subtractions where the result might be NULL.
+  if ((!wi_includes_zero_p (type, lh_lb, lh_ub)
+   || !wi_includes_zero_p (type, rh_lb, rh_ub))
+  && !TYPE_OVERFLOW_WRAPS (type)
+  && (flag_delete_null_pointer_checks
+ || !wi::sign_mask (rh_ub)))
+r.set_nonzero (type);
+  else if (lh_lb == lh_ub && lh_lb == 0
+  && rh_lb == rh_ub && rh_lb == 0)
+r.set_zero (type);
+  else
+   r.set_varying (type);
+
+  update_known_bitmask (r, POINTER_PLUS_EXPR, op1, op2);
+  return true;
+}
+
+bool
+pointer_plus_operator::op2_range (irange , tree type,
+ const prange  ATTRIBUTE_UNUSED,
+ const prange  ATTRIBUTE_UNUSED,
+ relation_trio trio) const
+{
+  relation_kind rel = trio.lhs_op1 ();
+  r.set_varying (type);
+
+  // If the LHS and OP1 are equal, the op2 must be zero.
+  if (rel == VREL_EQ)
+r.set_zero (type);
+  // If the LHS and OP1 are not equal, the offset must be non-zero.
+  else if (rel == VREL_NE)
+r.set_nonzero (type);
+  else
+return false;
+  return true;
+}
+
+bool
+pointer_plus_operator::pointers_handled_p (range_op_dispatch_type type,
+  unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+  return dispatch == RO_PPI;
+case DISPATCH_OP2_RANGE:
+  return dispatch == RO_IPP;
+default:
+  return true;
+}
+}
+
 void
 pointer_plus_operator::wi_fold (irange , tree type,
const wide_int _lb,


[gcc r15-153] Implement operator_addr_expr for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:54d3fd6d9f5d029c23ab376df2f5decb4902907d

commit r15-153-g54d3fd6d9f5d029c23ab376df2f5decb4902907d
Author: Aldy Hernandez 
Date:   Wed Mar 20 09:51:33 2024 +0100

Implement operator_addr_expr for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_addr_expr::op1_range): New.
(operator_addr_expr::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  4 
 gcc/range-op-ptr.cc  | 38 ++
 2 files changed, 42 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index b69e674a78b..0df300781f1 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -655,6 +655,10 @@ public:
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio rel = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const prange , const prange ,
+ relation_trio rel = TRIO_VARYING) const final override;
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_bitwise_not : public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 0addd1096c2..38d9f65566f 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1021,6 +1021,44 @@ operator_max::pointers_handled_p (range_op_dispatch_type 
type,
 }
 }
 
+bool
+operator_addr_expr::op1_range (prange , tree type,
+  const prange ,
+  const prange ,
+  relation_trio) const
+{
+  if (empty_range_varying (r, type, lhs, op2))
+return true;
+
+  // Return a non-null pointer of the LHS type (passed in op2), but only
+  // if we cant overflow, eitherwise a no-zero offset could wrap to zero.
+  // See PR 111009.
+  if (!lhs.undefined_p ()
+  && !range_includes_zero_p (lhs)
+  && TYPE_OVERFLOW_UNDEFINED (type))
+r.set_nonzero (type);
+  else
+r.set_varying (type);
+  return true;
+}
+
+bool
+operator_addr_expr::pointers_handled_p (range_op_dispatch_type type,
+   unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+  // NOTE: It looks like we never generate this combination.
+  gcc_unreachable ();
+  return false;
+case DISPATCH_OP1_RANGE:
+  return dispatch == RO_PPP;
+default:
+  return true;
+}
+}
+
 // Initialize any pointer operators to the primary table
 
 void


[gcc r15-152] Implement operator_min and operator_max for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:1a4f5d499109d3f2a06bfd1403b6d47d6f55e481

commit r15-152-g1a4f5d499109d3f2a06bfd1403b6d47d6f55e481
Author: Aldy Hernandez 
Date:   Wed Mar 20 08:44:49 2024 +0100

Implement operator_min and operator_max for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_min::fold_range): New.
(operator_min::pointers_handled_p): New.
(operator_max::fold_range): New.
(operator_max::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h | 12 +
 gcc/range-op-ptr.cc  | 70 
 2 files changed, 82 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 11b1bf0bca4..b69e674a78b 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -761,12 +761,18 @@ protected:
 class operator_min : public range_operator
 {
 public:
+  using range_operator::fold_range;
   using range_operator::update_bitmask;
+  bool fold_range (prange , tree type,
+  const prange ,
+  const prange ,
+  relation_trio) const final override;
   void update_bitmask (irange , const irange ,
   const irange ) const override;
   // Check compatibility of all operands.
   bool operand_check_p (tree t1, tree t2, tree t3) const final override
 { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 protected:
   void wi_fold (irange , tree type, const wide_int _lb,
const wide_int _ub, const wide_int _lb,
@@ -776,12 +782,18 @@ protected:
 class operator_max : public range_operator
 {
 public:
+  using range_operator::fold_range;
   using range_operator::update_bitmask;
+  bool fold_range (prange , tree type,
+  const prange ,
+  const prange ,
+  relation_trio) const final override;
   void update_bitmask (irange , const irange ,
   const irange ) const override;
   // Check compatibility of all operands.
   bool operand_check_p (tree t1, tree t2, tree t3) const final override
 { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 protected:
   void wi_fold (irange , tree type, const wide_int _lb,
const wide_int _ub, const wide_int _lb,
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index b8f86c8e838..0addd1096c2 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -951,6 +951,76 @@ operator_cast::pointers_handled_p (range_op_dispatch_type 
type,
 }
 }
 
+bool
+operator_min::fold_range (prange , tree type,
+ const prange ,
+ const prange ,
+ relation_trio) const
+{
+  // For MIN/MAX expressions with pointers, we only care about
+  // nullness.  If both are non null, then the result is nonnull.
+  // If both are null, then the result is null.  Otherwise they
+  // are varying.
+  if (!range_includes_zero_p (op1)
+  && !range_includes_zero_p (op2))
+r.set_nonzero (type);
+  else if (op1.zero_p () && op2.zero_p ())
+r.set_zero (type);
+  else
+r.set_varying (type);
+
+  update_known_bitmask (r, MIN_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_min::pointers_handled_p (range_op_dispatch_type type,
+ unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+  return dispatch == RO_PPP;
+default:
+  return true;
+}
+}
+
+bool
+operator_max::fold_range (prange , tree type,
+ const prange ,
+ const prange ,
+ relation_trio) const
+{
+  // For MIN/MAX expressions with pointers, we only care about
+  // nullness.  If both are non null, then the result is nonnull.
+  // If both are null, then the result is null.  Otherwise they
+  // are varying.
+  if (!range_includes_zero_p (op1)
+  && !range_includes_zero_p (op2))
+r.set_nonzero (type);
+  else if (op1.zero_p () && op2.zero_p ())
+r.set_zero (type);
+  else
+r.set_varying (type);
+
+  update_known_bitmask (r, MAX_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_max::pointers_handled_p (range_op_dispatch_type type,
+ unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+  return dispatch == RO_PPP;
+default:
+  return true;
+}
+}
+
 // Initialize any pointer operators to the primary table
 
 void


[gcc r15-151] Implement operator_cast for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:95fce0dc73002d5c9557fa7260c7ba1e761136ff

commit r15-151-g95fce0dc73002d5c9557fa7260c7ba1e761136ff
Author: Aldy Hernandez 
Date:   Wed Mar 20 08:04:32 2024 +0100

Implement operator_cast for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_cast::fold_range): New.
(operator_cast::op1_range): New.
(operator_cast::lhs_op1_relation): New.
(operator_cast::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  28 ++
 gcc/range-op-ptr.cc  | 245 +++
 2 files changed, 273 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 04c8acbd94a..11b1bf0bca4 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -400,14 +400,42 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio rel = TRIO_VARYING) const final override;
+  bool fold_range (prange , tree type,
+  const prange , const prange ,
+  relation_trio rel = TRIO_VARYING) const final override;
+  bool fold_range (irange , tree type,
+  const prange , const irange ,
+  relation_trio rel = TRIO_VARYING) const final override;
+  bool fold_range (prange , tree type,
+  const irange , const prange ,
+  relation_trio rel = TRIO_VARYING) const final override;
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio rel = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const prange , const prange ,
+ relation_trio rel = TRIO_VARYING) const final override;
+  bool op1_range (irange , tree type,
+ const prange , const irange ,
+ relation_trio rel = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const irange , const prange ,
+ relation_trio rel = TRIO_VARYING) const final override;
   relation_kind lhs_op1_relation (const irange ,
  const irange , const irange ,
  relation_kind) const final override;
+  relation_kind lhs_op1_relation (const prange ,
+ const prange , const prange ,
+ relation_kind) const final override;
+  relation_kind lhs_op1_relation (const prange ,
+ const irange , const irange ,
+ relation_kind) const final override;
+  relation_kind lhs_op1_relation (const irange ,
+ const prange , const prange ,
+ relation_kind) const final override;
   void update_bitmask (irange , const irange ,
   const irange ) const final override;
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 private:
   bool truncating_cast_p (const irange , const irange ) const;
   bool inside_domain_p (const wide_int , const wide_int ,
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index e59e278cbd7..b8f86c8e838 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -706,6 +706,251 @@ operator_cst::pointers_handled_p (range_op_dispatch_type 
type,
 }
 }
 
+// Cast between pointers.
+
+bool
+operator_cast::fold_range (prange , tree type,
+  const prange ,
+  const prange ,
+  relation_trio) const
+{
+  if (empty_range_varying (r, type, inner, outer))
+return true;
+
+  r.set (type, inner.lower_bound (), inner.upper_bound ());
+  r.update_bitmask (inner.get_bitmask ());
+  return true;
+}
+
+// Cast a pointer to an integer.
+
+bool
+operator_cast::fold_range (irange , tree type,
+  const prange ,
+  const irange ,
+  relation_trio) const
+{
+  if (empty_range_varying (r, type, inner, outer))
+return true;
+
+  // Represent INNER as an integer of the same size, and then cast it
+  // to the resulting integer type.
+  tree pointer_uint_type = make_unsigned_type (TYPE_PRECISION (inner.type ()));
+  r.set (pointer_uint_type, inner.lower_bound (), inner.upper_bound ());
+  r.update_bitmask (inner.get_bitmask ());
+  range_cast (r, type);
+  return true;
+}
+
+// Cast an integer to a pointer.
+
+bool
+operator_cast::fold_range (prange , tree type,
+  const irange ,
+  const prange ,
+  relation_trio) const
+{
+  if (empty_range_varying (r, type, inner, outer))
+return true;
+
+  // Cast INNER to an integer of the same size as the pointer we want,
+  // and then copy the bounds to the resulting pointer 

[gcc r15-150] Implement operator_cst for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:a91fd7b4342dbeaf1d2514beaee3af0bb5680b81

commit r15-150-ga91fd7b4342dbeaf1d2514beaee3af0bb5680b81
Author: Aldy Hernandez 
Date:   Wed Mar 20 07:55:57 2024 +0100

Implement operator_cst for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for pointer 
variants.
* range-op-ptr.cc (operator_cst::fold_range): New.
(operator_cst::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  4 
 gcc/range-op-ptr.cc  | 23 +++
 2 files changed, 27 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 60aaea9563d..04c8acbd94a 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -380,9 +380,13 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio rel = TRIO_VARYING) const final override;
+  bool fold_range (prange , tree type,
+  const prange , const prange ,
+  relation_trio rel = TRIO_VARYING) const final override;
   bool fold_range (frange , tree type,
   const frange , const frange ,
   relation_trio = TRIO_VARYING) const final override;
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 08419bfc798..e59e278cbd7 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -683,6 +683,29 @@ operator_identity::pointers_handled_p 
(range_op_dispatch_type type,
 }
 }
 
+bool
+operator_cst::fold_range (prange , tree type ATTRIBUTE_UNUSED,
+ const prange ,
+ const prange & ATTRIBUTE_UNUSED,
+ relation_trio) const
+{
+  r = lh;
+  return true;
+}
+
+bool
+operator_cst::pointers_handled_p (range_op_dispatch_type type,
+ unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+  return dispatch == RO_PPP;
+default:
+  return true;
+}
+}
+
 // Initialize any pointer operators to the primary table
 
 void


[gcc r15-149] Implement operator_identity for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:e7b6e9663e9b31e681fb0302338bcb4bb306a334

commit r15-149-ge7b6e9663e9b31e681fb0302338bcb4bb306a334
Author: Aldy Hernandez 
Date:   Wed Mar 20 07:50:11 2024 +0100

Implement operator_identity for prange.

gcc/ChangeLog:

* range-op-mixed.h: Add overloaded declarations for fold_range, 
op1_range,
lhs_op1_relation, pointers_handled_p.
* range-op-ptr.cc (operator_identity::fold_range): New.
(operator_identity::lhs_op1_relation): New.
(operator_identity::op1_range): New.
(operator_identity::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h | 10 ++
 gcc/range-op-ptr.cc  | 47 +++
 2 files changed, 57 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 8163a4b53ca..60aaea9563d 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -349,18 +349,28 @@ public:
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio rel = TRIO_VARYING) const final override;
+  bool fold_range (prange , tree type,
+  const prange , const prange ,
+  relation_trio rel = TRIO_VARYING) const final override;
   bool fold_range (frange , tree type ATTRIBUTE_UNUSED,
   const frange , const frange  ATTRIBUTE_UNUSED,
   relation_trio = TRIO_VARYING) const final override;
   bool op1_range (irange , tree type,
  const irange , const irange ,
  relation_trio rel = TRIO_VARYING) const final override;
+  bool op1_range (prange , tree type,
+ const prange , const prange ,
+ relation_trio rel = TRIO_VARYING) const final override;
   bool op1_range (frange , tree type ATTRIBUTE_UNUSED,
  const frange , const frange  ATTRIBUTE_UNUSED,
  relation_trio = TRIO_VARYING) const final override;
   relation_kind lhs_op1_relation (const irange ,
  const irange , const irange ,
  relation_kind rel) const final override;
+  relation_kind lhs_op1_relation (const prange ,
+ const prange , const prange ,
+ relation_kind rel) const final override;
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_cst : public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 560c798b90a..08419bfc798 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -636,6 +636,53 @@ public:
 }
 } op_hybrid_max;
 
+bool
+operator_identity::fold_range (prange , tree type ATTRIBUTE_UNUSED,
+  const prange  ATTRIBUTE_UNUSED,
+  const prange  ATTRIBUTE_UNUSED,
+  relation_trio) const
+{
+  r = lh;
+  return true;
+}
+
+relation_kind
+operator_identity::lhs_op1_relation (const prange ,
+const prange  ATTRIBUTE_UNUSED,
+const prange  ATTRIBUTE_UNUSED,
+relation_kind) const
+{
+  if (lhs.undefined_p ())
+return VREL_VARYING;
+  // Simply a copy, so they are equivalent.
+  return VREL_EQ;
+}
+
+bool
+operator_identity::op1_range (prange , tree type ATTRIBUTE_UNUSED,
+ const prange ,
+ const prange  ATTRIBUTE_UNUSED,
+ relation_trio) const
+{
+  r = lhs;
+  return true;
+}
+
+bool
+operator_identity::pointers_handled_p (range_op_dispatch_type type,
+  unsigned dispatch) const
+{
+  switch (type)
+{
+case DISPATCH_FOLD_RANGE:
+case DISPATCH_OP1_RANGE:
+case DISPATCH_LHS_OP1_RELATION:
+  return dispatch == RO_PPP;
+default:
+  return true;
+}
+}
+
 // Initialize any pointer operators to the primary table
 
 void


[gcc r15-147] Add prange implementation for get_legacy_range.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:ddf039adef5e2695f1cb27e0b6e5056fef4be2ee

commit r15-147-gddf039adef5e2695f1cb27e0b6e5056fef4be2ee
Author: Aldy Hernandez 
Date:   Wed Mar 20 06:39:48 2024 +0100

Add prange implementation for get_legacy_range.

gcc/ChangeLog:

* value-range.cc (get_legacy_range): New version for prange.

Diff:
---
 gcc/value-range.cc | 35 +--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 62170a438bf..3e1ecf69517 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1377,6 +1377,38 @@ get_legacy_range (const irange , tree , tree )
   return VR_RANGE;
 }
 
+static value_range_kind
+get_legacy_range (const prange , tree , tree )
+{
+  if (r.undefined_p ())
+{
+  min = NULL_TREE;
+  max = NULL_TREE;
+  return VR_UNDEFINED;
+}
+
+  tree type = r.type ();
+  if (r.varying_p ())
+{
+  min = r.lbound ();
+  max = r.ubound ();
+  return VR_VARYING;
+}
+  if (r.zero_p ())
+{
+  min = max = r.lbound ();
+  return VR_RANGE;
+}
+  if (r.nonzero_p ())
+{
+  min = max = build_zero_cst (type);
+  return VR_ANTI_RANGE;
+}
+  min = r.lbound ();
+  max = r.ubound ();
+  return VR_RANGE;
+}
+
 // Given a range in V, return an old-style legacy range consisting of
 // a value_range_kind with a MIN/MAX.  This is to maintain
 // compatibility with passes that still depend on VR_ANTI_RANGE, and
@@ -1388,8 +1420,7 @@ get_legacy_range (const vrange , tree , tree )
   if (is_a  (v))
 return get_legacy_range (as_a  (v), min, max);
 
-  gcc_unreachable ();
-  return VR_UNDEFINED;
+  return get_legacy_range (as_a  (v), min, max);
 }
 
 /* Set value range to the canonical form of {VRTYPE, MIN, MAX, EQUIV}.


[gcc r15-148] Implement range-op dispatch for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3

commit r15-148-g31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3
Author: Aldy Hernandez 
Date:   Wed Mar 20 07:19:45 2024 +0100

Implement range-op dispatch for prange.

This patch adds the range-op dispatch code for prange, and adds some
temporary sanity checks (for flag_checking only) to make sure we handle
all the pointer/integer variants.

In order to make sure I got all the combinations right, I started with
a clean slate, trapping on all pointer operands.  Then I added support
for each one piecemeal.  To verify the work, I added a
pointers_handled_p() helper that is implemented for each range-op
entry and returns TRUE iff the operator can handle a given combination
of pointers.  If this helper returns false, we will trap, because it
indicates an operator that was not implemented.  This is temporary
checking code, and I will rip it out once the the dust has
settled in a few days.

gcc/ChangeLog:

* range-op-mixed.h: Add using declarator for all classes.
* range-op-ptr.cc (range_operator::pointers_handled_p): New.
(range_operator::fold_range): New.
(range_operator::op1_op2_relation_effect): New.
(range_operator::op1_range): New.
(range_operator::op2_range): New.
(range_operator::op1_op2_relation): New.
(range_operator::lhs_op1_relation): New.
(range_operator::update_bitmask): New.
(class pointer_plus_operator): New.
(class operator_pointer_diff): New.
(class hybrid_min_operator): New.
(class hybrid_max_operator): New.
* range-op.cc: Add RO_PPP, RO_PPI, RO_IPP, RO_IPI, RO_PIP, RO_PII.
(range_op_handler::discriminator_fail): New.
(has_pointer_operand_p): New.
(range_op_handler::fold_range): Add pointer support.
(range_op_handler::op1_range): Same.
(range_op_handler::op2_range): Same.
(range_op_handler::lhs_op1_relation): Same.
(range_op_handler::lhs_op2_relation): Same.
(range_op_handler::op1_op2_relation): Same.
(class operator_div): Add using.
(class operator_lshift): Add using.
(class operator_rshift):Add using.
(class operator_trunc_mod):Add using.
(class operator_absu):Add using.
* range-op.h (enum range_op_dispatch_type): New.
Add extern definitions for RO_*.

Diff:
---
 gcc/range-op-mixed.h |  19 +
 gcc/range-op-ptr.cc  | 220 +++
 gcc/range-op.cc  | 124 +
 gcc/range-op.h   | 111 ++
 4 files changed, 474 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 3ee7c9d6e0d..8163a4b53ca 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -111,6 +111,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -150,6 +151,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -189,6 +191,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -225,6 +228,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -264,6 +268,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange , tree type,
   const irange , const irange ,
   relation_trio = TRIO_VARYING) const final override;
@@ -302,6 +307,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange , tree type,
   const irange , const irange ,
  

[gcc r15-146] Add hashing support for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:7c1b136630790eb34d57c45d9a816b32fd904e3f

commit r15-146-g7c1b136630790eb34d57c45d9a816b32fd904e3f
Author: Aldy Hernandez 
Date:   Wed Mar 20 06:39:07 2024 +0100

Add hashing support for prange.

gcc/ChangeLog:

* value-range.cc (add_vrange): Add prange support.

Diff:
---
 gcc/value-range.cc | 16 
 1 file changed, 16 insertions(+)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 84113ccfbd0..62170a438bf 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -346,6 +346,22 @@ add_vrange (const vrange , inchash::hash ,
   hstate.add_wide_int (bm.mask ());
   return;
 }
+  if (is_a  (v))
+{
+  const prange  = as_a  (v);
+  if (r.varying_p ())
+   hstate.add_int (VR_VARYING);
+  else
+   {
+ hstate.add_int (VR_RANGE);
+ hstate.add_wide_int (r.lower_bound ());
+ hstate.add_wide_int (r.upper_bound ());
+ irange_bitmask bm = r.get_bitmask ();
+ hstate.add_wide_int (bm.value ());
+ hstate.add_wide_int (bm.mask ());
+   }
+  return;
+}
   if (is_a  (v))
 {
   const frange  = as_a  (v);


[gcc r15-145] Add storage support for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:f859996a976ca185f371a8ed395e9c8e459e05b0

commit r15-145-gf859996a976ca185f371a8ed395e9c8e459e05b0
Author: Aldy Hernandez 
Date:   Wed Mar 20 06:38:06 2024 +0100

Add storage support for prange.

gcc/ChangeLog:

* value-range-storage.cc (vrange_allocator::clone_varying): Add
prange support.
(vrange_allocator::clone_undefined): Same.
(vrange_storage::alloc): Same.
(vrange_storage::set_vrange): Same.
(vrange_storage::get_vrange): Same.
(vrange_storage::fits_p): Same.
(vrange_storage::equal_p): Same.
(prange_storage::alloc): New.
(prange_storage::prange_storage): New.
(prange_storage::set_prange): New.
(prange_storage::get_prange): New.
(prange_storage::equal_p): New.
(prange_storage::fits_p): New.
* value-range-storage.h (class prange_storage): Add prange support.

Diff:
---
 gcc/value-range-storage.cc | 117 +
 gcc/value-range-storage.h  |  33 +
 2 files changed, 150 insertions(+)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 09a29776a0e..bbae0da4772 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -118,6 +118,8 @@ vrange_allocator::clone_varying (tree type)
 {
   if (irange::supports_p (type))
 return irange_storage::alloc (*m_alloc, int_range <1> (type));
+  if (prange::supports_p (type))
+return prange_storage::alloc (*m_alloc, prange (type));
   if (frange::supports_p (type))
 return frange_storage::alloc (*m_alloc, frange (type));
   return NULL;
@@ -128,6 +130,8 @@ vrange_allocator::clone_undefined (tree type)
 {
   if (irange::supports_p (type))
 return irange_storage::alloc (*m_alloc, int_range<1> ());
+  if (prange::supports_p (type))
+return prange_storage::alloc (*m_alloc, prange ());
   if (frange::supports_p (type))
 return frange_storage::alloc  (*m_alloc, frange ());
   return NULL;
@@ -141,6 +145,8 @@ vrange_storage::alloc (vrange_internal_alloc , 
const vrange )
 {
   if (is_a  (r))
 return irange_storage::alloc (allocator, as_a  (r));
+  if (is_a  (r))
+return prange_storage::alloc (allocator, as_a  (r));
   if (is_a  (r))
 return frange_storage::alloc (allocator, as_a  (r));
   return NULL;
@@ -157,6 +163,12 @@ vrange_storage::set_vrange (const vrange )
   gcc_checking_assert (s->fits_p (as_a  (r)));
   s->set_irange (as_a  (r));
 }
+  else if (is_a  (r))
+{
+  prange_storage *s = static_cast  (this);
+  gcc_checking_assert (s->fits_p (as_a  (r)));
+  s->set_prange (as_a  (r));
+}
   else if (is_a  (r))
 {
   frange_storage *s = static_cast  (this);
@@ -190,6 +202,11 @@ vrange_storage::get_vrange (vrange , tree type) const
   const irange_storage *s = static_cast  (this);
   s->get_irange (as_a  (r), type);
 }
+  else if (is_a  (r))
+{
+  const prange_storage *s = static_cast  (this);
+  s->get_prange (as_a  (r), type);
+}
   else if (is_a  (r))
 {
   const frange_storage *s = static_cast  (this);
@@ -209,6 +226,11 @@ vrange_storage::fits_p (const vrange ) const
   const irange_storage *s = static_cast  (this);
   return s->fits_p (as_a  (r));
 }
+  if (is_a  (r))
+{
+  const prange_storage *s = static_cast  (this);
+  return s->fits_p (as_a  (r));
+}
   if (is_a  (r))
 {
   const frange_storage *s = static_cast  (this);
@@ -230,6 +252,11 @@ vrange_storage::equal_p (const vrange ) const
   const irange_storage *s = static_cast  (this);
   return s->equal_p (as_a  (r));
 }
+  if (is_a  (r))
+{
+  const prange_storage *s = static_cast  (this);
+  return s->equal_p (as_a  (r));
+}
   if (is_a  (r))
 {
   const frange_storage *s = static_cast  (this);
@@ -559,6 +586,96 @@ frange_storage::fits_p (const frange &) const
   return true;
 }
 
+//
+// prange_storage implementation
+//
+
+prange_storage *
+prange_storage::alloc (vrange_internal_alloc , const prange )
+{
+  // Assume all pointers are the same size.
+  unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
+  gcc_checking_assert (r.undefined_p () || TYPE_PRECISION (r.type ()) == prec);
+
+  typedef trailing_wide_ints twi;
+  size_t size = sizeof (prange_storage) + twi::extra_size (prec);
+  prange_storage *p = static_cast  (allocator.alloc (size));
+  new (p) prange_storage (r);
+  return p;
+}
+
+// Initialize the storage with R.
+
+prange_storage::prange_storage (const prange )
+{
+  // It is the caller's responsibility to allocate enough space such
+  // that the precision fits.
+  unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
+  

[gcc r15-144] Add streaming support for prange.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:a7f1285380029d2928d61e61032c1948ccabc495

commit r15-144-ga7f1285380029d2928d61e61032c1948ccabc495
Author: Aldy Hernandez 
Date:   Wed Mar 20 06:34:26 2024 +0100

Add streaming support for prange.

gcc/ChangeLog:

* data-streamer-in.cc (streamer_read_value_range): Add prange 
support.
* data-streamer-out.cc (streamer_write_vrange): Same.

Diff:
---
 gcc/data-streamer-in.cc  | 12 
 gcc/data-streamer-out.cc | 10 ++
 2 files changed, 22 insertions(+)

diff --git a/gcc/data-streamer-in.cc b/gcc/data-streamer-in.cc
index 3a0d3c6ad0f..12cb10e42c0 100644
--- a/gcc/data-streamer-in.cc
+++ b/gcc/data-streamer-in.cc
@@ -268,6 +268,18 @@ streamer_read_value_range (class lto_input_block *ib, 
data_in *data_in,
}
   return;
 }
+  if (is_a  (vr))
+{
+  prange  = as_a  (vr);
+  wide_int lb = streamer_read_wide_int (ib);
+  wide_int ub = streamer_read_wide_int (ib);
+  r.set (type, lb, ub);
+  wide_int value = streamer_read_wide_int (ib);
+  wide_int mask = streamer_read_wide_int (ib);
+  irange_bitmask bm (value, mask);
+  r.update_bitmask (bm);
+  return;
+}
   gcc_unreachable ();
 }
 
diff --git a/gcc/data-streamer-out.cc b/gcc/data-streamer-out.cc
index 07cc6bd2018..c237e30f704 100644
--- a/gcc/data-streamer-out.cc
+++ b/gcc/data-streamer-out.cc
@@ -450,6 +450,16 @@ streamer_write_vrange (struct output_block *ob, const 
vrange )
}
   return;
 }
+  if (is_a  (v))
+{
+  const prange  = as_a  (v);
+  streamer_write_wide_int (ob, r.lower_bound ());
+  streamer_write_wide_int (ob, r.upper_bound ());
+  irange_bitmask bm = r.get_bitmask ();
+  streamer_write_wide_int (ob, bm.value ());
+  streamer_write_wide_int (ob, bm.mask ());
+  return;
+}
   gcc_unreachable ();
 }


[gcc r15-143] Implement basic prange class.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:64993a89ad75814ab69addade1b2c0020a180f41

commit r15-143-g64993a89ad75814ab69addade1b2c0020a180f41
Author: Aldy Hernandez 
Date:   Wed Mar 20 06:25:52 2024 +0100

Implement basic prange class.

This provides a bare prange class with bounds and bitmasks.  It will
be a drop-in replacement for pointer ranges, so we can pull their
support from irange.  The range-op code will be contributed as a
follow-up.

The code is disabled by default, as irange::supports_p still accepts
pointers:

inline bool
irange::supports_p (const_tree type)
{
  return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
}

Once the prange operators are implemented in range-ops, pointer
support will be removed from irange to activate pranges.

gcc/ChangeLog:

* value-range-pretty-print.cc (vrange_printer::visit): New.
* value-range-pretty-print.h: Declare prange visit() method.
* value-range.cc (vrange::operator=): Add prange support.
(vrange::operator==): Same.
(prange::accept): New.
(prange::set_nonnegative): New.
(prange::set): New.
(prange::contains_p): New.
(prange::singleton_p): New.
(prange::lbound): New.
(prange::ubound): New.
(prange::union_): New.
(prange::intersect): New.
(prange::operator=): New.
(prange::operator==): New.
(prange::invert): New.
(prange::verify_range): New.
(prange::update_bitmask): New.
(range_tests_misc): Use prange.
* value-range.h (enum value_range_discriminator): Add VR_PRANGE.
(class prange): New.
(Value_Range::init): Add prange support.
(Value_Range::operator=): Same.
(Value_Range::supports_type_p): Same.
(prange::prange):  New.
(prange::supports_p): New.
(prange::supports_type_p): New.
(prange::set_undefined): New.
(prange::set_varying): New.
(prange::set_nonzero): New.
(prange::set_zero): New.
(prange::contains_p): New.
(prange::zero_p): New.
(prange::nonzero_p): New.
(prange::type): New.
(prange::lower_bound): New.
(prange::upper_bound): New.
(prange::varying_compatible_p): New.
(prange::get_bitmask): New.
(prange::fits_p): New.

Diff:
---
 gcc/value-range-pretty-print.cc |  25 
 gcc/value-range-pretty-print.h  |   1 +
 gcc/value-range.cc  | 303 +++-
 gcc/value-range.h   | 199 +++---
 4 files changed, 500 insertions(+), 28 deletions(-)

diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc
index b6d23dce6d2..b11d6494774 100644
--- a/gcc/value-range-pretty-print.cc
+++ b/gcc/value-range-pretty-print.cc
@@ -112,6 +112,31 @@ vrange_printer::visit (const irange ) const
   print_irange_bitmasks (pp, r.m_bitmask);
 }
 
+void
+vrange_printer::visit (const prange ) const
+{
+  pp_string (pp, "[prange] ");
+  if (r.undefined_p ())
+{
+  pp_string (pp, "UNDEFINED");
+  return;
+}
+  dump_generic_node (pp, r.type (), 0, TDF_NONE | TDF_NOUID, false);
+  pp_character (pp, ' ');
+  if (r.varying_p ())
+{
+  pp_string (pp, "VARYING");
+  return;
+}
+
+  pp_character (pp, '[');
+  print_int_bound (pp, r.lower_bound (), r.type ());
+  pp_string (pp, ", ");
+  print_int_bound (pp, r.upper_bound (), r.type ());
+  pp_character (pp, ']');
+  print_irange_bitmasks (pp, r.m_bitmask);
+}
+
 void
 vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE ) const
 {
diff --git a/gcc/value-range-pretty-print.h b/gcc/value-range-pretty-print.h
index 44cd6e81298..5522aad0673 100644
--- a/gcc/value-range-pretty-print.h
+++ b/gcc/value-range-pretty-print.h
@@ -27,6 +27,7 @@ public:
   vrange_printer (pretty_printer *pp_) : pp (pp_) { }
   void visit (const unsupported_range &) const override;
   void visit (const irange &) const override;
+  void visit (const prange &) const override;
   void visit (const frange &) const override;
 private:
   void print_frange_nan (const frange &) const;
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 7250115261f..84113ccfbd0 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -251,6 +251,8 @@ vrange::operator= (const vrange )
 {
   if (is_a  (src))
 as_a  (*this) = as_a  (src);
+  else if (is_a  (src))
+as_a  (*this) = as_a  (src);
   else if (is_a  (src))
 as_a  (*this) = as_a  (src);
   else
@@ -268,6 +270,8 @@ vrange::operator== (const vrange ) const
 {
   if (is_a  (src))
 return as_a  (*this) == as_a  (src);
+  if (is_a  (src))
+return as_a  (*this) == as_a  (src);
   if (is_a  (src))
 return as_a  (*this) == as_a  (src);
   

[gcc r15-142] Minimal prange class showing inlining degradation to VRP.

2024-05-04 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:f5891967947562060076956bd953e5df4c7289bf

commit r15-142-gf5891967947562060076956bd953e5df4c7289bf
Author: Aldy Hernandez 
Date:   Sat May 4 06:45:18 2024 +0200

Minimal prange class showing inlining degradation to VRP.

There is a 2% slowdown to VRP unrelated to the work at hand.  This patch
is a skeleton implementation of prange that exhibits this degradation.  It
is meant as a place in the commit history we can return to in order to 
revisit
the issue.

The relevant discussion is here:

https://gcc.gnu.org/pipermail/gcc/2024-May/243898.html

gcc/ChangeLog:

* value-range.h (class prange): New.

Diff:
---
 gcc/value-range.h | 59 +++
 1 file changed, 59 insertions(+)

diff --git a/gcc/value-range.h b/gcc/value-range.h
index 934eec9e386..f52d5165707 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -378,6 +378,39 @@ private:
   wide_int m_ranges[N*2];
 };
 
+class prange : public vrange
+{
+public:
+  static bool supports_p (const_tree) { return false; }
+  virtual bool supports_type_p (const_tree) const final override { return 
false; }
+  virtual void accept (const vrange_visitor &) const final override {}
+  virtual void set_undefined () final override {}
+  virtual void set_varying (tree) final override {}
+  virtual void set_nonzero (tree) final override {}
+  virtual void set_zero (tree) final override;
+  virtual void set_nonnegative (tree) final override {}
+  virtual bool contains_p (tree) const final override { return false; }
+  virtual bool fits_p (const vrange &) const final override { return false; }
+  virtual bool singleton_p (tree * = NULL) const final override { return 
false; }
+  virtual bool zero_p () const final override { return false; }
+  virtual bool nonzero_p () const final override { return false; }
+  virtual void set (tree, tree, value_range_kind = VR_RANGE) final override {}
+  virtual tree type () const final override { return NULL; }
+  virtual bool union_ (const vrange &) final override { return false; }
+  virtual bool intersect (const vrange &) final override { return false; }
+  virtual tree lbound () const final override { return NULL; }
+  virtual tree ubound () const final override { return NULL; }
+
+  wide_int lower_bound () const;
+  wide_int upper_bound () const;
+  irange_bitmask get_bitmask () const final override;
+  void update_bitmask (const irange_bitmask &) final override {}
+private:
+  wide_int m_min;
+  wide_int m_max;
+  irange_bitmask m_bitmask;
+};
+
 // Unsupported temporaries may be created by ranger before it's known
 // they're unsupported, or by vr_values::get_value_range.
 
@@ -1187,6 +1220,32 @@ irange_val_max (const_tree type)
   return wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
 }
 
+inline void
+prange::set_zero (tree type)
+{
+  wide_int zero = wi::zero (TYPE_PRECISION (type));
+  m_min = m_max = zero;
+  m_bitmask = irange_bitmask (zero, zero);
+}
+
+inline wide_int
+prange::lower_bound () const
+{
+  return m_min;
+}
+
+inline wide_int
+prange::upper_bound () const
+{
+  return m_max;
+}
+
+inline irange_bitmask
+prange::get_bitmask () const
+{
+  return m_bitmask;
+}
+
 inline
 frange::frange ()
   : vrange (VR_FRANGE)


[gcc r15-88] Reduce startup costs for Value_Range.

2024-05-01 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:c60b3e211c555706cdc2dc8bfcdd540152cff350

commit r15-88-gc60b3e211c555706cdc2dc8bfcdd540152cff350
Author: Aldy Hernandez 
Date:   Tue Apr 30 19:39:00 2024 +0200

Reduce startup costs for Value_Range.

Value_Range is our polymorphic temporary that can hold any range.  It
is used for type agnostic code where it isn't known ahead of time,
what the type of the range will be (irange, france, etc).  Currently,
there is a temporary of each type in the object, which means we need
to construct each range for every temporary.  This isn't scaling
well now that prange is about to add yet another range type.

This patch removes each range, opting to use in-place new for a byte
buffer sufficiently large to hold ranges of any type.  It reduces the
memory footprint by 14% for every Value_Range temporary (from 792 to
680 bytes), and we are guaranteed it will never again grow as we add
more range types (strings, complex numbers, etc).

Surprisingly, it improves VRP performance by 6.61% and overall
compilation by 0.44%, which is a lot more than we bargained for
when we started working on prange performance.

There is a slight change in semantics for Value_Range.  The default
constructor does not initialize the object at all.  It must be
manually initialized with either Value_Range::set_type(), or by
assigning a range to it.  This means that IPA's m_known_value_ranges
must be initialized at allocation, instead of depending on the empty
constructor to initialize it to VR_UNDEFINED for unsupported_range.

I have taken the time to properly document both the class, and each
method.  If anything isn't clear, please let me know so I can adjust it
accordingly.

gcc/ChangeLog:

* ipa-fnsummary.cc (evaluate_properties_for_edge): Initialize 
Value_Range's.
* value-range.h (class Value_Range): Add a buffer and remove
m_irange and m_frange.
(Value_Range::Value_Range): Call init.
(Value_Range::set_type): Same.
(Value_Range::init): Use in place new to initialize buffer.
(Value_Range::operator=): Tidy.

Diff:
---
 gcc/ipa-fnsummary.cc |   8 +++-
 gcc/value-range.h| 127 ---
 2 files changed, 76 insertions(+), 59 deletions(-)

diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index dff40cd8aa5..668a01ef175 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -681,8 +681,12 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool 
inline_p,
if (!vr.undefined_p () && !vr.varying_p ())
  {
if (!avals->m_known_value_ranges.length ())
- avals->m_known_value_ranges.safe_grow_cleared (count,
-true);
+ {
+   avals->m_known_value_ranges.safe_grow_cleared 
(count,
+  
true);
+   for (int i = 0; i < count; ++i)
+ avals->m_known_value_ranges[i].set_type 
(void_type_node);
+ }
avals->m_known_value_ranges[i] = vr;
  }
  }
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 471f362f388..f1c638f8cd0 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -684,6 +684,16 @@ typedef int_range<2> value_range;
 // This is an "infinite" precision range object for use in temporary
 // calculations for any of the handled types.  The object can be
 // transparently used as a vrange.
+//
+// Using any of the various constructors initializes the object
+// appropriately, but the default constructor is uninitialized and
+// must be initialized either with set_type() or by assigning into it.
+//
+// Assigning between incompatible types is allowed.  For example if a
+// temporary holds an irange, you can assign an frange into it, and
+// all the right things will happen.  However, before passing this
+// object to a function accepting a vrange, the correct type must be
+// set.  If it isn't, you can do so with set_type().
 
 class Value_Range
 {
@@ -693,6 +703,7 @@ public:
   Value_Range (tree type);
   Value_Range (tree, tree, value_range_kind kind = VR_RANGE);
   Value_Range (const Value_Range &);
+  ~Value_Range ();
   void set_type (tree type);
   vrange& operator= (const vrange &);
   Value_Range& operator= (const Value_Range &);
@@ -726,16 +737,29 @@ public:
   void accept (const vrange_visitor ) const { m_vrange->accept (v); }
 private:
   void init (tree type);
-  unsupported_range m_unsupported;
+  void init (const vrange &);
+
   vrange *m_vrange;
-  int_range_max m_irange;
-  frange m_frange;
+  // The buffer must be at least the size of the 

[gcc r15-87] Cleanups to unsupported_range.

2024-05-01 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:1b5732de7e3980aa5197b1ac818f48f1ce9f87ab

commit r15-87-g1b5732de7e3980aa5197b1ac818f48f1ce9f87ab
Author: Aldy Hernandez 
Date:   Tue Apr 30 18:54:11 2024 +0200

Cleanups to unsupported_range.

Here are some cleanups to unsupported_range so the assignment operator
takes an unsupported_range and behaves like the other ranges.  This
makes subsequent cleanups easier.

gcc/ChangeLog:

* value-range.cc (unsupported_range::union_): Cast vrange to
unsupported_range.
(unsupported_range::intersect): Same.
(unsupported_range::operator=): Make argument an unsupported_range.
* value-range.h: New constructor.

Diff:
---
 gcc/value-range.cc | 10 +++---
 gcc/value-range.h  |  7 ++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index ca6d521c625..7250115261f 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -147,8 +147,10 @@ unsupported_range::set_varying (tree)
 }
 
 bool
-unsupported_range::union_ (const vrange )
+unsupported_range::union_ (const vrange )
 {
+  const unsupported_range  = as_a  (v);
+
   if (r.undefined_p () || varying_p ())
 return false;
   if (undefined_p () || r.varying_p ())
@@ -161,8 +163,10 @@ unsupported_range::union_ (const vrange )
 }
 
 bool
-unsupported_range::intersect (const vrange )
+unsupported_range::intersect (const vrange )
 {
+  const unsupported_range  = as_a  (v);
+
   if (undefined_p () || r.varying_p ())
 return false;
   if (r.undefined_p ())
@@ -216,7 +220,7 @@ unsupported_range::fits_p (const vrange &) const
 }
 
 unsupported_range &
-unsupported_range::operator= (const vrange )
+unsupported_range::operator= (const unsupported_range )
 {
   if (r.undefined_p ())
 set_undefined ();
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 11c73faca1b..471f362f388 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -389,6 +389,11 @@ public:
   {
 set_undefined ();
   }
+  unsupported_range (const unsupported_range )
+: vrange (VR_UNKNOWN)
+  {
+unsupported_range::operator= (src);
+  }
   void set (tree min, tree, value_range_kind = VR_RANGE) final override;
   tree type () const final override;
   bool supports_type_p (const_tree) const final override;
@@ -405,7 +410,7 @@ public:
   void set_zero (tree type) final override;
   void set_nonnegative (tree type) final override;
   bool fits_p (const vrange &) const final override;
-  unsupported_range& operator= (const vrange );
+  unsupported_range& operator= (const unsupported_range );
   tree lbound () const final override;
   tree ubound () const final override;
 };


[gcc r15-70] Change int_range<2> to infinite precision.

2024-04-30 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:0b2735e0797fee9b4ec5cd74f22afe0483f888dd

commit r15-70-g0b2735e0797fee9b4ec5cd74f22afe0483f888dd
Author: Aldy Hernandez 
Date:   Tue Apr 30 10:36:58 2024 +0200

Change int_range<2> to infinite precision.

In my previous change I mistakenly changed Value_Range to
int_range<2>.  The former has "infinite" precision for integer ranges,
whereas int_range<2> has two sub-ranges.  This should have been
int_range_max.

gcc/ChangeLog:

* gimple-ssa-warn-access.cc (check_nul_terminated_array): Change
int_range<2> to int_range_max.
(memmodel_to_uhwi): Same.
* tree-ssa-loop-niter.cc (refine_value_range_using_guard): Same.
(determine_value_range): Same.
(infer_loop_bounds_from_signedness): Same.
(scev_var_range_cant_overflow): Same.

Diff:
---
 gcc/gimple-ssa-warn-access.cc |  4 ++--
 gcc/tree-ssa-loop-niter.cc| 12 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 450c1caa765..2c10d19e7f3 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -330,7 +330,7 @@ check_nul_terminated_array (GimpleOrTree expr, tree src, 
tree bound)
   wide_int bndrng[2];
   if (bound)
 {
-  int_range<2> r (TREE_TYPE (bound));
+  int_range_max r (TREE_TYPE (bound));
 
   get_range_query (cfun)->range_of_expr (r, bound);
 
@@ -2816,7 +2816,7 @@ memmodel_to_uhwi (tree ord, gimple *stmt, unsigned 
HOST_WIDE_INT *cstval)
 {
   /* Use the range query to determine constant values in the absence
 of constant propagation (such as at -O0).  */
-  int_range<2> rng (TREE_TYPE (ord));
+  int_range_max rng (TREE_TYPE (ord));
   if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
  || !rng.singleton_p ())
return false;
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index adbc1936982..0fde07e626f 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -214,7 +214,7 @@ refine_value_range_using_guard (tree type, tree var,
   get_type_static_bounds (type, mint, maxt);
   mpz_init (minc1);
   mpz_init (maxc1);
-  int_range<2> r (TREE_TYPE (varc1));
+  int_range_max r (TREE_TYPE (varc1));
   /* Setup range information for varc1.  */
   if (integer_zerop (varc1))
 {
@@ -368,7 +368,7 @@ determine_value_range (class loop *loop, tree type, tree 
var, mpz_t off,
   gphi_iterator gsi;
 
   /* Either for VAR itself...  */
-  int_range<2> var_range (TREE_TYPE (var));
+  int_range_max var_range (TREE_TYPE (var));
   get_range_query (cfun)->range_of_expr (var_range, var);
   if (var_range.varying_p () || var_range.undefined_p ())
rtype = VR_VARYING;
@@ -382,7 +382,7 @@ determine_value_range (class loop *loop, tree type, tree 
var, mpz_t off,
 
   /* Or for PHI results in loop->header where VAR is used as
 PHI argument from the loop preheader edge.  */
-  int_range<2> phi_range (TREE_TYPE (var));
+  int_range_max phi_range (TREE_TYPE (var));
   for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next 
())
{
  gphi *phi = gsi.phi ();
@@ -408,7 +408,7 @@ determine_value_range (class loop *loop, tree type, tree 
var, mpz_t off,
 involved.  */
  if (wi::gt_p (minv, maxv, sgn))
{
- int_range<2> vr (TREE_TYPE (var));
+ int_range_max vr (TREE_TYPE (var));
  get_range_query (cfun)->range_of_expr (vr, var);
  if (vr.varying_p () || vr.undefined_p ())
rtype = VR_VARYING;
@@ -4367,7 +4367,7 @@ infer_loop_bounds_from_signedness (class loop *loop, 
gimple *stmt)
 
   low = lower_bound_in_type (type, type);
   high = upper_bound_in_type (type, type);
-  int_range<2> r (TREE_TYPE (def));
+  int_range_max r (TREE_TYPE (def));
   get_range_query (cfun)->range_of_expr (r, def);
   if (!r.varying_p () && !r.undefined_p ())
 {
@@ -5426,7 +5426,7 @@ scev_var_range_cant_overflow (tree var, tree step, class 
loop *loop)
   if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb))
 return false;
 
-  int_range<2> r (TREE_TYPE (var));
+  int_range_max r (TREE_TYPE (var));
   get_range_query (cfun)->range_of_expr (r, var);
   if (r.varying_p () || r.undefined_p ())
 return false;


[gcc r15-41] Callers of irange_bitmask must normalize value/mask pairs.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:d71308d5a681de00ea291136c162e5b46c7c

commit r15-41-gd71308d5a681de00ea291136c162e5b46c7c
Author: Aldy Hernandez 
Date:   Tue Apr 23 10:12:56 2024 +0200

Callers of irange_bitmask must normalize value/mask pairs.

As per the documentation, irange_bitmask must have the unknown bits in
the mask set to 0 in the value field.  Even though we say we must have
normalized value/mask bits, we don't enforce it, opting to normalize
on the fly in union and intersect.  Avoiding this lazy enforcing as
well as the extra saving/restoring involved in returning the changed
status, gives us a performance increase of 1.25% for VRP and 1.51% for
ipa-CP.

gcc/ChangeLog:

* tree-ssa-ccp.cc (ccp_finalize): Normalize before calling
set_bitmask.
* value-range.cc (irange::intersect_bitmask): Calculate changed
irange_bitmask bits on our own.
(irange::union_bitmask): Same.
(irange_bitmask::verify_mask): Verify that bits are normalized.
* value-range.h (irange_bitmask::union_): Do not normalize.
Remove return value.
(irange_bitmask::intersect): Same.

Diff:
---
 gcc/tree-ssa-ccp.cc |  1 +
 gcc/value-range.cc  |  7 +--
 gcc/value-range.h   | 24 ++--
 3 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index f6a5cd0ee6e..3749126b5f7 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -1024,6 +1024,7 @@ ccp_finalize (bool nonzero_p)
  unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value));
  wide_int value = wi::to_wide (val->value);
  wide_int mask = wide_int::from (val->mask, precision, UNSIGNED);
+ value = value & ~mask;
  set_bitmask (name, value, mask);
}
 }
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index a27de5534e1..ca6d521c625 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2067,7 +2067,8 @@ irange::intersect_bitmask (const irange )
 
   irange_bitmask bm = get_bitmask ();
   irange_bitmask save = bm;
-  if (!bm.intersect (r.get_bitmask ()))
+  bm.intersect (r.get_bitmask ());
+  if (save == bm)
 return false;
 
   m_bitmask = bm;
@@ -2099,7 +2100,8 @@ irange::union_bitmask (const irange )
 
   irange_bitmask bm = get_bitmask ();
   irange_bitmask save = bm;
-  if (!bm.union_ (r.get_bitmask ()))
+  bm.union_ (r.get_bitmask ());
+  if (save == bm)
 return false;
 
   m_bitmask = bm;
@@ -2133,6 +2135,7 @@ void
 irange_bitmask::verify_mask () const
 {
   gcc_assert (m_value.get_precision () == m_mask.get_precision ());
+  gcc_checking_assert (wi::bit_and (m_mask, m_value) == 0);
 }
 
 void
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 0ab717697f0..11c73faca1b 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -139,8 +139,8 @@ public:
   void set_unknown (unsigned prec);
   bool unknown_p () const;
   unsigned get_precision () const;
-  bool union_ (const irange_bitmask );
-  bool intersect (const irange_bitmask );
+  void union_ (const irange_bitmask );
+  void intersect (const irange_bitmask );
   bool operator== (const irange_bitmask ) const;
   bool operator!= (const irange_bitmask ) const { return !(*this == src); }
   void verify_mask () const;
@@ -233,29 +233,18 @@ irange_bitmask::operator== (const irange_bitmask ) 
const
   return m_value == src.m_value && m_mask == src.m_mask;
 }
 
-inline bool
-irange_bitmask::union_ (const irange_bitmask _src)
+inline void
+irange_bitmask::union_ (const irange_bitmask )
 {
-  // Normalize mask.
-  irange_bitmask src (orig_src.m_value & ~orig_src.m_mask, orig_src.m_mask);
-  m_value &= ~m_mask;
-
-  irange_bitmask save (*this);
   m_mask = (m_mask | src.m_mask) | (m_value ^ src.m_value);
   m_value = m_value & src.m_value;
   if (flag_checking)
 verify_mask ();
-  return *this != save;
 }
 
-inline bool
-irange_bitmask::intersect (const irange_bitmask _src)
+inline void
+irange_bitmask::intersect (const irange_bitmask )
 {
-  // Normalize mask.
-  irange_bitmask src (orig_src.m_value & ~orig_src.m_mask, orig_src.m_mask);
-  m_value &= ~m_mask;
-
-  irange_bitmask save (*this);
   // If we have two known bits that are incompatible, the resulting
   // bit is undefined.  It is unclear whether we should set the entire
   // range to UNDEFINED, or just a subset of it.  For now, set the
@@ -274,7 +263,6 @@ irange_bitmask::intersect (const irange_bitmask _src)
 }
   if (flag_checking)
 verify_mask ();
-  return *this != save;
 }
 
 // An integer range without any storage.


[gcc r15-40] Remove range_zero and range_nonzero.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:3b9abfd2df5fe720798aab1e21b4a11876607561

commit r15-40-g3b9abfd2df5fe720798aab1e21b4a11876607561
Author: Aldy Hernandez 
Date:   Wed Mar 20 05:51:55 2024 +0100

Remove range_zero and range_nonzero.

Remove legacy range_zero and range_nonzero as they return by value,
which make it not work in a separate irange and prange world.  Also,
we already have set_zero and set_nonzero methods in vrange.

gcc/ChangeLog:

* range-op-ptr.cc (pointer_plus_operator::wi_fold): Use method
range setters instead of out of line functions.
(pointer_min_max_operator::wi_fold): Same.
(pointer_and_operator::wi_fold): Same.
(pointer_or_operator::wi_fold): Same.
* range-op.cc (operator_negate::fold_range): Same.
(operator_addr_expr::fold_range): Same.
(range_op_cast_tests): Same.
* range.cc (range_zero): Remove.
(range_nonzero): Remove.
* range.h (range_zero): Remove.
(range_nonzero): Remove.
* value-range.cc (range_tests_misc): Use method instead of out of
line function.

Diff:
---
 gcc/range-op-ptr.cc | 14 +++---
 gcc/range-op.cc | 14 --
 gcc/range.cc| 14 --
 gcc/range.h |  2 --
 gcc/value-range.cc  |  7 ---
 5 files changed, 19 insertions(+), 32 deletions(-)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 2c85d75b5e8..7343ef635f3 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -101,10 +101,10 @@ pointer_plus_operator::wi_fold (irange , tree type,
   && !TYPE_OVERFLOW_WRAPS (type)
   && (flag_delete_null_pointer_checks
  || !wi::sign_mask (rh_ub)))
-r = range_nonzero (type);
+r.set_nonzero (type);
   else if (lh_lb == lh_ub && lh_lb == 0
   && rh_lb == rh_ub && rh_lb == 0)
-r = range_zero (type);
+r.set_zero (type);
   else
r.set_varying (type);
 }
@@ -150,9 +150,9 @@ pointer_min_max_operator::wi_fold (irange , tree type,
   // are varying.
   if (!wi_includes_zero_p (type, lh_lb, lh_ub)
   && !wi_includes_zero_p (type, rh_lb, rh_ub))
-r = range_nonzero (type);
+r.set_nonzero (type);
   else if (wi_zero_p (type, lh_lb, lh_ub) && wi_zero_p (type, rh_lb, rh_ub))
-r = range_zero (type);
+r.set_zero (type);
   else
 r.set_varying (type);
 }
@@ -175,7 +175,7 @@ pointer_and_operator::wi_fold (irange , tree type,
   // For pointer types, we are really only interested in asserting
   // whether the expression evaluates to non-NULL.
   if (wi_zero_p (type, lh_lb, lh_ub) || wi_zero_p (type, lh_lb, lh_ub))
-r = range_zero (type);
+r.set_zero (type);
   else
 r.set_varying (type);
 }
@@ -236,9 +236,9 @@ pointer_or_operator::wi_fold (irange , tree type,
   // whether the expression evaluates to non-NULL.
   if (!wi_includes_zero_p (type, lh_lb, lh_ub)
   && !wi_includes_zero_p (type, rh_lb, rh_ub))
-r = range_nonzero (type);
+r.set_nonzero (type);
   else if (wi_zero_p (type, lh_lb, lh_ub) && wi_zero_p (type, rh_lb, rh_ub))
-r = range_zero (type);
+r.set_zero (type);
   else
 r.set_varying (type);
 }
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 6ea7d624a9b..ab3a4f0b200 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -4364,9 +4364,11 @@ operator_negate::fold_range (irange , tree type,
 {
   if (empty_range_varying (r, type, lh, rh))
 return true;
-  // -X is simply 0 - X.
-  return range_op_handler (MINUS_EXPR).fold_range (r, type,
-  range_zero (type), lh);
+
+// -X is simply 0 - X.
+  int_range<1> zero;
+  zero.set_zero (type);
+  return range_op_handler (MINUS_EXPR).fold_range (r, type, zero, lh);
 }
 
 bool
@@ -4391,7 +4393,7 @@ operator_addr_expr::fold_range (irange , tree type,
 
   // Return a non-null pointer of the LHS type (passed in op2).
   if (lh.zero_p ())
-r = range_zero (type);
+r.set_zero (type);
   else if (lh.undefined_p () || contains_zero_p (lh))
 r.set_varying (type);
   else
@@ -4675,7 +4677,7 @@ range_op_cast_tests ()
   if (TYPE_PRECISION (integer_type_node)
   > TYPE_PRECISION (short_integer_type_node))
 {
-  r0 = range_nonzero (integer_type_node);
+  r0.set_nonzero (integer_type_node);
   range_cast (r0, short_integer_type_node);
   r1 = int_range<1> (short_integer_type_node,
 min_limit (short_integer_type_node),
@@ -4687,7 +4689,7 @@ range_op_cast_tests ()
   //
   // NONZERO signed 16-bits is [-MIN_16,-1][1, +MAX_16].
   // Converting this to 32-bits signed is [-MIN_16,-1][1, +MAX_16].
-  r0 = range_nonzero (short_integer_type_node);
+  r0.set_nonzero (short_integer_type_node);
   range_cast (r0, integer_type_node);
   r1 = int_range<1> (integer_type_node, INT (-32768), INT (-1));
   r2 = int_range<1> (integer_type_node, INT (1), INT (32767));
diff --git a/gcc/range.cc b/gcc/range.cc

[gcc r15-39] Move print_irange_* out of vrange_printer class.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:df6a1bc59a355c9fee10d29f54c9dca81612afb6

commit r15-39-gdf6a1bc59a355c9fee10d29f54c9dca81612afb6
Author: Aldy Hernandez 
Date:   Tue Mar 19 20:26:27 2024 +0100

Move print_irange_* out of vrange_printer class.

Move some code out of the irange pretty printers so it can be shared
with pointers.

gcc/ChangeLog:

* value-range-pretty-print.cc (print_int_bound): New.
(print_irange_bitmasks): New.
(vrange_printer::print_irange_bound): Remove.
(vrange_printer::print_irange_bitmasks): Remove.
* value-range-pretty-print.h: Remove print_irange_bitmasks and
print_irange_bound

Diff:
---
 gcc/value-range-pretty-print.cc | 83 -
 gcc/value-range-pretty-print.h  |  2 -
 2 files changed, 41 insertions(+), 44 deletions(-)

diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc
index c75cbea3955..b6d23dce6d2 100644
--- a/gcc/value-range-pretty-print.cc
+++ b/gcc/value-range-pretty-print.cc
@@ -30,6 +30,44 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-range.h"
 #include "value-range-pretty-print.h"
 
+static void
+print_int_bound (pretty_printer *pp, const wide_int , tree type)
+{
+  wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+  wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+
+  if (INTEGRAL_TYPE_P (type)
+  && !TYPE_UNSIGNED (type)
+  && bound == type_min
+  && TYPE_PRECISION (type) != 1)
+pp_string (pp, "-INF");
+  else if (bound == type_max && TYPE_PRECISION (type) != 1)
+pp_string (pp, "+INF");
+  else
+pp_wide_int (pp, bound, TYPE_SIGN (type));
+}
+
+static void
+print_irange_bitmasks (pretty_printer *pp, const irange_bitmask )
+{
+  if (bm.unknown_p ())
+return;
+
+  pp_string (pp, " MASK ");
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
+  unsigned len_mask, len_val;
+  if (print_hex_buf_size (bm.mask (), _mask)
+  | print_hex_buf_size (bm.value (), _val))
+p = XALLOCAVEC (char, MAX (len_mask, len_val));
+  else
+p = buf;
+  print_hex (bm.mask (), p);
+  pp_string (pp, p);
+  pp_string (pp, " VALUE ");
+  print_hex (bm.value (), p);
+  pp_string (pp, p);
+}
+
 void
 vrange_printer::visit (const unsupported_range ) const
 {
@@ -66,51 +104,12 @@ vrange_printer::visit (const irange ) const
   for (unsigned i = 0; i < r.num_pairs (); ++i)
 {
   pp_character (pp, '[');
-  print_irange_bound (r.lower_bound (i), r.type ());
+  print_int_bound (pp, r.lower_bound (i), r.type ());
   pp_string (pp, ", ");
-  print_irange_bound (r.upper_bound (i), r.type ());
+  print_int_bound (pp, r.upper_bound (i), r.type ());
   pp_character (pp, ']');
 }
- print_irange_bitmasks (r);
-}
-
-void
-vrange_printer::print_irange_bound (const wide_int , tree type) const
-{
-  wide_int type_min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
-  wide_int type_max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
-
-  if (INTEGRAL_TYPE_P (type)
-  && !TYPE_UNSIGNED (type)
-  && bound == type_min
-  && TYPE_PRECISION (type) != 1)
-pp_string (pp, "-INF");
-  else if (bound == type_max && TYPE_PRECISION (type) != 1)
-pp_string (pp, "+INF");
-  else
-pp_wide_int (pp, bound, TYPE_SIGN (type));
-}
-
-void
-vrange_printer::print_irange_bitmasks (const irange ) const
-{
-  irange_bitmask bm = r.m_bitmask;
-  if (bm.unknown_p ())
-return;
-
-  pp_string (pp, " MASK ");
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
-  unsigned len_mask, len_val;
-  if (print_hex_buf_size (bm.mask (), _mask)
-  | print_hex_buf_size (bm.value (), _val))
-p = XALLOCAVEC (char, MAX (len_mask, len_val));
-  else
-p = buf;
-  print_hex (bm.mask (), p);
-  pp_string (pp, p);
-  pp_string (pp, " VALUE ");
-  print_hex (bm.value (), p);
-  pp_string (pp, p);
+  print_irange_bitmasks (pp, r.m_bitmask);
 }
 
 void
diff --git a/gcc/value-range-pretty-print.h b/gcc/value-range-pretty-print.h
index ca85fd6157c..44cd6e81298 100644
--- a/gcc/value-range-pretty-print.h
+++ b/gcc/value-range-pretty-print.h
@@ -29,8 +29,6 @@ public:
   void visit (const irange &) const override;
   void visit (const frange &) const override;
 private:
-  void print_irange_bound (const wide_int , tree type) const;
-  void print_irange_bitmasks (const irange &) const;
   void print_frange_nan (const frange &) const;
   void print_real_value (tree type, const REAL_VALUE_TYPE ) const;


[gcc r15-37] Make some integer specific ranges generic Value_Range's.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:c284f8d2d16ce9c29defce3329419ccc54605ad4

commit r15-37-gc284f8d2d16ce9c29defce3329419ccc54605ad4
Author: Aldy Hernandez 
Date:   Tue Mar 19 18:22:08 2024 +0100

Make some integer specific ranges generic Value_Range's.

There are some irange uses that should be Value_Range, because they
can be either integers or pointers.  This will become a problem when
prange comes live.

gcc/ChangeLog:

* tree-ssa-loop-split.cc (split_at_bb_p): Make int_range a 
Value_Range.
* tree-ssa-strlen.cc (get_range): Same.
* value-query.cc (range_query::get_tree_range):  Handle both
integers and pointers.
* vr-values.cc (simplify_using_ranges::fold_cond_with_ops): Make
r0 and r1 Value_Range's.

Diff:
---
 gcc/tree-ssa-loop-split.cc | 6 +++---
 gcc/tree-ssa-strlen.cc | 2 +-
 gcc/value-query.cc | 4 +---
 gcc/vr-values.cc   | 3 ++-
 4 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/gcc/tree-ssa-loop-split.cc b/gcc/tree-ssa-loop-split.cc
index a770ea371a2..a6be0cef7b0 100644
--- a/gcc/tree-ssa-loop-split.cc
+++ b/gcc/tree-ssa-loop-split.cc
@@ -144,18 +144,18 @@ split_at_bb_p (class loop *loop, basic_block bb, tree 
*border, affine_iv *iv,
   value range.  */
else
  {
-   int_range<2> r;
+   Value_Range r (TREE_TYPE (op0));
get_global_range_query ()->range_of_expr (r, op0, stmt);
if (!r.varying_p () && !r.undefined_p ()
&& TREE_CODE (op1) == INTEGER_CST)
  {
wide_int val = wi::to_wide (op1);
-   if (known_eq (val, r.lower_bound ()))
+   if (known_eq (val, wi::to_wide (r.lbound (
  {
code = (code == EQ_EXPR) ? LE_EXPR : GT_EXPR;
break;
  }
-   else if (known_eq (val, r.upper_bound ()))
+   else if (known_eq (val, wi::to_wide (r.ubound (
  {
code = (code == EQ_EXPR) ? GE_EXPR : LT_EXPR;
break;
diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index e09c9cc081f..61c3da22322 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -215,7 +215,7 @@ get_range (tree val, gimple *stmt, wide_int minmax[2],
   rvals = get_range_query (cfun);
 }
 
-  value_range vr;
+  Value_Range vr (TREE_TYPE (val));
   if (!rvals->range_of_expr (vr, val, stmt))
 return NULL_TREE;
 
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index eda71dc89d3..052b7511565 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -156,11 +156,9 @@ range_query::get_tree_range (vrange , tree expr, gimple 
*stmt)
 {
 case INTEGER_CST:
   {
-   irange  = as_a  (r);
if (TREE_OVERFLOW_P (expr))
  expr = drop_tree_overflow (expr);
-   wide_int w = wi::to_wide (expr);
-   i.set (TREE_TYPE (expr), w, w);
+   r.set (expr, expr);
return true;
   }
 
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index ff68d40c355..0572bf6c8c7 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -310,7 +310,8 @@ tree
 simplify_using_ranges::fold_cond_with_ops (enum tree_code code,
   tree op0, tree op1, gimple *s)
 {
-  int_range_max r0, r1;
+  Value_Range r0 (TREE_TYPE (op0));
+  Value_Range r1 (TREE_TYPE (op1));
   if (!query->range_of_expr (r0, op0, s)
   || !query->range_of_expr (r1, op1, s))
 return NULL_TREE;


[gcc r15-38] Accept any vrange in range_includes_zero_p.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:b102633be7d0b763d106b0a883679bb1497ca17c

commit r15-38-gb102633be7d0b763d106b0a883679bb1497ca17c
Author: Aldy Hernandez 
Date:   Tue Mar 19 18:29:21 2024 +0100

Accept any vrange in range_includes_zero_p.

Accept a vrange, as this will be used for either integers or pointers.

gcc/ChangeLog:

* value-range.h (range_includes_zero_p): Accept vrange.

Diff:
---
 gcc/value-range.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/gcc/value-range.h b/gcc/value-range.h
index ede90a496d8..0ab717697f0 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -970,7 +970,7 @@ irange::contains_p (tree cst) const
 }
 
 inline bool
-range_includes_zero_p (const irange )
+range_includes_zero_p (const vrange )
 {
   if (vr.undefined_p ())
 return false;
@@ -978,8 +978,7 @@ range_includes_zero_p (const irange )
   if (vr.varying_p ())
 return true;
 
-  wide_int zero = wi::zero (TYPE_PRECISION (vr.type ()));
-  return vr.contains_p (zero);
+  return vr.contains_p (build_zero_cst (vr.type ()));
 }
 
 // Constructors for irange


[gcc r15-36] Move get_bitmask_from_range out of irange class.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:2caf7a50a6a9de80d2767d82b8cdb69d63469aaf

commit r15-36-g2caf7a50a6a9de80d2767d82b8cdb69d63469aaf
Author: Aldy Hernandez 
Date:   Tue Mar 19 18:04:55 2024 +0100

Move get_bitmask_from_range out of irange class.

prange will also have bitmasks, so it will need to use 
get_bitmask_from_range.

gcc/ChangeLog:

* value-range.cc (get_bitmask_from_range): Move out of irange class.
(irange::get_bitmask): Call function instead of internal method.
* value-range.h (class irange): Remove get_bitmask_from_range.

Diff:
---
 gcc/value-range.cc | 52 ++--
 gcc/value-range.h  |  1 -
 2 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 44929b210aa..d9689bd469f 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -31,6 +31,30 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "gimple-range.h"
 
+// Return the bitmask inherent in a range.
+
+static irange_bitmask
+get_bitmask_from_range (tree type,
+   const wide_int , const wide_int )
+{
+  unsigned prec = TYPE_PRECISION (type);
+
+  // All the bits of a singleton are known.
+  if (min == max)
+{
+  wide_int mask = wi::zero (prec);
+  wide_int value = min;
+  return irange_bitmask (value, mask);
+}
+
+  wide_int xorv = min ^ max;
+
+  if (xorv != 0)
+xorv = wi::mask (prec - wi::clz (xorv), false, prec);
+
+  return irange_bitmask (wi::zero (prec), min | xorv);
+}
+
 void
 irange::accept (const vrange_visitor ) const
 {
@@ -1881,31 +1905,6 @@ irange::invert ()
 verify_range ();
 }
 
-// Return the bitmask inherent in the range.
-
-irange_bitmask
-irange::get_bitmask_from_range () const
-{
-  unsigned prec = TYPE_PRECISION (type ());
-  wide_int min = lower_bound ();
-  wide_int max = upper_bound ();
-
-  // All the bits of a singleton are known.
-  if (min == max)
-{
-  wide_int mask = wi::zero (prec);
-  wide_int value = lower_bound ();
-  return irange_bitmask (value, mask);
-}
-
-  wide_int xorv = min ^ max;
-
-  if (xorv != 0)
-xorv = wi::mask (prec - wi::clz (xorv), false, prec);
-
-  return irange_bitmask (wi::zero (prec), min | xorv);
-}
-
 // Remove trailing ranges that this bitmask indicates can't exist.
 
 void
@@ -2027,7 +2026,8 @@ irange::get_bitmask () const
   // in the mask.
   //
   // See also the note in irange_bitmask::intersect.
-  irange_bitmask bm = get_bitmask_from_range ();
+  irange_bitmask bm
+= get_bitmask_from_range (type (), lower_bound (), upper_bound ());
   if (!m_bitmask.unknown_p ())
 bm.intersect (m_bitmask);
   return bm;
diff --git a/gcc/value-range.h b/gcc/value-range.h
index d2e8fd5a4d9..ede90a496d8 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -352,7 +352,6 @@ private:
   bool varying_compatible_p () const;
   bool intersect_bitmask (const irange );
   bool union_bitmask (const irange );
-  irange_bitmask get_bitmask_from_range () const;
   bool set_range_from_bitmask ();
 
   bool intersect (const wide_int& lb, const wide_int& ub);


[gcc r15-34] Verify that reading back from vrange_storage doesn't drop bits.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:92f74ee21218cab08d7bb7769004a65e8a291fa3

commit r15-34-g92f74ee21218cab08d7bb7769004a65e8a291fa3
Author: Aldy Hernandez 
Date:   Tue Mar 19 16:35:41 2024 +0100

Verify that reading back from vrange_storage doesn't drop bits.

We have a sanity check in the irange storage code to make sure that
reading back a cache entry we have just written to yields exactly the
same range.  There's no need to do this only for integers.  This patch
moves the code to a more generic place.

However, doing so tickles a latent bug in the frange code where a
range is being pessimized from [0.0, 1.0] to [-0.0, 1.0].  Exclude
checking frange's until this bug is fixed.

gcc/ChangeLog:

* value-range-storage.cc (irange_storage::set_irange): Move
verification code from here...
(vrange_storage::set_vrange): ...to here.

Diff:
---
 gcc/value-range-storage.cc | 20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index f00474ad0e6..09a29776a0e 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -165,6 +165,19 @@ vrange_storage::set_vrange (const vrange )
 }
   else
 gcc_unreachable ();
+
+  // Verify that reading back from the cache didn't drop bits.
+  if (flag_checking
+  // FIXME: Avoid checking frange, as it currently pessimizes some ranges:
+  //
+  // gfortran.dg/pr49472.f90 pessimizes [0.0, 1.0] into [-0.0, 1.0].
+  && !is_a  (r)
+  && !r.undefined_p ())
+{
+  Value_Range tmp (r);
+  get_vrange (tmp, r.type ());
+  gcc_checking_assert (tmp == r);
+}
 }
 
 // Restore R from storage.
@@ -306,13 +319,6 @@ irange_storage::set_irange (const irange )
   irange_bitmask bm = r.m_bitmask;
   write_wide_int (val, len, bm.value ());
   write_wide_int (val, len, bm.mask ());
-
-  if (flag_checking)
-{
-  int_range_max tmp;
-  get_irange (tmp, r.type ());
-  gcc_checking_assert (tmp == r);
-}
 }
 
 static inline void


[gcc r15-35] Accept a vrange in get_legacy_range.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:9a2f0d152d98dd55efc9accd07ea507b929c3516

commit r15-35-g9a2f0d152d98dd55efc9accd07ea507b929c3516
Author: Aldy Hernandez 
Date:   Tue Mar 19 17:17:53 2024 +0100

Accept a vrange in get_legacy_range.

In preparation for prange, make get_legacy_range take a generic
vrange, not just an irange.

gcc/ChangeLog:

* value-range.cc (get_legacy_range): Make static and add another
version of get_legacy_range that takes a vrange.
* value-range.h (class irange): Remove unnecessary friendship with
get_legacy_range.
(get_legacy_range): Accept a vrange.

Diff:
---
 gcc/value-range.cc | 17 -
 gcc/value-range.h  |  3 +--
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index b901c864a7b..44929b210aa 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -1004,7 +1004,7 @@ irange::operator= (const irange )
   return *this;
 }
 
-value_range_kind
+static value_range_kind
 get_legacy_range (const irange , tree , tree )
 {
   if (r.undefined_p ())
@@ -1041,6 +1041,21 @@ get_legacy_range (const irange , tree , tree )
   return VR_RANGE;
 }
 
+// Given a range in V, return an old-style legacy range consisting of
+// a value_range_kind with a MIN/MAX.  This is to maintain
+// compatibility with passes that still depend on VR_ANTI_RANGE, and
+// only works for integers and pointers.
+
+value_range_kind
+get_legacy_range (const vrange , tree , tree )
+{
+  if (is_a  (v))
+return get_legacy_range (as_a  (v), min, max);
+
+  gcc_unreachable ();
+  return VR_UNDEFINED;
+}
+
 /* Set value range to the canonical form of {VRTYPE, MIN, MAX, EQUIV}.
This means adjusting VRTYPE, MIN and MAX representing the case of a
wrapping range with MAX < MIN covering [MIN, type_max] U [type_min, MAX]
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 62f123e2a4b..d2e8fd5a4d9 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -281,7 +281,6 @@ irange_bitmask::intersect (const irange_bitmask _src)
 
 class irange : public vrange
 {
-  friend value_range_kind get_legacy_range (const irange &, tree &, tree &);
   friend class irange_storage;
   friend class vrange_printer;
 public:
@@ -886,7 +885,7 @@ Value_Range::supports_type_p (const_tree type)
   return irange::supports_p (type) || frange::supports_p (type);
 }
 
-extern value_range_kind get_legacy_range (const irange &, tree , tree 
);
+extern value_range_kind get_legacy_range (const vrange &, tree , tree 
);
 extern void dump_value_range (FILE *, const vrange *);
 extern bool vrp_operand_equal_p (const_tree, const_tree);
 inline REAL_VALUE_TYPE frange_val_min (const_tree type);


[gcc r15-33] Change range_includes_zero_p argument to a reference.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:d883fc7d00ed6bf5ee151de4fd3e05431582bd5f

commit r15-33-gd883fc7d00ed6bf5ee151de4fd3e05431582bd5f
Author: Aldy Hernandez 
Date:   Tue Mar 19 16:33:47 2024 +0100

Change range_includes_zero_p argument to a reference.

Make range_includes_zero_p take an argument instead of a pointer for
consistency in the range-op code.

gcc/ChangeLog:

* gimple-range-op.cc (cfn_clz::fold_range): Change
range_includes_zero_p argument to a reference.
(cfn_ctz::fold_range): Same.
* range-op.cc (operator_plus::lhs_op1_relation): Same.
* value-range.h (range_includes_zero_p): Same.

Diff:
---
 gcc/gimple-range-op.cc |  6 +++---
 gcc/range-op.cc|  2 +-
 gcc/value-range.h  | 10 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index a98f7db62a7..9c50c00549e 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -853,7 +853,7 @@ public:
 // __builtin_ffs* and __builtin_popcount* return [0, prec].
 int prec = TYPE_PRECISION (lh.type ());
 // If arg is non-zero, then ffs or popcount are non-zero.
-int mini = range_includes_zero_p () ? 0 : 1;
+int mini = range_includes_zero_p (lh) ? 0 : 1;
 int maxi = prec;
 
 // If some high bits are known to be zero, decrease the maximum.
@@ -945,7 +945,7 @@ cfn_clz::fold_range (irange , tree type, const irange ,
   if (mini == -2)
mini = 0;
 }
-  else if (!range_includes_zero_p ())
+  else if (!range_includes_zero_p (lh))
 {
   mini = 0;
   maxi = prec - 1;
@@ -1007,7 +1007,7 @@ cfn_ctz::fold_range (irange , tree type, const irange 
,
mini = -2;
 }
   // If arg is non-zero, then use [0, prec - 1].
-  if (!range_includes_zero_p ())
+  if (!range_includes_zero_p (lh))
 {
   mini = 0;
   maxi = prec - 1;
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index aeff55cfd78..6ea7d624a9b 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -1657,7 +1657,7 @@ operator_plus::lhs_op1_relation (const irange ,
 }
 
   // If op2 does not contain 0, then LHS and OP1 can never be equal.
-  if (!range_includes_zero_p ())
+  if (!range_includes_zero_p (op2))
 return VREL_NE;
 
   return VREL_VARYING;
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 2650ded6d10..62f123e2a4b 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -972,16 +972,16 @@ irange::contains_p (tree cst) const
 }
 
 inline bool
-range_includes_zero_p (const irange *vr)
+range_includes_zero_p (const irange )
 {
-  if (vr->undefined_p ())
+  if (vr.undefined_p ())
 return false;
 
-  if (vr->varying_p ())
+  if (vr.varying_p ())
 return true;
 
-  wide_int zero = wi::zero (TYPE_PRECISION (vr->type ()));
-  return vr->contains_p (zero);
+  wide_int zero = wi::zero (TYPE_PRECISION (vr.type ()));
+  return vr.contains_p (zero);
 }
 
 // Constructors for irange


[gcc r15-32] Make fold_cond_with_ops use a boolean type for range_true/range_false.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:039e88b1aea5723221e8b0b926c35afb2f96a8a9

commit r15-32-g039e88b1aea5723221e8b0b926c35afb2f96a8a9
Author: Aldy Hernandez 
Date:   Wed Feb 7 11:27:29 2024 +0100

Make fold_cond_with_ops use a boolean type for range_true/range_false.

Conditional operators are always boolean, regardless of their
operands.  Getting the type wrong is not currently a problem, but will
be when prange's can no longer store an integer.

gcc/ChangeLog:

* vr-values.cc (simplify_using_ranges::fold_cond_with_ops): Remove
type from range_true and range_false.

Diff:
---
 gcc/vr-values.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index a7e291a16e5..ff68d40c355 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -320,9 +320,9 @@ simplify_using_ranges::fold_cond_with_ops (enum tree_code 
code,
   range_op_handler handler (code);
   if (handler && handler.fold_range (res, type, r0, r1))
 {
-  if (res == range_true (type))
+  if (res == range_true ())
return boolean_true_node;
-  if (res == range_false (type))
+  if (res == range_false ())
return boolean_false_node;
 }
   return NULL;


[gcc r15-31] Remove GTY support for vrange and derived classes.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:eeef1f69c5e77ecf13fdcf44df5bcf592a9993e6

commit r15-31-geeef1f69c5e77ecf13fdcf44df5bcf592a9993e6
Author: Aldy Hernandez 
Date:   Wed Feb 21 09:34:29 2024 +0100

Remove GTY support for vrange and derived classes.

Now that we have a vrange storage class to save ranges in long-term
memory, there is no need for GTY markers for any of the vrange
classes, since they should never live in GC.

gcc/ChangeLog:

* value-range-storage.h: Remove friends.
* value-range.cc (gt_ggc_mx): Remove.
(gt_pch_nx): Remove.
* value-range.h (class vrange): Remove GTY markers.
(class irange): Same.
(class int_range): Same.
(class frange): Same.
(gt_ggc_mx): Remove.
(gt_pch_nx): Remove.

Diff:
---
 gcc/value-range-storage.h |  4 ---
 gcc/value-range.cc| 73 ---
 gcc/value-range.h | 46 +++--
 3 files changed, 4 insertions(+), 119 deletions(-)

diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h
index d94c520aa73..5756de7e32d 100644
--- a/gcc/value-range-storage.h
+++ b/gcc/value-range-storage.h
@@ -75,10 +75,6 @@ private:
   static size_t size (const irange );
   const unsigned short *lengths_address () const;
   unsigned short *write_lengths_address ();
-  friend void gt_ggc_mx_irange_storage (void *);
-  friend void gt_pch_p_14irange_storage (void *, void *,
- gt_pointer_operator, void *);
-  friend void gt_pch_nx_irange_storage (void *);
 
   // The shared precision of each number.
   unsigned short m_precision;
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 926f7b707ea..b901c864a7b 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2165,79 +2165,6 @@ vrp_operand_equal_p (const_tree val1, const_tree val2)
   return true;
 }
 
-void
-gt_ggc_mx (irange *x)
-{
-  if (!x->undefined_p ())
-gt_ggc_mx (x->m_type);
-}
-
-void
-gt_pch_nx (irange *x)
-{
-  if (!x->undefined_p ())
-gt_pch_nx (x->m_type);
-}
-
-void
-gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie)
-{
-  for (unsigned i = 0; i < x->m_num_ranges; ++i)
-{
-  op (>m_base[i * 2], NULL, cookie);
-  op (>m_base[i * 2 + 1], NULL, cookie);
-}
-}
-
-void
-gt_ggc_mx (frange *x)
-{
-  gt_ggc_mx (x->m_type);
-}
-
-void
-gt_pch_nx (frange *x)
-{
-  gt_pch_nx (x->m_type);
-}
-
-void
-gt_pch_nx (frange *x, gt_pointer_operator op, void *cookie)
-{
-  op (>m_type, NULL, cookie);
-}
-
-void
-gt_ggc_mx (vrange *x)
-{
-  if (is_a  (*x))
-return gt_ggc_mx ((irange *) x);
-  if (is_a  (*x))
-return gt_ggc_mx ((frange *) x);
-  gcc_unreachable ();
-}
-
-void
-gt_pch_nx (vrange *x)
-{
-  if (is_a  (*x))
-return gt_pch_nx ((irange *) x);
-  if (is_a  (*x))
-return gt_pch_nx ((frange *) x);
-  gcc_unreachable ();
-}
-
-void
-gt_pch_nx (vrange *x, gt_pointer_operator op, void *cookie)
-{
-  if (is_a  (*x))
-gt_pch_nx ((irange *) x, op, cookie);
-  else if (is_a  (*x))
-gt_pch_nx ((frange *) x, op, cookie);
-  else
-gcc_unreachable ();
-}
-
 #define DEFINE_INT_RANGE_INSTANCE(N)   \
   template int_range::int_range(tree_node *,
\
   const wide_int &,\
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 991ffeafcb8..2650ded6d10 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -72,7 +72,7 @@ enum value_range_discriminator
 // if (f.supports_type_p (type)) ...
 //}
 
-class GTY((user)) vrange
+class vrange
 {
   template  friend bool is_a (vrange &);
   friend class Value_Range;
@@ -279,7 +279,7 @@ irange_bitmask::intersect (const irange_bitmask _src)
 
 // An integer range without any storage.
 
-class GTY((user)) irange : public vrange
+class irange : public vrange
 {
   friend value_range_kind get_legacy_range (const irange &, tree &, tree &);
   friend class irange_storage;
@@ -350,10 +350,6 @@ protected:
   // Hard limit on max ranges allowed.
   static const int HARD_MAX_RANGES = 255;
 private:
-  friend void gt_ggc_mx (irange *);
-  friend void gt_pch_nx (irange *);
-  friend void gt_pch_nx (irange *, gt_pointer_operator, void *);
-
   bool varying_compatible_p () const;
   bool intersect_bitmask (const irange );
   bool union_bitmask (const irange );
@@ -379,7 +375,7 @@ protected:
 // HARD_MAX_RANGES.  This new storage is freed upon destruction.
 
 template
-class GTY((user)) int_range : public irange
+class int_range : public irange
 {
 public:
   int_range ();
@@ -484,13 +480,10 @@ nan_state::neg_p () const
 // The representation is a type with a couple of endpoints, unioned
 // with the set of { -NAN, +Nan }.
 
-class GTY((user)) frange : public vrange
+class frange : public vrange
 {
   friend class frange_storage;
   friend class vrange_printer;
-  friend void gt_ggc_mx 

[gcc r15-29] Add tree versions of lower and upper bounds to vrange.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:ba1a8e8eed963c0253c6e5550c8bccc264c5d469

commit r15-29-gba1a8e8eed963c0253c6e5550c8bccc264c5d469
Author: Aldy Hernandez 
Date:   Mon Apr 22 13:34:48 2024 +0200

Add tree versions of lower and upper bounds to vrange.

This patch adds vrange::lbound() and vrange::ubound() that return
trees.  These can be used in generic code that is type agnostic, and
avoids special casing for pointers and integers in places where we
handle both.  It also cleans up a wart in the Value_Range class.

gcc/ChangeLog:

* tree-ssa-loop-niter.cc (refine_value_range_using_guard): Convert
bound to wide_int.
* value-range.cc (Value_Range::lower_bound): Remove.
(Value_Range::upper_bound): Remove.
(unsupported_range::lbound): New.
(unsupported_range::ubound): New.
(frange::lbound): New.
(frange::ubound): New.
(irange::lbound): New.
(irange::ubound): New.
* value-range.h (class vrange): Add lbound() and ubound().
(class irange): Same.
(class frange): Same.
(class unsupported_range): Same.
(class Value_Range): Rename lower_bound and upper_bound to lbound
and ubound respectively.

Diff:
---
 gcc/tree-ssa-loop-niter.cc |  4 ++--
 gcc/value-range.cc | 56 +-
 gcc/value-range.h  | 13 ---
 3 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index cbc9dbc5a1f..adbc1936982 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -4067,7 +4067,7 @@ record_nonwrapping_iv (class loop *loop, tree base, tree 
step, gimple *stmt,
   Value_Range base_range (TREE_TYPE (orig_base));
   if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
  && !base_range.undefined_p ())
-   max = base_range.upper_bound ();
+   max = wi::to_wide (base_range.ubound ());
   extreme = fold_convert (unsigned_type, low);
   if (TREE_CODE (orig_base) == SSA_NAME
  && TREE_CODE (high) == INTEGER_CST
@@ -4090,7 +4090,7 @@ record_nonwrapping_iv (class loop *loop, tree base, tree 
step, gimple *stmt,
   Value_Range base_range (TREE_TYPE (orig_base));
   if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
  && !base_range.undefined_p ())
-   min = base_range.lower_bound ();
+   min = wi::to_wide (base_range.lbound ());
   extreme = fold_convert (unsigned_type, high);
   if (TREE_CODE (orig_base) == SSA_NAME
  && TREE_CODE (low) == INTEGER_CST
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 632d77305cc..ccac517d4c4 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -37,26 +37,6 @@ irange::accept (const vrange_visitor ) const
   v.visit (*this);
 }
 
-// Convenience function only available for integers and pointers.
-
-wide_int
-Value_Range::lower_bound () const
-{
-  if (is_a  (*m_vrange))
-return as_a  (*m_vrange).lower_bound ();
-  gcc_unreachable ();
-}
-
-// Convenience function only available for integers and pointers.
-
-wide_int
-Value_Range::upper_bound () const
-{
-  if (is_a  (*m_vrange))
-return as_a  (*m_vrange).upper_bound ();
-  gcc_unreachable ();
-}
-
 void
 Value_Range::dump (FILE *out) const
 {
@@ -211,6 +191,18 @@ unsupported_range::operator= (const vrange )
   return *this;
 }
 
+tree
+unsupported_range::lbound () const
+{
+  return NULL;
+}
+
+tree
+unsupported_range::ubound () const
+{
+  return NULL;
+}
+
 // Assignment operator for generic ranges.  Copying incompatible types
 // is not allowed.
 
@@ -957,6 +949,18 @@ frange::set_nonnegative (tree type)
   set (type, dconst0, frange_val_max (type));
 }
 
+tree
+frange::lbound () const
+{
+  return build_real (type (), lower_bound ());
+}
+
+tree
+frange::ubound () const
+{
+  return build_real (type (), upper_bound ());
+}
+
 // Here we copy between any two irange's.
 
 irange &
@@ -2086,6 +2090,18 @@ irange::union_bitmask (const irange )
   return true;
 }
 
+tree
+irange::lbound () const
+{
+  return wide_int_to_tree (type (), lower_bound ());
+}
+
+tree
+irange::ubound () const
+{
+  return wide_int_to_tree (type (), upper_bound ());
+}
+
 void
 irange_bitmask::verify_mask () const
 {
diff --git a/gcc/value-range.h b/gcc/value-range.h
index b7c83982385..f216f1b82c1 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -96,6 +96,8 @@ public:
   virtual void set_nonnegative (tree type) = 0;
   virtual bool fits_p (const vrange ) const = 0;
   virtual ~vrange () { }
+  virtual tree lbound () const = 0;
+  virtual tree ubound () const = 0;
 
   bool varying_p () const;
   bool undefined_p () const;
@@ -298,6 +300,8 @@ public:
   wide_int lower_bound (unsigned = 0) const;
   wide_int upper_bound (unsigned) const;
   wide_int upper_bound () const;
+  virtual tree lbound () const 

[gcc r15-30] Move bitmask routines to vrange base class.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:fd4cf7a092bb2ce21c0d8246c17c0b7f82de440c

commit r15-30-gfd4cf7a092bb2ce21c0d8246c17c0b7f82de440c
Author: Aldy Hernandez 
Date:   Thu Feb 22 09:18:46 2024 +0100

Move bitmask routines to vrange base class.

Any range can theoretically have a bitmask of set bits.  This patch
moves the bitmask accessors to the base class.  This cleans up some
users in IPA*, and will provide a cleaner interface when prange is in
place.

gcc/ChangeLog:

* ipa-cp.cc (propagate_bits_across_jump_function): Access bitmask
through base class.
(ipcp_store_vr_results): Same.
* ipa-prop.cc (ipa_compute_jump_functions_for_edge): Same.
(ipcp_get_parm_bits): Same.
(ipcp_update_vr): Same.
* range-op-mixed.h (update_known_bitmask): Change argument to 
vrange.
* range-op.cc (update_known_bitmask): Same.
* value-range.cc (vrange::update_bitmask):  New.
(irange::set_nonzero_bits): Move to vrange class.
(irange::get_nonzero_bits): Same.
* value-range.h (class vrange): Add update_bitmask, get_bitmask,
get_nonzero_bits, and set_nonzero_bits.
(class irange): Make bitmask methods virtual overrides.
(class Value_Range): Add get_bitmask and update_bitmask.

Diff:
---
 gcc/ipa-cp.cc|  9 +++--
 gcc/ipa-prop.cc  | 10 --
 gcc/range-op-mixed.h |  2 +-
 gcc/range-op.cc  |  4 ++--
 gcc/value-range.cc   | 16 ++--
 gcc/value-range.h| 14 +-
 6 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index b7add455bd5..a688dced5c9 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -2485,8 +2485,7 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int 
idx,
   jfunc->m_vr->get_vrange (vr);
   if (!vr.undefined_p () && !vr.varying_p ())
{
- irange  = as_a  (vr);
- irange_bitmask bm = r.get_bitmask ();
+ irange_bitmask bm = vr.get_bitmask ();
  widest_int mask
= widest_int::from (bm.mask (), TYPE_SIGN (parm_type));
  widest_int value
@@ -6346,14 +6345,13 @@ ipcp_store_vr_results (void)
{
  Value_Range tmp = plats->m_value_range.m_vr;
  tree type = ipa_get_type (info, i);
- irange  = as_a (tmp);
  irange_bitmask bm (wide_int::from (bits->get_value (),
 TYPE_PRECISION (type),
 TYPE_SIGN (type)),
 wide_int::from (bits->get_mask (),
 TYPE_PRECISION (type),
 TYPE_SIGN (type)));
- r.update_bitmask (bm);
+ tmp.update_bitmask (bm);
  ipa_vr vr (tmp);
  ts->m_vr->quick_push (vr);
}
@@ -6368,14 +6366,13 @@ ipcp_store_vr_results (void)
  tree type = ipa_get_type (info, i);
  Value_Range tmp;
  tmp.set_varying (type);
- irange  = as_a (tmp);
  irange_bitmask bm (wide_int::from (bits->get_value (),
 TYPE_PRECISION (type),
 TYPE_SIGN (type)),
 wide_int::from (bits->get_mask (),
 TYPE_PRECISION (type),
 TYPE_SIGN (type)));
- r.update_bitmask (bm);
+ tmp.update_bitmask (bm);
  ipa_vr vr (tmp);
  ts->m_vr->quick_push (vr);
}
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index 374e998aa64..b57f9750431 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -2381,8 +2381,7 @@ ipa_compute_jump_functions_for_edge (struct 
ipa_func_body_info *fbi,
  irange_bitmask bm (value, mask);
  if (!addr_nonzero)
vr.set_varying (TREE_TYPE (arg));
- irange  = as_a  (vr);
- r.update_bitmask (bm);
+ vr.update_bitmask (bm);
  ipa_set_jfunc_vr (jfunc, vr);
}
  else if (addr_nonzero)
@@ -5785,8 +5784,8 @@ ipcp_get_parm_bits (tree parm, tree *value, widest_int 
*mask)
   vr[i].get_vrange (tmp);
   if (tmp.undefined_p () || tmp.varying_p ())
 return false;
-  irange  = as_a  (tmp);
-  irange_bitmask bm = r.get_bitmask ();
+  irange_bitmask bm;
+  bm = tmp.get_bitmask ();
   *mask = widest_int::from (bm.mask (), TYPE_SIGN (TREE_TYPE (parm)));
   *value = wide_int_to_tree (TREE_TYPE (parm), bm.value ());
   return true;
@@ -5857,8 +5856,7 @@ ipcp_update_vr (struct cgraph_node *node, 
ipcp_transformation *ts)
  if (POINTER_TYPE_P (TREE_TYPE (parm))

[gcc r15-28] Make some Value_Range's explicitly integer.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:a46564e4876c9a863d9897d72963cc4f03689adc

commit r15-28-ga46564e4876c9a863d9897d72963cc4f03689adc
Author: Aldy Hernandez 
Date:   Mon Apr 22 13:29:39 2024 +0200

Make some Value_Range's explicitly integer.

Fix some Value_Range's that we know ahead of time will be only
integers.  This avoids using the polymorphic Value_Range unnecessarily

gcc/ChangeLog:

* gimple-ssa-warn-access.cc (check_nul_terminated_array): Make 
Value_Range an int_range.
(memmodel_to_uhwi): Same
* tree-ssa-loop-niter.cc (refine_value_range_using_guard): Same.
(determine_value_range): Same.
(infer_loop_bounds_from_signedness): Same.
(scev_var_range_cant_overflow): Same.

Diff:
---
 gcc/gimple-ssa-warn-access.cc |  4 ++--
 gcc/tree-ssa-loop-niter.cc| 12 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index dedaae27b31..450c1caa765 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -330,7 +330,7 @@ check_nul_terminated_array (GimpleOrTree expr, tree src, 
tree bound)
   wide_int bndrng[2];
   if (bound)
 {
-  Value_Range r (TREE_TYPE (bound));
+  int_range<2> r (TREE_TYPE (bound));
 
   get_range_query (cfun)->range_of_expr (r, bound);
 
@@ -2816,7 +2816,7 @@ memmodel_to_uhwi (tree ord, gimple *stmt, unsigned 
HOST_WIDE_INT *cstval)
 {
   /* Use the range query to determine constant values in the absence
 of constant propagation (such as at -O0).  */
-  Value_Range rng (TREE_TYPE (ord));
+  int_range<2> rng (TREE_TYPE (ord));
   if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
  || !rng.singleton_p ())
return false;
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index c6d010f6d89..cbc9dbc5a1f 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -214,7 +214,7 @@ refine_value_range_using_guard (tree type, tree var,
   get_type_static_bounds (type, mint, maxt);
   mpz_init (minc1);
   mpz_init (maxc1);
-  Value_Range r (TREE_TYPE (varc1));
+  int_range<2> r (TREE_TYPE (varc1));
   /* Setup range information for varc1.  */
   if (integer_zerop (varc1))
 {
@@ -368,7 +368,7 @@ determine_value_range (class loop *loop, tree type, tree 
var, mpz_t off,
   gphi_iterator gsi;
 
   /* Either for VAR itself...  */
-  Value_Range var_range (TREE_TYPE (var));
+  int_range<2> var_range (TREE_TYPE (var));
   get_range_query (cfun)->range_of_expr (var_range, var);
   if (var_range.varying_p () || var_range.undefined_p ())
rtype = VR_VARYING;
@@ -382,7 +382,7 @@ determine_value_range (class loop *loop, tree type, tree 
var, mpz_t off,
 
   /* Or for PHI results in loop->header where VAR is used as
 PHI argument from the loop preheader edge.  */
-  Value_Range phi_range (TREE_TYPE (var));
+  int_range<2> phi_range (TREE_TYPE (var));
   for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next 
())
{
  gphi *phi = gsi.phi ();
@@ -408,7 +408,7 @@ determine_value_range (class loop *loop, tree type, tree 
var, mpz_t off,
 involved.  */
  if (wi::gt_p (minv, maxv, sgn))
{
- Value_Range vr (TREE_TYPE (var));
+ int_range<2> vr (TREE_TYPE (var));
  get_range_query (cfun)->range_of_expr (vr, var);
  if (vr.varying_p () || vr.undefined_p ())
rtype = VR_VARYING;
@@ -4367,7 +4367,7 @@ infer_loop_bounds_from_signedness (class loop *loop, 
gimple *stmt)
 
   low = lower_bound_in_type (type, type);
   high = upper_bound_in_type (type, type);
-  Value_Range r (TREE_TYPE (def));
+  int_range<2> r (TREE_TYPE (def));
   get_range_query (cfun)->range_of_expr (r, def);
   if (!r.varying_p () && !r.undefined_p ())
 {
@@ -5426,7 +5426,7 @@ scev_var_range_cant_overflow (tree var, tree step, class 
loop *loop)
   if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb))
 return false;
 
-  Value_Range r (TREE_TYPE (var));
+  int_range<2> r (TREE_TYPE (var));
   get_range_query (cfun)->range_of_expr (r, var);
   if (r.varying_p () || r.undefined_p ())
 return false;


[gcc r15-27] Add a virtual vrange destructor.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:a78dfb0fc83606e9b83b76575deb7e43300254fa

commit r15-27-ga78dfb0fc83606e9b83b76575deb7e43300254fa
Author: Aldy Hernandez 
Date:   Wed Feb 21 09:33:19 2024 +0100

Add a virtual vrange destructor.

Richi mentioned in PR113476 that it would be cleaner to move the
destructor from int_range to the base class.  Although this isn't
strictly necessary, as there are no users, it is good to future proof
things, and the overall impact is miniscule.

gcc/ChangeLog:

* value-range.h (vrange::~vrange): New.
(int_range::~int_range): Make final override.

Diff:
---
 gcc/value-range.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/value-range.h b/gcc/value-range.h
index e7f61950a24..b7c83982385 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -95,6 +95,7 @@ public:
   virtual void set_zero (tree type) = 0;
   virtual void set_nonnegative (tree type) = 0;
   virtual bool fits_p (const vrange ) const = 0;
+  virtual ~vrange () { }
 
   bool varying_p () const;
   bool undefined_p () const;
@@ -382,7 +383,7 @@ public:
   int_range (tree type);
   int_range (const int_range &);
   int_range (const irange &);
-  virtual ~int_range ();
+  ~int_range () final override;
   int_range& operator= (const int_range &);
 protected:
   int_range (tree, tree, value_range_kind = VR_RANGE);


[gcc r15-26] Make vrange an abstract class.

2024-04-28 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:21713edf52974d14238cdda865fc662eca58302a

commit r15-26-g21713edf52974d14238cdda865fc662eca58302a
Author: Aldy Hernandez 
Date:   Wed Feb 21 20:37:14 2024 +0100

Make vrange an abstract class.

Explicitly make vrange an abstract class.  This involves fleshing out
the unsupported_range overrides which we were inheriting by default
from vrange.

gcc/ChangeLog:

* value-range.cc (unsupported_range::accept): Move down.
(vrange::contains_p):  Rename to...
(unsupported_range::contains_p): ...this.
(vrange::singleton_p): Rename to...
(unsupported_range::singleton_p): ...this.
(vrange::set): Rename to...
(unsupported_range::set): ...this.
(vrange::type): Rename to...
(unsupported_range::type): ...this.
(vrange::supports_type_p): Rename to...
(unsupported_range::supports_type_p): ...this.
(vrange::set_undefined): Rename to...
(unsupported_range::set_undefined): ...this.
(vrange::set_varying): Rename to...
(unsupported_range::set_varying): ...this.
(vrange::union_): Rename to...
(unsupported_range::union_): ...this.
(vrange::intersect): Rename to...
(unsupported_range::intersect): ...this.
(vrange::zero_p): Rename to...
(unsupported_range::zero_p): ...this.
(vrange::nonzero_p): Rename to...
(unsupported_range::nonzero_p): ...this.
(vrange::set_nonzero): Rename to...
(unsupported_range::set_nonzero): ...this.
(vrange::set_zero): Rename to...
(unsupported_range::set_zero): ...this.
(vrange::set_nonnegative): Rename to...
(unsupported_range::set_nonnegative): ...this.
(vrange::fits_p): Rename to...
(unsupported_range::fits_p): ...this.
(unsupported_range::operator=): New.
(frange::fits_p): New.
* value-range.h (class vrange): Make an abstract class.
(class unsupported_range): Declare override methods.

Diff:
---
 gcc/value-range.cc | 62 +++---
 gcc/value-range.h  | 53 --
 2 files changed, 73 insertions(+), 42 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 70375f7abf9..632d77305cc 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -37,12 +37,6 @@ irange::accept (const vrange_visitor ) const
   v.visit (*this);
 }
 
-void
-unsupported_range::accept (const vrange_visitor ) const
-{
-  v.visit (*this);
-}
-
 // Convenience function only available for integers and pointers.
 
 wide_int
@@ -86,52 +80,58 @@ debug (const irange_bitmask )
   fprintf (stderr, "\n");
 }
 
-// Default vrange definitions.
+// Definitions for unsupported_range.
+
+void
+unsupported_range::accept (const vrange_visitor ) const
+{
+  v.visit (*this);
+}
 
 bool
-vrange::contains_p (tree) const
+unsupported_range::contains_p (tree) const
 {
   return varying_p ();
 }
 
 bool
-vrange::singleton_p (tree *) const
+unsupported_range::singleton_p (tree *) const
 {
   return false;
 }
 
 void
-vrange::set (tree min, tree, value_range_kind)
+unsupported_range::set (tree min, tree, value_range_kind)
 {
   set_varying (TREE_TYPE (min));
 }
 
 tree
-vrange::type () const
+unsupported_range::type () const
 {
   return void_type_node;
 }
 
 bool
-vrange::supports_type_p (const_tree) const
+unsupported_range::supports_type_p (const_tree) const
 {
   return false;
 }
 
 void
-vrange::set_undefined ()
+unsupported_range::set_undefined ()
 {
   m_kind = VR_UNDEFINED;
 }
 
 void
-vrange::set_varying (tree)
+unsupported_range::set_varying (tree)
 {
   m_kind = VR_VARYING;
 }
 
 bool
-vrange::union_ (const vrange )
+unsupported_range::union_ (const vrange )
 {
   if (r.undefined_p () || varying_p ())
 return false;
@@ -145,7 +145,7 @@ vrange::union_ (const vrange )
 }
 
 bool
-vrange::intersect (const vrange )
+unsupported_range::intersect (const vrange )
 {
   if (undefined_p () || r.varying_p ())
 return false;
@@ -164,41 +164,53 @@ vrange::intersect (const vrange )
 }
 
 bool
-vrange::zero_p () const
+unsupported_range::zero_p () const
 {
   return false;
 }
 
 bool
-vrange::nonzero_p () const
+unsupported_range::nonzero_p () const
 {
   return false;
 }
 
 void
-vrange::set_nonzero (tree type)
+unsupported_range::set_nonzero (tree type)
 {
   set_varying (type);
 }
 
 void
-vrange::set_zero (tree type)
+unsupported_range::set_zero (tree type)
 {
   set_varying (type);
 }
 
 void
-vrange::set_nonnegative (tree type)
+unsupported_range::set_nonnegative (tree type)
 {
   set_varying (type);
 }
 
 bool
-vrange::fits_p (const vrange &) const
+unsupported_range::fits_p (const vrange &) const
 {
   return true;
 }
 
+unsupported_range &
+unsupported_range::operator= (const