https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118115
Bug ID: 118115 Summary: Missed Optimization: Failure to Elide Branch When Copying Overlapping Union Members Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: jonathan.gruber.jg at gmail dot com Target Milestone: --- GCC fails to elide a branch or conditional move for choosing which of overlapping union members to copy. I have only tested this with targets x86_64, aarch64, and riscv64, but I presume other targets have the same problem. Minimal test case: union U { struct { void *a, *b; }; void *c; }; union U copy_union(bool is_ab, union U x) { union U ret; if (is_ab) { ret.a = x.a; ret.b = x.b; } else { ret.c = x.c; } return ret; } For brevity, the generated assemblies below are with -O3, but other optimization levels exhibit the same problem. x86_64: copy_union: xor eax, eax test dil, dil cmovne rax, rdx mov rdx, rax mov rax, rsi ret aarch64: copy_union: tst w0, 1 mov x0, x1 csel x1, x2, xzr, ne ret riscv64: copy_union: addi sp,sp,-32 beq a0,zero,.L2 mv a5,a2 .L2: mv a0,a1 mv a1,a5 addi sp,sp,32 jr ra Meanwhile, Clang generates the following assemblies, which lack branches and conditional moves: x86_64: copy_union: mov rax, rsi ret aarch64: copy_union: mov x0, x1 mov x1, x2 ret riscv64: copy_union: mv a0, a1 mv a1, a2 ret Host system type: Arch Linux, x86_64 gcc information: Version: 14.2.1 20240910 (GCC) Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror aarch64-linux-gnu-gcc information: Version: 14.2.0 Configured with: /build/aarch64-linux-gnu-gcc/src/gcc-14.2.0/configure --prefix=/usr --program-prefix=aarch64-linux-gnu- --with-local-prefix=/usr/aarch64-linux-gnu --with-sysroot=/usr/aarch64-linux-gnu --with-build-sysroot=/usr/aarch64-linux-gnu --with-native-system-header-dir=/include --libdir=/usr/lib --libexecdir=/usr/lib --target=aarch64-linux-gnu --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-nls --enable-default-pie --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --disable-multilib --disable-werror --enable-checking=release riscv64-linux-gnu-gcc information: Version: 14.2.0 Configured with: /build/riscv64-linux-gnu-gcc/src/gcc-14.2.0/configure --prefix=/usr --program-prefix=riscv64-linux-gnu- --with-local-prefix=/usr/riscv64-linux-gnu --with-sysroot=/usr/riscv64-linux-gnu --with-build-sysroot=/usr/riscv64-linux-gnu --libdir=/usr/lib --libexecdir=/usr/lib --target=riscv64-linux-gnu --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --with-system-zlib --with-isl --with-linker-hash-style=gnu --disable-nls --disable-libunwind-exceptions --disable-libstdcxx-pch --disable-libssp --disable-multilib --disable-werror --enable-languages=c,c++ --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --enable-gnu-indirect-function --enable-default-pie --enable-checking=release