In r17-987-g14617bda37f8c7, the g++.dg/tree-ssa/pr109442.C test case start failing for arm-none-eabi. Testing tree-ssa/pr109442.C, -std=gnu++11 doing compile Executing on host: /build/r17-1372-g80b78b2504fba0/bin/arm-none-eabi-g++ /build/gcc_src/gcc/testsuite/g++.dg/tree-ssa/pr109442.C -mthumb -march=armv6s-m -mtune=cortex-m0 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -fmessage-length=0 -std=gnu++11 -O2 -fdump-tree-optimized -S -o pr109442.s (timeout = 800) spawn -ignore SIGHUP /build/r17-1372-g80b78b2504fba0/bin/arm-none-eabi-g++ /build/gcc_src/gcc/testsuite/g++.dg/tree-ssa/pr109442.C -mthumb -march=armv6s-m -mtune=cortex-m0 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -fmessage-length=0 -std=gnu++11 -O2 -fdump-tree-optimized -S -o pr109442.s pid is 430895 -430895 pid is -1 output is status 0 PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++11 (test for excess errors) PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++11 scan-tree-dump-not optimized "_M_start" PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++11 scan-tree-dump-not optimized "delete" Testing tree-ssa/pr109442.C, -std=gnu++23 doing compile Executing on host: /build/r17-1372-g80b78b2504fba0/bin/arm-none-eabi-g++ /build/gcc_src/gcc/testsuite/g++.dg/tree-ssa/pr109442.C -mthumb -march=armv6s-m -mtune=cortex-m0 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -fmessage-length=0 -std=gnu++23 -O2 -fdump-tree-optimized -S -o pr109442.s (timeout = 800) spawn -ignore SIGHUP /build/r17-1372-g80b78b2504fba0/bin/arm-none-eabi-g++ /build/gcc_src/gcc/testsuite/g++.dg/tree-ssa/pr109442.C -mthumb -march=armv6s-m -mtune=cortex-m0 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -fmessage-length=0 -std=gnu++23 -O2 -fdump-tree-optimized -S -o pr109442.s pid is 431059 -431059 pid is -1 output is status 0 PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++23 (test for excess errors) FAIL: g++.dg/tree-ssa/pr109442.C -std=gnu++23 scan-tree-dump-not optimized "_M_start" FAIL: g++.dg/tree-ssa/pr109442.C -std=gnu++23 scan-tree-dump-not optimized "delete" Testing tree-ssa/pr109442.C, -std=gnu++20 doing compile Executing on host: /build/r17-1372-g80b78b2504fba0/bin/arm-none-eabi-g++ /build/gcc_src/gcc/testsuite/g++.dg/tree-ssa/pr109442.C -mthumb -march=armv6s-m -mtune=cortex-m0 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -fmessage-length=0 -std=gnu++20 -O2 -fdump-tree-optimized -S -o pr109442.s (timeout = 800) spawn -ignore SIGHUP /build/r17-1372-g80b78b2504fba0/bin/arm-none-eabi-g++ /build/gcc_src/gcc/testsuite/g++.dg/tree-ssa/pr109442.C -mthumb -march=armv6s-m -mtune=cortex-m0 -mfloat-abi=soft -mfpu=auto -fdiagnostics-plain-output -fmessage-length=0 -std=gnu++20 -O2 -fdump-tree-optimized -S -o pr109442.s pid is 431306 -431306 pid is -1 output is status 0 PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++20 (test for excess errors) PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++20 scan-tree-dump-not optimized "_M_start" PASS: g++.dg/tree-ssa/pr109442.C -std=gnu++20 scan-tree-dump-not optimized "delete" std_list: 20 98 26 With -std=gnu+20, it produces code like: .type _Z4vat1St6vectorIiSaIiEE, %function _Z4vat1St6vectorIiSaIiEE: .fnstart .LFB1718: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. movs r0, #10 @ sp needed bx lr .cantunwind .fnend .size _Z4vat1St6vectorIiSaIiEE, .-_Z4vat1St6vectorIiSaIiEE With -std=gnu+23, it instead produces code like: .type _Z4vat1St6vectorIiSaIiEE, %function _Z4vat1St6vectorIiSaIiEE: .fnstart .LFB1898: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 ldmia r0, {r0, r3} subs r0, r3, r0 push {r4, r5, r6, lr} .save {r4, r5, r6, lr} asrs r5, r0, #2 beq .L2 movs r2, #7 adds r3, r0, #7 bics r3, r2 asrs r2, r3, #31 subs r3, r3, r0 adds r3, r2, r3 movs r4, r0 cmp r3, #3 bls .L10 adds r0, r0, #4 bl _Znwj ldr r3, .L11 adds r5, r5, #1 cmp r5, r3 bls .L5 movs r5, r3 .L5: lsls r4, r5, #2 movs r1, r4 bl _ZdlPvj .L2: @ sp needed movs r0, #10 pop {r4, r5, r6, pc} .L10: bl _Znwj movs r1, r4 bl _ZdlPvj b .L2 .L12: .align 2 .L11: .word 536870911 .fnend .size _Z4vat1St6vectorIiSaIiEE, .-_Z4vat1St6vectorIiSaIiEE The same tests pass'es on x86_64-pc-linux-gnu. Issue first reported at https://gcc.gnu.org/pipermail/gcc-patches/2026-June/719939.html
The first difference is __STDCPP_DEFAULT_NEW_ALIGNMENT__ is 8 for arm while 16 for ia32. And then with that difference there seems to be a jump threading which creates duplicates the block containing `operator new` and we get: ``` _43 = __bytes_42 + 7; __max_44 = _43 & 4294967288; __max.0_45 = (signed int) __max_44; _46 = __max.0_45 >> 31; _47 = (unsigned int) _46; _61 = __max_44 - __bytes_42; __spare_49 = _47 + _61; if (__spare_49 > 3) goto <bb 5>; [50.00%] else goto <bb 4>; [50.00%] <bb 4> [local count: 483183820]: _20 = operator new (__bytes_42); goto <bb 6>; [100.00%] <bb 5> [local count: 483183820]: __n_50 = _18 + 1; __bytes_51 = __bytes_42 + 4; _35 = operator new (__bytes_51); _12 = MIN_EXPR <__n_50, 536870911>; _67 = _12 * 4; <bb 6> [local count: 966367642]: # _32 = PHI <_20(4), _35(5)> # prephitmp_2 = PHI <__bytes_42(4), _67(5)> operator delete (_32, prephitmp_2); ``` While we don't re-commonialize the `operator new` here. The way dce works for deleting operator delete/new pairs is only requires a pair so in this case we have 2 operator new for the operator delete and that gets confused.
I can also reproduce the same issue under x86_64 using T defined as long.
I guess one way of fixing this is basically PR 125793. I guess I might look at that next week; I was not planning on working on that except this regression is causing me to rethink it. Oh I thought there was another bug that talked about the 2 operator new but I can't find it right now either.
Enhancing DCE to handle multiple allocations/frees might be also possible (though it might get awkward). Heuristics for jump threading around [special] calls are possible as well. But sure, commoning the allocation would be great.
The same failure happens on 32-bit SPARC (both Solaris and Linux).