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); + 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); + bitint_extended_p = info.extended; + } + + if (bitint_extended_p) + p2 = fold_convert_loc (loc, I_type, + build2_loc (loc, MEM_REF, TREE_TYPE (p2type), + p2, build_zero_cst (p2type))); + /* Otherwise, the padding bits might not be preserved, as stated above. */ + else + p2 = build2_loc (loc, MEM_REF, I_type, + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2), + build_zero_cst (p2type)); + (*params)[2] = p2; /* The rest of the parameters are fine. NULL means no special return value -- 2.46.0