aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-08-06 11:28:37 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-08-06 11:29:32 +0200
commitd175a6b119b8ab177ab9d9fb81dcac1794d18ad6 (patch)
tree6afa36165c29cd03b0b5a8d6a6e07a23c0e22c77 /gcc
parent4f2cd5a88838ce0af9f4d6425c55e702e44ae8d2 (diff)
downloadgcc-d175a6b119b8ab177ab9d9fb81dcac1794d18ad6.zip
gcc-d175a6b119b8ab177ab9d9fb81dcac1794d18ad6.tar.gz
gcc-d175a6b119b8ab177ab9d9fb81dcac1794d18ad6.tar.bz2
bitint: Fix up handling of uninitialized mul/div/float cast operands [PR121127]
handle_operand_addr (used for the cases where we use libgcc APIs, so multiplication, division, modulo, casts of _BitInt to float/dfp) when it sees default definition of an SSA_NAME which is not PARM_DECL (i.e. uninitialized one) just allocates single uninitialized limb, there is no need to waste more memory on it, it can just tell libgcc that it has 64-bit precision, not say 1024 bit etc. Unfortunately, doing this runs into some asserts when we have a narrowing cast of the uninitialized SSA_NAME (but still large/huge _BitInt). The following patch fixes that by using a magic value in *prec_stored for the uninitialized cases (0) and just don't do any *prec tweaks for narrowing casts from that. precs still needs to be maintained as before, that one is used for big endian adjustment. 2025-08-06 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/121127 * gimple-lower-bitint.cc (bitint_large_huge::handle_operand_addr): For uninitialized SSA_NAME, set *prec_stored to 0 rather than *prec. Handle that case in narrowing casts. If prec_stored is non-NULL, set *prec_stored to prec_stored_val. * gcc.dg/bitint-125.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-lower-bitint.cc15
-rw-r--r--gcc/testsuite/gcc.dg/bitint-125.c15
2 files changed, 27 insertions, 3 deletions
diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc
index 8fb7a60..ff5b12c 100644
--- a/gcc/gimple-lower-bitint.cc
+++ b/gcc/gimple-lower-bitint.cc
@@ -2373,7 +2373,7 @@ range_to_prec (tree op, gimple *stmt)
from that precision, if it is negative, the operand is sign-extended
from -*PREC. If PREC_STORED is NULL, it is the toplevel call,
otherwise *PREC_STORED is prec from the innermost call without
- range optimizations. */
+ range optimizations (0 for uninitialized SSA_NAME). */
tree
bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
@@ -2481,7 +2481,7 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
*prec = TYPE_UNSIGNED (TREE_TYPE (op)) ? limb_prec : -limb_prec;
precs = *prec;
if (prec_stored)
- *prec_stored = precs;
+ *prec_stored = 0;
tree var = create_tmp_var (m_limb_type);
TREE_ADDRESSABLE (var) = 1;
ret = build_fold_addr_expr (var);
@@ -2510,6 +2510,13 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
int prec_stored_val = 0;
ret = handle_operand_addr (rhs1, g, &prec_stored_val, prec);
precs = prec_stored_val;
+ if (prec_stored)
+ *prec_stored = prec_stored_val;
+ if (precs == 0)
+ {
+ gcc_assert (*prec == limb_prec || *prec == -limb_prec);
+ precs = *prec;
+ }
if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (rhs_type))
{
if (TYPE_UNSIGNED (lhs_type)
@@ -2518,7 +2525,9 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
}
else
{
- if (*prec > 0 && *prec < TYPE_PRECISION (lhs_type))
+ if (prec_stored_val == 0)
+ /* Non-widening cast of uninitialized value. */;
+ else if (*prec > 0 && *prec < TYPE_PRECISION (lhs_type))
;
else if (TYPE_UNSIGNED (lhs_type))
{
diff --git a/gcc/testsuite/gcc.dg/bitint-125.c b/gcc/testsuite/gcc.dg/bitint-125.c
new file mode 100644
index 0000000..5ef0e32
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-125.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/121127 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2 -w" } */
+
+#if __BITINT_MAXWIDTH__ >= 576
+_BitInt(575)
+foo (void)
+{
+ _BitInt(576) d;
+ _BitInt(575) e = d * 42wb;
+ return e;
+}
+#else
+int i;
+#endif