https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112604
Bug ID: 112604 Summary: [ia64] Output register not preserved after a branch is not taken Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: jakub at jermar dot eu Target Milestone: --- After an upgrade to GCC 13.2 the HelenOS VFS server started to crash on IA-64 (see http://www.helenos.org/ticket/864). I looked into the issue and the problem seems to be that in the following code snippet: fibril_mutex_lock(&vfs_data->lock); if (!vfs_data->files) { vfs_data->files = malloc(VFS_MAX_OPEN_FILES * sizeof(vfs_file_t *)); if (!vfs_data->files) { fibril_mutex_unlock(&vfs_data->lock); return false; } memset(vfs_data->files, 0, VFS_MAX_OPEN_FILES * sizeof(vfs_file_t *)); } fibril_mutex_unlock(&vfs_data->lock); The output argument prepared for the possible call to malloc (1024 in this case) destroys the argument for fibril_mutex_unlock() if the branch is not taken. In assembly it looks like this: 4000000000001a00 <_vfs_fd_alloc>: 4000000000001a00: 08 48 39 18 80 05 [MMI] alloc r41=ar.pfs,14,12,0 4000000000001a06: c0 02 80 00 42 00 mov r44=r32 4000000000001a0c: 05 00 c4 00 mov r40=b0 4000000000001a10: 09 38 01 41 00 21 [MMI] adds r39=64,r32 4000000000001a16: a0 02 04 00 42 40 mov r42=r1 4000000000001a1c: 04 10 41 00 zxt1 r34=r34;; 4000000000001a20: 11 28 fd 01 00 24 [MIB] mov r37=127 4000000000001a26: b0 02 04 65 00 00 mov.i r43=ar.lc 4000000000001a2c: e8 b4 01 50 br.call.sptk.many b0=400000000001cf00 <fibril_mutex_lock>;; 4000000000001a30: 08 60 01 40 00 21 [MMI] mov r44=r32 4000000000001a36: e0 00 9c 30 20 20 ld8 r14=[r39] 4000000000001a3c: 00 50 01 84 mov r1=r42 4000000000001a40: 0a 68 05 00 00 24 [MMI] mov r45=1;; 4000000000001a46: c0 02 00 10 48 e0 mov r44=1024 4000000000001a4c: 00 70 18 e4 cmp.eq p7,p6=0,r14 4000000000001a50: 16 00 00 00 00 c8 [BBB] nop.b 0x0 4000000000001a56: 01 f0 01 80 21 00 (p07) br.cond.dpnt.few 4000000000001e30 <_vfs_fd_alloc+0x430> 4000000000001a5c: 10 00 00 40 br.few 4000000000001a60 <_vfs_fd_alloc+0x60> 4000000000001a60: 11 00 00 00 01 00 [MIB] nop.m 0x0 4000000000001a66: 00 00 00 02 00 00 nop.i 0x0 4000000000001a6c: 28 ba 01 50 br.call.sptk.many b0=400000000001d480 <fibril_mutex_unlock>;; 4000000000001a70: 08 60 01 40 00 21 [MMI] mov r44=r32 The out0 is r44 in this context. Note how it is first correctly restored to the mutex address at address 1a30 after the fibril_mutex_lock call. But then this value is not used and gets rewritten to 1024 at address 1a46 in preparation for a possible branch and a consequent call to malloc. If the branch is taken, the register is restored properly (not shown here), but if the branch is not taken at address 1a56, the call to fibril_mutex_unlock at address 1a6c is made with a wrong value of r44. We used the following command line to compile the above snippet: usr/local/cross/bin/ia64-helenos-gcc -Iuspace/srv_vfs.p -Iuspace -I../../../uspace -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -std=gnu11 -imacros /home/jermar/software/HelenOS/helenos/build_all/ia64/ski/config.h -O3 -fexec-charset=UTF-8 -finput-charset=UTF-8 -D_HELENOS_SOURCE -Wa,--fatal-warnings -Wall -Wextra -Wwrite-strings -Wunknown-pragmas -Wno-unused-parameter -pipe -ffunction-sections -fdata-sections -fno-common -fdebug-prefix-map=/home/jermar/software/HelenOS/helenos/= -fdebug-prefix-map=../../= -Wsystem-headers -Werror -Wmissing-prototypes -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers -Wno-unused-parameter -Wno-clobbered -Wno-nonnull-compare -fno-builtin-strftime -isystem../../../common/include -isystem../../../abi/include -isystem../../../abi/arch/ia64/include -isystem../../../uspace/lib/c/arch/ia64/include -isystem../../../uspace/lib/c/include -D__LE__ -fno-unwind-tables -MD -MQ uspace/srv_vfs.p/srv_vfs_vfs_file.c.o -MF uspace/srv_vfs.p/srv_vfs_vfs_file.c.o.d -o uspace/srv_vfs.p/srv_vfs_vfs_file.c.o -c ../../../uspace/srv/vfs/vfs_file.c $ /usr/local/cross/bin/ia64-helenos-gcc -v 1209ms Sat 18 Nov 2023 12:42:07 PM UTC Using built-in specs. COLLECT_GCC=/usr/local/cross/bin/ia64-helenos-gcc COLLECT_LTO_WRAPPER=/home/jermar/toolchain/cross/bin/../libexec/gcc/ia64-helenos/13.2.0/lto-wrapper Target: ia64-helenos Configured with: /home/jermar/software/HelenOS/helenos/tools/downloads/gcc-13.2/configure --target=ia64-helenos --prefix=/usr/local/cross --program-prefix=ia64-helenos- --with-gnu-as --with-gnu-ld --disable-nls --enable-languages=c,c++,go --enable-lto --disable-shared --disable-werror --without-headers Thread model: single Supported LTO compression algorithms: zlib zstd gcc version 13.2.0 (GCC) Note that even though I am reporting this for 13.2.0, I saw the same issue already with 13.1.1.