Bug 115767 - [13/14/15/16/17 regression] GCC loses track of value on aarch64 with -O2 since r11-3308-gd119f34c952f87
Summary: [13/14/15/16/17 regression] GCC loses track of value on aarch64 with -O2 sinc...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: ipa (show other bugs)
Version: 15.0
: P2 normal
Target Milestone: 13.5
Assignee: Not yet assigned to anyone
URL:
Keywords: needs-reduction, wrong-code
Depends on:
Blocks: modref
  Show dependency treegraph
 
Reported: 2024-07-03 10:07 UTC by Ignacy Gawędzki
Modified: 2026-04-22 14:36 UTC (History)
8 users (show)

See Also:
Host:
Target: aarch64 x86_64
Build:
Known to work: 10.5.0
Known to fail: 11.5.0, 15.0
Last reconfirmed: 2026-03-03 00:00:00


Attachments
The preprocessed source file. (397.37 KB, application/gzip)
2024-07-03 10:09 UTC, Ignacy Gawędzki
Details
First step, remove some unused code (152.32 KB, application/x-xz)
2025-01-01 01:04 UTC, Drea Pinski
Details
Checkpoint (44.72 KB, application/x-xz)
2025-01-01 07:15 UTC, Drea Pinski
Details
checkpoint2 (22.60 KB, application/x-xz)
2025-01-01 17:06 UTC, Drea Pinski
Details
Checkpoint3 (18.63 KB, text/plain)
2025-01-01 21:54 UTC, Drea Pinski
Details
checkpoint4 (16.88 KB, text/plain)
2025-01-01 23:37 UTC, Drea Pinski
Details
27k bytes reduced testcase (5.02 KB, text/plain)
2025-04-16 19:54 UTC, mcccs
Details
minimized.cpp (459 bytes, text/plain)
2025-04-19 20:28 UTC, mcccs
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ignacy Gawędzki 2024-07-03 10:07:24 UTC
I've stumbled upon what looks like a compiler bug with the following code, compiled for aarch64:

#include <cassert>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>

int main()
{
  using map_type = boost::bimap<boost::bimaps::set_of<int>,
				boost::bimaps::unordered_set_of<int>>;
  map_type	map;
  auto	x = map.insert({0, 0}).first;
  map.replace_right(x, 42);
  auto	y = map.find(map_type::value_type{0, 42});
  assert(y != map.end());
  assert(x == y);
  assert(&x->right == &y->right);
  assert(y->right != 0);
  assert(x->right != 0);
}

The last assert fails with -O2.  I've managed to track the optimization flags down to -O1 -fcode-hoisting -fipa-sra -fstrict-aliasing .

In the .s, it looks like x is kept in register x19 while x->right is kept in w23, but after the call to replace_right, w23 is not updated using x19 and thus holds the old value (0).

I've tested that with GCC master (e9fb6efa1cf542353fd44ddcbb5136344c463fd0) and Boost/bimap master (6865e94cc56a33bb8b162bf8d62cfe620b06d2b6), cross-compiled with GCC 13.2.0-23ubuntu4 for aarch64 using Buildroot 2024.02.1 with the following configure flags:

Using built-in specs.
COLLECT_AS_OPTIONS='--version'
COLLECT_GCC=[...]/host/bin/aarch64-linux-g++.br_real
COLLECT_LTO_WRAPPER=[...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/lto-wrapper
aarch64-linux-g++.br_real (Buildroot 2024.02.1-6309-g2fd20014a8) 15.0.0 20240703 (experimental)
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Target: aarch64-buildroot-linux-musl
Configured with: ./configure --prefix=[...]/host --sysconfdir=[...]/host/etc --enable-static --target=aarch64-buildroot-linux-musl --with-sysroot=[...]/host/aarch64-buildroot-linux-musl/sysroot --enable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --disable-decimal-float --enable-plugins --enable-lto --with-gmp=[...]/host --with-mpc=[...]/host --with-mpfr=[...]/host --with-pkgversion='Buildroot 2024.02.1-6309-g2fd20014a8' --with-bugurl=http://bugs.buildroot.net/ --without-zstd --with-debug-prefix-map=[...]=buildroot --disable-libmpx --disable-libquadmath --disable-libquadmath-support --disable-libsanitizer --enable-tls --enable-threads --without-isl --without-cloog --with-abi=lp64 --with-cpu=cortex-a53 --enable-languages=c,c++ --with-build-time-tools=[...]/host/aarch64-buildroot-linux-musl/bin --enable-shared --disable-libgomp
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 15.0.0 20240703 (experimental) (Buildroot 2024.02.1-6309-g2fd20014a8) 
COMPILER_PATH=[...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/:[...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/:[...]/host/libexec/gcc/aarch64-buildroot-linux-musl/:[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/:[...]/host/lib/gcc/aarch64-buildroot-linux-musl/:[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/bin/
LIBRARY_PATH=[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/:[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/lib/../lib64/:[...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/:[...]/host/aarch64-buildroot-linux-musl/sysroot/usr/lib/../lib64/:[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/lib/:[...]/host/aarch64-buildroot-linux-musl/sysroot/lib/:[...]/host/aarch64-buildroot-linux-musl/sysroot/usr/lib/
COLLECT_GCC_OPTIONS='--sysroot=[...]/host/aarch64-buildroot-linux-musl/sysroot' '-fstack-protector-strong' '-ffile-prefix-map=[...]=buildroot' '-fPIE' '-pie' '--version' '-v' '-shared-libgcc' '-mcpu=cortex-a53' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a.'
 [...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/collect2 -plugin [...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/liblto_plugin.so -plugin-opt=[...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccP2tEjt.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=[...]/host/aarch64-buildroot-linux-musl/sysroot --eh-frame-hdr -dynamic-linker /lib/ld-musl-aarch64.so.1 -X -EL -maarch64linux -pie --version [...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/Scrt1.o [...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/crti.o [...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/crtbeginS.o -L[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0 -L[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/lib/../lib64 -L[...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64 -L[...]/host/aarch64-buildroot-linux-musl/sysroot/usr/lib/../lib64 -L[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/lib -L[...]/host/aarch64-buildroot-linux-musl/sysroot/lib -L[...]/host/aarch64-buildroot-linux-musl/sysroot/usr/lib -z max-page-size=4096 -z common-page-size=4096 --build-id=none -z relro -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc [...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/crtendS.o [...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/crtn.o
collect2 version 15.0.0 20240703 (experimental)
[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/bin/ld -plugin [...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/liblto_plugin.so -plugin-opt=[...]/host/libexec/gcc/aarch64-buildroot-linux-musl/15.0.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccP2tEjt.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=[...]/host/aarch64-buildroot-linux-musl/sysroot --eh-frame-hdr -dynamic-linker /lib/ld-musl-aarch64.so.1 -X -EL -maarch64linux -pie --version [...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/Scrt1.o [...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/crti.o [...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/crtbeginS.o -L[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0 -L[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/lib/../lib64 -L[...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64 -L[...]/host/aarch64-buildroot-linux-musl/sysroot/usr/lib/../lib64 -L[...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/../../../../aarch64-buildroot-linux-musl/lib -L[...]/host/aarch64-buildroot-linux-musl/sysroot/lib -L[...]/host/aarch64-buildroot-linux-musl/sysroot/usr/lib -z max-page-size=4096 -z common-page-size=4096 --build-id=none -z relro -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc [...]/host/lib/gcc/aarch64-buildroot-linux-musl/15.0.0/crtendS.o [...]/host/aarch64-buildroot-linux-musl/sysroot/lib/../lib64/crtn.o
GNU ld (GNU Binutils) 2.40
Copyright (C) 2023 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
COLLECT_GCC_OPTIONS='--sysroot=[...]/host/aarch64-buildroot-linux-musl/sysroot' '-fstack-protector-strong' '-ffile-prefix-map=[...]=buildroot' '-fPIE' '-pie' '--version' '-v' '-shared-libgcc' '-mcpu=cortex-a53' '-mlittle-endian' '-mabi=lp64' '-dumpdir' 'a.'
Comment 1 Ignacy Gawędzki 2024-07-03 10:09:32 UTC
Created attachment 58581 [details]
The preprocessed source file.
Comment 2 Sam James 2024-07-04 03:39:46 UTC
On amd64, it starts to fail with 11.
Comment 3 Ignacy Gawędzki 2024-07-04 04:41:34 UTC
(In reply to Sam James from comment #2)
> On amd64, it starts to fail with 11.

Oh yes, indeed.  I've overlooked that fact.
Comment 4 Xi Ruoyao 2024-07-04 05:02:26 UTC
Note that -fno-strict-aliasing helps and in the boost code path for replace_right there's:

return *reinterpret_cast< const View* >(boost::addressof(m));

But maybe this line is innocent and -fno-strict-aliasing just happens to hide the issue somehow OTOH.
Comment 5 Ignacy Gawędzki 2024-07-04 09:52:26 UTC
FWIW, I ran a git bisect from releases/gcc-10.5.0 to releases/gcc-11.1.0 and the first bad commit is d119f34c952f8718fdbabc63e2f369a16e92fa07, which adds modref/ipa_modref optimization passes.
Comment 6 Richard Biener 2024-07-04 13:21:04 UTC
There are some open IPA modref issues, thanks for bisecting.  I hope Honza will look at this and the others.
Comment 7 Richard Biener 2024-07-19 13:26:06 UTC
GCC 11 branch is being closed.
Comment 8 Sam James 2024-07-20 04:05:58 UTC
While we wait for Honza, Ignacy, if you could try reduce it to get rid of the Boost dependency, it'd be appreciated.

You can cvise for runtime testcases, just add several checks with different compilers and UBSAN and friends.
Comment 9 Ignacy Gawędzki 2024-07-24 17:18:33 UTC
(In reply to Sam James from comment #8)
> While we wait for Honza, Ignacy, if you could try reduce it to get rid of
> the Boost dependency, it'd be appreciated.

I'm struggling to get a minimal example.  I found what looks like a bug in Boost Bimap along the way, but it makes the problem go away only on x86_64, not on aarch64.

I tried to find strict aliasing violations in the code by disabling ipa-modref on smaller and smaller parts of the execution path (using a function attribute), while checking that the problem goes away.  All I ended up with was a method so simple that I can tell for sure it doesn't violate anything, and still, removing the attribute on it makes the problem appear.  I believe the appearance of the problem is sensitive to even slight changes in register allocation, which makes finding a minimal example a very difficult task.

> You can cvise for runtime testcases, just add several checks with different
> compilers and UBSAN and friends.

I tried to run cvise on the preprocessed code with no success at all.  All the resulting code I got after hours of processing was either trivially useless (as it did not reproduce the problem), or did not compile at all.  I suppose my lack of experience with this tool is to blame.
Comment 10 Sam James 2024-07-25 12:07:22 UTC
Could you try trunk or the 14.2 RC1? A bunch of IPA fixes landed.
Comment 11 Ignacy Gawędzki 2024-08-05 11:17:02 UTC
(In reply to Sam James from comment #10)
> Could you try trunk or the 14.2 RC1? A bunch of IPA fixes landed.

I tested with 162a1ed70303a031c81b0aaac499aaf394560390 and the problem is still there with vanilla Boost Bimap, but apparently goes away with my patch (https://github.com/boostorg/bimap/pull/45).

I then ran a bisect and found that the first commit that makes the problem disappear on aarch64 with the patched Boost Bimap is 03a810da10d8dfb5aec9261372cad7bf090e6986.

The commit message doesn't look like it is related to ipa-modref, but maybe I simply have no clue or this is just a coincidence.  It is hard for me to tell for sure.
Comment 12 Sam James 2024-09-21 00:23:48 UTC
(In reply to Ignacy Gawędzki from comment #11)
> I then ran a bisect and found that the first commit that makes the problem
> disappear on aarch64 with the patched Boost Bimap is
> 03a810da10d8dfb5aec9261372cad7bf090e6986.

I wouldn't expect it to.
Comment 13 Drea Pinski 2024-12-31 23:32:10 UTC
I am going to try to reduce this.
Comment 14 Drea Pinski 2025-01-01 01:04:40 UTC
Created attachment 60024 [details]
First step, remove some unused code
Comment 15 Drea Pinski 2025-01-01 07:15:39 UTC
Created attachment 60025 [details]
Checkpoint
Comment 16 Drea Pinski 2025-01-01 17:06:53 UTC
Created attachment 60029 [details]
checkpoint2
Comment 17 Drea Pinski 2025-01-01 21:54:29 UTC
Created attachment 60030 [details]
Checkpoint3

This time no need to compress
Comment 18 Drea Pinski 2025-01-01 23:18:24 UTC
There might be a strict aliasing violation dealing with iterators. I am not 100% yet though.
Comment 19 Drea Pinski 2025-01-01 23:25:19 UTC
So far in my reduced testcase:

This fails:
  auto find() { return this->template functor<typename base_::iterator_from_base>()( this->base().find(0)); }


While this works:
  auto find() { return  this->base().find(0); }

Which is why I said there seems to be some aliasing issue with iterators.
Comment 20 Drea Pinski 2025-01-01 23:37:33 UTC
Created attachment 60031 [details]
checkpoint4
Comment 21 Jeffrey A. Law 2025-02-09 15:04:17 UTC
Might be an aliasing problem or may be a codegen issue.  The former obviously makes this INVALID, the latter would start as a P1 issue.
Comment 22 Xi Ruoyao 2025-02-09 15:05:19 UTC
Maybe it's worthy to try the new LLVM TBAA sanitizer for this?
Comment 23 Sam James 2025-02-10 06:21:45 UTC
(In reply to Xi Ruoyao from comment #22)
> Maybe it's worthy to try the new LLVM TBAA sanitizer for this?

Good idea. It has no complaints.
Comment 24 Richard Biener 2025-02-20 13:46:49 UTC
It can only be P2 since we shipped countless releases with it.
Comment 25 mcccs 2025-04-12 22:13:06 UTC
I used creduce and some de-namespacing and brought it to about 60k lines, I hope to post the checkpoint soon
Comment 26 Sam James 2025-04-12 22:14:53 UTC
(In reply to mcccs from comment #25)
> I used creduce and some de-namespacing and brought it to about 60k lines, I
> hope to post the checkpoint soon

Thank you! Even partial reductions often help a lot (though do keep going) because it makes it way easier to spot problematic lines.
Comment 27 mcccs 2025-04-12 22:19:05 UTC
*sorry I meant 60k bytes not lines
Comment 28 mcccs 2025-04-16 19:54:50 UTC
Created attachment 61145 [details]
27k bytes reduced testcase

further reduced with c-reduce. verified with various LLVM fsanitize's
Comment 29 mcccs 2025-04-16 20:41:07 UTC
fails with even -O1 -fstrict-aliasing -fcode-hoisting
Comment 30 mcccs 2025-04-19 20:27:39 UTC Comment hidden (obsolete)
Comment 31 mcccs 2025-04-19 20:28:25 UTC
Created attachment 61160 [details]
minimized.cpp

GCC -O1 -fstrict-aliasing or -O2 or -O3: aborts

I've attached the minimized human-readable reduced file. I do think it demonstrates GCC's fault in the original file, because if you:

change reinterpret_cast<templated_long_s<1> *> near the end of the file to reinterpret_cast<templated_long_s<0> *>, which has the exact same memory layout (the template parameter is a dummy parameter), the produced assembly changes and execution does not abort.


----


Comparing the "optimized" pass output with and without this mutation, it's seen that

MEM[(struct templated_long_s *)_9].right = 42;

only exists in the correct version. Therefore the testcase has the line

  reinterpreted->right = 42;

completely dropped due to optimization.

----

To experiment with the testcase, you may replace all 4 occurences of "long long" with "long" or "int".
Comment 32 mcccs 2025-04-19 20:29:46 UTC
Oh no I'm so sorry all! I tried to set the previous attachment obsolete unfortunately it quoted all of it and posted here! Sorry for the tall thread
Comment 33 Drea Pinski 2025-04-19 20:34:55 UTC
(In reply to mcccs from comment #31)
> Created attachment 61160 [details]
> minimized.cpp
> 
> GCC -O1 -fstrict-aliasing or -O2 or -O3: aborts
> 
> I've attached the minimized human-readable reduced file. I do think it
> demonstrates GCC's fault in the original file, because if you:
> 
> change reinterpret_cast<templated_long_s<1> *> near the end of the file to
> reinterpret_cast<templated_long_s<0> *>, which has the exact same memory
> layout (the template parameter is a dummy parameter), the produced assembly
> changes and execution does not abort.

This reduced testcase is definitely undefined because templated_long_s<1> and templated_long_s<0> are not compatiable types; they might have the same layout but they are not compatiable types for aliasing rules.
Comment 34 mcccs 2025-04-19 21:35:18 UTC
Thanks Andrew for the reply. In that case, the issue is probably invalid because checkpoint4.cpp also has several reinterpret_casts casting to things involving templates. Too bad, LLVM's -fsanitize=undefined and -fsanitize=type don't print any errors for this
Comment 35 Richard Biener 2025-07-11 09:20:22 UTC
GCC 12 branch is being closed.
Comment 36 Richard Biener 2026-02-03 09:57:51 UTC
Confirmed on x86_64.  -O2 fails, -O2 -fno-ipa-modref works.