From: Jakub Jelinek Date: Fri, 12 Jan 2024 16:11:49 +0000 (+0100) Subject: c: Avoid _BitInt indexes > sizetype in ARRAY_REFs [PR113315] X-Git-Tag: basepoints/gcc-15~2939 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=95440171d0e615b0a1aa6863e41ba30df86ac3f4;p=thirdparty%2Fgcc.git c: Avoid _BitInt indexes > sizetype in ARRAY_REFs [PR113315] When build_array_ref doesn't use ARRAY_REF, it casts the index to sizetype already, performs POINTER_PLUS_EXPR and then dereferences. While when emitting ARRAY_REF, we try to keep index expression as is in whatever type it had, which is reasonable e.g. for signed or unsigned types narrower than sizetype for loop optimizations etc. But if the index is wider than sizetype, we are unnecessarily computing bits beyond what is needed. For {,unsigned }__int128 on 64-bit arches or {,unsigned }long long on 32-bit arches we've been doing that for decades, so the following patch doesn't propose to change that (might be stage1 material), but for _BitInt at least the _BitInt lowering code doesn't expect to see large/huge _BitInt in the ARRAY_REF indexes, I was expecting one would see just casts of those to sizetype. So, the following patch makes sure that large/huge _BitInt indexes don't appear in ARRAY_REFs. 2024-01-12 Jakub Jelinek PR c/113315 * c-typeck.cc (build_array_ref): If index has BITINT_TYPE type with precision larger than sizetype precision, convert it to sizetype. * gcc.dg/bitint-65.c: New test. * gcc.dg/bitint-66.c: New test. --- diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 774dc1b3e6b4..66c6abc9f076 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2868,6 +2868,10 @@ build_array_ref (location_t loc, tree array, tree index) "array"); } + if (TREE_CODE (TREE_TYPE (index)) == BITINT_TYPE + && TYPE_PRECISION (TREE_TYPE (index)) > TYPE_PRECISION (sizetype)) + index = fold_convert (sizetype, index); + type = TREE_TYPE (TREE_TYPE (array)); rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are diff --git a/gcc/testsuite/gcc.dg/bitint-65.c b/gcc/testsuite/gcc.dg/bitint-65.c new file mode 100644 index 000000000000..f0b952047e87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-65.c @@ -0,0 +1,23 @@ +/* PR c/113315 */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-std=c23" } */ + +#if __BITINT_MAXWIDTH__ >= 535 +_BitInt(535) x; +#else +_BitInt(64) x; +#endif +extern int a[]; +extern char b[][10]; + +int +foo (void) +{ + return a[x]; +} + +int +bar (void) +{ + return __builtin_strlen (b[x]); +} diff --git a/gcc/testsuite/gcc.dg/bitint-66.c b/gcc/testsuite/gcc.dg/bitint-66.c new file mode 100644 index 000000000000..7bffa1285986 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-66.c @@ -0,0 +1,12 @@ +/* PR c/113315 */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-std=c23 -O2" } */ + +extern int a[5]; + +int +foo (void) +{ + _BitInt(535) i = 1; + return a[i]; +}