diff options
author | Yang Yujie <yangyujie@loongson.cn> | 2025-08-06 12:04:51 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-08-06 12:04:51 +0200 |
commit | ed1ee2311721124c53070f9fdb15071664b6da65 (patch) | |
tree | 38924cd41fcb7ce5a6beb4746674038040c91e0d | |
parent | 94d2bc6d08caad947a8897a538f2a9b64e16a11a (diff) | |
download | gcc-ed1ee2311721124c53070f9fdb15071664b6da65.zip gcc-ed1ee2311721124c53070f9fdb15071664b6da65.tar.gz gcc-ed1ee2311721124c53070f9fdb15071664b6da65.tar.bz2 |
bitint: Do not optimize away conversion to _BitInt before a VCE
A _BitInt value may rely on a conversion to become properly extended.
So a conversion to _BitInt is not trivially removable even if the
types of the result and the operand have the same precision and size.
This patch fixes gcc.dg/torture/bitint-64.c at -O2 on LoongArch,
which fails because extension of the result is dropped in a
compare-and-swap loop generated for incrementing an _Atomic _BitInt,
causing an ABI violation.
* match.pd: Preserve conversion to _BitInt before a VCE
if the _BitInt is extended.
* gcc.dg/torture/bitint-84.c: New test.
-rw-r--r-- | gcc/match.pd | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/bitint-84.c | 18 |
2 files changed, 35 insertions, 2 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 82e6e29..06a4a91 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5508,16 +5508,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (convert @0))) /* Strip inner integral conversions that do not change precision or size, or - zero-extend while keeping the same size (for bool-to-char). */ + zero-extend while keeping the same size (for bool-to-char). + However, keep this conversion if the result is an extended _BitInt, + since it may rely on this conversion to extend properly. */ + (simplify (view_convert (convert@0 @1)) + (with { + bool extended_bitint = false; + if (BITINT_TYPE_P (TREE_TYPE (@0))) + { + struct bitint_info info; + extended_bitint + = targetm.c.bitint_type_info (TYPE_PRECISION (TREE_TYPE (@0)), + &info); + extended_bitint = extended_bitint && info.extended; + } + } (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) && (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1))) + && !extended_bitint && TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1)) && (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)) || (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@1)) && TYPE_UNSIGNED (TREE_TYPE (@1))))) - (view_convert @1))) + (view_convert @1)))) /* Simplify a view-converted empty or single-element constructor. */ (simplify diff --git a/gcc/testsuite/gcc.dg/torture/bitint-84.c b/gcc/testsuite/gcc.dg/torture/bitint-84.c new file mode 100644 index 0000000..b3ecbef --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bitint-84.c @@ -0,0 +1,18 @@ +/* A simple variant of gcc.dg/torture/bitint-64.c */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c23" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#include "../bitintext.h" + +enum E : char { E22 = 22 } e = E22; + +int +main () +{ + _Atomic _BitInt (5) b = 0; + b += e; + BEXTC (b); + return 0; +} |