https://gcc.gnu.org/g:5a4f77eb6afffb16fae3effe9965dc8b216c84ce

commit r17-5409-g5a4f77eb6afffb16fae3effe9965dc8b216c84ce
Author: Richard Biener <[email protected]>
Date:   Tue Oct 20 12:14:31 2026 +0200

    lto/127922 - TBAA and unsigned vs. signed _BitInt
    
    With LTO we fail to ensure signed and unsigned _BitInt of the same
    precision get the same alias set.  Without LTO this is ensured
    by c_common_get_alias_set which uses the other signedness variants
    alias-set.  With LTO this is complicated by streaming not populating
    the bitint_type_cache so a similar approach cannot work.  The
    following instead handles this during canonical type merging.
    I have still fixed gimple_signed_or_unsigned_type to support _BitInt
    and amended gimple_get_alias_set with a comment.
    
            PR lto/127922
            * tree.cc (type_with_interoperable_signedness): Return true
            for BITINT_TYPE.
            * gimple.cc (gimple_signed_or_unsigned_type): Properly
            handle BITINT_TYPE.
            (gimple_get_alias_set): Add comment about signed/unsigned
            BITINT_TYPE.
    
            * gcc.dg/lto/bitint-lto-1_0.c: New testcase.

Diff:
---
 gcc/gimple.cc                             |  6 +++++-
 gcc/testsuite/gcc.dg/lto/bitint-lto-1_0.c | 22 ++++++++++++++++++++++
 gcc/tree.cc                               | 14 ++++++++++----
 3 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index 3b68902b6109..2295f353472b 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -2807,6 +2807,9 @@ gimple_signed_or_unsigned_type (bool unsignedp, tree type)
       || TYPE_UNSIGNED (type) == unsignedp)
     return type;
 
+  if (BITINT_TYPE_P (type))
+    return build_bitint_type (TYPE_PRECISION (type), unsignedp);
+
 #define TYPE_OK(node)                                                      \
   (TYPE_MODE (type) == TYPE_MODE (node)                                        
    \
    && TYPE_PRECISION (type) == TYPE_PRECISION (node))
@@ -2891,7 +2894,8 @@ gimple_get_alias_set (tree t)
     return 0;
 
   /* Allow aliasing between signed and unsigned variants of the same
-     type.  We treat the signed variant as canonical.  */
+     type.  We treat the signed variant as canonical.  BITINT_TYPEs
+     are handled by canonical type merging.  */
   if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
     {
       tree t1 = gimple_signed_type (t);
diff --git a/gcc/testsuite/gcc.dg/lto/bitint-lto-1_0.c 
b/gcc/testsuite/gcc.dg/lto/bitint-lto-1_0.c
new file mode 100644
index 000000000000..c73c79f3ad69
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/bitint-lto-1_0.c
@@ -0,0 +1,22 @@
+/* PR/127922 */
+/* { dg-lto-do run } */
+/* { dg-require-effective-target bitint } */
+
+typedef _BitInt(17) S;
+typedef unsigned _BitInt(17) U;
+
+__attribute__((noipa)) S
+f(S *p, U *q)
+{
+  *p = 1;
+  *q = 2;
+  return *p;
+}
+
+int main()
+{
+  S x = 0;
+  S result = f(&x, (U *)&x);
+  if (result != 2)
+    __builtin_abort ();
+}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 63edf1959ce2..e43a2b78c61c 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -14211,10 +14211,16 @@ type_with_interoperable_signedness (const_tree type)
      signed char and unsigned char.  Similarly fortran FE builds
      C_SIZE_T as signed type, while C defines it unsigned.  */
 
-  return tree_code_for_canonical_type_merging (TREE_CODE (type))
-          == INTEGER_TYPE
-         && (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)
-            || TYPE_PRECISION (type) == TYPE_PRECISION (size_type_node));
+  if (tree_code_for_canonical_type_merging (TREE_CODE (type)) == INTEGER_TYPE)
+    return (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)
+           || TYPE_PRECISION (type) == TYPE_PRECISION (size_type_node));
+
+  /* The C standard allows aliasing between signed and unsigned variants
+     of the same type.  For INTEGER_TYPEs gimple_get_alias_set handles
+     this and this works because the integer type cache is pre-loaded
+     during streaming.  We do not do this for bitint_type_cache, so handle
+     the aliasing via assigning the same canonical type.  */
+  return TREE_CODE (type) == BITINT_TYPE;
 }
 
 /* Return true iff T1 and T2 are structurally identical for what

Reply via email to