Bug 123888 - [16 Regression] Firefox 147 miscompilation with LTO+PGO on x86_64-linux
Summary: [16 Regression] Firefox 147 miscompilation with LTO+PGO on x86_64-linux
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: ipa (show other bugs)
Version: 16.0
: P1 normal
Target Milestone: 16.0
Assignee: Not yet assigned to anyone
URL:
Keywords: lto, wrong-code
Depends on:
Blocks:
 
Reported: 2026-01-30 13:16 UTC by Jakub Jelinek
Modified: 2026-03-09 12:37 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2026-02-27 00:00:00


Attachments
rh2431315.tar.xz (1.86 MB, application/x-xz)
2026-01-30 13:18 UTC, Jakub Jelinek
Details
rh2431315-2.tar.xz (1.55 MB, application/x-xz)
2026-02-02 10:24 UTC, Jakub Jelinek
Details
rh2431315-3.tar.xz (822.60 KB, application/x-xz)
2026-02-02 10:28 UTC, Jakub Jelinek
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2026-01-30 13:16:38 UTC
Firefox seems to be miscompiled with LTO+PGO in Fedora, during startup it segfaults in mozilla::net::nsStandardURL::Init.
I've reduced the problem a little bit, if everything in libxul.so is compiled with -fno-lto except Unified_cpp_netwerk_base{3,4}.o, which are still -flto -fprofile-use, then speculative devirtualization looks wrong in the NewStandardURI function.
In particular, if I under debugger in:
   0x00007fffe55b9032 <+498>:   mov    0x0(%r13),%rax                                                                                                                                 
   0x00007fffe55b9036 <+502>:   lea    0x531463(%rip),%rdx        #                                                                                                                   
0x7fffe5aea4a0                                                                                                                                                                        
<_ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator>                                                                  
   0x00007fffe55b903d <+509>:   mov    0x18(%rax),%rax                                                                                                                                
   0x00007fffe55b9041 <+513>:   cmp    %rdx,%rax                                                                                                                                      
   0x00007fffe55b9044 <+516>:   je     0x7fffe2b330dc                                                                                                                                 
<NewStandardURI()-44588388>                                                                                                                                                           
change temporarily $rdx not to be _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator, then
it doesn't take the speculative devirtualization path and works, if I don't do that, it ends up calling a method with NULL this pointer.
This was at least with r16-6809 but similar crash can be reproduced also with r16-7068.

I'll attach preprocessed sources.  The original commands to compile those with preprocessor and warning related stuff removed is
g++ -o Unified_cpp_netwerk_base3.o -c -flto -flifetime-dse=1 -fstack-protector-strong -fstrict-flex-arrays=1 -fno-rtti -fno-sized-deallocation -fno-aligned-new -ffunction-sections -fdata-sections -fno-math-errno -fno-exceptions -fPIC -O2 -g1 -fstack-protector-strong -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fpermissive -O3 -fomit-frame-pointer -funwind-tables -fno-strict-aliasing -ffp-contract=off -fprofile-use -fprofile-correction -Wno-coverage-mismatch Unified_cpp_netwerk_base3.ii
g++ -o Unified_cpp_netwerk_base4.o -c -flto -flifetime-dse=1 -fstack-protector-strong -fstrict-flex-arrays=1 -fno-rtti -fno-sized-deallocation -fno-aligned-new -ffunction-sections -fdata-sections -fno-math-errno -fno-exceptions -fPIC -O2 -g1 -fstack-protector-strong -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fpermissive -O3 -fomit-frame-pointer -funwind-tables -fno-strict-aliasing -ffp-contract=off -fprofile-use -fprofile-correction -Wno-coverage-mismatch Unified_cpp_netwerk_base4.ii
but not sure how to convince the linker to LTO link just those two together (-r and some option?).
g++ -fstack-protector-strong -fstrict-flex-arrays=1 -fno-rtti -fno-sized-deallocation -fno-aligned-new -ffunction-sections -fdata-sections -fno-math-errno -fno-exceptions -fPIC -O2 -g1 -fstack-protector-strong -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fpermissive -O3 -fomit-frame-pointer -funwind-tables -shared -o libxul.so -flto=32 -flifetime-dse=1 Unified_cpp_netwerk_base{3,4}.o
doesn't do that.  During the reproduction of course libxul.so is linked to 2300+ other objects (all -fno-lto except these two).
Comment 1 Jakub Jelinek 2026-01-30 13:18:20 UTC
Created attachment 63534 [details]
rh2431315.tar.xz

Preprocessed sources + gcda files.
Comment 2 Jakub Jelinek 2026-01-30 13:42:10 UTC
optimized dump has:
  _90 = MEM[(int (*__vtbl_ptr_type) () * *)_188];
  _94 = MEM[(int (*__vtbl_ptr_type) () *)_90 + 24B];
  if (_94 == _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator)
    goto <bb 20>; [0.00%]
  else
    goto <bb 23>; [100.00%]

  <bb 20> [count: 0]:
  _153 = MEM[(const struct RefPtr *)_188 + -8B].mRawPtr;
  MEM[(struct RefPtr *)_188 + -8B].mRawPtr = 0B;
  rv_160 = Init (_153, 2, aDefaultPort_270(D), aSpec_9(D), aCharset_269(D), aBaseURI_268(D));
...
  <bb 23> [count: 0]:
  _113 = _94 (_188, 2, aDefaultPort_270(D), aSpec_9(D), aCharset_269(D), aBaseURI_268(D), 0B);
where it works with the call to _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator with _188 as this, but _153 is clearly NULL and so calls Init (NULL, ...);
Comment 3 Jakub Jelinek 2026-01-30 14:19:57 UTC
g++ -fstack-protector-strong -fstrict-flex-arrays=1 -fno-rtti -fno-sized-deallocation -fno-aligned-new -ffunction-sections -fdata-sections -fno-math-errno -fno-exceptions -fPIC -O2 -g1 -fstack-protector-strong -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fpermissive -O3 -fomit-frame-pointer -funwind-tables -r -flinker-output=nolto-rel -o libxul.o -flto=32 -flifetime-dse=1 Unified_cpp_netwerk_base{3,4}.o
unfortunately ICEs given the above input (at least with r16-7159):
lto1: internal compiler error: in add_symbol_to_partition_1, at lto/lto-partition.cc:248
0x29c1fff internal_error(char const*, ...)
	../../gcc/diagnostic-global-context.cc:787
0xb0075d fancy_abort(char const*, int, char const*)
	../../gcc/diagnostics/context.cc:1812
0x405584 add_symbol_to_partition_1
	../../gcc/lto/lto-partition.cc:248
0xb4d567 add_references_to_partition
	../../gcc/lto/lto-partition.cc:144
0xb4d6b3 add_symbol_to_partition_1
	../../gcc/lto/lto-partition.cc:221
0xb4d567 add_references_to_partition
	../../gcc/lto/lto-partition.cc:144
0xb4d6b3 add_symbol_to_partition_1
	../../gcc/lto/lto-partition.cc:221
0xb4d7f1 add_symbol_to_partition_1
	../../gcc/lto/lto-partition.cc:211
0xb4d7f1 add_symbol_to_partition_1
	../../gcc/lto/lto-partition.cc:211
0xb508ca lto_balanced_map(int, int)
	../../gcc/lto/lto-partition.cc:1288
0xb40b0a do_whole_program_analysis
	../../gcc/lto/lto.cc:560
0xb40b0a lto_main()
	../../gcc/lto/lto.cc:675
Comment 4 Jakub Jelinek 2026-01-30 15:13:04 UTC
The rv_160 = Init (_153, 2, aDefaultPort_270(D), aSpec_9(D), aCharset_269(D), aBaseURI_268(D)); call in #c2 is
_ZN7mozilla3net13nsStandardURL4InitEjiRK12nsTSubstringIcEPKcP6nsIURI
aka
mozilla::net::nsStandardURL::Init(unsigned int, int, nsTSubstring<char> const&, char const*, nsIURI*)
while the other call is to
_ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
aka
non-virtual thunk to mozilla::net::nsStandardURL::TemplatedMutator<mozilla::net::nsStandardURL>::Init(unsigned int, int, nsTSubstring<char> const&, char const*, nsIURI*, nsIURIMutator**)
Now, looking at -O0 -fno-lto code from both TUs, the latter is
0000000000000185 <_ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator>:
 185:   f3 0f 1e fa             endbr64
 189:   48 83 ef 18             sub    $0x18,%rdi
 18d:   e9 6e fe ff ff          jmp    0 <_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator>
so subtracts 24 from this pointer, and _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
calls _ZN7mozilla3net13nsStandardURL4InitEjiRK12nsTSubstringIcEPKcP6nsIURI
with
  _3 = &this_21(D)->D.1360743.mURI;
  RefPtr<mozilla::net::nsStandardURL>::swap (_3, &uri);
...
  _8 = RefPtr<mozilla::net::nsStandardURL>::operator-> (&uri);
  rv_39 = mozilla::net::nsStandardURL::Init (_8, aURLType_33(D), aDefaultPort_34(D), aSpec_35(D), aCharset_36(D), aBaseURI_37(D));
Comment 5 Jakub Jelinek 2026-01-30 16:22:50 UTC
What I see under debugger (when using -g2 instead of -g1) at that cmp %rdx,%rax insn
above is
(gdb) p *(mozilla::net::nsStandardURL::TemplatedMutator<mozilla::net::nsStandardURL> *)($r13-24)
$9 = {<nsIURIMutator> = {<nsIURISetters> = {<nsIURISetSpec> = {<nsISupports> = {
          _vptr.nsISupports = 0x7fffebf39fe8 <vtable for mozilla::net::nsStandardURL::Mutator+16>, static kIID = {m0 = 0, m1 = 0, m2 = 0, 
            m3 = "\300\000\000\000\000\000\000F"}}, static kIID = {m0 = 533017175, m1 = 35211, m2 = 19550, m3 = "\266\234\005\274\204\264<BF>"}}, static kIID = {
        m0 = 1409525484, m1 = 39383, m2 = 16478, m3 = "\213E\237\200[\275\374", <incomplete sequence \357>}}, static kIID = {m0 = 1293889795, m1 = 7236, m2 = 19917, 
      m3 = "\267\027]\"\246\227\247", <incomplete sequence \331>}}, <BaseURIMutator<mozilla::net::nsStandardURL>> = {
    _vptr.BaseURIMutator = 0x7fffebf3a0e8 <vtable for mozilla::net::nsStandardURL::Mutator+272>, mURI = {mRawPtr = 0x0}}, <nsIStandardURLMutator> = {<nsISupports> = {
      _vptr.nsISupports = 0x7fffebf3a100 <vtable for mozilla::net::nsStandardURL::Mutator+296>, static kIID = {m0 = 0, m1 = 0, m2 = 0, 
        m3 = "\300\000\000\000\000\000\000F"}}, static kIID = {m0 = 4236856984, m1 = 9121, m2 = 17357, 
      m3 = "\247\376r\207o\216\242", <incomplete sequence \356>}}, <nsIURLMutator> = {<nsISupports> = {
      _vptr.nsISupports = 0x7fffebf3a138 <vtable for mozilla::net::nsStandardURL::Mutator+352>, static kIID = {m0 = 0, m1 = 0, m2 = 0, 
        m3 = "\300\000\000\000\000\000\000F"}}, static kIID = {m0 = 621227704, m1 = 61926, m2 = 18479, 
      m3 = "\234\251\355\335=e\026\232"}}, <nsIFileURLMutator> = {<nsISupports> = {
      _vptr.nsISupports = 0x7fffebf3a178 <vtable for mozilla::net::nsStandardURL::Mutator+416>, static kIID = {m0 = 0, m1 = 0, m2 = 0, 
        m3 = "\300\000\000\000\000\000\000F"}}, static kIID = {m0 = 2777200370, m1 = 53945, m2 = 16420, m3 = "\204<BF>3hTkW"}}, <nsISerializable> = {<nsISupports> = {
      _vptr.nsISupports = 0x7fffebf3a1b0 <vtable for mozilla::net::nsStandardURL::Mutator+472>, static kIID = {m0 = 0, m1 = 0, m2 = 0, 
        m3 = "\300\000\000\000\000\000\000F"}}, static kIID = {m0 = 2446109057, m1 = 49773, m2 = 17576, m3 = "\276\276\331\355H\221P:"}}, mMarkedFileURL = false}
(gdb) p &((mozilla::net::nsStandardURL::TemplatedMutator<mozilla::net::nsStandardURL> *)($r13-24))->mURI.mRawPtr
$10 = (mozilla::net::nsStandardURL **) 0x7fffccaf7700
(gdb) p/x $r13
$11 = 0x7fffccaf7708
(gdb) p/x $r13-24
$12 = 0x7fffccaf76f0

i.e. mURI.mRawPtr is NULL at that point, and MEM[(const struct RefPtr *)_188 + -8B].mRawPtr is the right offset to access it at that point - the non-virtual thunk subtracts 24 bytes.
Still, _ZN7mozilla3net13nsStandardURL4InitEjiRK12nsTSubstringIcEPKcP6nsIURI before IPA is doing among other things (note this is that this_20(D) is caller's _188 - 24):
  _51 = MEM[(const struct RefPtr *)this_20(D) + 16B].mRawPtr;
  if (_51 != 0B)
    goto <bb 5>; [INV]
  else
    goto <bb 6>; [INV]

  <bb 5> :
  MEM[(struct RefPtr *)this_20(D) + 16B].mRawPtr = 0B;
  goto <bb 8>; [INV]

  <bb 6> :
  _4 = this_20(D)->D.1367904.D.273177.D.273160.D.273079._vptr.nsISupports;
  _6 = MEM[(int (*__vtbl_ptr_type) () *)_4 + 200B];
  _7 = OBJ_TYPE_REF(_6;(struct TemplatedMutator)this_20(D)->25B) (this_20(D));
  if (_7 != 0B)
    goto <bb 7>; [70.00%]
  else
    goto <bb 8>; [30.00%]

  <bb 7> :
  _55 = _7->D.1368030.D.1350637.D.1350598.D.272311._vptr.nsISupports;
  _56 = MEM[(int (*__vtbl_ptr_type) () *)_55 + 8B];
  OBJ_TYPE_REF(_56;(struct nsStandardURL)_7->1B) (_7);

  <bb 8> :
  # uri$mRawPtr_70 = PHI <_51(5), _7(7), 0B(6)>
  rv_38 = mozilla::net::nsStandardURL::Init (uri$mRawPtr_70, aURLType_32(D), aDefaultPort_33(D), aSpec_34(D), aCharset_35(D), aBaseURI_36(D));
i.e. if _51 is not NULL, stores there NULL and calls nsStandardURL::Init with _51 as this, if it is NULL (the case during firefox startup), then
some function to create it.  And that conditional is clearly gone in the optimized dump.

Now, looking at libxul.so.ltrans2.ltrans.121t.phiprop2, I see there the conditional:
  _153 = MEM[(const struct RefPtr *)_233 + 16B].mRawPtr;
  if (_153 != 0B)
    goto <bb 31>; [0.00%]
  else
    goto <bb 32>; [100.00%]

  <bb 31> [count: 0]:
  MEM[(struct RefPtr *)_233 + 16B].mRawPtr = 0B;
  rv_160 = Init (_153, 2, _99, aSpec_9(D), aCharset_269(D), aBaseURI_268(D));
  _161 = (signed int) rv_160;
  _162 = _161 != 0;
  _163 = (long int) _162;
  _164 = _163;
  if (_164 != 0)
    goto <bb 35>; [0.00%]
  else
    goto <bb 33>; [0.00%]

  <bb 32> [count: 0]:
  _154 = MEM[(struct TemplatedMutator *)_233].D.6066.D.5807.D.5804.D.5801._vptr.nsISupports;
  _155 = MEM[(int (*__vtbl_ptr_type) () *)_154 + 200B];
  __builtin_unreachable ();
but clearly IPA thinks that for some reason the code for mRawPtr == 0 invokes UB.
In the inline dump there is:
Expanding speculative call of NewStandardURI/60 -> Finalize/65 count: 47149 (adjusted)
Expanding speculative call of NewStandardURI/60 -> Release/66 count: 47149 (adjusted)
Expanding speculative call of NewStandardURI/60 -> AddRef/80 count: 47149 (adjusted)
Expanding speculative call of NewStandardURI/60 -> Release/81 count: 47149 (adjusted)
Expanding speculative call of NewStandardURI/60 -> _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.artificial_thunk
.0/84 count: 47149 (adjusted)
Expanding speculative call of NewStandardURI/60 -> AddRef/95 count: 47149 (adjusted)
Introduced new external node (__builtin_unreachable/966).
Comment 6 Jakub Jelinek 2026-01-30 16:35:03 UTC
Note, _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator in another ltrans has after IPA for the mRawPtr == 0 case:
  _20 = adjusted_this.133_3->D.7611.D.7550.D.7547.D.7544._vptr.nsISupports;
  _21 = MEM[(int (*__vtbl_ptr_type) () *)_20 + 200B];
  PROF_38 = [obj_type_ref] OBJ_TYPE_REF(_21;(struct TemplatedMutator)adjusted_this.133_3->25B);
  PROF_39 = (void *) Create;
  if (PROF_39 == PROF_38)
    goto <bb 7>; [100.00%]
  else
    goto <bb 21>; [0.00%]
so clearly it is not unreachable, it is even speculatively devirtualizable (and to the right function that is actually called).
Comment 7 Drea Pinski 2026-01-30 16:56:19 UTC
I wonder if PR 122058 is the same bug and maybe ICU is easier to debug than the full firefox.
Comment 8 Jakub Jelinek 2026-01-30 17:26:07 UTC
I'll see tomorrow if reverting the r16-4000 commits makes a difference here (if it can be easily reverted).
Comment 9 Jan Hubicka 2026-02-02 09:54:12 UTC
--param max-devirt-targets=1 should get us to the same behaviour as before the patch.
Comment 10 Jan Hubicka 2026-02-02 10:02:21 UTC
Expanding speculative call of NewStandardURI/60 -> AddRef/95 count: 47149 (adjusted)
Introduced new external node (__builtin_unreachable/966).

If redirection to unreachable happens at inline transformation time, it should be already visible in cgraph dumps at WPA time that the call in question is redirected (or otherwise constant folding must decide so).

Do you see unreachables at NewStandardURI callers at the end of WPA dumps?
Comment 11 Jakub Jelinek 2026-02-02 10:24:29 UTC
Created attachment 63552 [details]
rh2431315-2.tar.xz

Some wpa dump files.
Comment 12 Jakub Jelinek 2026-02-02 10:28:55 UTC
Created attachment 63553 [details]
rh2431315-3.tar.xz

Further wpa dumps (left out *.lto-stream-out) and early ltrans2 dumps which show to __builtin_unreachable in there.
Comment 13 Jakub Jelinek 2026-02-02 10:34:57 UTC
--param max-devirt-targets=1 doesn't help when specified on the g++ -shared link line,
will try to specify it on the -c -flto -fprofile-use command lines next.
Comment 14 Jakub Jelinek 2026-02-02 10:39:08 UTC
It doesn't help to specify it on the -c -flto -fprofile-use command lines in addition to the -shared -flto link line either.  Or does it need to be specified also in the -flto -fprofile-generate command lines?
Comment 15 Jakub Jelinek 2026-02-02 10:40:29 UTC
The ltrans2 ccp2 dump is still
  if (_101 == _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator)
    goto <bb 30>; [100.00%]
  else
    goto <bb 37>; [0.00%]

  <bb 30> [count: 47149]:
  _233 = _96 + 18446744073709551592;
  _153 = MEM[(const struct RefPtr *)_233 + 16B].mRawPtr;
  if (_153 != 0B)
    goto <bb 31>; [0.00%]
  else
    goto <bb 32>; [100.00%]
...
  <bb 32> [count: 47149]:
  _154 = MEM[(struct TemplatedMutator *)_233].D.6066.D.5807.D.5804.D.5801._vptr.nsISupports;
  _155 = MEM[(int (*__vtbl_ptr_type) () *)_154 + 200B];
  __builtin_unreachable ();
Comment 16 Jan Hubicka 2026-02-02 10:46:00 UTC
> --param max-devirt-targets=1 doesn't help when specified on the g++ -shared
> link line,
> will try to specify it on the -c -flto -fprofile-use command lines next.
It is an optimization option, so it is streamed into the .o files and
needs to be set at compile time.  I am looking into the WPA files.
Comment 17 Jan Hubicka 2026-02-02 10:55:56 UTC
In ltrans stream in we have:

__builtin_unreachable/835 (__builtin_unreachable)
  Type: function
  Visibility: semantic_interposition external public 
  References: 
  Referring:  
  Read from file: /tmp/ccPBdf0n.ltrans2.o
  Unit id: 1
  Function flags: 
  Called by: _ZN7mozilla3net13nsStandardURL9SegmentIsERKNS1_10URLSegmentEPKcb.constprop.0/534 (0 (precise),0.00 per call) _ZN7mozilla3net13nsStandardURL9SegmentIsERKNS1_10URLSegmentEPKcb.constprop.0/530 (0 (precise),0.00 per call) _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0/87 (indirect_inlining) _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0/87 (0 (precise),0.00 per call)

so there is one indirect call redirected which may be the problem.

_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0/87 (Init.constprop)
  Type: function definition analyzed
  Visibility:
  References: 
  Referring: 
  Read from file: /tmp/ccPBdf0n.ltrans2.o
  Function Init.constprop/87 is inline copy in NewStandardURI/60

That function is inlined into NewStandardURI, so I think it is likely the problematic one.
Comment 18 Jan Hubicka 2026-02-02 11:06:55 UTC
In WPA dumps the calls appears in
_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0/6423 (Init.constprop)
  Type: function definition analyzed
  Visibility:
  next sharing asm name: 5963
  References:
  Referring: 
  Read from file: ../../../../objdir/netwerk/base/Unified_cpp_netwerk_base4.o
  Function Init.constprop/6423 is inline copy in NewStandardURI/1673
  Clone of _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0/5963
  Availability: local
  Unit id: 2 
  Function flags: first_run:3640 local hot
  Called by: _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.artificial_thunk.0/6422 (inlined)
  Calls: __builtin_unreachable/5924 (indirect_inlining) __builtin_expect/2318 _ZN7mozilla3net13nsStandardURL4InitEjiRK12nsTSubstringIcEPKcP6nsIURI/4740 __builtin_unreachable/5924 (0 (precise),0.00 per call)
       indirect polymorphic callsite, vptr not changed, calling param -1, offset 0otr_token 2, otr_type struct nsStandardURL, context     Outer type (dynamic):struct nsStandardURL (or a derived type) offset 0, flags 0, num speculative call targets: 0
       indirect polymorphic callsite, vptr not changed, calling param -1, offset 0otr_token 2, otr_type struct nsStandardURL, context     Outer type (dynamic):struct nsStandardURL (or a derived type) offset 0, flags 0, num speculative call targets: 0
       indirect polymorphic callsite, vptr not changed, calling param -1, offset 0otr_token 1, otr_type struct nsStandardURL, context     Outer type (dynamic):struct nsStandardURL (or a derived type) offset 0, flags 0, num speculative call targets: 0

If we can confirm that this is the problematic unreachable, I guess it is time to dive into why polymorphic calls thinks the context is invalid (which may be related to thunk it sits in - without indirect inlining we hardly see thinks in the code)
Comment 19 Jan Hubicka 2026-02-02 11:13:23 UTC
The redirection happens in

Considering Apply.constprop/5961 with 134 size
 to be inlined into NewStandardURI.constprop/6052 in unknown:-1
 Estimated badness is -0.088834, frequency 0.75.
 Called 46506 (adjusted) times
    Badness calculation for NewStandardURI.constprop/6052 -> Apply.constprop/5961
      size growth 107, time 151.699898 unspec 169.699898 IPA hints: declared_inline known_hot
      -0.011104: guessed profile. frequency 0.752342, count 46506 caller count 61815 time saved 27.836642 overall growth -27 (current) 31 (original) 961 (compensated)
      Adjusted by hints -0.088834
Callee count is 0; not updating callee profile
Calee count is too small (profile is inconsistent); not updating callee profile
                Scaling time by probability:0.000000
                Accounting size:2.00, time:0.00 on predicate exec:(true)
                Accounting size:51.50, time:34.23 on predicate exec:(true)
                Accounting size:4.00, time:3.01 on predicate exec:(true)
Processing frequency Apply.constprop/5961
  Called by NewStandardURI.constprop/6052 that is normal or hot
Processing frequency assign_from_qi_with_error.constprop/6407
  Called by Apply.constprop/5961 that is normal or hot
Processing frequency _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.artificial_thunk.0/5964
  Called by Apply.constprop/5961 that is normal or hot
Processing frequency Init.constprop/5963
  Called by _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.artificial_thunk.0/5964 that is normal o
                Accounting size:-10.00, time:-14.29 on predicate exec:(true)
                Accounting size:5.00, time:10.53 on predicate exec:(true)
                Accounting size:4.00, time:8.43 on predicate exec:(true)
                Accounting size:8.00, time:17.00 on predicate exec:(true)
                Accounting size:5.00, time:17.00 on predicate exec:(true)
                Accounting size:4.00, time:16.00 on predicate exec:(true)
                Accounting size:4.00, time:0.00 on predicate exec:(true)
                Accounting size:4.00, time:0.00 on predicate exec:(true)
                Accounting size:2.00, time:8.28 on predicate exec:(true)
                Accounting size:4.00, time:0.00 on predicate exec:(true)
                Accounting size:4.00, time:0.00 on predicate exec:(true)
                Accounting size:11.00, time:0.00 on predicate exec:(true)
                Accounting size:4.00, time:12.04 on predicate exec:(true)
optimized: discovered direct call non-invariant Apply.constprop/5961
No devirtualization target in Init.constprop/5963
ipa-prop: Discovered a virtual call to a known target (Init.constprop/5963 -> __builtin_unreachable/5924), for stmt with uid 50

there are two occurrences of this in inline dump.
Comment 20 Jakub Jelinek 2026-02-02 11:14:31 UTC
Do you have ideas how to reproduce this without all the non-LTO object files?
Or at least with r16-6809 if the gcda files are incompatible with current trunk?
In the real reproduction, I have those 2 -flto built *.o files and thousands of *.o files and some libraries built without -flto.
If I try just g++ -shared -O2 -flto -o libxul.small.so Unified_cpp_netwerk_base{3,4}.o
then for some reason it doesn't LTO compile anything, and the #c3 attempt ICEd.

I can upload the *.o files somewhere if needed though if there is no other way, just not to bugzilla because of the 2MB limit.
Comment 21 Jakub Jelinek 2026-02-02 11:26:01 UTC
The function is originally
static nsresult NewStandardURI(const nsACString& aSpec, const char* aCharset,
                               nsIURI* aBaseURI, int32_t aDefaultPort,
                               nsIURI** aURI) {
  return NS_MutateURI(new nsStandardURL::Mutator())
      .Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY,
             aDefaultPort, aSpec, aCharset, aBaseURI, nullptr)
      .Finalize(aURI);
}
and as I wrote, in the case when this crashes without devirtualization this would call
_ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
and Create is what is called in there.
That is nsStandardURI.h:
      RefPtr<T> uri;
      if (BaseURIMutator<T>::mURI) {
        // We don't need a new URI object if we already have one
        BaseURIMutator<T>::mURI.swap(uri);
      } else {
        uri = Create();
      }
and Create is I think
    T* Create() override { return new T(mMarkedFileURL); }
which I think is _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E6CreateEv.
The dumps have in other spots
libxul.so.ltrans3.ltrans.273t.optimized:  if (PROF_26 == _ZThn8_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E6CreateEv)
libxul.so.ltrans3.ltrans.273t.optimized:  if (PROF_22 == _ZThn8_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E6CreateEv)
libxul.so.ltrans7.ltrans.273t.optimized:;; Function Create (_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E6CreateEv.lto_priv.0, funcdef_no=224, decl_uid=7990, cgraph_uid=576, symbol_order=531) (hot)
Comment 22 Jan Hubicka 2026-02-02 12:21:00 UTC
> Do you have ideas how to reproduce this without all the non-LTO object files?
It is not clear to me why .o files are needed.  Inline dump has the
following which summarizes what happens in the function:
IPA function summary for NewStandardURI/1673 inlinable
  global time:     208.377017
  self size:       58
  global size:     213
  min size:       209
  self stack:      28
  global stack:    60
  estimated growth:152
    size:121.000000, time:100.121370
    size:3.000000, time:2.000000,  executed if:(not inlined)
    size:0.500000, time:0.500000,  executed if:(op4 not sra candidate)
  calls:
    Finalize/6202 inlined
      freq:1.00
      Stack frame offset 28, callee self size 0
    Release/6544 inlined
      freq:1.00 cross module
      Stack frame offset 28, callee self size 0
      __dt_del /6545 inlined
        freq:0.34
        Stack frame offset 28, callee self size 0
        free/2326 function body not available
          freq:0.34 cross module loop depth: 0 size: 2 time: 11
        indirect call loop depth: 0 freq:0.00 size: 4 time: 16
    __builtin_expect/2318 function body not available
      freq:1.00 loop depth: 0 size: 0 time:  0
       op1 is compile time invariant
       op1 points to local or readonly memory
    __builtin_expect/2318 function body not available
      freq:1.00 loop depth: 0 size: 0 time:  0
       op1 is compile time invariant
       op1 points to local or readonly memory
    Apply.constprop/6420 inlined
      freq:1.00
      Stack frame offset 28, callee self size 24
      AddRef/6421 inlined
        freq:1.00
        Stack frame offset 52, callee self size 0
      Release/6548 inlined
        freq:1.00 cross module
        Stack frame offset 52, callee self size 0
        __dt_del /6549 inlined
          freq:0.34
          Stack frame offset 52, callee self size 0
          free/2326 function body not available
            freq:0.34 cross module loop depth: 0 size: 2 time: 11
          indirect call loop depth: 0 freq:0.00 size: 4 time: 16
      _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.artificial_thunk.0/6422 inlined
        freq:1.00 cross module
        Stack frame offset 52, callee self size 0
        Init.constprop/6423 inlined
          freq:1.00
          Stack frame offset 52, callee self size 0
          __builtin_unreachable/5924 function body not available
            freq:1.00 cross module loop depth: 0 size: 3 time: 12
          __builtin_expect/2318 function body not available
            freq:1.00 cross module loop depth: 0 size: 0 time:  0
             op1 is compile time invariant
             op1 points to local or readonly memory
          Init/4740 --param max-inline-insns-auto limit reached
            freq:1.00 loop depth: 0 size: 8 time: 17 callee size:139 stack:104
          __builtin_unreachable/5924 unreachable
            freq:0.00 cross module loop depth: 0 size: 0 time:  0 predicate: (false)
          indirect call loop depth: 0 freq:0.00 size: 4 time: 16
          indirect call loop depth: 0 freq:0.00 size: 4 time: 16
          indirect call loop depth: 0 freq:1.00 size: 4 time: 16
      __builtin_expect/2318 function body not available
        freq:1.00 loop depth: 0 size: 0 time:  0
         op1 is compile time invariant
         op1 points to local or readonly memory
      assign_from_qi_with_error.constprop/6424 inlined
        freq:1.00
        Stack frame offset 52, callee self size 8
        operator()/2543 function body not available
          freq:1.00 loop depth: 0 size: 5 time: 14
        __builtin_expect/2318 function body not available
          freq:1.00 loop depth: 0 size: 0 time:  0
           op1 is compile time invariant
           op1 points to local or readonly memory
        indirect call loop depth: 0 freq:0.70 size: 4 time: 16
      __builtin_expect/2318 function body not available
        freq:1.00 loop depth: 0 size: 0 time:  0
         op1 is compile time invariant
         op1 points to local or readonly memory
      indirect call loop depth: 0 freq:1.00 size: 4 time: 16
      indirect call loop depth: 0 freq:0.00 size:11 time: 23
      indirect call loop depth: 0 freq:0.00 size: 4 time: 16
      indirect call loop depth: 0 freq:0.00 size: 4 time: 16
    __ct_base /6522 inlined
      freq:1.00
      Stack frame offset 28, callee self size 0
      AddRef/6523 inlined
        freq:1.00
        Stack frame offset 28, callee self size 0
      indirect call loop depth: 0 freq:0.00 size: 4 time: 16
      indirect call loop depth: 0 freq:0.00 size: 4 time: 16
    moz_xmalloc/2322 function body not available
      freq:1.00 loop depth: 0 size: 3 time: 12
    indirect call loop depth: 0 freq:0.00 size: 4 time: 16

So the chain of inlines going to the unreachable is
NewStandsdURI <- Apply <- _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.artificial_thunk.0 <- Init 

forcing it by hand may reproduce same problem assuming that
__builtin_unreachable inside of Init is indeed to wrong one.

I have to leave now but will be back around 4pm.
Comment 23 Jakub Jelinek 2026-02-02 12:35:50 UTC
So, I've tried to add a.C:
extern "C" int _Z38NS_LoadPersistentPropertiesFromURISpecPP23nsIPersistentPropertiesRK12nsTSubstringIcE ();

int
foo ()
{
  return _Z38NS_LoadPersistentPropertiesFromURISpecPP23nsIPersistentPropertiesRK12nsTSubstringIcE ();
}
g++ -o Unified_cpp_netwerk_base3.o -c -flto -flifetime-dse=1 -fstack-protector-strong -fstrict-flex-arrays=1 -fno-rtti -pthread -fno-sized-deallocation -fno-aligned-new -ffunction-sections -fdata-sections -fno-math-errno -fno-exceptions -fPIC -O2 -g1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fpermissive -O3 -fomit-frame-pointer -funwind-tables -fno-strict-aliasing -ffp-contract=off -fprofile-use -fprofile-correction Unified_cpp_netwerk_base3.ii -Wno-coverage-mismatch
g++ -o Unified_cpp_netwerk_base4.o -c -flto -flifetime-dse=1 -fstack-protector-strong -fstrict-flex-arrays=1 -fno-rtti -pthread -fno-sized-deallocation -fno-aligned-new -ffunction-sections -fdata-sections -fno-math-errno -fno-exceptions -fPIC -O2 -g1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fpermissive -O3 -fomit-frame-pointer -funwind-tables -fno-strict-aliasing -ffp-contract=off -fprofile-use -fprofile-correction Unified_cpp_netwerk_base4.ii -Wno-coverage-mismatch

../g++ -shared -flto -fno-whole-program -fPIC -O2 -o libxul.so a.C Unified_cpp_netwerk_base{3,4}.o 
a.C:1:16: warning: type of ‘_Z38NS_LoadPersistentPropertiesFromURISpecPP23nsIPersistentPropertiesRK12nsTSubstringIcE’ does not match original declaration [-Wlto-type-mismatch]
    1 | extern "C" int _Z38NS_LoadPersistentPropertiesFromURISpecPP23nsIPersistentPropertiesRK12nsTSubstringIcE ();
      |                ^
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsNetUtil.cpp:2128:10: note: return value type mismatch
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/ErrorList.h:56:12: note: type ‘nsresult’ should match type ‘int’
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsNetUtil.cpp:2128:10: note: ‘NS_LoadPersistentPropertiesFromURISpec’ was previously declared here
lto-wrapper: warning: using serial compilation of 2 LTRANS jobs
lto-wrapper: note: see the ‘-flto’ option documentation for more information
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `nsCOMPtr<nsIPrefBranch>::assign_from_gs_contractid(nsGetServiceByContractID, nsID const&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsCOMPtr.h:870:(.text+0x79): undefined reference to `nsGetServiceByContractID::operator()(nsID const&, void**) const'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `NS_MutateURI& NS_MutateURI::Apply<nsresult (nsIStandardURLMutator::*)(unsigned int, int, nsTSubstring<char> const&, char const*, nsIURI*, nsIURIMutator**), nsIStandardURL::{unnamed type#1}, int, nsTSubstring<char> const&, char const*&, nsIURI*&, decltype(nullptr)>(nsresult (nsIStandardURLMutator::*)(unsigned int, int, nsTSubstring<char> const&, char const*, nsIURI*, nsIURIMutator**), nsIStandardURL::{unnamed type#1}&&, int&&, nsTSubstring<char> const&, char const*&, nsIURI*&, decltype(nullptr)&&) [clone .constprop.0]':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsCOMPtr.h:189:(.text+0x26e): undefined reference to `nsQueryInterfaceISupportsWithError::operator()(nsID const&, void**) const'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsCOMPtr.h:189:(.text+0x31a): undefined reference to `nsQueryInterfaceISupportsWithError::operator()(nsID const&, void**) const'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::GetPathQueryRef(nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTDependentSubstring.h:67:(.text+0x438): undefined reference to `nsTDependentSubstring<char>::Rebind(nsTSubstring<char> const&, unsigned long, unsigned long)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::GetPathQueryRef(nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:526:(.text+0x443): undefined reference to `nsTSubstring<char>::Assign(nsTSubstring<char> const&)'
/usr/bin/ld: /builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0x44b): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::SchemeIs(char const*, bool*)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTDependentSubstring.h:67:(.text+0x4db): undefined reference to `nsTDependentSubstring<char>::Rebind(nsTSubstring<char> const&, unsigned long, unsigned long)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::SchemeIs(char const*, bool*)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsSimpleURI.cpp:556:(.text+0x4fa): undefined reference to `mozilla::detail::nsTStringRepr<char>::EqualsIgnoreCase(std::basic_string_view<char, std::char_traits<char> > const&) const'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::SchemeIs(char const*, bool*)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0x505): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::GetAsciiSpec(nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:526:(.text+0x54f): undefined reference to `nsTSubstring<char>::Assign(nsTSubstring<char> const&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::GetScheme(nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTDependentSubstring.h:67:(.text+0x5ae): undefined reference to `nsTDependentSubstring<char>::Rebind(nsTSubstring<char> const&, unsigned long, unsigned long)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsSimpleURI::GetScheme(nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:530:(.text+0x5b9): undefined reference to `nsTSubstring<char>::Assign(nsTSubstring<char>&&)'
/usr/bin/ld: /builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0x5c1): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTPromiseFlatString.h:104:(.text+0x8bb): undefined reference to `nsTPromiseFlatString<char>::Init(nsTSubstring<char> const&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:465:(.text+0x8fd): undefined reference to `nsTSubstring<char>::Truncate()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:481:(.text+0x93e): undefined reference to `mozilla::ASCIIMask::MaskCRLFTab()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:526:(.text+0x999): undefined reference to `nsTSubstring<char>::Assign(nsTSubstring<char> const&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTDependentSubstring.h:67:(.text+0xa10): undefined reference to `nsTDependentSubstring<char>::Rebind(nsTSubstring<char> const&, unsigned long, unsigned long)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTString.h:315:(.text+0xa50): undefined reference to `nsTSubstring<char>::Assign(nsTSubstring<char>&&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xa5d): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTDependentSubstring.h:131:(.text+0xac1): undefined reference to `nsTDependentSubstring<char>::nsTDependentSubstring(char const*, char const*)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:399:(.text+0xada): undefined reference to `mozilla::TTokenizer<char>::TTokenizer(nsTSubstring<char> const&, char const*, char const*)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xae7): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:400:(.text+0xaf4): undefined reference to `mozilla::TTokenizer<char>::Record(mozilla::TTokenizer<char>::ClaimInclusion)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:401:(.text+0xb03): undefined reference to `mozilla::TTokenizer<char>::CheckChar(bool (*)(char))'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:406:(.text+0xb1b): undefined reference to `mozilla::TTokenizer<char>::CheckChar(bool (*)(char))'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/mozilla/Tokenizer.h:308:(.text+0xb2c): undefined reference to `mozilla::TokenizerBase<char>::Token::Whitespace()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/mozilla/Tokenizer.h:308:(.text+0xb3c): undefined reference to `mozilla::TTokenizer<char>::Check(mozilla::TokenizerBase<char>::Token const&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xb4c): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xb59): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xb66): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/mozilla/Tokenizer.h:314:(.text+0xb7d): undefined reference to `mozilla::TokenizerBase<char>::Token::Char(char)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/mozilla/Tokenizer.h:314:(.text+0xb8d): undefined reference to `mozilla::TTokenizer<char>::Check(mozilla::TokenizerBase<char>::Token const&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xb9d): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xbaa): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTSubstring.h:327:(.text+0xbb7): undefined reference to `nsTSubstring<char>::Finalize()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:414:(.text+0xbd8): undefined reference to `mozilla::TTokenizer<char>::Claim(nsTSubstring<char>&, mozilla::TTokenizer<char>::ClaimInclusion)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:415:(.text+0xbdd): undefined reference to `mozilla::ASCIIMask::MaskCRLFTab()'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:415:(.text+0xbe8): undefined reference to `nsTSubstring<char>::StripTaggedASCII(std::array<bool, 128ul> const&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o:/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/netwerk/base/nsURLHelper.cpp:416:(.text+0xbf0): undefined reference to `ToLowerCase(nsTSubstring<char>&)'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: in function `mozilla::net::nsStandardURL::Resolve(nsTSubstring<char> const&, nsTSubstring<char>&)':
/builddir/build/BUILD/firefox-147.0.1-build/firefox-147.0.1/objdir/dist/include/nsTArray.h:3101:(.text+0xc06): undefined reference to `sEmptyTArrayHeader'
/usr/bin/ld: /tmp/cckKR9qr.ltrans0.ltrans.o: relocation R_X86_64_PC32 against undefined hidden symbol `sEmptyTArrayHeader' can not be used when making a shared object
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

Though, if I add -fdump-ipa-all-details -fdump-tree-all to the -shared command line, it already shows the problem in there, in
libxul.so.ltrans0.ltrans.114t.ccp2 I see that
  if (_1079 == _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator)
    goto <bb 112>; [100.00%]
  else
    goto <bb 119>; [0.00%]

  <bb 112> [count: 46506]:
  _1769 = _1074 + 18446744073709551592;
  _1131 = MEM[(const struct RefPtr *)_1769 + 16B].mRawPtr;
  if (_1131 != 0B)
    goto <bb 113>; [0.00%]
  else
    goto <bb 114>; [100.00%]
  
  <bb 113> [count: 0]:
  MEM[(struct RefPtr *)_1769 + 16B].mRawPtr = 0B;
  rv_1138 = Init (_1131, 2, 80, aSpec_5(D), _35, _34);
  _1139 = (signed int) rv_1138;
  _1140 = _1139 != 0;
  _1141 = (long int) _1140;
  _1142 = _1141;
  if (_1142 != 0)
    goto <bb 117>; [0.00%]
  else
    goto <bb 115>; [100.00%]
  
  <bb 114> [count: 46506]:
  _1132 = MEM[(struct TemplatedMutator *)_1769].D.5920.D.5700.D.5698.D.5695._vptr.nsISupports;
  _1133 = MEM[(int (*__vtbl_ptr_type) () *)_1132 + 200B];
  __builtin_unreachable ();
again.  This was with r16-7218.  So while we don't have anything close to a testcase for the testsuite, I think you can reproduce this yourself.
Comment 24 Jakub Jelinek 2026-02-06 12:49:08 UTC
_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
(whose thunk is the speculated call on one of the OBJ_TYPE_REF calls in NewStandardURI) is clearly const propagated, because
  return NS_MutateURI(new nsStandardURL::Mutator())
      .Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY,
             aDefaultPort, aSpec, aCharset, aBaseURI, nullptr)
      .Finalize(aURI);
passes NULL to it as the last argument (i.e. aMutator).
And during wpa I see redirect_to_unreachable being called when
_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
is being cloned to
_ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0 but unsure why, during
#0  redirect_to_unreachable (e=0x7fffe7462888) at ../../gcc/ipa-fnsummary.cc:263
#1  0x000000000099bdf7 in edge_set_predicate (e=0x7fffe7462888, predicate=0x7ffffffeb140) at ../../gcc/ipa-fnsummary.cc:300
#2  0x000000000099e2ba in ipa_fn_summary_t::duplicate (this=0x7fffe7b7eb60, src=0x7fffe81e9550, dst=0x7fffe8040770, src_info=0x7fffe781ddc0, info=0x7fffe7fb8b58)
    at ../../gcc/ipa-fnsummary.cc:939
#3  0x00000000009b1fe0 in fast_function_summary<ipa_fn_summary*, va_gc>::symtab_duplication (node=0x7fffe81e9550, node2=0x7fffe8040770, data=0x7fffe7b7eb60)
    at ../../gcc/symbol-summary.h:509
#4  0x0000000000587bf9 in symbol_table::call_cgraph_duplication_hooks (this=0x7fffe9806000, node=0x7fffe81e9550, node2=0x7fffe8040770) at ../../gcc/cgraph.cc:650
#5  0x00000000005a72a8 in cgraph_node::create_virtual_clone (this=0x7fffe81e9550, redirect_callers=..., tree_map=0x7fffe76b88e8, param_adjustments=0x7fffe7cb9480, 
    suffix=0x4e38ee9 "constprop", num_suffix=0) at ../../gcc/cgraphclones.cc:746
#6  0x000000000384797f in create_specialized_node (node=0x7fffe81e9550, known_csts=..., known_contexts=..., aggvals=0x0, callers=...) at ../../gcc/ipa-cp.cc:5188
the src->indirect_calls edges have NULL callee rather than unreachable.
Comment 25 Jan Hubicka 2026-02-06 14:48:08 UTC
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123888
> 
> --- Comment #24 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
> _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
> (whose thunk is the speculated call on one of the OBJ_TYPE_REF calls in
> NewStandardURI) is clearly const propagated, because
>   return NS_MutateURI(new nsStandardURL::Mutator())
>       .Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY,
>              aDefaultPort, aSpec, aCharset, aBaseURI, nullptr)
>       .Finalize(aURI);
> passes NULL to it as the last argument (i.e. aMutator).
> And during wpa I see redirect_to_unreachable being called when
> _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator
> is being cloned to
> _ZN7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator.constprop.0
> but unsure why, during
> #0  redirect_to_unreachable (e=0x7fffe7462888) at
> ../../gcc/ipa-fnsummary.cc:263
> #1  0x000000000099bdf7 in edge_set_predicate (e=0x7fffe7462888,
> predicate=0x7ffffffeb140) at ../../gcc/ipa-fnsummary.cc:300
> #2  0x000000000099e2ba in ipa_fn_summary_t::duplicate (this=0x7fffe7b7eb60,
> src=0x7fffe81e9550, dst=0x7fffe8040770, src_info=0x7fffe781ddc0,
> info=0x7fffe7fb8b58)
>     at ../../gcc/ipa-fnsummary.cc:939
> #3  0x00000000009b1fe0 in fast_function_summary<ipa_fn_summary*,
> va_gc>::symtab_duplication (node=0x7fffe81e9550, node2=0x7fffe8040770,
> data=0x7fffe7b7eb60)
>     at ../../gcc/symbol-summary.h:509
> #4  0x0000000000587bf9 in symbol_table::call_cgraph_duplication_hooks
> (this=0x7fffe9806000, node=0x7fffe81e9550, node2=0x7fffe8040770) at
> ../../gcc/cgraph.cc:650
> #5  0x00000000005a72a8 in cgraph_node::create_virtual_clone
> param_adjustments=0x7fffe7cb9480, 
>     suffix=0x4e38ee9 "constprop", num_suffix=0) at
> ../../gcc/cgraphclones.cc:746
> #6  0x000000000384797f in create_specialized_node (node=0x7fffe81e9550,
> known_csts=..., known_contexts=..., aggvals=0x0, callers=...) at
> ../../gcc/ipa-cp.cc:5188
> the src->indirect_calls edges have NULL callee rather than unreachable.

This code is updating summary for ipa-cp clone and doing that it folds
predicates for a given context (newly known constants/value ranges).  If
predicate folds to false (as it does here), all calls (direct or
indirect) are marked as unreachable so the inliner/ipacp heuristics does
not try to otimize acorss them.

So there should be a constnat propagation that implies makes predicat
false and if the call is still reachable in real code, there is some bug
in that.

I am going back from winter school today so I will try to reproduce it
myself.

Honza
Comment 26 Richard Biener 2026-02-25 12:42:08 UTC
Any update here?  Does the issue still happen?  If so please set to NEW at least.
Comment 27 Martin Jambor 2026-02-27 13:38:14 UTC
Can I suggest to try with commit 431453e3364 fixing PR 123229?  Unfortunately that bug can in theory manifest in very many weird ways.
Comment 28 Jakub Jelinek 2026-02-27 20:05:19 UTC
Will try on Monday.
Comment 29 Jakub Jelinek 2026-03-02 11:49:30 UTC
At least from eyeballing the dumps it looks like it probably it is r16-7756
In the problematic part of ccp2 dump I see (trunk with r16-7756 reverted to trunk):
...
   if (_1079 == _ZThn24_N7mozilla3net13nsStandardURL16TemplatedMutatorIS1_E4InitEjiRK12nsTSubstringIcEPKcP6nsIURIPP13nsIURIMutator)
     goto <bb 112>; [100.00%]
   else
-    goto <bb 119>; [0.00%]
+    goto <bb 121>; [0.00%]
 
   <bb 112> [count: 46506]:
-  _1769 = _1074 + 18446744073709551592;
-  _1131 = MEM[(const struct RefPtr *)_1769 + 16B].mRawPtr;
+  _1770 = _1074 + 18446744073709551592;
+  _1131 = MEM[(const struct RefPtr *)_1770 + 16B].mRawPtr;
   if (_1131 != 0B)
     goto <bb 113>; [0.00%]
   else
     goto <bb 114>; [100.00%]
 
   <bb 113> [count: 0]:
-  MEM[(struct RefPtr *)_1769 + 16B].mRawPtr = 0B;
-  rv_1138 = Init (_1131, 2, 80, aSpec_5(D), _35, _34);
+  MEM[(struct RefPtr *)_1770 + 16B].mRawPtr = 0B;
+  goto <bb 116>; [100.00%]
+
+  <bb 114> [count: 46506]:
+  _1132 = MEM[(struct TemplatedMutator *)_1770].D.5920.D.5700.D.5698.D.5695._vptr.nsISupports;
+  _1133 = MEM[(int (*__vtbl_ptr_type) () *)_1132 + 200B];
+  _1134 = OBJ_TYPE_REF(_1133;(struct TemplatedMutator)_1770->25B) (_1770);
+  if (_1134 != 0B)
+    goto <bb 115>; [100.00%]
+  else
+    goto <bb 116>; [0.00%]
+
+  <bb 115> [count: 46506]:
+  _1135 = _1134->D.5778.D.5729.D.5725.D.5674._vptr.nsISupports;
+  _1136 = MEM[(int (*__vtbl_ptr_type) () *)_1135 + 8B];
+  OBJ_TYPE_REF(_1136;(struct nsStandardURL)_1134->1B) (_1134);
+
+  <bb 116> [count: 46506]:
+  # uri$mRawPtr_1137 = PHI <_1131(113), 0B(114), _1134(115)>
+  rv_1138 = Init (uri$mRawPtr_1137, 2, 80, aSpec_5(D), _35, _34);
   _1139 = (signed int) rv_1138;
   _1140 = _1139 != 0;
   _1141 = (long int) _1140;
   _1142 = _1141;
   if (_1142 != 0)
-    goto <bb 117>; [0.00%]
+    goto <bb 119>; [0.00%]
   else
-    goto <bb 115>; [100.00%]
-
-  <bb 114> [count: 46506]:
-  _1132 = MEM[(struct TemplatedMutator *)_1769].D.5920.D.5700.D.5698.D.5695._vptr.nsISupports;
-  _1133 = MEM[(int (*__vtbl_ptr_type) () *)_1132 + 200B];
-  __builtin_unreachable ();
+    goto <bb 117>; [100.00%]
 
-  <bb 115> [count: 46506]:
-  oldPtr_1143 = MEM[(struct RefPtr *)_1769 + 16B].mRawPtr;
-  MEM[(struct RefPtr *)_1769 + 16B].mRawPtr = _1131;
+  <bb 117> [count: 46506]:
+  oldPtr_1143 = MEM[(struct RefPtr *)_1770 + 16B].mRawPtr;
+  MEM[(struct RefPtr *)_1770 + 16B].mRawPtr = uri$mRawPtr_1137;
   if (oldPtr_1143 != 0B)
-    goto <bb 116>; [0.00%]
+    goto <bb 118>; [0.00%]
   else
-    goto <bb 117>; [100.00%]
+    goto <bb 119>; [100.00%]
 
-  <bb 116> [count: 0]:
+  <bb 118> [count: 0]:
   _1144 = oldPtr_1143->D.5778.D.5729.D.5725.D.5674._vptr.nsISupports;
   _1145 = MEM[(int (*__vtbl_ptr_type) () *)_1144 + 16B];
   OBJ_TYPE_REF(_1145;(struct nsStandardURL)oldPtr_1143->2B) (oldPtr_1143);
...
Comment 30 Jan Hubicka 2026-03-08 20:31:55 UTC
Is it working now? (I hope so)
Comment 31 Jakub Jelinek 2026-03-09 12:37:46 UTC
It is.  So fixed by r16-7756