ipa: Remove ipa_bits

Message ID ZR6rbAKYvtP+kIzu@tucnak
State Unresolved
Headers
Series ipa: Remove ipa_bits |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jakub Jelinek Oct. 5, 2023, 12:26 p.m. UTC
  Hi!

The following patch removes ipa_bits struct pointer/vector from ipa
jump functions and ipa cp transformations.

The reason is because the struct uses widest_int to represent
mask/value pair, which in the RFC patches to allow larger precisions
for wide_int/widest_int is GC unfriendly because those types become
non-trivially default constructible/copyable/destructible.
One option would be to use trailing_wide_int for that instead, but
as pointed out by Aldy, irange_storage which we already use under
the hood for ipa_vr when type of parameter is integral or pointer
already stores the mask/value pair because VRP now does the bit cp
as well.
So, this patch just uses m_vr to store both the value range and
the bitmask.  There is still separate propagation of the
ipcp_bits_lattice from propagation of the ipcp_vr_lattice, but
when storing we merge the two into the same container.

I've bootstrapped/regtested a slightly older version of this
patch on x86_64-linux and i686-linux and that version regressed
+FAIL: gcc.dg/ipa/propalign-3.c scan-ipa-dump-not cp "align:"
+FAIL: gcc.dg/ipa/propalign-3.c scan-tree-dump optimized "fail_the_test"
+FAIL: gcc.dg/ipa/propbits-1.c scan-ipa-dump cp "Adjusting mask for param 0 to 0x7"
+FAIL: gcc.dg/ipa/propbits-2.c scan-ipa-dump cp "Adjusting mask for param 0 to 0xf"
The last 2 were solely about the earlier patch not actually copying
the if (dump_file) dumping of message that we set some mask for some
parameter (since then added in the @@ -5985,6 +5741,77 @@ hunk).
The first testcase is a test for -fno-ipa-bit-cp disabling bit cp
for alignments.  For integral types I'm afraid it is a lost case
when -fno-ipa-bit-cp -fipa-vrp is on when value ranges track bit cp
as well, but for pointer alignments I've added
  && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp)
and
  && opt_for_fn (node->decl, flag_ipa_bit_cp)
guards such that even just -fno-ipa-bit-cp disables it (alternatively
we could just add -fno-ipa-vrp to propalign-3.c dg-options).

Ok for trunk if this passes another bootstrap/regtest?
Or defer until it is really needed (when the wide_int/widest_int
changes are about to be committed)?

2023-10-05  Jakub Jelinek  <jakub@redhat.com>

	* ipa-prop.h (ipa_bits): Remove.
	(struct ipa_jump_func): Remove bits member.
	(struct ipcp_transformation): Remove bits member, adjust
	ctor and dtor.
	(ipa_get_ipa_bits_for_value): Remove.
	* ipa-prop.cc (struct ipa_bit_ggc_hash_traits): Remove.
	(ipa_bits_hash_table): Remove.
	(ipa_print_node_jump_functions_for_edge): Don't print bits.
	(ipa_get_ipa_bits_for_value): Remove.
	(ipa_set_jfunc_bits): Remove.
	(ipa_compute_jump_functions_for_edge): For pointers query
	pointer alignment before ipa_set_jfunc_vr and update_bitmask
	in there.  For integral types, just rely on bitmask already
	being handled in value ranges.
	(ipa_check_create_edge_args): Don't create ipa_bits_hash_table.
	(ipcp_transformation_initialize): Neither here.
	(ipcp_transformation_t::duplicate): Don't copy bits vector.
	(ipa_write_jump_function): Don't stream bits here.
	(ipa_read_jump_function): Neither here.
	(useful_ipcp_transformation_info_p): Don't test bits vec.
	(write_ipcp_transformation_info): Don't stream bits here.
	(read_ipcp_transformation_info): Neither here.
	(ipcp_get_parm_bits): Get mask and value from m_vr rather
	than bits.
	(ipcp_update_bits): Remove.
	(ipcp_update_vr): For pointers, set_ptr_info_alignment from
	bitmask stored in value range.
	(ipcp_transform_function): Don't test bits vector, don't call
	ipcp_update_bits.
	* ipa-cp.cc (propagate_bits_across_jump_function): Don't use
	jfunc->bits, instead get mask and value from jfunc->m_vr.
	(ipcp_store_bits_results): Remove.
	(ipcp_store_vr_results): Incorporate parts of
	ipcp_store_bits_results here, merge the bitmasks with value
	range if both are supplied.
	(ipcp_driver): Don't call ipcp_store_bits_results.
	* ipa-sra.cc (zap_useless_ipcp_results): Remove *ts->bits
	clearing.


	Jakub
  

Comments

Aldy Hernandez Oct. 5, 2023, 2:06 p.m. UTC | #1
On Thu, Oct 5, 2023, 8:26 a.m. Jakub Jelinek <jakub@redhat.com> wrote:

> Hi!
>
> The following patch removes ipa_bits struct pointer/vector from ipa
> jump functions and ipa cp transformations.
>
> The reason is because the struct uses widest_int to represent
> mask/value pair, which in the RFC patches to allow larger precisions
> for wide_int/widest_int is GC unfriendly because those types become
> non-trivially default constructible/copyable/destructible.
> One option would be to use trailing_wide_int for that instead, but
> as pointed out by Aldy, irange_storage which we already use under
> the hood for ipa_vr when type of parameter is integral or pointer
> already stores the mask/value pair because VRP now does the bit cp
> as well.
> So, this patch just uses m_vr to store both the value range and
> the bitmask.  There is still separate propagation of the
> ipcp_bits_lattice from propagation of the ipcp_vr_lattice, but
> when storing we merge the two into the same container.
>
> I've bootstrapped/regtested a slightly older version of this
> patch on x86_64-linux and i686-linux and that version regressed
> +FAIL: gcc.dg/ipa/propalign-3.c scan-ipa-dump-not cp "align:"
> +FAIL: gcc.dg/ipa/propalign-3.c scan-tree-dump optimized "fail_the_test"
> +FAIL: gcc.dg/ipa/propbits-1.c scan-ipa-dump cp "Adjusting mask for param
> 0 to 0x7"
> +FAIL: gcc.dg/ipa/propbits-2.c scan-ipa-dump cp "Adjusting mask for param
> 0 to 0xf"
> The last 2 were solely about the earlier patch not actually copying
> the if (dump_file) dumping of message that we set some mask for some
> parameter (since then added in the @@ -5985,6 +5741,77 @@ hunk).
> The first testcase is a test for -fno-ipa-bit-cp disabling bit cp
> for alignments.  For integral types I'm afraid it is a lost case
> when -fno-ipa-bit-cp -fipa-vrp is on when value ranges track bit cp
> as well, but for pointer alignments I've added
>   && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp)
> and
>   && opt_for_fn (node->decl, flag_ipa_bit_cp)
> guards such that even just -fno-ipa-bit-cp disables it (alternatively
> we could just add -fno-ipa-vrp to propalign-3.c dg-options).
>
> Ok for trunk if this passes another bootstrap/regtest?
> Or defer until it is really needed (when the wide_int/widest_int
> changes are about to be committed)?
>

Up to the maintainers, but this looks like a nice cleanup that has merit on
its own. It's exactly what I had in mind when I worked on IPA earlier this
cycle.

Thanks.
Aldy


> 2023-10-05  Jakub Jelinek  <jakub@redhat.com>
>
>         * ipa-prop.h (ipa_bits): Remove.
>         (struct ipa_jump_func): Remove bits member.
>         (struct ipcp_transformation): Remove bits member, adjust
>         ctor and dtor.
>         (ipa_get_ipa_bits_for_value): Remove.
>         * ipa-prop.cc (struct ipa_bit_ggc_hash_traits): Remove.
>         (ipa_bits_hash_table): Remove.
>         (ipa_print_node_jump_functions_for_edge): Don't print bits.
>         (ipa_get_ipa_bits_for_value): Remove.
>         (ipa_set_jfunc_bits): Remove.
>         (ipa_compute_jump_functions_for_edge): For pointers query
>         pointer alignment before ipa_set_jfunc_vr and update_bitmask
>         in there.  For integral types, just rely on bitmask already
>         being handled in value ranges.
>         (ipa_check_create_edge_args): Don't create ipa_bits_hash_table.
>         (ipcp_transformation_initialize): Neither here.
>         (ipcp_transformation_t::duplicate): Don't copy bits vector.
>         (ipa_write_jump_function): Don't stream bits here.
>         (ipa_read_jump_function): Neither here.
>         (useful_ipcp_transformation_info_p): Don't test bits vec.
>         (write_ipcp_transformation_info): Don't stream bits here.
>         (read_ipcp_transformation_info): Neither here.
>         (ipcp_get_parm_bits): Get mask and value from m_vr rather
>         than bits.
>         (ipcp_update_bits): Remove.
>         (ipcp_update_vr): For pointers, set_ptr_info_alignment from
>         bitmask stored in value range.
>         (ipcp_transform_function): Don't test bits vector, don't call
>         ipcp_update_bits.
>         * ipa-cp.cc (propagate_bits_across_jump_function): Don't use
>         jfunc->bits, instead get mask and value from jfunc->m_vr.
>         (ipcp_store_bits_results): Remove.
>         (ipcp_store_vr_results): Incorporate parts of
>         ipcp_store_bits_results here, merge the bitmasks with value
>         range if both are supplied.
>         (ipcp_driver): Don't call ipcp_store_bits_results.
>         * ipa-sra.cc (zap_useless_ipcp_results): Remove *ts->bits
>         clearing.
>
> --- gcc/ipa-prop.h.jj   2023-10-05 11:32:40.172739988 +0200
> +++ gcc/ipa-prop.h      2023-10-05 11:36:45.405378086 +0200
> @@ -292,18 +292,6 @@ public:
>    array_slice<const ipa_argagg_value> m_elts;
>  };
>
> -/* Information about zero/non-zero bits.  */
> -class GTY(()) ipa_bits
> -{
> -public:
> -  /* The propagated value.  */
> -  widest_int value;
> -  /* Mask corresponding to the value.
> -     Similar to ccp_lattice_t, if xth bit of mask is 0,
> -     implies xth bit of value is constant.  */
> -  widest_int mask;
> -};
> -
>  /* Info about value ranges.  */
>
>  class GTY(()) ipa_vr
> @@ -342,11 +330,6 @@ struct GTY (()) ipa_jump_func
>       and its description.  */
>    struct ipa_agg_jump_function agg;
>
> -  /* Information about zero/non-zero bits.  The pointed to structure is
> shared
> -     betweed different jump functions.  Use ipa_set_jfunc_bits to set this
> -     field.  */
> -  class ipa_bits *bits;
> -
>    /* Information about value range, containing valid data only when
> vr_known is
>       true.  The pointed to structure is shared betweed different jump
>       functions.  Use ipa_set_jfunc_vr to set this field.  */
> @@ -940,15 +923,13 @@ struct GTY(()) ipcp_transformation
>  {
>    /* Default constructor.  */
>    ipcp_transformation ()
> -    : m_agg_values (nullptr), bits (nullptr), m_vr (nullptr),
> -    m_uid_to_idx (nullptr)
> +    : m_agg_values (nullptr), m_vr (nullptr), m_uid_to_idx (nullptr)
>    { }
>
>    /* Default destructor.  */
>    ~ipcp_transformation ()
>    {
>      vec_free (m_agg_values);
> -    vec_free (bits);
>      vec_free (m_vr);
>    }
>
> @@ -968,8 +949,6 @@ struct GTY(()) ipcp_transformation
>
>    /* Known aggregate values.  */
>    vec<ipa_argagg_value, va_gc>  *m_agg_values;
> -  /* Known bits information.  */
> -  vec<ipa_bits *, va_gc> *bits;
>    /* Value range information.  */
>    vec<ipa_vr, va_gc> *m_vr;
>    /* If there are many parameters, this is a vector sorted by their
> DECL_UIDs
> @@ -1172,8 +1151,6 @@ tree ipa_get_indirect_edge_target (struc
>  struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *,
> tree,
>                                                     bool speculative =
> false);
>  tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);
> -ipa_bits *ipa_get_ipa_bits_for_value (const widest_int &value,
> -                                     const widest_int &mask);
>
>
>  /* Functions related to both.  */
> --- gcc/ipa-prop.cc.jj  2023-10-05 11:32:40.154740234 +0200
> +++ gcc/ipa-prop.cc     2023-10-05 14:06:13.742885839 +0200
> @@ -66,49 +66,6 @@ function_summary <ipcp_transformation *>
>  /* Edge summary for IPA-CP edge information.  */
>  ipa_edge_args_sum_t *ipa_edge_args_sum;
>
> -/* Traits for a hash table for reusing already existing ipa_bits. */
> -
> -struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
> -{
> -  typedef ipa_bits *value_type;
> -  typedef ipa_bits *compare_type;
> -  static hashval_t
> -  hash (const ipa_bits *p)
> -  {
> -    hashval_t t = (hashval_t) p->value.to_shwi ();
> -    return iterative_hash_host_wide_int (p->mask.to_shwi (), t);
> -  }
> -  static bool
> -  equal (const ipa_bits *a, const ipa_bits *b)
> -    {
> -      return a->value == b->value && a->mask == b->mask;
> -    }
> -  static const bool empty_zero_p = true;
> -  static void
> -  mark_empty (ipa_bits *&p)
> -    {
> -      p = NULL;
> -    }
> -  static bool
> -  is_empty (const ipa_bits *p)
> -    {
> -      return p == NULL;
> -    }
> -  static bool
> -  is_deleted (const ipa_bits *p)
> -    {
> -      return p == reinterpret_cast<const ipa_bits *> (1);
> -    }
> -  static void
> -  mark_deleted (ipa_bits *&p)
> -    {
> -      p = reinterpret_cast<ipa_bits *> (1);
> -    }
> -};
> -
> -/* Hash table for avoid repeated allocations of equal ipa_bits.  */
> -static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits>
> *ipa_bits_hash_table;
> -
>  /* Traits for a hash table for reusing ranges.  */
>
>  struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <ipa_vr *>
> @@ -528,17 +485,6 @@ ipa_print_node_jump_functions_for_edge (
>           ctx->dump (dump_file);
>         }
>
> -      if (jump_func->bits)
> -       {
> -         fprintf (f, "         value: ");
> -         print_hex (jump_func->bits->value, f);
> -         fprintf (f, ", mask: ");
> -         print_hex (jump_func->bits->mask, f);
> -         fprintf (f, "\n");
> -       }
> -      else
> -       fprintf (f, "         Unknown bits\n");
> -
>        if (jump_func->m_vr)
>         {
>           jump_func->m_vr->dump (f);
> @@ -2267,39 +2213,6 @@ ipa_get_callee_param_type (struct cgraph
>    return NULL;
>  }
>
> -/* Return ipa_bits with VALUE and MASK values, which can be either a newly
> -   allocated structure or a previously existing one shared with other jump
> -   functions and/or transformation summaries.  */
> -
> -ipa_bits *
> -ipa_get_ipa_bits_for_value (const widest_int &value, const widest_int
> &mask)
> -{
> -  ipa_bits tmp;
> -  tmp.value = value;
> -  tmp.mask = mask;
> -
> -  ipa_bits **slot = ipa_bits_hash_table->find_slot (&tmp, INSERT);
> -  if (*slot)
> -    return *slot;
> -
> -  ipa_bits *res = ggc_alloc<ipa_bits> ();
> -  res->value = value;
> -  res->mask = mask;
> -  *slot = res;
> -
> -  return res;
> -}
> -
> -/* Assign to JF a pointer to ipa_bits structure with VALUE and MASK.  Use
> hash
> -   table in order to avoid creating multiple same ipa_bits structures.  */
> -
> -static void
> -ipa_set_jfunc_bits (ipa_jump_func *jf, const widest_int &value,
> -                   const widest_int &mask)
> -{
> -  jf->bits = ipa_get_ipa_bits_for_value (value, mask);
> -}
> -
>  /* Return a pointer to an ipa_vr just like TMP, but either find it in
>     ipa_vr_hash_table or allocate it in GC memory.  */
>
> @@ -2393,10 +2306,31 @@ ipa_compute_jump_functions_for_edge (str
>             addr_nonzero = true;
>
>           if (addr_nonzero)
> +           vr.set_nonzero (TREE_TYPE (arg));
> +
> +         unsigned HOST_WIDE_INT bitpos;
> +         unsigned align, prec = TYPE_PRECISION (TREE_TYPE (arg));
> +
> +         get_pointer_alignment_1 (arg, &align, &bitpos);
> +
> +         if (align > BITS_PER_UNIT
> +             && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp))
>             {
> -             vr.set_nonzero (TREE_TYPE (arg));
> +             wide_int mask
> +               = wi::bit_and_not (wi::mask (prec, false, prec),
> +                                  wide_int::from (align / BITS_PER_UNIT -
> 1,
> +                                                  prec, UNSIGNED));
> +             wide_int value = wide_int::from (bitpos / BITS_PER_UNIT,
> prec,
> +                                              UNSIGNED);
> +             irange_bitmask bm (value, mask);
> +             if (!addr_nonzero)
> +               vr.set_varying (TREE_TYPE (arg));
> +             irange &r = as_a <irange> (vr);
> +             r.update_bitmask (bm);
>               ipa_set_jfunc_vr (jfunc, vr);
>             }
> +         else if (addr_nonzero)
> +           ipa_set_jfunc_vr (jfunc, vr);
>           else
>             gcc_assert (!jfunc->m_vr);
>         }
> @@ -2421,30 +2355,6 @@ ipa_compute_jump_functions_for_edge (str
>             gcc_assert (!jfunc->m_vr);
>         }
>
> -      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)) && !vr.undefined_p ())
> -       {
> -         irange &r = as_a <irange> (vr);
> -         irange_bitmask bm = r.get_bitmask ();
> -         signop sign = TYPE_SIGN (TREE_TYPE (arg));
> -         ipa_set_jfunc_bits (jfunc,
> -                             widest_int::from (bm.value (), sign),
> -                             widest_int::from (bm.mask (), sign));
> -       }
> -      else if (POINTER_TYPE_P (TREE_TYPE (arg)))
> -       {
> -         unsigned HOST_WIDE_INT bitpos;
> -         unsigned align;
> -
> -         get_pointer_alignment_1 (arg, &align, &bitpos);
> -         widest_int mask = wi::bit_and_not
> -           (wi::mask<widest_int> (TYPE_PRECISION (TREE_TYPE (arg)),
> false),
> -            align / BITS_PER_UNIT - 1);
> -         widest_int value = bitpos / BITS_PER_UNIT;
> -         ipa_set_jfunc_bits (jfunc, value, mask);
> -       }
> -      else
> -       gcc_assert (!jfunc->bits);
> -
>        if (is_gimple_ip_invariant (arg)
>           || (VAR_P (arg)
>               && is_global_var (arg)
> @@ -4398,8 +4308,6 @@ ipa_check_create_edge_args (void)
>      ipa_edge_args_sum
>        = (new (ggc_alloc_no_dtor<ipa_edge_args_sum_t> ())
>          ipa_edge_args_sum_t (symtab, true));
> -  if (!ipa_bits_hash_table)
> -    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc
> (37);
>    if (!ipa_vr_hash_table)
>      ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc
> (37);
>  }
> @@ -4432,8 +4340,6 @@ ipa_free_all_node_params (void)
>  void
>  ipcp_transformation_initialize (void)
>  {
> -  if (!ipa_bits_hash_table)
> -    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc
> (37);
>    if (!ipa_vr_hash_table)
>      ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc
> (37);
>    if (ipcp_transformation_sum == NULL)
> @@ -4636,7 +4542,6 @@ ipcp_transformation_t::duplicate(cgraph_
>    if (dst->inlined_to)
>      return;
>    dst_trans->m_agg_values = vec_safe_copy (src_trans->m_agg_values);
> -  dst_trans->bits = vec_safe_copy (src_trans->bits);
>    dst_trans->m_vr = vec_safe_copy (src_trans->m_vr);
>  }
>
> @@ -4859,13 +4764,6 @@ ipa_write_jump_function (struct output_b
>      }
>
>    bp = bitpack_create (ob->main_stream);
> -  bp_pack_value (&bp, !!jump_func->bits, 1);
> -  streamer_write_bitpack (&bp);
> -  if (jump_func->bits)
> -    {
> -      streamer_write_widest_int (ob, jump_func->bits->value);
> -      streamer_write_widest_int (ob, jump_func->bits->mask);
> -    }
>    if (jump_func->m_vr)
>      jump_func->m_vr->streamer_write (ob);
>    else
> @@ -4992,18 +4890,6 @@ ipa_read_jump_function (class lto_input_
>          jump_func->agg.items->quick_push (item);
>      }
>
> -  struct bitpack_d bp = streamer_read_bitpack (ib);
> -  bool bits_known = bp_unpack_value (&bp, 1);
> -  if (bits_known)
> -    {
> -      widest_int value = streamer_read_widest_int (ib);
> -      widest_int mask = streamer_read_widest_int (ib);
> -      if (prevails)
> -       ipa_set_jfunc_bits (jump_func, value, mask);
> -    }
> -  else
> -    jump_func->bits = NULL;
> -
>    ipa_vr vr;
>    vr.streamer_read (ib, data_in);
>    if (vr.known_p ())
> @@ -5387,7 +5273,6 @@ useful_ipcp_transformation_info_p (ipcp_
>    if (!ts)
>      return false;
>    if (!vec_safe_is_empty (ts->m_agg_values)
> -      || !vec_safe_is_empty (ts->bits)
>        || !vec_safe_is_empty (ts->m_vr))
>      return true;
>    return false;
> @@ -5420,19 +5305,6 @@ write_ipcp_transformation_info (output_b
>    streamer_write_uhwi (ob, vec_safe_length (ts->m_vr));
>    for (const ipa_vr &parm_vr : ts->m_vr)
>      parm_vr.streamer_write (ob);
> -
> -  streamer_write_uhwi (ob, vec_safe_length (ts->bits));
> -  for (const ipa_bits *bits_jfunc : ts->bits)
> -    {
> -      struct bitpack_d bp = bitpack_create (ob->main_stream);
> -      bp_pack_value (&bp, !!bits_jfunc, 1);
> -      streamer_write_bitpack (&bp);
> -      if (bits_jfunc)
> -       {
> -         streamer_write_widest_int (ob, bits_jfunc->value);
> -         streamer_write_widest_int (ob, bits_jfunc->mask);
> -       }
> -    }
>  }
>
>  /* Stream in the aggregate value replacement chain for NODE from IB.  */
> @@ -5473,24 +5345,6 @@ read_ipcp_transformation_info (lto_input
>           parm_vr->streamer_read (ib, data_in);
>         }
>      }
> -  count = streamer_read_uhwi (ib);
> -  if (count > 0)
> -    {
> -      vec_safe_grow_cleared (ts->bits, count, true);
> -      for (i = 0; i < count; i++)
> -       {
> -         struct bitpack_d bp = streamer_read_bitpack (ib);
> -         bool known = bp_unpack_value (&bp, 1);
> -         if (known)
> -           {
> -             const widest_int value = streamer_read_widest_int (ib);
> -             const widest_int mask = streamer_read_widest_int (ib);
> -             ipa_bits *bits
> -               = ipa_get_ipa_bits_for_value (value, mask);
> -             (*ts->bits)[i] = bits;
> -           }
> -       }
> -    }
>  }
>
>  /* Write all aggregate replacement for nodes in set.  */
> @@ -5796,7 +5650,9 @@ ipcp_get_parm_bits (tree parm, tree *val
>  {
>    cgraph_node *cnode = cgraph_node::get (current_function_decl);
>    ipcp_transformation *ts = ipcp_get_transformation_summary (cnode);
> -  if (!ts || vec_safe_length (ts->bits) == 0)
> +  if (!ts
> +      || vec_safe_length (ts->m_vr) == 0
> +      || !irange::supports_p (TREE_TYPE (parm)))
>      return false;
>
>    int i = ts->get_param_index (current_function_decl, parm);
> @@ -5810,120 +5666,20 @@ ipcp_get_parm_bits (tree parm, tree *val
>         return false;
>      }
>
> -  vec<ipa_bits *, va_gc> &bits = *ts->bits;
> -  if (!bits[i])
> +  vec<ipa_vr, va_gc> &vr = *ts->m_vr;
> +  if (!vr[i].known_p ())
>      return false;
> -  *mask = bits[i]->mask;
> -  *value = wide_int_to_tree (TREE_TYPE (parm), bits[i]->value);
> +  Value_Range tmp;
> +  vr[i].get_vrange (tmp);
> +  if (tmp.undefined_p () || tmp.varying_p ())
> +    return false;
> +  irange &r = as_a <irange> (tmp);
> +  irange_bitmask bm = r.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;
>  }
>
> -/* Update bits info of formal parameters of NODE as described in TS.  */
> -
> -static void
> -ipcp_update_bits (struct cgraph_node *node, ipcp_transformation *ts)
> -{
> -  if (vec_safe_is_empty (ts->bits))
> -    return;
> -  vec<ipa_bits *, va_gc> &bits = *ts->bits;
> -  unsigned count = bits.length ();
> -  if (!count)
> -    return;
> -
> -  auto_vec<int, 16> new_indices;
> -  bool need_remapping = false;
> -  clone_info *cinfo = clone_info::get (node);
> -  if (cinfo && cinfo->param_adjustments)
> -    {
> -      cinfo->param_adjustments->get_updated_indices (&new_indices);
> -      need_remapping = true;
> -    }
> -  auto_vec <tree, 16> parm_decls;
> -  push_function_arg_decls (&parm_decls, node->decl);
> -
> -  for (unsigned i = 0; i < count; ++i)
> -    {
> -      tree parm;
> -      if (need_remapping)
> -       {
> -         if (i >= new_indices.length ())
> -           continue;
> -         int idx = new_indices[i];
> -         if (idx < 0)
> -           continue;
> -         parm = parm_decls[idx];
> -       }
> -      else
> -       parm = parm_decls[i];
> -      gcc_checking_assert (parm);
> -
> -
> -      if (!bits[i]
> -         || !(INTEGRAL_TYPE_P (TREE_TYPE (parm))
> -              || POINTER_TYPE_P (TREE_TYPE (parm)))
> -         || !is_gimple_reg (parm))
> -       continue;
> -
> -      tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl),
> parm);
> -      if (!ddef)
> -       continue;
> -
> -      if (dump_file)
> -       {
> -         fprintf (dump_file, "Adjusting mask for param %u to ", i);
> -         print_hex (bits[i]->mask, dump_file);
> -         fprintf (dump_file, "\n");
> -       }
> -
> -      if (INTEGRAL_TYPE_P (TREE_TYPE (ddef)))
> -       {
> -         unsigned prec = TYPE_PRECISION (TREE_TYPE (ddef));
> -         signop sgn = TYPE_SIGN (TREE_TYPE (ddef));
> -         wide_int mask = wide_int::from (bits[i]->mask, prec, UNSIGNED);
> -         wide_int value = wide_int::from (bits[i]->value, prec, sgn);
> -         set_bitmask (ddef, value, mask);
> -       }
> -      else
> -       {
> -         unsigned tem = bits[i]->mask.to_uhwi ();
> -         unsigned HOST_WIDE_INT bitpos = bits[i]->value.to_uhwi ();
> -         unsigned align = tem & -tem;
> -         unsigned misalign = bitpos & (align - 1);
> -
> -         if (align > 1)
> -           {
> -             if (dump_file)
> -               fprintf (dump_file, "Adjusting align: %u, misalign: %u\n",
> align, misalign);
> -
> -             unsigned old_align, old_misalign;
> -             struct ptr_info_def *pi = get_ptr_info (ddef);
> -             bool old_known = get_ptr_info_alignment (pi, &old_align,
> &old_misalign);
> -
> -             if (old_known
> -                 && old_align > align)
> -               {
> -                 if (dump_file)
> -                   {
> -                     fprintf (dump_file, "But alignment was already
> %u.\n", old_align);
> -                     if ((old_misalign & (align - 1)) != misalign)
> -                       fprintf (dump_file, "old_misalign (%u) and
> misalign (%u) mismatch\n",
> -                                old_misalign, misalign);
> -                   }
> -                 continue;
> -               }
> -
> -             if (old_known
> -                 && ((misalign & (old_align - 1)) != old_misalign)
> -                 && dump_file)
> -               fprintf (dump_file, "old_misalign (%u) and misalign (%u)
> mismatch\n",
> -                        old_misalign, misalign);
> -
> -             set_ptr_info_alignment (pi, align, misalign);
> -           }
> -       }
> -    }
> -}
> -
>  /* Update value range of formal parameters of NODE as described in TS.  */
>
>  static void
> @@ -5985,6 +5741,77 @@ ipcp_update_vr (struct cgraph_node *node
>                   fprintf (dump_file, "]\n");
>                 }
>               set_range_info (ddef, tmp);
> +
> +             if (POINTER_TYPE_P (TREE_TYPE (parm))
> +                 && opt_for_fn (node->decl, flag_ipa_bit_cp))
> +               {
> +                 irange &r = as_a<irange> (tmp);
> +                 irange_bitmask bm = r.get_bitmask ();
> +                 unsigned tem = bm.mask ().to_uhwi ();
> +                 unsigned HOST_WIDE_INT bitpos = bm.value ().to_uhwi ();
> +                 unsigned align = tem & -tem;
> +                 unsigned misalign = bitpos & (align - 1);
> +
> +                 if (align > 1)
> +                   {
> +                     if (dump_file)
> +                       {
> +                         fprintf (dump_file,
> +                                  "Adjusting mask for param %u to ", i);
> +                         print_hex (bm.mask (), dump_file);
> +                         fprintf (dump_file, "\n");
> +                       }
> +
> +                     if (dump_file)
> +                       fprintf (dump_file,
> +                                "Adjusting align: %u, misalign: %u\n",
> +                                align, misalign);
> +
> +                     unsigned old_align, old_misalign;
> +                     struct ptr_info_def *pi = get_ptr_info (ddef);
> +                     bool old_known = get_ptr_info_alignment (pi,
> &old_align,
> +
> &old_misalign);
> +
> +                     if (old_known && old_align > align)
> +                       {
> +                         if (dump_file)
> +                           {
> +                             fprintf (dump_file,
> +                                      "But alignment was already %u.\n",
> +                                      old_align);
> +                             if ((old_misalign & (align - 1)) != misalign)
> +                               fprintf (dump_file,
> +                                        "old_misalign (%u) and misalign "
> +                                        "(%u) mismatch\n",
> +                                        old_misalign, misalign);
> +                           }
> +                         continue;
> +                       }
> +
> +                     if (dump_file
> +                         && old_known
> +                         && ((misalign & (old_align - 1)) !=
> old_misalign))
> +                       fprintf (dump_file,
> +                                "old_misalign (%u) and misalign (%u) "
> +                                "mismatch\n",
> +                                old_misalign, misalign);
> +
> +                     set_ptr_info_alignment (pi, align, misalign);
> +                   }
> +               }
> +             else if (dump_file && INTEGRAL_TYPE_P (TREE_TYPE (parm)))
> +               {
> +                 irange &r = as_a<irange> (tmp);
> +                 irange_bitmask bm = r.get_bitmask ();
> +                 unsigned prec = TYPE_PRECISION (TREE_TYPE (parm));
> +                 if (wi::ne_p (bm.mask (), wi::shwi (-1, prec)))
> +                   {
> +                     fprintf (dump_file,
> +                              "Adjusting mask for param %u to ", i);
> +                     print_hex (bm.mask (), dump_file);
> +                     fprintf (dump_file, "\n");
> +                   }
> +               }
>             }
>         }
>      }
> @@ -6008,12 +5835,10 @@ ipcp_transform_function (struct cgraph_n
>    ipcp_transformation *ts = ipcp_get_transformation_summary (node);
>    if (!ts
>        || (vec_safe_is_empty (ts->m_agg_values)
> -         && vec_safe_is_empty (ts->bits)
>           && vec_safe_is_empty (ts->m_vr)))
>      return 0;
>
>    ts->maybe_create_parm_idx_map (cfun->decl);
> -  ipcp_update_bits (node, ts);
>    ipcp_update_vr (node, ts);
>    if (vec_safe_is_empty (ts->m_agg_values))
>        return 0;
> --- gcc/ipa-cp.cc.jj    2023-10-05 11:32:39.828744703 +0200
> +++ gcc/ipa-cp.cc       2023-10-05 11:36:45.408378045 +0200
> @@ -2749,11 +2749,22 @@ propagate_bits_across_jump_function (cgr
>         }
>      }
>
> -  if (jfunc->bits)
> -    return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
> -                                   precision);
> -  else
> -    return dest_lattice->set_to_bottom ();
> +  Value_Range vr (parm_type);
> +  if (jfunc->m_vr)
> +    {
> +      jfunc->m_vr->get_vrange (vr);
> +      if (!vr.undefined_p () && !vr.varying_p ())
> +       {
> +         irange &r = as_a <irange> (vr);
> +         irange_bitmask bm = r.get_bitmask ();
> +         widest_int mask
> +           = widest_int::from (bm.mask (), TYPE_SIGN (parm_type));
> +         widest_int value
> +           = widest_int::from (bm.value (), TYPE_SIGN (parm_type));
> +         return dest_lattice->meet_with (value, mask, precision);
> +       }
> +    }
> +  return dest_lattice->set_to_bottom ();
>  }
>
>  /* Propagate value range across jump function JFUNC that is associated
> with
> @@ -6521,89 +6532,8 @@ ipcp_decision_stage (class ipa_topo_info
>      }
>  }
>
> -/* Look up all the bits information that we have discovered and copy it
> over
> -   to the transformation summary.  */
> -
> -static void
> -ipcp_store_bits_results (void)
> -{
> -  cgraph_node *node;
> -
> -  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
> -    {
> -      ipa_node_params *info = ipa_node_params_sum->get (node);
> -      bool dumped_sth = false;
> -      bool found_useful_result = false;
> -
> -      if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
> -       {
> -         if (dump_file)
> -           fprintf (dump_file, "Not considering %s for ipa bitwise
> propagation "
> -                               "; -fipa-bit-cp: disabled.\n",
> -                               node->dump_name ());
> -         continue;
> -       }
> -
> -      if (info->ipcp_orig_node)
> -       info = ipa_node_params_sum->get (info->ipcp_orig_node);
> -      if (!info->lattices)
> -       /* Newly expanded artificial thunks do not have lattices.  */
> -       continue;
> -
> -      unsigned count = ipa_get_param_count (info);
> -      for (unsigned i = 0; i < count; i++)
> -       {
> -         ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> -         if (plats->bits_lattice.constant_p ())
> -           {
> -             found_useful_result = true;
> -             break;
> -           }
> -       }
> -
> -      if (!found_useful_result)
> -       continue;
> -
> -      ipcp_transformation_initialize ();
> -      ipcp_transformation *ts = ipcp_transformation_sum->get_create
> (node);
> -      vec_safe_reserve_exact (ts->bits, count);
> -
> -      for (unsigned i = 0; i < count; i++)
> -       {
> -         ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> -         ipa_bits *jfbits;
> -
> -         if (plats->bits_lattice.constant_p ())
> -           {
> -             jfbits
> -               = ipa_get_ipa_bits_for_value
> (plats->bits_lattice.get_value (),
> -                                             plats->bits_lattice.get_mask
> ());
> -             if (!dbg_cnt (ipa_cp_bits))
> -               jfbits = NULL;
> -           }
> -         else
> -           jfbits = NULL;
> -
> -         ts->bits->quick_push (jfbits);
> -         if (!dump_file || !jfbits)
> -           continue;
> -         if (!dumped_sth)
> -           {
> -             fprintf (dump_file, "Propagated bits info for function
> %s:\n",
> -                      node->dump_name ());
> -             dumped_sth = true;
> -           }
> -         fprintf (dump_file, " param %i: value = ", i);
> -         print_hex (jfbits->value, dump_file);
> -         fprintf (dump_file, ", mask = ");
> -         print_hex (jfbits->mask, dump_file);
> -         fprintf (dump_file, "\n");
> -       }
> -    }
> -}
> -
> -/* Look up all VR information that we have discovered and copy it over
> -   to the transformation summary.  */
> +/* Look up all VR and bits information that we have discovered and copy it
> +   over to the transformation summary.  */
>
>  static void
>  ipcp_store_vr_results (void)
> @@ -6613,7 +6543,10 @@ ipcp_store_vr_results (void)
>    FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
>      {
>        ipa_node_params *info = ipa_node_params_sum->get (node);
> +      bool dumped_sth = false;
>        bool found_useful_result = false;
> +      bool do_vr = true;
> +      bool do_bits = true;
>
>        if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
>         {
> @@ -6621,8 +6554,18 @@ ipcp_store_vr_results (void)
>             fprintf (dump_file, "Not considering %s for VR discovery "
>                      "and propagate; -fipa-ipa-vrp: disabled.\n",
>                      node->dump_name ());
> -         continue;
> +         do_vr = false;
> +       }
> +      if (!info || !opt_for_fn (node->decl, flag_ipa_bit_cp))
> +       {
> +         if (dump_file)
> +           fprintf (dump_file, "Not considering %s for ipa bitwise "
> +                               "propagation ; -fipa-bit-cp: disabled.\n",
> +                               node->dump_name ());
> +         do_bits = false;
>         }
> +      if (!do_bits && !do_vr)
> +       continue;
>
>        if (info->ipcp_orig_node)
>         info = ipa_node_params_sum->get (info->ipcp_orig_node);
> @@ -6634,12 +6577,18 @@ ipcp_store_vr_results (void)
>        for (unsigned i = 0; i < count; i++)
>         {
>           ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> -         if (!plats->m_value_range.bottom_p ()
> +         if (do_vr
> +             && !plats->m_value_range.bottom_p ()
>               && !plats->m_value_range.top_p ())
>             {
>               found_useful_result = true;
>               break;
>             }
> +         if (do_bits && plats->bits_lattice.constant_p ())
> +           {
> +             found_useful_result = true;
> +             break;
> +           }
>         }
>        if (!found_useful_result)
>         continue;
> @@ -6651,12 +6600,53 @@ ipcp_store_vr_results (void)
>        for (unsigned i = 0; i < count; i++)
>         {
>           ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> +         ipcp_bits_lattice *bits = NULL;
> +
> +         if (do_bits
> +             && plats->bits_lattice.constant_p ()
> +             && dbg_cnt (ipa_cp_bits))
> +           bits = &plats->bits_lattice;
>
> -         if (!plats->m_value_range.bottom_p ()
> +         if (do_vr
> +             && !plats->m_value_range.bottom_p ()
>               && !plats->m_value_range.top_p ()
>               && dbg_cnt (ipa_cp_vr))
>             {
> -             ipa_vr vr (plats->m_value_range.m_vr);
> +             if (bits)
> +               {
> +                 Value_Range tmp = plats->m_value_range.m_vr;
> +                 tree type = ipa_get_type (info, i);
> +                 irange &r = as_a<irange> (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);
> +                 ipa_vr vr (tmp);
> +                 ts->m_vr->quick_push (vr);
> +               }
> +             else
> +               {
> +                 ipa_vr vr (plats->m_value_range.m_vr);
> +                 ts->m_vr->quick_push (vr);
> +               }
> +           }
> +         else if (bits)
> +           {
> +             tree type = ipa_get_type (info, i);
> +             Value_Range tmp;
> +             tmp.set_varying (type);
> +             irange &r = as_a<irange> (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);
> +             ipa_vr vr (tmp);
>               ts->m_vr->quick_push (vr);
>             }
>           else
> @@ -6664,6 +6654,21 @@ ipcp_store_vr_results (void)
>               ipa_vr vr;
>               ts->m_vr->quick_push (vr);
>             }
> +
> +         if (!dump_file || !bits)
> +           continue;
> +
> +         if (!dumped_sth)
> +           {
> +             fprintf (dump_file, "Propagated bits info for function
> %s:\n",
> +                      node->dump_name ());
> +             dumped_sth = true;
> +           }
> +         fprintf (dump_file, " param %i: value = ", i);
> +         print_hex (bits->get_value (), dump_file);
> +         fprintf (dump_file, ", mask = ");
> +         print_hex (bits->get_mask (), dump_file);
> +         fprintf (dump_file, "\n");
>         }
>      }
>  }
> @@ -6696,9 +6701,7 @@ ipcp_driver (void)
>    ipcp_propagate_stage (&topo);
>    /* Decide what constant propagation and cloning should be performed.  */
>    ipcp_decision_stage (&topo);
> -  /* Store results of bits propagation.  */
> -  ipcp_store_bits_results ();
> -  /* Store results of value range propagation.  */
> +  /* Store results of value range and bits propagation.  */
>    ipcp_store_vr_results ();
>
>    /* Free all IPCP structures.  */
> --- gcc/ipa-sra.cc.jj   2023-10-05 11:32:40.233739151 +0200
> +++ gcc/ipa-sra.cc      2023-10-05 11:36:45.408378045 +0200
> @@ -4134,22 +4134,8 @@ zap_useless_ipcp_results (const isra_fun
>    else if (removed_item)
>      ts->m_agg_values->truncate (dst_index);
>
> -  bool useful_bits = false;
> -  unsigned count = vec_safe_length (ts->bits);
> -  for (unsigned i = 0; i < count; i++)
> -    if ((*ts->bits)[i])
> -    {
> -      const isra_param_desc *desc = &(*ifs->m_parameters)[i];
> -      if (desc->locally_unused)
> -       (*ts->bits)[i] = NULL;
> -      else
> -       useful_bits = true;
> -    }
> -  if (!useful_bits)
> -    ts->bits = NULL;
> -
>    bool useful_vr = false;
> -  count = vec_safe_length (ts->m_vr);
> +  unsigned count = vec_safe_length (ts->m_vr);
>    for (unsigned i = 0; i < count; i++)
>      if ((*ts->m_vr)[i].known_p ())
>        {
>
>         Jakub
>
>
  
Jan Hubicka Oct. 5, 2023, 2:42 p.m. UTC | #2
> Hi!
> 
> The following patch removes ipa_bits struct pointer/vector from ipa
> jump functions and ipa cp transformations.
> 
> The reason is because the struct uses widest_int to represent
> mask/value pair, which in the RFC patches to allow larger precisions
> for wide_int/widest_int is GC unfriendly because those types become
> non-trivially default constructible/copyable/destructible.
> One option would be to use trailing_wide_int for that instead, but
> as pointed out by Aldy, irange_storage which we already use under
> the hood for ipa_vr when type of parameter is integral or pointer
> already stores the mask/value pair because VRP now does the bit cp
> as well.
> So, this patch just uses m_vr to store both the value range and
> the bitmask.  There is still separate propagation of the
> ipcp_bits_lattice from propagation of the ipcp_vr_lattice, but
> when storing we merge the two into the same container.
> 
> I've bootstrapped/regtested a slightly older version of this
> patch on x86_64-linux and i686-linux and that version regressed
> +FAIL: gcc.dg/ipa/propalign-3.c scan-ipa-dump-not cp "align:"
> +FAIL: gcc.dg/ipa/propalign-3.c scan-tree-dump optimized "fail_the_test"
> +FAIL: gcc.dg/ipa/propbits-1.c scan-ipa-dump cp "Adjusting mask for param 0 to 0x7"
> +FAIL: gcc.dg/ipa/propbits-2.c scan-ipa-dump cp "Adjusting mask for param 0 to 0xf"
> The last 2 were solely about the earlier patch not actually copying
> the if (dump_file) dumping of message that we set some mask for some
> parameter (since then added in the @@ -5985,6 +5741,77 @@ hunk).
> The first testcase is a test for -fno-ipa-bit-cp disabling bit cp
> for alignments.  For integral types I'm afraid it is a lost case
> when -fno-ipa-bit-cp -fipa-vrp is on when value ranges track bit cp
> as well, but for pointer alignments I've added
>   && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp)
> and
>   && opt_for_fn (node->decl, flag_ipa_bit_cp)
> guards such that even just -fno-ipa-bit-cp disables it (alternatively
> we could just add -fno-ipa-vrp to propalign-3.c dg-options).
> 
> Ok for trunk if this passes another bootstrap/regtest?
> Or defer until it is really needed (when the wide_int/widest_int
> changes are about to be committed)?

It does look like a nice cleanup to me.
I wonder if you did some compare of the bit information propagated with
new code and old code?  Theoretically they should be equivalent?

Honza
  
Jakub Jelinek Oct. 5, 2023, 2:59 p.m. UTC | #3
On Thu, Oct 05, 2023 at 04:42:42PM +0200, Jan Hubicka wrote:
> It does look like a nice cleanup to me.
> I wonder if you did some compare of the bit information propagated with
> new code and old code?  Theoretically they should be equivalent?

Beyond testsuite, I've tried
__attribute__((noinline, noclone)) static int
foo (int x, int y, int *p)
{
  return p[x + y];
}

__attribute__((noinline, noclone)) static int
bar (int x, int y, int *p)
{
  return foo (x, y & 0xff, p);
}

int
baz (int x, int y, int *p)
{
  return bar ((x & 0x55555555) | 0x12345678, (x & 0xaaaaaaaa) | 0x87654321, __builtin_assume_aligned (p, 32, 16));
}
and -fdump-tree-ccp2-alias was identical before/after the patch,
so the expected
  # RANGE [irange] int [305419896, +INF] MASK 0x45410105 VALUE 0x12345678
  int x_5(D) = x;
  # RANGE [irange] int [0, 255] MASK 0x8a VALUE 0x21
  int y_6(D) = y;
  # PT = nonlocal null
  # ALIGN = 32, MISALIGN = 16
  int * p_7(D) = p;
in foo (-O2).  With -O2 -fno-ipa-vrp
  # RANGE [irange] int [-INF, +INF] MASK 0x45410105 VALUE 0x12345678
  int x_5(D) = x;
  # RANGE [irange] int [-INF, +INF] MASK 0x8a VALUE 0x21
  int y_6(D) = y;
  # PT = nonlocal null
  # ALIGN = 32, MISALIGN = 16
  int * p_7(D) = p;
and -O2 -fno-ipa-bit-cp
  # RANGE [irange] int [305419896, +INF] MASK 0x45410105 VALUE 0x12345678
  int x_5(D) = x;
  # RANGE [irange] int [0, 255] MASK 0x8a VALUE 0x21
  int y_6(D) = y;
  # PT = nonlocal null
  int * p_7(D) = p;
All that is the same as before.

	Jakub
  
Richard Biener Oct. 6, 2023, 5:54 a.m. UTC | #4
On Thu, 5 Oct 2023, Jakub Jelinek wrote:

> Hi!
> 
> The following patch removes ipa_bits struct pointer/vector from ipa
> jump functions and ipa cp transformations.
> 
> The reason is because the struct uses widest_int to represent
> mask/value pair, which in the RFC patches to allow larger precisions
> for wide_int/widest_int is GC unfriendly because those types become
> non-trivially default constructible/copyable/destructible.
> One option would be to use trailing_wide_int for that instead, but
> as pointed out by Aldy, irange_storage which we already use under
> the hood for ipa_vr when type of parameter is integral or pointer
> already stores the mask/value pair because VRP now does the bit cp
> as well.
> So, this patch just uses m_vr to store both the value range and
> the bitmask.  There is still separate propagation of the
> ipcp_bits_lattice from propagation of the ipcp_vr_lattice, but
> when storing we merge the two into the same container.
> 
> I've bootstrapped/regtested a slightly older version of this
> patch on x86_64-linux and i686-linux and that version regressed
> +FAIL: gcc.dg/ipa/propalign-3.c scan-ipa-dump-not cp "align:"
> +FAIL: gcc.dg/ipa/propalign-3.c scan-tree-dump optimized "fail_the_test"
> +FAIL: gcc.dg/ipa/propbits-1.c scan-ipa-dump cp "Adjusting mask for param 0 to 0x7"
> +FAIL: gcc.dg/ipa/propbits-2.c scan-ipa-dump cp "Adjusting mask for param 0 to 0xf"
> The last 2 were solely about the earlier patch not actually copying
> the if (dump_file) dumping of message that we set some mask for some
> parameter (since then added in the @@ -5985,6 +5741,77 @@ hunk).
> The first testcase is a test for -fno-ipa-bit-cp disabling bit cp
> for alignments.  For integral types I'm afraid it is a lost case
> when -fno-ipa-bit-cp -fipa-vrp is on when value ranges track bit cp
> as well, but for pointer alignments I've added
>   && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp)
> and
>   && opt_for_fn (node->decl, flag_ipa_bit_cp)
> guards such that even just -fno-ipa-bit-cp disables it (alternatively
> we could just add -fno-ipa-vrp to propalign-3.c dg-options).
> 
> Ok for trunk if this passes another bootstrap/regtest?

OK.

Richard.

> Or defer until it is really needed (when the wide_int/widest_int
> changes are about to be committed)?
> 
> 2023-10-05  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* ipa-prop.h (ipa_bits): Remove.
> 	(struct ipa_jump_func): Remove bits member.
> 	(struct ipcp_transformation): Remove bits member, adjust
> 	ctor and dtor.
> 	(ipa_get_ipa_bits_for_value): Remove.
> 	* ipa-prop.cc (struct ipa_bit_ggc_hash_traits): Remove.
> 	(ipa_bits_hash_table): Remove.
> 	(ipa_print_node_jump_functions_for_edge): Don't print bits.
> 	(ipa_get_ipa_bits_for_value): Remove.
> 	(ipa_set_jfunc_bits): Remove.
> 	(ipa_compute_jump_functions_for_edge): For pointers query
> 	pointer alignment before ipa_set_jfunc_vr and update_bitmask
> 	in there.  For integral types, just rely on bitmask already
> 	being handled in value ranges.
> 	(ipa_check_create_edge_args): Don't create ipa_bits_hash_table.
> 	(ipcp_transformation_initialize): Neither here.
> 	(ipcp_transformation_t::duplicate): Don't copy bits vector.
> 	(ipa_write_jump_function): Don't stream bits here.
> 	(ipa_read_jump_function): Neither here.
> 	(useful_ipcp_transformation_info_p): Don't test bits vec.
> 	(write_ipcp_transformation_info): Don't stream bits here.
> 	(read_ipcp_transformation_info): Neither here.
> 	(ipcp_get_parm_bits): Get mask and value from m_vr rather
> 	than bits.
> 	(ipcp_update_bits): Remove.
> 	(ipcp_update_vr): For pointers, set_ptr_info_alignment from
> 	bitmask stored in value range.
> 	(ipcp_transform_function): Don't test bits vector, don't call
> 	ipcp_update_bits.
> 	* ipa-cp.cc (propagate_bits_across_jump_function): Don't use
> 	jfunc->bits, instead get mask and value from jfunc->m_vr.
> 	(ipcp_store_bits_results): Remove.
> 	(ipcp_store_vr_results): Incorporate parts of
> 	ipcp_store_bits_results here, merge the bitmasks with value
> 	range if both are supplied.
> 	(ipcp_driver): Don't call ipcp_store_bits_results.
> 	* ipa-sra.cc (zap_useless_ipcp_results): Remove *ts->bits
> 	clearing.
> 
> --- gcc/ipa-prop.h.jj	2023-10-05 11:32:40.172739988 +0200
> +++ gcc/ipa-prop.h	2023-10-05 11:36:45.405378086 +0200
> @@ -292,18 +292,6 @@ public:
>    array_slice<const ipa_argagg_value> m_elts;
>  };
>  
> -/* Information about zero/non-zero bits.  */
> -class GTY(()) ipa_bits
> -{
> -public:
> -  /* The propagated value.  */
> -  widest_int value;
> -  /* Mask corresponding to the value.
> -     Similar to ccp_lattice_t, if xth bit of mask is 0,
> -     implies xth bit of value is constant.  */
> -  widest_int mask;
> -};
> -
>  /* Info about value ranges.  */
>  
>  class GTY(()) ipa_vr
> @@ -342,11 +330,6 @@ struct GTY (()) ipa_jump_func
>       and its description.  */
>    struct ipa_agg_jump_function agg;
>  
> -  /* Information about zero/non-zero bits.  The pointed to structure is shared
> -     betweed different jump functions.  Use ipa_set_jfunc_bits to set this
> -     field.  */
> -  class ipa_bits *bits;
> -
>    /* Information about value range, containing valid data only when vr_known is
>       true.  The pointed to structure is shared betweed different jump
>       functions.  Use ipa_set_jfunc_vr to set this field.  */
> @@ -940,15 +923,13 @@ struct GTY(()) ipcp_transformation
>  {
>    /* Default constructor.  */
>    ipcp_transformation ()
> -    : m_agg_values (nullptr), bits (nullptr), m_vr (nullptr),
> -    m_uid_to_idx (nullptr)
> +    : m_agg_values (nullptr), m_vr (nullptr), m_uid_to_idx (nullptr)
>    { }
>  
>    /* Default destructor.  */
>    ~ipcp_transformation ()
>    {
>      vec_free (m_agg_values);
> -    vec_free (bits);
>      vec_free (m_vr);
>    }
>  
> @@ -968,8 +949,6 @@ struct GTY(()) ipcp_transformation
>  
>    /* Known aggregate values.  */
>    vec<ipa_argagg_value, va_gc>  *m_agg_values;
> -  /* Known bits information.  */
> -  vec<ipa_bits *, va_gc> *bits;
>    /* Value range information.  */
>    vec<ipa_vr, va_gc> *m_vr;
>    /* If there are many parameters, this is a vector sorted by their DECL_UIDs
> @@ -1172,8 +1151,6 @@ tree ipa_get_indirect_edge_target (struc
>  struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
>  						    bool speculative = false);
>  tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);
> -ipa_bits *ipa_get_ipa_bits_for_value (const widest_int &value,
> -				      const widest_int &mask);
>  
>  
>  /* Functions related to both.  */
> --- gcc/ipa-prop.cc.jj	2023-10-05 11:32:40.154740234 +0200
> +++ gcc/ipa-prop.cc	2023-10-05 14:06:13.742885839 +0200
> @@ -66,49 +66,6 @@ function_summary <ipcp_transformation *>
>  /* Edge summary for IPA-CP edge information.  */
>  ipa_edge_args_sum_t *ipa_edge_args_sum;
>  
> -/* Traits for a hash table for reusing already existing ipa_bits. */
> -
> -struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
> -{
> -  typedef ipa_bits *value_type;
> -  typedef ipa_bits *compare_type;
> -  static hashval_t
> -  hash (const ipa_bits *p)
> -  {
> -    hashval_t t = (hashval_t) p->value.to_shwi ();
> -    return iterative_hash_host_wide_int (p->mask.to_shwi (), t);
> -  }
> -  static bool
> -  equal (const ipa_bits *a, const ipa_bits *b)
> -    {
> -      return a->value == b->value && a->mask == b->mask;
> -    }
> -  static const bool empty_zero_p = true;
> -  static void
> -  mark_empty (ipa_bits *&p)
> -    {
> -      p = NULL;
> -    }
> -  static bool
> -  is_empty (const ipa_bits *p)
> -    {
> -      return p == NULL;
> -    }
> -  static bool
> -  is_deleted (const ipa_bits *p)
> -    {
> -      return p == reinterpret_cast<const ipa_bits *> (1);
> -    }
> -  static void
> -  mark_deleted (ipa_bits *&p)
> -    {
> -      p = reinterpret_cast<ipa_bits *> (1);
> -    }
> -};
> -
> -/* Hash table for avoid repeated allocations of equal ipa_bits.  */
> -static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> *ipa_bits_hash_table;
> -
>  /* Traits for a hash table for reusing ranges.  */
>  
>  struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <ipa_vr *>
> @@ -528,17 +485,6 @@ ipa_print_node_jump_functions_for_edge (
>  	  ctx->dump (dump_file);
>  	}
>  
> -      if (jump_func->bits)
> -	{
> -	  fprintf (f, "         value: ");
> -	  print_hex (jump_func->bits->value, f);
> -	  fprintf (f, ", mask: ");
> -	  print_hex (jump_func->bits->mask, f);
> -	  fprintf (f, "\n");
> -	}
> -      else
> -	fprintf (f, "         Unknown bits\n");
> -
>        if (jump_func->m_vr)
>  	{
>  	  jump_func->m_vr->dump (f);
> @@ -2267,39 +2213,6 @@ ipa_get_callee_param_type (struct cgraph
>    return NULL;
>  }
>  
> -/* Return ipa_bits with VALUE and MASK values, which can be either a newly
> -   allocated structure or a previously existing one shared with other jump
> -   functions and/or transformation summaries.  */
> -
> -ipa_bits *
> -ipa_get_ipa_bits_for_value (const widest_int &value, const widest_int &mask)
> -{
> -  ipa_bits tmp;
> -  tmp.value = value;
> -  tmp.mask = mask;
> -
> -  ipa_bits **slot = ipa_bits_hash_table->find_slot (&tmp, INSERT);
> -  if (*slot)
> -    return *slot;
> -
> -  ipa_bits *res = ggc_alloc<ipa_bits> ();
> -  res->value = value;
> -  res->mask = mask;
> -  *slot = res;
> -
> -  return res;
> -}
> -
> -/* Assign to JF a pointer to ipa_bits structure with VALUE and MASK.  Use hash
> -   table in order to avoid creating multiple same ipa_bits structures.  */
> -
> -static void
> -ipa_set_jfunc_bits (ipa_jump_func *jf, const widest_int &value,
> -		    const widest_int &mask)
> -{
> -  jf->bits = ipa_get_ipa_bits_for_value (value, mask);
> -}
> -
>  /* Return a pointer to an ipa_vr just like TMP, but either find it in
>     ipa_vr_hash_table or allocate it in GC memory.  */
>  
> @@ -2393,10 +2306,31 @@ ipa_compute_jump_functions_for_edge (str
>  	    addr_nonzero = true;
>  
>  	  if (addr_nonzero)
> +	    vr.set_nonzero (TREE_TYPE (arg));
> +
> +	  unsigned HOST_WIDE_INT bitpos;
> +	  unsigned align, prec = TYPE_PRECISION (TREE_TYPE (arg));
> +
> +	  get_pointer_alignment_1 (arg, &align, &bitpos);
> +
> +	  if (align > BITS_PER_UNIT
> +	      && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp))
>  	    {
> -	      vr.set_nonzero (TREE_TYPE (arg));
> +	      wide_int mask
> +		= wi::bit_and_not (wi::mask (prec, false, prec),
> +				   wide_int::from (align / BITS_PER_UNIT - 1,
> +						   prec, UNSIGNED));
> +	      wide_int value = wide_int::from (bitpos / BITS_PER_UNIT, prec,
> +					       UNSIGNED);
> +	      irange_bitmask bm (value, mask);
> +	      if (!addr_nonzero)
> +		vr.set_varying (TREE_TYPE (arg));
> +	      irange &r = as_a <irange> (vr);
> +	      r.update_bitmask (bm);
>  	      ipa_set_jfunc_vr (jfunc, vr);
>  	    }
> +	  else if (addr_nonzero)
> +	    ipa_set_jfunc_vr (jfunc, vr);
>  	  else
>  	    gcc_assert (!jfunc->m_vr);
>  	}
> @@ -2421,30 +2355,6 @@ ipa_compute_jump_functions_for_edge (str
>  	    gcc_assert (!jfunc->m_vr);
>  	}
>  
> -      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)) && !vr.undefined_p ())
> -	{
> -	  irange &r = as_a <irange> (vr);
> -	  irange_bitmask bm = r.get_bitmask ();
> -	  signop sign = TYPE_SIGN (TREE_TYPE (arg));
> -	  ipa_set_jfunc_bits (jfunc,
> -			      widest_int::from (bm.value (), sign),
> -			      widest_int::from (bm.mask (), sign));
> -	}
> -      else if (POINTER_TYPE_P (TREE_TYPE (arg)))
> -	{
> -	  unsigned HOST_WIDE_INT bitpos;
> -	  unsigned align;
> -
> -	  get_pointer_alignment_1 (arg, &align, &bitpos);
> -	  widest_int mask = wi::bit_and_not
> -	    (wi::mask<widest_int> (TYPE_PRECISION (TREE_TYPE (arg)), false),
> -	     align / BITS_PER_UNIT - 1);
> -	  widest_int value = bitpos / BITS_PER_UNIT;
> -	  ipa_set_jfunc_bits (jfunc, value, mask);
> -	}
> -      else
> -	gcc_assert (!jfunc->bits);
> -
>        if (is_gimple_ip_invariant (arg)
>  	  || (VAR_P (arg)
>  	      && is_global_var (arg)
> @@ -4398,8 +4308,6 @@ ipa_check_create_edge_args (void)
>      ipa_edge_args_sum
>        = (new (ggc_alloc_no_dtor<ipa_edge_args_sum_t> ())
>  	 ipa_edge_args_sum_t (symtab, true));
> -  if (!ipa_bits_hash_table)
> -    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc (37);
>    if (!ipa_vr_hash_table)
>      ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
>  }
> @@ -4432,8 +4340,6 @@ ipa_free_all_node_params (void)
>  void
>  ipcp_transformation_initialize (void)
>  {
> -  if (!ipa_bits_hash_table)
> -    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc (37);
>    if (!ipa_vr_hash_table)
>      ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
>    if (ipcp_transformation_sum == NULL)
> @@ -4636,7 +4542,6 @@ ipcp_transformation_t::duplicate(cgraph_
>    if (dst->inlined_to)
>      return;
>    dst_trans->m_agg_values = vec_safe_copy (src_trans->m_agg_values);
> -  dst_trans->bits = vec_safe_copy (src_trans->bits);
>    dst_trans->m_vr = vec_safe_copy (src_trans->m_vr);
>  }
>  
> @@ -4859,13 +4764,6 @@ ipa_write_jump_function (struct output_b
>      }
>  
>    bp = bitpack_create (ob->main_stream);
> -  bp_pack_value (&bp, !!jump_func->bits, 1);
> -  streamer_write_bitpack (&bp);
> -  if (jump_func->bits)
> -    {
> -      streamer_write_widest_int (ob, jump_func->bits->value);
> -      streamer_write_widest_int (ob, jump_func->bits->mask);
> -    }
>    if (jump_func->m_vr)
>      jump_func->m_vr->streamer_write (ob);
>    else
> @@ -4992,18 +4890,6 @@ ipa_read_jump_function (class lto_input_
>          jump_func->agg.items->quick_push (item);
>      }
>  
> -  struct bitpack_d bp = streamer_read_bitpack (ib);
> -  bool bits_known = bp_unpack_value (&bp, 1);
> -  if (bits_known)
> -    {
> -      widest_int value = streamer_read_widest_int (ib);
> -      widest_int mask = streamer_read_widest_int (ib);
> -      if (prevails)
> -	ipa_set_jfunc_bits (jump_func, value, mask);
> -    }
> -  else
> -    jump_func->bits = NULL;
> -
>    ipa_vr vr;
>    vr.streamer_read (ib, data_in);
>    if (vr.known_p ())
> @@ -5387,7 +5273,6 @@ useful_ipcp_transformation_info_p (ipcp_
>    if (!ts)
>      return false;
>    if (!vec_safe_is_empty (ts->m_agg_values)
> -      || !vec_safe_is_empty (ts->bits)
>        || !vec_safe_is_empty (ts->m_vr))
>      return true;
>    return false;
> @@ -5420,19 +5305,6 @@ write_ipcp_transformation_info (output_b
>    streamer_write_uhwi (ob, vec_safe_length (ts->m_vr));
>    for (const ipa_vr &parm_vr : ts->m_vr)
>      parm_vr.streamer_write (ob);
> -
> -  streamer_write_uhwi (ob, vec_safe_length (ts->bits));
> -  for (const ipa_bits *bits_jfunc : ts->bits)
> -    {
> -      struct bitpack_d bp = bitpack_create (ob->main_stream);
> -      bp_pack_value (&bp, !!bits_jfunc, 1);
> -      streamer_write_bitpack (&bp);
> -      if (bits_jfunc)
> -	{
> -	  streamer_write_widest_int (ob, bits_jfunc->value);
> -	  streamer_write_widest_int (ob, bits_jfunc->mask);
> -	}
> -    }
>  }
>  
>  /* Stream in the aggregate value replacement chain for NODE from IB.  */
> @@ -5473,24 +5345,6 @@ read_ipcp_transformation_info (lto_input
>  	  parm_vr->streamer_read (ib, data_in);
>  	}
>      }
> -  count = streamer_read_uhwi (ib);
> -  if (count > 0)
> -    {
> -      vec_safe_grow_cleared (ts->bits, count, true);
> -      for (i = 0; i < count; i++)
> -	{
> -	  struct bitpack_d bp = streamer_read_bitpack (ib);
> -	  bool known = bp_unpack_value (&bp, 1);
> -	  if (known)
> -	    {
> -	      const widest_int value = streamer_read_widest_int (ib);
> -	      const widest_int mask = streamer_read_widest_int (ib);
> -	      ipa_bits *bits
> -		= ipa_get_ipa_bits_for_value (value, mask);
> -	      (*ts->bits)[i] = bits;
> -	    }
> -	}
> -    }
>  }
>  
>  /* Write all aggregate replacement for nodes in set.  */
> @@ -5796,7 +5650,9 @@ ipcp_get_parm_bits (tree parm, tree *val
>  {
>    cgraph_node *cnode = cgraph_node::get (current_function_decl);
>    ipcp_transformation *ts = ipcp_get_transformation_summary (cnode);
> -  if (!ts || vec_safe_length (ts->bits) == 0)
> +  if (!ts
> +      || vec_safe_length (ts->m_vr) == 0
> +      || !irange::supports_p (TREE_TYPE (parm)))
>      return false;
>  
>    int i = ts->get_param_index (current_function_decl, parm);
> @@ -5810,120 +5666,20 @@ ipcp_get_parm_bits (tree parm, tree *val
>  	return false;
>      }
>  
> -  vec<ipa_bits *, va_gc> &bits = *ts->bits;
> -  if (!bits[i])
> +  vec<ipa_vr, va_gc> &vr = *ts->m_vr;
> +  if (!vr[i].known_p ())
>      return false;
> -  *mask = bits[i]->mask;
> -  *value = wide_int_to_tree (TREE_TYPE (parm), bits[i]->value);
> +  Value_Range tmp;
> +  vr[i].get_vrange (tmp);
> +  if (tmp.undefined_p () || tmp.varying_p ())
> +    return false;
> +  irange &r = as_a <irange> (tmp);
> +  irange_bitmask bm = r.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;
>  }
>  
> -/* Update bits info of formal parameters of NODE as described in TS.  */
> -
> -static void
> -ipcp_update_bits (struct cgraph_node *node, ipcp_transformation *ts)
> -{
> -  if (vec_safe_is_empty (ts->bits))
> -    return;
> -  vec<ipa_bits *, va_gc> &bits = *ts->bits;
> -  unsigned count = bits.length ();
> -  if (!count)
> -    return;
> -
> -  auto_vec<int, 16> new_indices;
> -  bool need_remapping = false;
> -  clone_info *cinfo = clone_info::get (node);
> -  if (cinfo && cinfo->param_adjustments)
> -    {
> -      cinfo->param_adjustments->get_updated_indices (&new_indices);
> -      need_remapping = true;
> -    }
> -  auto_vec <tree, 16> parm_decls;
> -  push_function_arg_decls (&parm_decls, node->decl);
> -
> -  for (unsigned i = 0; i < count; ++i)
> -    {
> -      tree parm;
> -      if (need_remapping)
> -	{
> -	  if (i >= new_indices.length ())
> -	    continue;
> -	  int idx = new_indices[i];
> -	  if (idx < 0)
> -	    continue;
> -	  parm = parm_decls[idx];
> -	}
> -      else
> -	parm = parm_decls[i];
> -      gcc_checking_assert (parm);
> -
> -
> -      if (!bits[i]
> -	  || !(INTEGRAL_TYPE_P (TREE_TYPE (parm))
> -	       || POINTER_TYPE_P (TREE_TYPE (parm)))
> -	  || !is_gimple_reg (parm))
> -	continue;
> -
> -      tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm);
> -      if (!ddef)
> -	continue;
> -
> -      if (dump_file)
> -	{
> -	  fprintf (dump_file, "Adjusting mask for param %u to ", i);
> -	  print_hex (bits[i]->mask, dump_file);
> -	  fprintf (dump_file, "\n");
> -	}
> -
> -      if (INTEGRAL_TYPE_P (TREE_TYPE (ddef)))
> -	{
> -	  unsigned prec = TYPE_PRECISION (TREE_TYPE (ddef));
> -	  signop sgn = TYPE_SIGN (TREE_TYPE (ddef));
> -	  wide_int mask = wide_int::from (bits[i]->mask, prec, UNSIGNED);
> -	  wide_int value = wide_int::from (bits[i]->value, prec, sgn);
> -	  set_bitmask (ddef, value, mask);
> -	}
> -      else
> -	{
> -	  unsigned tem = bits[i]->mask.to_uhwi ();
> -	  unsigned HOST_WIDE_INT bitpos = bits[i]->value.to_uhwi ();
> -	  unsigned align = tem & -tem;
> -	  unsigned misalign = bitpos & (align - 1);
> -
> -	  if (align > 1)
> -	    {
> -	      if (dump_file)
> -		fprintf (dump_file, "Adjusting align: %u, misalign: %u\n", align, misalign); 
> -
> -	      unsigned old_align, old_misalign;
> -	      struct ptr_info_def *pi = get_ptr_info (ddef);
> -	      bool old_known = get_ptr_info_alignment (pi, &old_align, &old_misalign);
> -
> -	      if (old_known
> -		  && old_align > align)
> -		{
> -		  if (dump_file)
> -		    {
> -		      fprintf (dump_file, "But alignment was already %u.\n", old_align);
> -		      if ((old_misalign & (align - 1)) != misalign)
> -			fprintf (dump_file, "old_misalign (%u) and misalign (%u) mismatch\n",
> -				 old_misalign, misalign);
> -		    }
> -		  continue;
> -		}
> -
> -	      if (old_known
> -		  && ((misalign & (old_align - 1)) != old_misalign)
> -		  && dump_file)
> -		fprintf (dump_file, "old_misalign (%u) and misalign (%u) mismatch\n",
> -			 old_misalign, misalign);
> -
> -	      set_ptr_info_alignment (pi, align, misalign); 
> -	    }
> -	}
> -    }
> -}
> -
>  /* Update value range of formal parameters of NODE as described in TS.  */
>  
>  static void
> @@ -5985,6 +5741,77 @@ ipcp_update_vr (struct cgraph_node *node
>  		  fprintf (dump_file, "]\n");
>  		}
>  	      set_range_info (ddef, tmp);
> +
> +	      if (POINTER_TYPE_P (TREE_TYPE (parm))
> +		  && opt_for_fn (node->decl, flag_ipa_bit_cp))
> +		{
> +		  irange &r = as_a<irange> (tmp);
> +		  irange_bitmask bm = r.get_bitmask ();
> +		  unsigned tem = bm.mask ().to_uhwi ();
> +		  unsigned HOST_WIDE_INT bitpos = bm.value ().to_uhwi ();
> +		  unsigned align = tem & -tem;
> +		  unsigned misalign = bitpos & (align - 1);
> +
> +		  if (align > 1)
> +		    {
> +		      if (dump_file)
> +			{
> +			  fprintf (dump_file,
> +				   "Adjusting mask for param %u to ", i);
> +			  print_hex (bm.mask (), dump_file);
> +			  fprintf (dump_file, "\n");
> +			}
> +
> +		      if (dump_file)
> +			fprintf (dump_file,
> +				 "Adjusting align: %u, misalign: %u\n",
> +				 align, misalign);
> +
> +		      unsigned old_align, old_misalign;
> +		      struct ptr_info_def *pi = get_ptr_info (ddef);
> +		      bool old_known = get_ptr_info_alignment (pi, &old_align,
> +							       &old_misalign);
> +
> +		      if (old_known && old_align > align)
> +			{
> +			  if (dump_file)
> +			    {
> +			      fprintf (dump_file,
> +				       "But alignment was already %u.\n",
> +				       old_align);
> +			      if ((old_misalign & (align - 1)) != misalign)
> +				fprintf (dump_file,
> +					 "old_misalign (%u) and misalign "
> +					 "(%u) mismatch\n",
> +					 old_misalign, misalign);
> +			    }
> +			  continue;
> +			}
> +
> +		      if (dump_file
> +			  && old_known
> +			  && ((misalign & (old_align - 1)) != old_misalign))
> +			fprintf (dump_file,
> +				 "old_misalign (%u) and misalign (%u) "
> +				 "mismatch\n",
> +				 old_misalign, misalign);
> +
> +		      set_ptr_info_alignment (pi, align, misalign);
> +		    }
> +		}
> +	      else if (dump_file && INTEGRAL_TYPE_P (TREE_TYPE (parm)))
> +		{
> +		  irange &r = as_a<irange> (tmp);
> +		  irange_bitmask bm = r.get_bitmask ();
> +		  unsigned prec = TYPE_PRECISION (TREE_TYPE (parm));
> +		  if (wi::ne_p (bm.mask (), wi::shwi (-1, prec)))
> +		    {
> +		      fprintf (dump_file,
> +			       "Adjusting mask for param %u to ", i);
> +		      print_hex (bm.mask (), dump_file);
> +		      fprintf (dump_file, "\n");
> +		    }
> +		}
>  	    }
>  	}
>      }
> @@ -6008,12 +5835,10 @@ ipcp_transform_function (struct cgraph_n
>    ipcp_transformation *ts = ipcp_get_transformation_summary (node);
>    if (!ts
>        || (vec_safe_is_empty (ts->m_agg_values)
> -	  && vec_safe_is_empty (ts->bits)
>  	  && vec_safe_is_empty (ts->m_vr)))
>      return 0;
>  
>    ts->maybe_create_parm_idx_map (cfun->decl);
> -  ipcp_update_bits (node, ts);
>    ipcp_update_vr (node, ts);
>    if (vec_safe_is_empty (ts->m_agg_values))
>        return 0;
> --- gcc/ipa-cp.cc.jj	2023-10-05 11:32:39.828744703 +0200
> +++ gcc/ipa-cp.cc	2023-10-05 11:36:45.408378045 +0200
> @@ -2749,11 +2749,22 @@ propagate_bits_across_jump_function (cgr
>  	}
>      }
>  
> -  if (jfunc->bits)
> -    return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
> -				    precision);
> -  else
> -    return dest_lattice->set_to_bottom ();
> +  Value_Range vr (parm_type);
> +  if (jfunc->m_vr)
> +    {
> +      jfunc->m_vr->get_vrange (vr);
> +      if (!vr.undefined_p () && !vr.varying_p ())
> +	{
> +	  irange &r = as_a <irange> (vr);
> +	  irange_bitmask bm = r.get_bitmask ();
> +	  widest_int mask
> +	    = widest_int::from (bm.mask (), TYPE_SIGN (parm_type));
> +	  widest_int value
> +	    = widest_int::from (bm.value (), TYPE_SIGN (parm_type));
> +	  return dest_lattice->meet_with (value, mask, precision);
> +	}
> +    }
> +  return dest_lattice->set_to_bottom ();
>  }
>  
>  /* Propagate value range across jump function JFUNC that is associated with
> @@ -6521,89 +6532,8 @@ ipcp_decision_stage (class ipa_topo_info
>      }
>  }
>  
> -/* Look up all the bits information that we have discovered and copy it over
> -   to the transformation summary.  */
> -
> -static void
> -ipcp_store_bits_results (void)
> -{
> -  cgraph_node *node;
> -
> -  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
> -    {
> -      ipa_node_params *info = ipa_node_params_sum->get (node);
> -      bool dumped_sth = false;
> -      bool found_useful_result = false;
> -
> -      if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
> -	{
> -	  if (dump_file)
> -	    fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
> -				"; -fipa-bit-cp: disabled.\n",
> -				node->dump_name ());
> -	  continue;
> -	}
> -
> -      if (info->ipcp_orig_node)
> -	info = ipa_node_params_sum->get (info->ipcp_orig_node);
> -      if (!info->lattices)
> -	/* Newly expanded artificial thunks do not have lattices.  */
> -	continue;
> -
> -      unsigned count = ipa_get_param_count (info);
> -      for (unsigned i = 0; i < count; i++)
> -	{
> -	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> -	  if (plats->bits_lattice.constant_p ())
> -	    {
> -	      found_useful_result = true;
> -	      break;
> -	    }
> -	}
> -
> -      if (!found_useful_result)
> -	continue;
> -
> -      ipcp_transformation_initialize ();
> -      ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
> -      vec_safe_reserve_exact (ts->bits, count);
> -
> -      for (unsigned i = 0; i < count; i++)
> -	{
> -	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> -	  ipa_bits *jfbits;
> -
> -	  if (plats->bits_lattice.constant_p ())
> -	    {
> -	      jfbits
> -		= ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
> -					      plats->bits_lattice.get_mask ());
> -	      if (!dbg_cnt (ipa_cp_bits))
> -		jfbits = NULL;
> -	    }
> -	  else
> -	    jfbits = NULL;
> -
> -	  ts->bits->quick_push (jfbits);
> -	  if (!dump_file || !jfbits)
> -	    continue;
> -	  if (!dumped_sth)
> -	    {
> -	      fprintf (dump_file, "Propagated bits info for function %s:\n",
> -		       node->dump_name ());
> -	      dumped_sth = true;
> -	    }
> -	  fprintf (dump_file, " param %i: value = ", i);
> -	  print_hex (jfbits->value, dump_file);
> -	  fprintf (dump_file, ", mask = ");
> -	  print_hex (jfbits->mask, dump_file);
> -	  fprintf (dump_file, "\n");
> -	}
> -    }
> -}
> -
> -/* Look up all VR information that we have discovered and copy it over
> -   to the transformation summary.  */
> +/* Look up all VR and bits information that we have discovered and copy it
> +   over to the transformation summary.  */
>  
>  static void
>  ipcp_store_vr_results (void)
> @@ -6613,7 +6543,10 @@ ipcp_store_vr_results (void)
>    FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
>      {
>        ipa_node_params *info = ipa_node_params_sum->get (node);
> +      bool dumped_sth = false;
>        bool found_useful_result = false;
> +      bool do_vr = true;
> +      bool do_bits = true;
>  
>        if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
>  	{
> @@ -6621,8 +6554,18 @@ ipcp_store_vr_results (void)
>  	    fprintf (dump_file, "Not considering %s for VR discovery "
>  		     "and propagate; -fipa-ipa-vrp: disabled.\n",
>  		     node->dump_name ());
> -	  continue;
> +	  do_vr = false;
> +	}
> +      if (!info || !opt_for_fn (node->decl, flag_ipa_bit_cp))
> +	{
> +	  if (dump_file)
> +	    fprintf (dump_file, "Not considering %s for ipa bitwise "
> +				"propagation ; -fipa-bit-cp: disabled.\n",
> +				node->dump_name ());
> +	  do_bits = false;
>  	}
> +      if (!do_bits && !do_vr)
> +	continue;
>  
>        if (info->ipcp_orig_node)
>  	info = ipa_node_params_sum->get (info->ipcp_orig_node);
> @@ -6634,12 +6577,18 @@ ipcp_store_vr_results (void)
>        for (unsigned i = 0; i < count; i++)
>  	{
>  	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> -	  if (!plats->m_value_range.bottom_p ()
> +	  if (do_vr
> +	      && !plats->m_value_range.bottom_p ()
>  	      && !plats->m_value_range.top_p ())
>  	    {
>  	      found_useful_result = true;
>  	      break;
>  	    }
> +	  if (do_bits && plats->bits_lattice.constant_p ())
> +	    {
> +	      found_useful_result = true;
> +	      break;
> +	    }
>  	}
>        if (!found_useful_result)
>  	continue;
> @@ -6651,12 +6600,53 @@ ipcp_store_vr_results (void)
>        for (unsigned i = 0; i < count; i++)
>  	{
>  	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
> +	  ipcp_bits_lattice *bits = NULL;
> +
> +	  if (do_bits
> +	      && plats->bits_lattice.constant_p ()
> +	      && dbg_cnt (ipa_cp_bits))
> +	    bits = &plats->bits_lattice;
>  
> -	  if (!plats->m_value_range.bottom_p ()
> +	  if (do_vr
> +	      && !plats->m_value_range.bottom_p ()
>  	      && !plats->m_value_range.top_p ()
>  	      && dbg_cnt (ipa_cp_vr))
>  	    {
> -	      ipa_vr vr (plats->m_value_range.m_vr);
> +	      if (bits)
> +		{
> +		  Value_Range tmp = plats->m_value_range.m_vr;
> +		  tree type = ipa_get_type (info, i);
> +		  irange &r = as_a<irange> (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);
> +		  ipa_vr vr (tmp);
> +		  ts->m_vr->quick_push (vr);
> +		}
> +	      else
> +		{
> +		  ipa_vr vr (plats->m_value_range.m_vr);
> +		  ts->m_vr->quick_push (vr);
> +		}
> +	    }
> +	  else if (bits)
> +	    {
> +	      tree type = ipa_get_type (info, i);
> +	      Value_Range tmp;
> +	      tmp.set_varying (type);
> +	      irange &r = as_a<irange> (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);
> +	      ipa_vr vr (tmp);
>  	      ts->m_vr->quick_push (vr);
>  	    }
>  	  else
> @@ -6664,6 +6654,21 @@ ipcp_store_vr_results (void)
>  	      ipa_vr vr;
>  	      ts->m_vr->quick_push (vr);
>  	    }
> +
> +	  if (!dump_file || !bits)
> +	    continue;
> +
> +	  if (!dumped_sth)
> +	    {
> +	      fprintf (dump_file, "Propagated bits info for function %s:\n",
> +		       node->dump_name ());
> +	      dumped_sth = true;
> +	    }
> +	  fprintf (dump_file, " param %i: value = ", i);
> +	  print_hex (bits->get_value (), dump_file);
> +	  fprintf (dump_file, ", mask = ");
> +	  print_hex (bits->get_mask (), dump_file);
> +	  fprintf (dump_file, "\n");
>  	}
>      }
>  }
> @@ -6696,9 +6701,7 @@ ipcp_driver (void)
>    ipcp_propagate_stage (&topo);
>    /* Decide what constant propagation and cloning should be performed.  */
>    ipcp_decision_stage (&topo);
> -  /* Store results of bits propagation.  */
> -  ipcp_store_bits_results ();
> -  /* Store results of value range propagation.  */
> +  /* Store results of value range and bits propagation.  */
>    ipcp_store_vr_results ();
>  
>    /* Free all IPCP structures.  */
> --- gcc/ipa-sra.cc.jj	2023-10-05 11:32:40.233739151 +0200
> +++ gcc/ipa-sra.cc	2023-10-05 11:36:45.408378045 +0200
> @@ -4134,22 +4134,8 @@ zap_useless_ipcp_results (const isra_fun
>    else if (removed_item)
>      ts->m_agg_values->truncate (dst_index);
>  
> -  bool useful_bits = false;
> -  unsigned count = vec_safe_length (ts->bits);
> -  for (unsigned i = 0; i < count; i++)
> -    if ((*ts->bits)[i])
> -    {
> -      const isra_param_desc *desc = &(*ifs->m_parameters)[i];
> -      if (desc->locally_unused)
> -	(*ts->bits)[i] = NULL;
> -      else
> -	useful_bits = true;
> -    }
> -  if (!useful_bits)
> -    ts->bits = NULL;
> -
>    bool useful_vr = false;
> -  count = vec_safe_length (ts->m_vr);
> +  unsigned count = vec_safe_length (ts->m_vr);
>    for (unsigned i = 0; i < count; i++)
>      if ((*ts->m_vr)[i].known_p ())
>        {
> 
> 	Jakub
> 
>
  

Patch

--- gcc/ipa-prop.h.jj	2023-10-05 11:32:40.172739988 +0200
+++ gcc/ipa-prop.h	2023-10-05 11:36:45.405378086 +0200
@@ -292,18 +292,6 @@  public:
   array_slice<const ipa_argagg_value> m_elts;
 };
 
-/* Information about zero/non-zero bits.  */
-class GTY(()) ipa_bits
-{
-public:
-  /* The propagated value.  */
-  widest_int value;
-  /* Mask corresponding to the value.
-     Similar to ccp_lattice_t, if xth bit of mask is 0,
-     implies xth bit of value is constant.  */
-  widest_int mask;
-};
-
 /* Info about value ranges.  */
 
 class GTY(()) ipa_vr
@@ -342,11 +330,6 @@  struct GTY (()) ipa_jump_func
      and its description.  */
   struct ipa_agg_jump_function agg;
 
-  /* Information about zero/non-zero bits.  The pointed to structure is shared
-     betweed different jump functions.  Use ipa_set_jfunc_bits to set this
-     field.  */
-  class ipa_bits *bits;
-
   /* Information about value range, containing valid data only when vr_known is
      true.  The pointed to structure is shared betweed different jump
      functions.  Use ipa_set_jfunc_vr to set this field.  */
@@ -940,15 +923,13 @@  struct GTY(()) ipcp_transformation
 {
   /* Default constructor.  */
   ipcp_transformation ()
-    : m_agg_values (nullptr), bits (nullptr), m_vr (nullptr),
-    m_uid_to_idx (nullptr)
+    : m_agg_values (nullptr), m_vr (nullptr), m_uid_to_idx (nullptr)
   { }
 
   /* Default destructor.  */
   ~ipcp_transformation ()
   {
     vec_free (m_agg_values);
-    vec_free (bits);
     vec_free (m_vr);
   }
 
@@ -968,8 +949,6 @@  struct GTY(()) ipcp_transformation
 
   /* Known aggregate values.  */
   vec<ipa_argagg_value, va_gc>  *m_agg_values;
-  /* Known bits information.  */
-  vec<ipa_bits *, va_gc> *bits;
   /* Value range information.  */
   vec<ipa_vr, va_gc> *m_vr;
   /* If there are many parameters, this is a vector sorted by their DECL_UIDs
@@ -1172,8 +1151,6 @@  tree ipa_get_indirect_edge_target (struc
 struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
 						    bool speculative = false);
 tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);
-ipa_bits *ipa_get_ipa_bits_for_value (const widest_int &value,
-				      const widest_int &mask);
 
 
 /* Functions related to both.  */
--- gcc/ipa-prop.cc.jj	2023-10-05 11:32:40.154740234 +0200
+++ gcc/ipa-prop.cc	2023-10-05 14:06:13.742885839 +0200
@@ -66,49 +66,6 @@  function_summary <ipcp_transformation *>
 /* Edge summary for IPA-CP edge information.  */
 ipa_edge_args_sum_t *ipa_edge_args_sum;
 
-/* Traits for a hash table for reusing already existing ipa_bits. */
-
-struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
-{
-  typedef ipa_bits *value_type;
-  typedef ipa_bits *compare_type;
-  static hashval_t
-  hash (const ipa_bits *p)
-  {
-    hashval_t t = (hashval_t) p->value.to_shwi ();
-    return iterative_hash_host_wide_int (p->mask.to_shwi (), t);
-  }
-  static bool
-  equal (const ipa_bits *a, const ipa_bits *b)
-    {
-      return a->value == b->value && a->mask == b->mask;
-    }
-  static const bool empty_zero_p = true;
-  static void
-  mark_empty (ipa_bits *&p)
-    {
-      p = NULL;
-    }
-  static bool
-  is_empty (const ipa_bits *p)
-    {
-      return p == NULL;
-    }
-  static bool
-  is_deleted (const ipa_bits *p)
-    {
-      return p == reinterpret_cast<const ipa_bits *> (1);
-    }
-  static void
-  mark_deleted (ipa_bits *&p)
-    {
-      p = reinterpret_cast<ipa_bits *> (1);
-    }
-};
-
-/* Hash table for avoid repeated allocations of equal ipa_bits.  */
-static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> *ipa_bits_hash_table;
-
 /* Traits for a hash table for reusing ranges.  */
 
 struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <ipa_vr *>
@@ -528,17 +485,6 @@  ipa_print_node_jump_functions_for_edge (
 	  ctx->dump (dump_file);
 	}
 
-      if (jump_func->bits)
-	{
-	  fprintf (f, "         value: ");
-	  print_hex (jump_func->bits->value, f);
-	  fprintf (f, ", mask: ");
-	  print_hex (jump_func->bits->mask, f);
-	  fprintf (f, "\n");
-	}
-      else
-	fprintf (f, "         Unknown bits\n");
-
       if (jump_func->m_vr)
 	{
 	  jump_func->m_vr->dump (f);
@@ -2267,39 +2213,6 @@  ipa_get_callee_param_type (struct cgraph
   return NULL;
 }
 
-/* Return ipa_bits with VALUE and MASK values, which can be either a newly
-   allocated structure or a previously existing one shared with other jump
-   functions and/or transformation summaries.  */
-
-ipa_bits *
-ipa_get_ipa_bits_for_value (const widest_int &value, const widest_int &mask)
-{
-  ipa_bits tmp;
-  tmp.value = value;
-  tmp.mask = mask;
-
-  ipa_bits **slot = ipa_bits_hash_table->find_slot (&tmp, INSERT);
-  if (*slot)
-    return *slot;
-
-  ipa_bits *res = ggc_alloc<ipa_bits> ();
-  res->value = value;
-  res->mask = mask;
-  *slot = res;
-
-  return res;
-}
-
-/* Assign to JF a pointer to ipa_bits structure with VALUE and MASK.  Use hash
-   table in order to avoid creating multiple same ipa_bits structures.  */
-
-static void
-ipa_set_jfunc_bits (ipa_jump_func *jf, const widest_int &value,
-		    const widest_int &mask)
-{
-  jf->bits = ipa_get_ipa_bits_for_value (value, mask);
-}
-
 /* Return a pointer to an ipa_vr just like TMP, but either find it in
    ipa_vr_hash_table or allocate it in GC memory.  */
 
@@ -2393,10 +2306,31 @@  ipa_compute_jump_functions_for_edge (str
 	    addr_nonzero = true;
 
 	  if (addr_nonzero)
+	    vr.set_nonzero (TREE_TYPE (arg));
+
+	  unsigned HOST_WIDE_INT bitpos;
+	  unsigned align, prec = TYPE_PRECISION (TREE_TYPE (arg));
+
+	  get_pointer_alignment_1 (arg, &align, &bitpos);
+
+	  if (align > BITS_PER_UNIT
+	      && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp))
 	    {
-	      vr.set_nonzero (TREE_TYPE (arg));
+	      wide_int mask
+		= wi::bit_and_not (wi::mask (prec, false, prec),
+				   wide_int::from (align / BITS_PER_UNIT - 1,
+						   prec, UNSIGNED));
+	      wide_int value = wide_int::from (bitpos / BITS_PER_UNIT, prec,
+					       UNSIGNED);
+	      irange_bitmask bm (value, mask);
+	      if (!addr_nonzero)
+		vr.set_varying (TREE_TYPE (arg));
+	      irange &r = as_a <irange> (vr);
+	      r.update_bitmask (bm);
 	      ipa_set_jfunc_vr (jfunc, vr);
 	    }
+	  else if (addr_nonzero)
+	    ipa_set_jfunc_vr (jfunc, vr);
 	  else
 	    gcc_assert (!jfunc->m_vr);
 	}
@@ -2421,30 +2355,6 @@  ipa_compute_jump_functions_for_edge (str
 	    gcc_assert (!jfunc->m_vr);
 	}
 
-      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)) && !vr.undefined_p ())
-	{
-	  irange &r = as_a <irange> (vr);
-	  irange_bitmask bm = r.get_bitmask ();
-	  signop sign = TYPE_SIGN (TREE_TYPE (arg));
-	  ipa_set_jfunc_bits (jfunc,
-			      widest_int::from (bm.value (), sign),
-			      widest_int::from (bm.mask (), sign));
-	}
-      else if (POINTER_TYPE_P (TREE_TYPE (arg)))
-	{
-	  unsigned HOST_WIDE_INT bitpos;
-	  unsigned align;
-
-	  get_pointer_alignment_1 (arg, &align, &bitpos);
-	  widest_int mask = wi::bit_and_not
-	    (wi::mask<widest_int> (TYPE_PRECISION (TREE_TYPE (arg)), false),
-	     align / BITS_PER_UNIT - 1);
-	  widest_int value = bitpos / BITS_PER_UNIT;
-	  ipa_set_jfunc_bits (jfunc, value, mask);
-	}
-      else
-	gcc_assert (!jfunc->bits);
-
       if (is_gimple_ip_invariant (arg)
 	  || (VAR_P (arg)
 	      && is_global_var (arg)
@@ -4398,8 +4308,6 @@  ipa_check_create_edge_args (void)
     ipa_edge_args_sum
       = (new (ggc_alloc_no_dtor<ipa_edge_args_sum_t> ())
 	 ipa_edge_args_sum_t (symtab, true));
-  if (!ipa_bits_hash_table)
-    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc (37);
   if (!ipa_vr_hash_table)
     ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
 }
@@ -4432,8 +4340,6 @@  ipa_free_all_node_params (void)
 void
 ipcp_transformation_initialize (void)
 {
-  if (!ipa_bits_hash_table)
-    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc (37);
   if (!ipa_vr_hash_table)
     ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
   if (ipcp_transformation_sum == NULL)
@@ -4636,7 +4542,6 @@  ipcp_transformation_t::duplicate(cgraph_
   if (dst->inlined_to)
     return;
   dst_trans->m_agg_values = vec_safe_copy (src_trans->m_agg_values);
-  dst_trans->bits = vec_safe_copy (src_trans->bits);
   dst_trans->m_vr = vec_safe_copy (src_trans->m_vr);
 }
 
@@ -4859,13 +4764,6 @@  ipa_write_jump_function (struct output_b
     }
 
   bp = bitpack_create (ob->main_stream);
-  bp_pack_value (&bp, !!jump_func->bits, 1);
-  streamer_write_bitpack (&bp);
-  if (jump_func->bits)
-    {
-      streamer_write_widest_int (ob, jump_func->bits->value);
-      streamer_write_widest_int (ob, jump_func->bits->mask);
-    }
   if (jump_func->m_vr)
     jump_func->m_vr->streamer_write (ob);
   else
@@ -4992,18 +4890,6 @@  ipa_read_jump_function (class lto_input_
         jump_func->agg.items->quick_push (item);
     }
 
-  struct bitpack_d bp = streamer_read_bitpack (ib);
-  bool bits_known = bp_unpack_value (&bp, 1);
-  if (bits_known)
-    {
-      widest_int value = streamer_read_widest_int (ib);
-      widest_int mask = streamer_read_widest_int (ib);
-      if (prevails)
-	ipa_set_jfunc_bits (jump_func, value, mask);
-    }
-  else
-    jump_func->bits = NULL;
-
   ipa_vr vr;
   vr.streamer_read (ib, data_in);
   if (vr.known_p ())
@@ -5387,7 +5273,6 @@  useful_ipcp_transformation_info_p (ipcp_
   if (!ts)
     return false;
   if (!vec_safe_is_empty (ts->m_agg_values)
-      || !vec_safe_is_empty (ts->bits)
       || !vec_safe_is_empty (ts->m_vr))
     return true;
   return false;
@@ -5420,19 +5305,6 @@  write_ipcp_transformation_info (output_b
   streamer_write_uhwi (ob, vec_safe_length (ts->m_vr));
   for (const ipa_vr &parm_vr : ts->m_vr)
     parm_vr.streamer_write (ob);
-
-  streamer_write_uhwi (ob, vec_safe_length (ts->bits));
-  for (const ipa_bits *bits_jfunc : ts->bits)
-    {
-      struct bitpack_d bp = bitpack_create (ob->main_stream);
-      bp_pack_value (&bp, !!bits_jfunc, 1);
-      streamer_write_bitpack (&bp);
-      if (bits_jfunc)
-	{
-	  streamer_write_widest_int (ob, bits_jfunc->value);
-	  streamer_write_widest_int (ob, bits_jfunc->mask);
-	}
-    }
 }
 
 /* Stream in the aggregate value replacement chain for NODE from IB.  */
@@ -5473,24 +5345,6 @@  read_ipcp_transformation_info (lto_input
 	  parm_vr->streamer_read (ib, data_in);
 	}
     }
-  count = streamer_read_uhwi (ib);
-  if (count > 0)
-    {
-      vec_safe_grow_cleared (ts->bits, count, true);
-      for (i = 0; i < count; i++)
-	{
-	  struct bitpack_d bp = streamer_read_bitpack (ib);
-	  bool known = bp_unpack_value (&bp, 1);
-	  if (known)
-	    {
-	      const widest_int value = streamer_read_widest_int (ib);
-	      const widest_int mask = streamer_read_widest_int (ib);
-	      ipa_bits *bits
-		= ipa_get_ipa_bits_for_value (value, mask);
-	      (*ts->bits)[i] = bits;
-	    }
-	}
-    }
 }
 
 /* Write all aggregate replacement for nodes in set.  */
@@ -5796,7 +5650,9 @@  ipcp_get_parm_bits (tree parm, tree *val
 {
   cgraph_node *cnode = cgraph_node::get (current_function_decl);
   ipcp_transformation *ts = ipcp_get_transformation_summary (cnode);
-  if (!ts || vec_safe_length (ts->bits) == 0)
+  if (!ts
+      || vec_safe_length (ts->m_vr) == 0
+      || !irange::supports_p (TREE_TYPE (parm)))
     return false;
 
   int i = ts->get_param_index (current_function_decl, parm);
@@ -5810,120 +5666,20 @@  ipcp_get_parm_bits (tree parm, tree *val
 	return false;
     }
 
-  vec<ipa_bits *, va_gc> &bits = *ts->bits;
-  if (!bits[i])
+  vec<ipa_vr, va_gc> &vr = *ts->m_vr;
+  if (!vr[i].known_p ())
     return false;
-  *mask = bits[i]->mask;
-  *value = wide_int_to_tree (TREE_TYPE (parm), bits[i]->value);
+  Value_Range tmp;
+  vr[i].get_vrange (tmp);
+  if (tmp.undefined_p () || tmp.varying_p ())
+    return false;
+  irange &r = as_a <irange> (tmp);
+  irange_bitmask bm = r.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;
 }
 
-/* Update bits info of formal parameters of NODE as described in TS.  */
-
-static void
-ipcp_update_bits (struct cgraph_node *node, ipcp_transformation *ts)
-{
-  if (vec_safe_is_empty (ts->bits))
-    return;
-  vec<ipa_bits *, va_gc> &bits = *ts->bits;
-  unsigned count = bits.length ();
-  if (!count)
-    return;
-
-  auto_vec<int, 16> new_indices;
-  bool need_remapping = false;
-  clone_info *cinfo = clone_info::get (node);
-  if (cinfo && cinfo->param_adjustments)
-    {
-      cinfo->param_adjustments->get_updated_indices (&new_indices);
-      need_remapping = true;
-    }
-  auto_vec <tree, 16> parm_decls;
-  push_function_arg_decls (&parm_decls, node->decl);
-
-  for (unsigned i = 0; i < count; ++i)
-    {
-      tree parm;
-      if (need_remapping)
-	{
-	  if (i >= new_indices.length ())
-	    continue;
-	  int idx = new_indices[i];
-	  if (idx < 0)
-	    continue;
-	  parm = parm_decls[idx];
-	}
-      else
-	parm = parm_decls[i];
-      gcc_checking_assert (parm);
-
-
-      if (!bits[i]
-	  || !(INTEGRAL_TYPE_P (TREE_TYPE (parm))
-	       || POINTER_TYPE_P (TREE_TYPE (parm)))
-	  || !is_gimple_reg (parm))
-	continue;
-
-      tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm);
-      if (!ddef)
-	continue;
-
-      if (dump_file)
-	{
-	  fprintf (dump_file, "Adjusting mask for param %u to ", i);
-	  print_hex (bits[i]->mask, dump_file);
-	  fprintf (dump_file, "\n");
-	}
-
-      if (INTEGRAL_TYPE_P (TREE_TYPE (ddef)))
-	{
-	  unsigned prec = TYPE_PRECISION (TREE_TYPE (ddef));
-	  signop sgn = TYPE_SIGN (TREE_TYPE (ddef));
-	  wide_int mask = wide_int::from (bits[i]->mask, prec, UNSIGNED);
-	  wide_int value = wide_int::from (bits[i]->value, prec, sgn);
-	  set_bitmask (ddef, value, mask);
-	}
-      else
-	{
-	  unsigned tem = bits[i]->mask.to_uhwi ();
-	  unsigned HOST_WIDE_INT bitpos = bits[i]->value.to_uhwi ();
-	  unsigned align = tem & -tem;
-	  unsigned misalign = bitpos & (align - 1);
-
-	  if (align > 1)
-	    {
-	      if (dump_file)
-		fprintf (dump_file, "Adjusting align: %u, misalign: %u\n", align, misalign); 
-
-	      unsigned old_align, old_misalign;
-	      struct ptr_info_def *pi = get_ptr_info (ddef);
-	      bool old_known = get_ptr_info_alignment (pi, &old_align, &old_misalign);
-
-	      if (old_known
-		  && old_align > align)
-		{
-		  if (dump_file)
-		    {
-		      fprintf (dump_file, "But alignment was already %u.\n", old_align);
-		      if ((old_misalign & (align - 1)) != misalign)
-			fprintf (dump_file, "old_misalign (%u) and misalign (%u) mismatch\n",
-				 old_misalign, misalign);
-		    }
-		  continue;
-		}
-
-	      if (old_known
-		  && ((misalign & (old_align - 1)) != old_misalign)
-		  && dump_file)
-		fprintf (dump_file, "old_misalign (%u) and misalign (%u) mismatch\n",
-			 old_misalign, misalign);
-
-	      set_ptr_info_alignment (pi, align, misalign); 
-	    }
-	}
-    }
-}
-
 /* Update value range of formal parameters of NODE as described in TS.  */
 
 static void
@@ -5985,6 +5741,77 @@  ipcp_update_vr (struct cgraph_node *node
 		  fprintf (dump_file, "]\n");
 		}
 	      set_range_info (ddef, tmp);
+
+	      if (POINTER_TYPE_P (TREE_TYPE (parm))
+		  && opt_for_fn (node->decl, flag_ipa_bit_cp))
+		{
+		  irange &r = as_a<irange> (tmp);
+		  irange_bitmask bm = r.get_bitmask ();
+		  unsigned tem = bm.mask ().to_uhwi ();
+		  unsigned HOST_WIDE_INT bitpos = bm.value ().to_uhwi ();
+		  unsigned align = tem & -tem;
+		  unsigned misalign = bitpos & (align - 1);
+
+		  if (align > 1)
+		    {
+		      if (dump_file)
+			{
+			  fprintf (dump_file,
+				   "Adjusting mask for param %u to ", i);
+			  print_hex (bm.mask (), dump_file);
+			  fprintf (dump_file, "\n");
+			}
+
+		      if (dump_file)
+			fprintf (dump_file,
+				 "Adjusting align: %u, misalign: %u\n",
+				 align, misalign);
+
+		      unsigned old_align, old_misalign;
+		      struct ptr_info_def *pi = get_ptr_info (ddef);
+		      bool old_known = get_ptr_info_alignment (pi, &old_align,
+							       &old_misalign);
+
+		      if (old_known && old_align > align)
+			{
+			  if (dump_file)
+			    {
+			      fprintf (dump_file,
+				       "But alignment was already %u.\n",
+				       old_align);
+			      if ((old_misalign & (align - 1)) != misalign)
+				fprintf (dump_file,
+					 "old_misalign (%u) and misalign "
+					 "(%u) mismatch\n",
+					 old_misalign, misalign);
+			    }
+			  continue;
+			}
+
+		      if (dump_file
+			  && old_known
+			  && ((misalign & (old_align - 1)) != old_misalign))
+			fprintf (dump_file,
+				 "old_misalign (%u) and misalign (%u) "
+				 "mismatch\n",
+				 old_misalign, misalign);
+
+		      set_ptr_info_alignment (pi, align, misalign);
+		    }
+		}
+	      else if (dump_file && INTEGRAL_TYPE_P (TREE_TYPE (parm)))
+		{
+		  irange &r = as_a<irange> (tmp);
+		  irange_bitmask bm = r.get_bitmask ();
+		  unsigned prec = TYPE_PRECISION (TREE_TYPE (parm));
+		  if (wi::ne_p (bm.mask (), wi::shwi (-1, prec)))
+		    {
+		      fprintf (dump_file,
+			       "Adjusting mask for param %u to ", i);
+		      print_hex (bm.mask (), dump_file);
+		      fprintf (dump_file, "\n");
+		    }
+		}
 	    }
 	}
     }
@@ -6008,12 +5835,10 @@  ipcp_transform_function (struct cgraph_n
   ipcp_transformation *ts = ipcp_get_transformation_summary (node);
   if (!ts
       || (vec_safe_is_empty (ts->m_agg_values)
-	  && vec_safe_is_empty (ts->bits)
 	  && vec_safe_is_empty (ts->m_vr)))
     return 0;
 
   ts->maybe_create_parm_idx_map (cfun->decl);
-  ipcp_update_bits (node, ts);
   ipcp_update_vr (node, ts);
   if (vec_safe_is_empty (ts->m_agg_values))
       return 0;
--- gcc/ipa-cp.cc.jj	2023-10-05 11:32:39.828744703 +0200
+++ gcc/ipa-cp.cc	2023-10-05 11:36:45.408378045 +0200
@@ -2749,11 +2749,22 @@  propagate_bits_across_jump_function (cgr
 	}
     }
 
-  if (jfunc->bits)
-    return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
-				    precision);
-  else
-    return dest_lattice->set_to_bottom ();
+  Value_Range vr (parm_type);
+  if (jfunc->m_vr)
+    {
+      jfunc->m_vr->get_vrange (vr);
+      if (!vr.undefined_p () && !vr.varying_p ())
+	{
+	  irange &r = as_a <irange> (vr);
+	  irange_bitmask bm = r.get_bitmask ();
+	  widest_int mask
+	    = widest_int::from (bm.mask (), TYPE_SIGN (parm_type));
+	  widest_int value
+	    = widest_int::from (bm.value (), TYPE_SIGN (parm_type));
+	  return dest_lattice->meet_with (value, mask, precision);
+	}
+    }
+  return dest_lattice->set_to_bottom ();
 }
 
 /* Propagate value range across jump function JFUNC that is associated with
@@ -6521,89 +6532,8 @@  ipcp_decision_stage (class ipa_topo_info
     }
 }
 
-/* Look up all the bits information that we have discovered and copy it over
-   to the transformation summary.  */
-
-static void
-ipcp_store_bits_results (void)
-{
-  cgraph_node *node;
-
-  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
-    {
-      ipa_node_params *info = ipa_node_params_sum->get (node);
-      bool dumped_sth = false;
-      bool found_useful_result = false;
-
-      if (!opt_for_fn (node->decl, flag_ipa_bit_cp) || !info)
-	{
-	  if (dump_file)
-	    fprintf (dump_file, "Not considering %s for ipa bitwise propagation "
-				"; -fipa-bit-cp: disabled.\n",
-				node->dump_name ());
-	  continue;
-	}
-
-      if (info->ipcp_orig_node)
-	info = ipa_node_params_sum->get (info->ipcp_orig_node);
-      if (!info->lattices)
-	/* Newly expanded artificial thunks do not have lattices.  */
-	continue;
-
-      unsigned count = ipa_get_param_count (info);
-      for (unsigned i = 0; i < count; i++)
-	{
-	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
-	  if (plats->bits_lattice.constant_p ())
-	    {
-	      found_useful_result = true;
-	      break;
-	    }
-	}
-
-      if (!found_useful_result)
-	continue;
-
-      ipcp_transformation_initialize ();
-      ipcp_transformation *ts = ipcp_transformation_sum->get_create (node);
-      vec_safe_reserve_exact (ts->bits, count);
-
-      for (unsigned i = 0; i < count; i++)
-	{
-	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
-	  ipa_bits *jfbits;
-
-	  if (plats->bits_lattice.constant_p ())
-	    {
-	      jfbits
-		= ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
-					      plats->bits_lattice.get_mask ());
-	      if (!dbg_cnt (ipa_cp_bits))
-		jfbits = NULL;
-	    }
-	  else
-	    jfbits = NULL;
-
-	  ts->bits->quick_push (jfbits);
-	  if (!dump_file || !jfbits)
-	    continue;
-	  if (!dumped_sth)
-	    {
-	      fprintf (dump_file, "Propagated bits info for function %s:\n",
-		       node->dump_name ());
-	      dumped_sth = true;
-	    }
-	  fprintf (dump_file, " param %i: value = ", i);
-	  print_hex (jfbits->value, dump_file);
-	  fprintf (dump_file, ", mask = ");
-	  print_hex (jfbits->mask, dump_file);
-	  fprintf (dump_file, "\n");
-	}
-    }
-}
-
-/* Look up all VR information that we have discovered and copy it over
-   to the transformation summary.  */
+/* Look up all VR and bits information that we have discovered and copy it
+   over to the transformation summary.  */
 
 static void
 ipcp_store_vr_results (void)
@@ -6613,7 +6543,10 @@  ipcp_store_vr_results (void)
   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
     {
       ipa_node_params *info = ipa_node_params_sum->get (node);
+      bool dumped_sth = false;
       bool found_useful_result = false;
+      bool do_vr = true;
+      bool do_bits = true;
 
       if (!info || !opt_for_fn (node->decl, flag_ipa_vrp))
 	{
@@ -6621,8 +6554,18 @@  ipcp_store_vr_results (void)
 	    fprintf (dump_file, "Not considering %s for VR discovery "
 		     "and propagate; -fipa-ipa-vrp: disabled.\n",
 		     node->dump_name ());
-	  continue;
+	  do_vr = false;
+	}
+      if (!info || !opt_for_fn (node->decl, flag_ipa_bit_cp))
+	{
+	  if (dump_file)
+	    fprintf (dump_file, "Not considering %s for ipa bitwise "
+				"propagation ; -fipa-bit-cp: disabled.\n",
+				node->dump_name ());
+	  do_bits = false;
 	}
+      if (!do_bits && !do_vr)
+	continue;
 
       if (info->ipcp_orig_node)
 	info = ipa_node_params_sum->get (info->ipcp_orig_node);
@@ -6634,12 +6577,18 @@  ipcp_store_vr_results (void)
       for (unsigned i = 0; i < count; i++)
 	{
 	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
-	  if (!plats->m_value_range.bottom_p ()
+	  if (do_vr
+	      && !plats->m_value_range.bottom_p ()
 	      && !plats->m_value_range.top_p ())
 	    {
 	      found_useful_result = true;
 	      break;
 	    }
+	  if (do_bits && plats->bits_lattice.constant_p ())
+	    {
+	      found_useful_result = true;
+	      break;
+	    }
 	}
       if (!found_useful_result)
 	continue;
@@ -6651,12 +6600,53 @@  ipcp_store_vr_results (void)
       for (unsigned i = 0; i < count; i++)
 	{
 	  ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
+	  ipcp_bits_lattice *bits = NULL;
+
+	  if (do_bits
+	      && plats->bits_lattice.constant_p ()
+	      && dbg_cnt (ipa_cp_bits))
+	    bits = &plats->bits_lattice;
 
-	  if (!plats->m_value_range.bottom_p ()
+	  if (do_vr
+	      && !plats->m_value_range.bottom_p ()
 	      && !plats->m_value_range.top_p ()
 	      && dbg_cnt (ipa_cp_vr))
 	    {
-	      ipa_vr vr (plats->m_value_range.m_vr);
+	      if (bits)
+		{
+		  Value_Range tmp = plats->m_value_range.m_vr;
+		  tree type = ipa_get_type (info, i);
+		  irange &r = as_a<irange> (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);
+		  ipa_vr vr (tmp);
+		  ts->m_vr->quick_push (vr);
+		}
+	      else
+		{
+		  ipa_vr vr (plats->m_value_range.m_vr);
+		  ts->m_vr->quick_push (vr);
+		}
+	    }
+	  else if (bits)
+	    {
+	      tree type = ipa_get_type (info, i);
+	      Value_Range tmp;
+	      tmp.set_varying (type);
+	      irange &r = as_a<irange> (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);
+	      ipa_vr vr (tmp);
 	      ts->m_vr->quick_push (vr);
 	    }
 	  else
@@ -6664,6 +6654,21 @@  ipcp_store_vr_results (void)
 	      ipa_vr vr;
 	      ts->m_vr->quick_push (vr);
 	    }
+
+	  if (!dump_file || !bits)
+	    continue;
+
+	  if (!dumped_sth)
+	    {
+	      fprintf (dump_file, "Propagated bits info for function %s:\n",
+		       node->dump_name ());
+	      dumped_sth = true;
+	    }
+	  fprintf (dump_file, " param %i: value = ", i);
+	  print_hex (bits->get_value (), dump_file);
+	  fprintf (dump_file, ", mask = ");
+	  print_hex (bits->get_mask (), dump_file);
+	  fprintf (dump_file, "\n");
 	}
     }
 }
@@ -6696,9 +6701,7 @@  ipcp_driver (void)
   ipcp_propagate_stage (&topo);
   /* Decide what constant propagation and cloning should be performed.  */
   ipcp_decision_stage (&topo);
-  /* Store results of bits propagation.  */
-  ipcp_store_bits_results ();
-  /* Store results of value range propagation.  */
+  /* Store results of value range and bits propagation.  */
   ipcp_store_vr_results ();
 
   /* Free all IPCP structures.  */
--- gcc/ipa-sra.cc.jj	2023-10-05 11:32:40.233739151 +0200
+++ gcc/ipa-sra.cc	2023-10-05 11:36:45.408378045 +0200
@@ -4134,22 +4134,8 @@  zap_useless_ipcp_results (const isra_fun
   else if (removed_item)
     ts->m_agg_values->truncate (dst_index);
 
-  bool useful_bits = false;
-  unsigned count = vec_safe_length (ts->bits);
-  for (unsigned i = 0; i < count; i++)
-    if ((*ts->bits)[i])
-    {
-      const isra_param_desc *desc = &(*ifs->m_parameters)[i];
-      if (desc->locally_unused)
-	(*ts->bits)[i] = NULL;
-      else
-	useful_bits = true;
-    }
-  if (!useful_bits)
-    ts->bits = NULL;
-
   bool useful_vr = false;
-  count = vec_safe_length (ts->m_vr);
+  unsigned count = vec_safe_length (ts->m_vr);
   for (unsigned i = 0; i < count; i++)
     if ((*ts->m_vr)[i].known_p ())
       {