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.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
OK?
Thanks,
Richard.
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.
---
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(-)
create mode 100644 gcc/testsuite/gcc.dg/lto/bitint-lto-1_0.c
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index 44fc8df46e4..45e7d8ad7c6 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -2839,6 +2839,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))
@@ -2923,7 +2926,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 00000000000..c73c79f3ad6
--- /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 63edf1959ce..e43a2b78c61 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
--
2.51.0