On Thu, Jun 19, 2025 at 05:59:06PM +0800, Yang Yujie wrote:
> For targets that have extended bitints, we need to ensure these
> are extended before writing to the memory, including via atomic
> exchange.
> 
> gcc/c-family/ChangeLog:
> 
>       * c-common.cc (resolve_overloaded_atomic_exchange): Extend
>       _BitInts before atomic exchange if needed.
>       (resolve_overloaded_atomic_compare_exchange): Same.
> ---
>  gcc/c-family/c-common.cc | 63 +++++++++++++++++++++++++++++++++++-----
>  1 file changed, 55 insertions(+), 8 deletions(-)
> 
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index f71cb2652d5..962e9d2a639 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -8059,11 +8059,35 @@ resolve_overloaded_atomic_exchange (location_t loc, 
> tree function,
>    /* Convert new value to required type, and dereference it.
>       If *p1 type can have padding or may involve floating point which
>       could e.g. be promoted to wider precision and demoted afterwards,
> -     state of padding bits might not be preserved.  */
> +     state of padding bits might not be preserved.
> +
> +     However, as a special case, we still want to preserve the padding
> +     bits of _BitInt values if the ABI requires them to be extended in
> +     memory.  */
> +
>    build_indirect_ref (loc, p1, RO_UNARY_STAR);
> -  p1 = build2_loc (loc, MEM_REF, I_type,
> -                build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1),
> -                build_zero_cst (TREE_TYPE (p1)));
> +
> +  tree p1type = TREE_TYPE (p1);
> +  bool bitint_extended_p = false;
> +  if (TREE_CODE (TREE_TYPE (p1type)) == BITINT_TYPE)
> +    {
> +      struct bitint_info info;
> +      unsigned prec = TYPE_PRECISION (TREE_TYPE (p1type));
> +      targetm.c.bitint_type_info (prec, &info);

I'd like to replace this line with
      bool ok = targetm.c.bitint_type_info (prec, &info);
      gcc_assert (ok);

> +      bitint_extended_p = info.extended;
> +    }
> +
> +  if (bitint_extended_p)
> +    p1 = fold_convert_loc (loc, I_type,
> +                        build2_loc (loc, MEM_REF, TREE_TYPE (p1type),
> +                                    p1, build_zero_cst (p1type)));
> +  /* Otherwise, the padding bits might not be preserved, as stated above.  */
> +  else
> +    p1 = build2_loc (loc, MEM_REF, I_type,
> +                  build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1),
> +                  build_zero_cst (p1type));
> +
> +
>    (*params)[1] = p1;
>  
>    /* Move memory model to the 3rd position, and end param list.  */
> @@ -8143,11 +8167,34 @@ resolve_overloaded_atomic_compare_exchange 
> (location_t loc, tree function,
>    /* Convert desired value to required type, and dereference it.
>       If *p2 type can have padding or may involve floating point which
>       could e.g. be promoted to wider precision and demoted afterwards,
> -     state of padding bits might not be preserved.  */
> +     state of padding bits might not be preserved.
> +
> +     However, as a special case, we still want to preserve the padding
> +     bits of _BitInt values if the ABI requires them to be extended in
> +     memory.  */
> +
>    build_indirect_ref (loc, p2, RO_UNARY_STAR);
> -  p2 = build2_loc (loc, MEM_REF, I_type,
> -                build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2),
> -                build_zero_cst (TREE_TYPE (p2)));
> +
> +  tree p2type = TREE_TYPE (p2);
> +  bool bitint_extended_p = false;
> +  if (TREE_CODE (TREE_TYPE (p2type)) == BITINT_TYPE)
> +    {
> +      struct bitint_info info;
> +      unsigned prec = TYPE_PRECISION (TREE_TYPE (p2type));
> +      targetm.c.bitint_type_info (prec, &info);

And here as well.

Plus there should be a testcase for both of those cases, using the
bitintext.h infrastructure like in gcc.dg/torture/bitint-82.c
that FAILs without this patch and succeeds with it.

        Jakub

Reply via email to