Bug 125741 - [17 Regression] FAIL: g++.dg/tree-ssa/pr109442.C -std=gnu++23 scan-tree-dump-not optimized
Summary: [17 Regression] FAIL: g++.dg/tree-ssa/pr109442.C -std=gnu++23 scan-tree-dum...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 17.0
: P3 normal
Target Milestone: 17.0
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization, testsuite-fail
Depends on: 125793
Blocks:
  Show dependency tree / graph
 
Reported: 2026-06-11 11:51 UTC by Torbjorn SVENSSON
Modified: 2026-07-14 10:15 UTC (History)
4 users (show)

See Also:
Host:
Target: arm sparc-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2026-06-11 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Torbjorn SVENSSON 2026-06-11 11:51:26 UTC
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
Comment 1 Drea Pinski 2026-06-17 17:04:40 UTC
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.
Comment 2 Drea Pinski 2026-06-17 17:14:04 UTC
I can also reproduce the same issue under x86_64 using T defined as long.
Comment 3 Drea Pinski 2026-06-17 20:50:14 UTC
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.
Comment 4 Richard Biener 2026-06-18 11:39:32 UTC
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.
Comment 5 Rainer Orth 2026-07-14 10:15:45 UTC
The same failure happens on 32-bit SPARC (both Solaris and Linux).