> Am 16.03.2024 um 08:11 schrieb Jakub Jelinek <ja...@redhat.com>:
> 
> Hi!
> 
> The verifier requires BIT_FIELD_REFs with INTEGRAL_TYPE_P first operand
> to have mode precision.  In most cases for the large/huge _BitInt bitfield
> stores the code uses bitfield representatives, which are typically arrays
> of chars, but if the bitfield starts at byte boundary on big endian,
> the code uses as nlhs in lower_mergeable_store COMPONENT_REF of the
> bitfield FIELD_DECL instead, which is fine for the limb accesses,
> but when used for the most significant limb can result in invalid
> BIT_FIELD_REF because the first operand then has BITINT_TYPE and
> usually VOIDmode.
> 
> The following patch adds a helper method for the 4 creatikons of
> BIT_FIELD_REF which when needed adds a VIEW_CONVERT_EXPR.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Richard 

> 2024-03-16  Jakub Jelinek  <ja...@redhat.com>
> 
>    PR tree-optimization/114329
>    * gimple-lower-bitint.cc (struct bitint_large_huge): Declare
>    build_bit_field_ref method.
>    (bitint_large_huge::build_bit_field_ref): New method.
>    (bitint_large_huge::lower_mergeable_stmt): Use it.
> 
>    * gcc.dg/bitint-101.c: New test.
> 
> --- gcc/gimple-lower-bitint.cc.jj    2024-03-15 09:16:36.464033118 +0100
> +++ gcc/gimple-lower-bitint.cc    2024-03-15 17:53:30.200276578 +0100
> @@ -427,6 +427,8 @@ struct bitint_large_huge
>   void insert_before (gimple *);
>   tree limb_access_type (tree, tree);
>   tree limb_access (tree, tree, tree, bool);
> +  tree build_bit_field_ref (tree, tree, unsigned HOST_WIDE_INT,
> +                unsigned HOST_WIDE_INT);
>   void if_then (gimple *, profile_probability, edge &, edge &);
>   void if_then_else (gimple *, profile_probability, edge &, edge &);
>   void if_then_if_then_else (gimple *g, gimple *,
> @@ -659,6 +661,31 @@ bitint_large_huge::limb_access (tree typ
>   return ret;
> }
> 
> +/* Build a BIT_FIELD_REF to access BITSIZE bits with FTYPE type at
> +   offset BITPOS inside of OBJ.  */
> +
> +tree
> +bitint_large_huge::build_bit_field_ref (tree ftype, tree obj,
> +                    unsigned HOST_WIDE_INT bitsize,
> +                    unsigned HOST_WIDE_INT bitpos)
> +{
> +  if (INTEGRAL_TYPE_P (TREE_TYPE (obj))
> +      && !type_has_mode_precision_p (TREE_TYPE (obj)))
> +    {
> +      unsigned HOST_WIDE_INT nelts
> +    = CEIL (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (obj))), limb_prec);
> +      tree ltype = m_limb_type;
> +      addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (obj));
> +      if (as != TYPE_ADDR_SPACE (ltype))
> +    ltype = build_qualified_type (ltype, TYPE_QUALS (ltype)
> +                      | ENCODE_QUAL_ADDR_SPACE (as));
> +      tree atype = build_array_type_nelts (ltype, nelts);
> +      obj = build1 (VIEW_CONVERT_EXPR, atype, obj);
> +    }
> +  return build3 (BIT_FIELD_REF, ftype, obj, bitsize_int (bitsize),
> +         bitsize_int (bitpos));
> +}
> +
> /* Emit a half diamond,
>    if (COND)
>      |\
> @@ -2651,9 +2678,9 @@ bitint_large_huge::lower_mergeable_stmt
>            }
>          tree ftype
>            = build_nonstandard_integer_type (limb_prec - bo_bit, 1);
> -          tree bfr = build3 (BIT_FIELD_REF, ftype, unshare_expr (nlhs),
> -                     bitsize_int (limb_prec - bo_bit),
> -                     bitsize_int (bo_idx * limb_prec + bo_bit));
> +          tree bfr = build_bit_field_ref (ftype, unshare_expr (nlhs),
> +                          limb_prec - bo_bit,
> +                          bo_idx * limb_prec + bo_bit);
>          tree t = add_cast (ftype, rhs1);
>          g = gimple_build_assign (bfr, t);
>          insert_before (g);
> @@ -2714,12 +2741,11 @@ bitint_large_huge::lower_mergeable_stmt
>            {
>              tree ftype
>            = build_nonstandard_integer_type (rprec + bo_bit, 1);
> -              tree bfr = build3 (BIT_FIELD_REF, ftype,
> -                     unshare_expr (nlhs),
> -                     bitsize_int (rprec + bo_bit),
> -                     bitsize_int ((bo_idx
> -                               + tprec / limb_prec)
> -                              * limb_prec));
> +              tree bfr
> +            = build_bit_field_ref (ftype, unshare_expr (nlhs),
> +                           rprec + bo_bit,
> +                           (bo_idx + tprec / limb_prec)
> +                           * limb_prec);
>              tree t = add_cast (ftype, rhs1);
>              g = gimple_build_assign (bfr, t);
>              done = true;
> @@ -2860,11 +2886,11 @@ bitint_large_huge::lower_mergeable_stmt
>        {
>          tree ftype
>            = build_nonstandard_integer_type (rprec + bo_bit, 1);
> -          tree bfr = build3 (BIT_FIELD_REF, ftype,
> -                     unshare_expr (nlhs),
> -                     bitsize_int (rprec + bo_bit),
> -                     bitsize_int ((bo_idx + tprec / limb_prec)
> -                          * limb_prec));
> +          tree bfr
> +            = build_bit_field_ref (ftype, unshare_expr (nlhs),
> +                       rprec + bo_bit,
> +                       (bo_idx + tprec / limb_prec)
> +                       * limb_prec);
>          tree t = add_cast (ftype, rhs1);
>          g = gimple_build_assign (bfr, t);
>          done = true;
> @@ -2909,10 +2935,10 @@ bitint_large_huge::lower_mergeable_stmt
>       unsigned int tprec = TYPE_PRECISION (type);
>       unsigned int rprec = tprec % limb_prec;
>       tree ftype = build_nonstandard_integer_type (rprec + bo_bit, 1);
> -      tree bfr = build3 (BIT_FIELD_REF, ftype, unshare_expr (nlhs),
> -             bitsize_int (rprec + bo_bit),
> -             bitsize_int ((bo_idx + tprec / limb_prec)
> -                      * limb_prec));
> +      tree bfr = build_bit_field_ref (ftype, unshare_expr (nlhs),
> +                      rprec + bo_bit,
> +                      (bo_idx + tprec / limb_prec)
> +                      * limb_prec);
>       rhs1 = bf_cur;
>       if (bf_cur != ext)
>    {
> --- gcc/testsuite/gcc.dg/bitint-101.c.jj    2024-03-15 18:59:01.386413294 
> +0100
> +++ gcc/testsuite/gcc.dg/bitint-101.c    2024-03-15 18:58:14.063059994 +0100
> @@ -0,0 +1,17 @@
> +/* PR tree-optimization/114329 */
> +/* { dg-do compile { target bitint } } */
> +/* { dg-options "-std=c23" } */
> +
> +#if __BITINT_MAXWIDTH__ >= 129
> +#define N 129
> +#else
> +#define N 63
> +#endif
> +
> +struct S { _BitInt(N) b : N; } s;
> +
> +void
> +foo (void)
> +{
> +  s.b ^= 42;
> +}
> 
>    Jakub
> 

Reply via email to