[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #35 from GCC Commits --- The master branch has been updated by Richard Biener : https://gcc.gnu.org/g:aa5ae523e84a97bf3a582ea0fa73d959afa9b9c7 commit r16-2085-gaa5ae523e84a97bf3a582ea0fa73d959afa9b9c7 Author: Richard Biener Date: Mon Jul 7 15:13:38 2025 +0200 tree-optimization/120358 - bogus PTA with structure access When we compute the constraint for something like MEM[(const struct QStringView &)&tok2 + 32] we go and compute what (const struct QStringView &)&tok2 + 32 points to and then add subvariables to its dereference that possibly fall in the range of the access according to the original refs size. In doing that we disregarded that the subvariable the starting address points to might not be aligned to it and thus the access might start at any point within that variable. The following conservatively adjusts the pruning of adjacent sub-variables to honor this. PR tree-optimization/120358 * tree-ssa-structalias.cc (get_constraint_for_1): Adjust pruning of sub-variables according to the imprecise known start offset.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Sam James changed: What|Removed |Added Attachment #61749|0 |1 is obsolete|| --- Comment #34 from Sam James --- Created attachment 61813 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61813&action=edit small.cxx Still a bit big.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #33 from Richard Biener ---
Something like the following might be a testcase, needs -fno-tree-sra
but it fails to demonstrate the particular sub-field layout for Y.
struct X { int *p; int *q; };
struct Y { struct X a; struct { unsigned pad : 1; struct X b; } b; };
static int i, j, k, l;
int foo (int c)
{
struct Y y;
y.b.b.p = &i;
y.b.b.q = &j;
char *p = (char *)&y;
struct X z;
z = *(struct X *)(p + sizeof (struct X) + sizeof (unsigned));
return *z.q;
}
so no nice small testcase for now.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #32 from Richard Biener ---
Hmm, or rather the logic is fine, there's simply no field at that offset in the
set of RHS constraints. There's the missing field
$21 = {id = 30, is_artificial_var = 0, is_special_var = 0,
is_unknown_size_var = 0, is_full_var = 0, is_heap_var = 0, is_reg_var = 0,
may_have_pointers = 1, only_restrict_pointers = 0, is_restrict_var = 0,
is_global_var = 0, is_ipa_escape_point = 0, is_fn_info = 0,
address_taken = 0, ruid = 0, next = 31, head = 27, offset = 320, size = 64,
fullsize = 448, shadow_var_uid = 0, name = 0x7fffee90d3e0 "tok2.320+64",
decl = , solution = 0x586ee50,
oldsolution = 0x0}
and the issue is in get_constraint_for_1 which doesn't take into account
the case where the offset doesn't align with the first field that is
accessed.
diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc
index deca44ae0bf..0215243d5be 100644
--- a/gcc/tree-ssa-structalias.cc
+++ b/gcc/tree-ssa-structalias.cc
@@ -3690,7 +3690,10 @@ get_constraint_for_1 (tree t, vec *results, bool
address_p,
size = -1;
for (; curr; curr = vi_next (curr))
{
- if (curr->offset - vi->offset < size)
+ /* The start of the access might happen anywhere
+within vi, so conservatively assume it was
+at its end. */
+ if (curr->offset - (vi->offset + vi->size - 1) < size)
{
cs.var = curr->id;
results->safe_push (cs);
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
Richard Biener changed:
What|Removed |Added
Last reconfirmed|2025-05-19 00:00:00 |2025-07-07
Ever confirmed|0 |1
Status|UNCONFIRMED |ASSIGNED
Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot
gnu.org
--- Comment #31 from Richard Biener ---
(In reply to Alexander Monakov from comment #28)
> Created attachment 61811 [details]
> standalone testcase
>
> A standalone variant of the comment #22 testcase, preprocessed and with
> enough noipa stubs added to avoid linking with QtBase.
Thanks, this produces with -O2 -std=gnu++20
> ./a.out
test2: 1 2 3
while -O3 -std=gnu++20
> ./a.out
test2: 1 2 3 18446744073709551615
it also reproduces with -O3 -fno-tree-vectorize, the main difference seems
to be IPA and inline differences. -fno-tree-pta fixes it.
There are exactly two(!) comparisons eliminated with the added path, the
2nd triggers the issue in VRP1:
Folding statement: if (e_137 != n_142)
Registering value_relation (e_137 != n_142) on (33->35)
Registering value_relation (e_137 == n_142) on (33->34)
Visiting conditional with predicate: if (e_137 != n_142)
With known ranges
e_137: [prange] const char16_t * [1, +INF] n_142: [prange] const
char16_t * VARYING
Predicate evaluates to: DON'T KNOW
***dbgcnt: lower limit 2 reached for prefetch.***
***dbgcnt: upper limit 2 reached for prefetch.***
gimple_simplified to if (1 != 0)
Folded into: if (1 != 0)
We have
# PT = null
e_137 = _130 + _136;
...
# PT = nonlocal escaped null const-pool { D.189684 } (escaped)
# USE = nonlocal escaped null const-pool { D.189684 } (escaped)
n_142 = QtPrivate::qustrchr (D.206385, 46);
D.206385 ={v} {CLOBBER(eos)};
if (e_137 != n_142)
the interesting thing is that VRP computes
e_137 : [prange] const char16_t * [1, +INF]
VRP clears PT = null on the pointer and thus makes the compare compare
'nothing' with 'something'. points-to computes
# PT = null
_130 = str.m_data;
the last initilizer is
[local count: 1034442871]:
_104 = state$start_100 + state$extra_101;
MEM[(struct QChar *)&D.206374 clique 15 base 1] ={v} {CLOBBER(bob)};
MEM[(struct QChar *)&D.206374 clique 15 base 1].ucs = 46;
str = MEM[(const struct QStringView &)&tok2 + 32];
PTA has
tok2.128+192 = __old_val_8
tok2.128+192 = &NONLOCAL
tok2.128+192 = &NONLOCAL
tok2.128+192 = __old_val_8
str.0+64 = tok2.128+192
_130 = str.64+64
for some reason the
str = MEM[(const struct QStringView &)&tok2 + 32];
assignment does not generate a
str.64+64 = tok2.192+64
constraint, that is, the source and dest varinfos do not seem to overlap.
We end up with
(gdb) p lhsc
$3 = {> = {m_vec = 0x5219080 = {{
type = SCALAR, var = 145, offset = 0}, {type = SCALAR, var = 146,
offset = 0}}}, }
(gdb) p rhsc
$6 = {> = {m_vec = 0x5824f60 = {{
type = SCALAR, var = 29, offset = 0}}}, }
where for the RHS that's the third var from 'tok2'. Having the copy
offset by 32 is a bit odd sice that puts us inside the third subobject
that we have not sub-setted.
In any case the issue seems to be that do_structure_copy applies
the offset "twice" here, it does
if (!get_ref_base_and_extent_hwi (lhsop, &lhsoffset, &lhssize, &reverse)
|| !get_ref_base_and_extent_hwi (rhsop, &rhsoffset, &rhssize,
&reverse))
{
process_all_all_constraints (lhsc, rhsc);
return;
computing 256 for rhsoffset (from the MEM_REF offset of 32 bytes) and
then checking overlap of two varinfos with
|| ranges_overlap_p (lhsv->offset + rhsoffset, lhsv->size,
rhsv->offset + lhsoffset, rhsv->size)))
the 2nd var of the LHS does not satisfy overlap.
I think the logic might only work when the offset computed by
get_ref_base_and_extent_hwi aligns with any of the fields offsets.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #30 from Alexander Monakov ---
Forgot to mention that the offending match.pd rule is
/* Simplify pointer equality compares using PTA. */
(for neeq (ne eq)
(simplify
(neeq @0 @1)
(if (POINTER_TYPE_P (TREE_TYPE (@0))
&& ptrs_compare_unequal (@0, @1))
{ constant_boolean_node (neeq != EQ_EXPR, type); })))
and ptrs_compare_unequal unexpectedly returns true (as already hinted in
comment #5)
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #29 from Alexander Monakov ---
The above is bisectable on the 'match' dbgcnt, which ends on this transform in
vrp1:
Folding statement: if (e_137 != n_142)
Registering value_relation (e_137 != n_142) on (33->35)
Registering value_relation (e_137 == n_142) on (33->34)
Visiting conditional with predicate: if (e_137 != n_142)
With known ranges
e_137: [prange] const char16_t * [1, +INF] n_142: [prange] const
char16_t * VARYING
Predicate evaluates to: DON'T KNOW
Matching expression match.pd:2934, gimple-match-8.cc:90
Matching expression match.pd:2938, gimple-match-4.cc:77
***dbgcnt: upper limit 22638 reached for match.***
Applying pattern match.pd:7956, gimple-match-9.cc:4682
gimple_simplified to if (1 != 0)
Folded into: if (1 != 0)
which looks highly suspicious as it eliminates this branch:
# PT = nonlocal escaped null const-pool { D.189389 } (escaped)
# USE = nonlocal escaped null const-pool { D.189389 } (escaped)
n_142 = QtPrivate::qustrchr (D.204906, 46);
D.204906 ={v} {CLOBBER(eos)};
if (e_137 != n_142)
goto ; [98.33%]
else
goto ; [1.67%]
above that, for e_137 we have
# PT =
e_137 = _130 + _136;
and for _130
# PT = null
_130 = str.m_data;
which is wrong?
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Alexander Monakov changed: What|Removed |Added CC||amonakov at gcc dot gnu.org --- Comment #28 from Alexander Monakov --- Created attachment 61811 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61811&action=edit standalone testcase A standalone variant of the comment #22 testcase, preprocessed and with enough noipa stubs added to avoid linking with QtBase.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #27 from Holger Hoffstätte ---
If I add lifetime-extending printfs to QStringTokenizerBase::next() like this:
--- qstringtokenizer.h 2025-07-04 17:56:28.523676630 +0200
+++ qstringtokenizer-printf.h 2025-07-04 17:56:03.998840901 +0200
@@ -389,11 +389,14 @@ auto QStringTokenizerBase return final element:
result = m_haystack.sliced(state.start);
+__builtin_printf("\nfinal: '%s'\n",
result.toString().toStdString().c_str());
}
if ((m_sb & Qt::SkipEmptyParts) && result.isEmpty()) {
+__builtin_printf("\nskipping empty result: '%s'\n",
result.toString().toStdString().c_str());
continue;
}
return {result, true, state};
..it starts to work. Removing any one of these printfs breaks the lifetime of
the
intermediate "Haystack result" and leads to garbage when trying to find the
last element.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #26 from Sam James --- I'm going to try clean it up with my poor C++, as I can't follow it at all right now.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #24 from Sam James ---
(In reply to Sam James from comment #11)
> Created attachment 61749 [details]
> small.cxx
OK, on this, with a small adjustment to change the two ""s as args to char*
str1, str2:
--- a/small.cxx.057t.local-fnsummary2
+++ b/small.cxx.057t.local-fnsummary2
@@ -1795,7 +1795,6 @@ IPA function summary for ar::as ar::aw(ao) [with
aq = QStringView]/104 i
calls:
long long int QtPrivate::ck(QStringView, long long int)/27 function not
considered for inlining
freq:0.41 loop depth: 0 size: 4 time: 13 callee size:12 stack: 0
predicate: (op1[offset: 32] >= 0)
- op1 points to local or readonly memory
struct as ar::aw (struct ar * const this, struct ao o)
{
@@ -1882,7 +1881,6 @@ IPA function summary for void ar::bc::operator++()
[with aq = QStringView]/7
calls:
long long int QtPrivate::ck(QStringView, long long int)/27 function not
considered for inlining
freq:0.41 loop depth: 0 size: 4 time: 13 callee size:12 stack: 0
predicate: (op0[ref offset: 256] >= 0)
- op1 points to local or readonly memory
void ar::bc::operator++ (struct bc * const this)
{
diff --git a/small.cxx.088i.fnsummary b/small.cxx.088i.fnsummary
index 3b673e5..09d0885 100644
--- a/small.cxx.088i.fnsummary
+++ b/small.cxx.088i.fnsummary
@@ -233,7 +233,6 @@ IPA function summary for void ar::bc::operator++()
[with aq = QStringView]/7
calls:
long long int QtPrivate::ck(QStringView, long long int)/27 function not
considered for inlining
freq:0.41 loop depth: 0 size: 4 time: 13 predicate: (op0[ref offset:
256] >= 0)
- op1 points to local or readonly memory
Analyzing function: decltype (QtPrivate::dc{0, l, df::t ...}) df(aq,
dd, de ...) [with aq = QString; dd = int; de = {am, }]/72
--- a/small.cxx.088i.fnsummary
+++ b/small.cxx.088i.fnsummary
@@ -233,7 +233,6 @@ IPA function summary for void ar::bc::operator++()
[with aq = QStringView]/7
calls:
long long int QtPrivate::ck(QStringView, long long int)/27 function not
considered for inlining
freq:0.41 loop depth: 0 size: 4 time: 13 predicate: (op0[ref offset:
256] >= 0)
- op1 points to local or readonly memory
Analyzing function: decltype (QtPrivate::dc{0, l, df::t ...}) df(aq,
dd, de ...) [with aq = QString; dd = int; de = {am, }]/72
diff --git a/small.cxx.089i.inline b/small.cxx.089i.inline
index c31c4f8..abe0280 100644
--- a/small.cxx.089i.inline
+++ b/small.cxx.089i.inline
@@ -182,7 +182,6 @@ IPA function summary for void ar::bc::operator++()
[with aq = QStringView]/7
calls:
long long int QtPrivate::ck(QStringView, long long int)/27 function not
considered for inlining
freq:0.41 loop depth: 0 size: 4 time: 13 callee size:12 stack: 0
predicate: (op0[ref offset: 256] >= 0)
- op1 points to local or readonly memory
IPA summary for bn< >::~bn() [with ag = QString]/68
is missing.
IPA function summary for bn< >::~bn() [with ag =
QString]/67 inlinable
@@ -820,7 +819,7 @@ Updated mod-ref summary for int main()/52
Considering long long int QtPrivate::ck(QStringView, long long int)/27 with 24
size
to be inlined into void ar::bc::operator++() [with aq = QStringView]/79
in small.cxx:177
Estimated badness is -0.15, frequency 3.36.
- Parm map: -1 -5
+ Parm map: -1 -1
Updated mod-ref summary for int main()/52
loads:
Base 0: alias set 8
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #25 from Sam James --- (In reply to Sam James from comment #24) > @@ -1882,7 +1881,6 @@ IPA function summary for void ar::bc::operator++() > [with aq = QStringView]/7 >calls: Adding __attribute__((noipa)) on that template works.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #23 from Holger Hoffstätte --- (In reply to Holger Hoffstätte from comment #22) > Created attachment 61758 [details] > Readable reproducer for debugging > > Slightly more reduced, no need for the join business. ..and not for the factory function either. I'm now sure that the added std::move is not accidental state reuse but "simply" a matter of instantiating one template working for both cases instead of two, where the second one goes off the rails. The executable differs in size. Why the second form (direct rvalue reference) makes a mess is unfortunately a mystery.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Holger Hoffstätte changed: What|Removed |Added Attachment #61755|0 |1 is obsolete|| --- Comment #22 from Holger Hoffstätte --- Created attachment 61758 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61758&action=edit Readable reproducer for debugging Slightly more reduced, no need for the join business.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #21 from Sam James --- (In reply to Holger Hoffstätte from comment #18) > results in *both* tests using HaystackPinning and working as expected - > though in the second case that might be accidental state reuse, which is > also concerning: -fstack-reuse=none doesn't help, but that doesn't prove much if it's a C++ FE issue.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #20 from Sam James --- (In reply to Holger Hoffstätte from comment #17) > I also get the impression that small.cxx now demonstrates a different > problem than before, but that might just be fallout from what I'm about to > show; this hole goes deeper. I can always re-run it with some specific condition keeping the list comparisons, but given it still kept the QList and dies w/o -fno-tree-pta, I figured it was the same. But I'm happy to spend some CPU on it if it provides some insight if people want ofc. (I had the same thought and went back and forth on it.) Next step if nobody has any insight yet is to do the debug counter I think and also see if anything leaps out from dumps, now that the file is much smaller.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #19 from Holger Hoffstätte ---
(In reply to Holger Hoffstätte from comment #18)
> Consequently the problematic second test (testNotOK) can be "fixed" by:
>
> auto tok = qTokenize(std::move(expected.join(u'.')), QLatin1Char('.'),
> Qt::CaseSensitive, Qt::SkipEmptyParts);
Sorry, no - this does *not* fix it. Sorry.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #18 from Holger Hoffstätte ---
Furthermore, using an explicit std::move to the first test like this:
auto joined = expected.join(u'.');
auto tok = qTokenize(std::move(joined), QLatin1Char('.'),
Qt::CaseSensitive, Qt::SkipEmptyParts);
results in *both* tests using HaystackPinning and working as expected - though
in the second case that might be accidental state reuse, which is also
concerning:
Breakpoint 1, dump > (tok=...) at
/usr/include/qt6/QtCore/qstringtokenizer.h:377
377 auto QStringTokenizerBase::next(tokenizer_state
state) const noexcept -> next_result
(gdb) p tok
$6 = (QStringTokenizer &) @0x7fffde40:
{> =
{> = {m_string = {d = {
d = 0x5556f640, ptr = 0x5556f650 u"a.ab.abc.abcd.abcde",
size = 19}}}, },
> = {> = {}, },
> = { = {
m_sb = {> =
{> = {static IntegerSize = 4,
i = 1}, }, }, m_cs =
Qt::CaseSensitive}, m_haystack = {m_size = 19, m_data = 0x5556f650
u"a.ab.abc.abcd.abcde"}, m_needle = {
ucs = 46 u'.'}}, }
(gdb) c
Continuing.
1 2 3 4 5
Breakpoint 1, dump > (tok=...) at
/usr/include/qt6/QtCore/qstringtokenizer.h:377
377 auto QStringTokenizerBase::next(tokenizer_state
state) const noexcept -> next_result
(gdb) p tok
$7 = (QStringTokenizer &) @0x7fffde40:
{> =
{> = {m_string = {d = {
d = 0x5556f640, ptr = 0x5556f650 u"a.ab.abc.abcd.abcde",
size = 19}}}, },
> = {> = {}, },
> = { = {
m_sb = {> =
{> = {static IntegerSize = 4,
i = 1}, }, }, m_cs =
Qt::CaseSensitive}, m_haystack = {m_size = 19, m_data = 0x5556f650
u"a.ab.abc.abcd.abcde"}, m_needle = {
ucs = 46 u'.'}}, }
(gdb) c
Continuing.
1 2 3 4 5
Consequently the problematic second test (testNotOK) can be "fixed" by:
auto tok = qTokenize(std::move(expected.join(u'.')), QLatin1Char('.'),
Qt::CaseSensitive, Qt::SkipEmptyParts);
Hope this helps.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #17 from Holger Hoffstätte --- Created attachment 61755 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61755&action=edit Readable reproducer for debugging (In reply to [email protected] from comment #16) > Does -fno-lifetime-dse help? It does not (in any example). I also get the impression that small.cxx now demonstrates a different problem than before, but that might just be fallout from what I'm about to show; this hole goes deeper. With my "readable.cpp" attachment (still needs Qt): holger>gdb a.out (gdb) b dump Breakpoint 1 at 0x148f: dump. (2 locations) (gdb) r Starting program: /mnt/tux/holger/Projects/qt6-gcc15/a.out [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Breakpoint 1.1, dump > (tok=...) at readable.cpp:8 8 for (auto &x : tok) { (gdb) p tok.m_haystack $1 = {m_size = 19, m_data = 0x5556f650 u"a.ab.abc.abcd.abcde"} --> looks fine (gdb) c Continuing. 1 2 3 4 5 --> as expected Breakpoint 1.2, dump > (tok=...) at readable.cpp:8 8 for (auto &x : tok) { (gdb) p tok.m_haystack $2 = {m_size = 93824992343616, m_data = 0x5556f650 u"a.ab.abc.abcd.abcde"} --> m_size is obviously bogus (gdb) c Continuing. 1 2 3 4 5 18446744073709551615 The interesting difference here is that the tokenizer "pins" moved-into haystacks and that's when things go wrong. Unpinned (good): Breakpoint 1.1, dump > (tok=...) at readable.cpp:8 8 for (auto &x : tok) { (gdb) p tok $1 = (QStringTokenizer &) : {> = {> = {}, }, > = {> = {}, }, > = { = { m_sb = {> = {> = {static IntegerSize = 4, i = }, }, }, m_cs = }, m_haystack = {m_size = 19, m_data = 0x5556f650 u"a.ab.abc.abcd.abcde"}, m_needle = {ucs = }}, } (gdb) c Continuing. 1 2 3 4 5 Pinned (wrong): Breakpoint 1.2, dump > (tok=...) at readable.cpp:8 8 for (auto &x : tok) { (gdb) p tok $2 = (QStringTokenizer &) @0x7fffde20: {> = {> = {m_string = {d = { d = 0x002e, ptr = 0x5556f650 u"a.ab.abc.abcd.abcde", size = 19}}}, }, > = {> = {}, }, > = { = { m_sb = {> = {> = {static IntegerSize = 4, i = 1}, }, }, m_cs = Qt::CaseSensitive}, m_haystack = {m_size = 93824992343616, m_data = 0x5556f650 u"a.ab.abc.abcd.abcde"}, m_needle = {ucs = 46 u'.'}}, } (gdb) c Continuing. 1 2 3 4 5 18446744073709551615 We can see that Pinning has size=19 (correct), but m_haystack has m_size = 93824992343616 (wrong).
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #16 from rguenther at suse dot de --- > Am 29.06.2025 um 02:08 schrieb sjames at gcc dot gnu.org > : > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 > > --- Comment #13 from Sam James --- > FWIW, it fails with -fno-strict-aliasing still (and the original). Does -fno-lifetime-dse help? > -- > You are receiving this mail because: > You are on the CC list for the bug.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #15 from Andrew Pinski --- (In reply to Sam James from comment #13) > FWIW, it fails with -fno-strict-aliasing still (and the original). oh.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #14 from Andrew Pinski --- https://doc.qt.io/qt-6/qchar.html yes what they mention is totally wrong. I am 99% sure QT code is not alias friendly at all and needs to be fixed and it looks hard to fix as they treat char16_t and QChar as compatible from an aliasing point of view but that is never true in C++. Doing stores via QChar and then loads via char16_t is fine but the opposite is undefined. And then in this case doing comparisons of pointers will cause issues.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #13 from Sam James --- FWIW, it fails with -fno-strict-aliasing still (and the original).
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #12 from Andrew Pinski ---
(In reply to Sam James from comment #11)
> Created attachment 61749 [details]
> small.cxx
I think there might be some aliasing issue with char16_t and Qchar.
```
QChar *begin() const { return reinterpret_cast(d.bp()); }
bn d;
bn::d :
ag *bp() const { return bv; }
ag *bv;
struct QChar {
QChar(char16_t) {}
char16_t bg;
};
```
I suspect this is true of the original code too.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Sam James changed: What|Removed |Added Attachment #61748|0 |1 is obsolete|| --- Comment #11 from Sam James --- Created attachment 61749 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61749&action=edit small.cxx
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #10 from Sam James --- Created attachment 61748 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61748&action=edit small.cxx Not sure if this testcase is valid but it aborts with >=15 with -O3 and works with -fno-tree-pta. It still needs to link against Qt though.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #9 from Sam James --- Created attachment 61740 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61740&action=edit foo.ii.xz
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
Sam James changed:
What|Removed |Added
CC||kacper.slominski72 at gmail
dot co
||m
--- Comment #8 from Sam James ---
Kacper Słomiński has got it down to:
```
#include
#include
int main() {
auto expected = QStringList{"a", "b", "c", "d", "e"};
auto tok = qTokenize(expected.join(u'x'), QLatin1Char('x'),
Qt::CaseSensitive, Qt::SkipEmptyParts);
QStringList r;
for (auto &&e : tok)
r.push_back(e.toString());
if (r.size() != expected.size()) abort();
}
```
which fails with:
```
$ g++ -DQT_NO_DEBUG $(pkg-config --libs --cflags Qt6Core) -std=gnu++17 foo.cxx
-o foo -O3 && ./foo
```
I'll attach preprocessed source for that but we're working on killing the Qt
dependency next.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #7 from Holger Hoffstätte ---
Sorry if the following is unhelpful - I'm just an interested observer.
Since I could easily reproduce the problem I decided to poke at things
in gdb and got a bit annoyed at the bad test code style. So I un-inlined
the call to expected.join() into a local and .. all tests pass.
Yay?
--- a/tst_qstringtokenizer.cpp.ii
+++ b/tst_qstringtokenizer_hh.cpp.ii
@@ -257685,7 +257685,8 @@ void tst_QStringTokenizer::basics() const
expected = skipped(expected);
using namespace std::string_literals;
-auto tok = qTokenize(expected.join(u'x'), QLatin1Char('x'), cs, sb);
+auto joined = expected.join(u'x');
+auto tok = qTokenize(joined, QLatin1Char('x'), cs, sb);
do { if (!QTest::qCompare(toQStringList(tok), expected,
"toQStringList(tok)", "expected",
"/home/sam/bugs/qt/qtbase-everywhere-src-6.9.0/tests/auto/corelib/text/qs>
}
Is this maybe a temporary/lifetime thing going wrong?
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #6 from Sam James --- (In reply to Richard Biener from comment #5) I'll find some time to try make more progress. Will try adding a counter if I cannot get further with reducing, but luckily, the C++ in the file isn't too complex ;)
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
--- Comment #5 from Richard Biener ---
(In reply to Sam James from comment #0)
> Looking at dumps between r15-579-ga9251ab3c91c8c and
> r15-580-gf3e5f4c58591f5, there's a lot of noise like:
> ```
> - # PT = nonlocal escaped null { D.387695 D.418643 } (nonlocal, escaped)
> - # USE = nonlocal escaped null { D.387695 D.418643 } (nonlocal, escaped)
> - # CLB = nonlocal escaped null { D.387695 D.418643 } (nonlocal, escaped)
> + # PT = nonlocal escaped null const-pool { D.387695 D.418643 } (nonlocal,
> escaped)
> + # USE = nonlocal escaped null const-pool { D.387695 D.418643 } (nonlocal,
> escaped)
> + # CLB = nonlocal escaped null const-pool { D.387695 D.418643 } (nonlocal,
> escaped)
> ```
without a testcase it's hard to see what goes wrong - the above is a
correctness fix, we get strictly larger points-to sets. For ptr-ptr
compares we rely on those being conservative, so possibly we miss more.
I'll note the newer preprocessed source doesn't build around the offending rev
(the old does).
The first actual IL difference happens in VRP1. Differences in wc -l for
all dump files (w/o details):
qt.ii.120t.threadfull1 0
qt.ii.121t.vrp1 20
qt.ii.122t.dse2 30
..
qt.ii.149t.walloca2 20
qt.ii.150t.pre 29
qt.ii.151t.sink1 53
qt.ii.155t.dse3 43
...
qt.ii.202t.thread2 7
qt.ii.203t.dom3 49
qt.ii.204t.strlen1 39
qt.ii.205t.threadfull2 180
qt.ii.206t.vrp2 106
it's not definite data since there's stuff that should be in -details
leaking into normal dumps. It's quite difficult to isolate an
offending transform. Possibly adding a dbgcnt to ptrs_compare_unequal
when it triggers the ptr-vs.-ptr case can track down the bogus offender...
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Richard Biener changed: What|Removed |Added Priority|P3 |P2 CC||rguenth at gcc dot gnu.org
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #4 from Andrew Pinski --- (In reply to Sam James from comment #3) > Created attachment 61474 [details] > tst_qstringtokenizer.cpp.ii.xz Just a quick note -march=znver2 is needed to compile this preprocessed source. Even though -march=x86-64-v4 is mentioned in comment #0 :).
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Andrew Pinski changed: What|Removed |Added Ever confirmed|1 |0 Status|WAITING |UNCONFIRMED
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Sam James changed: What|Removed |Added Attachment #61472|0 |1 is obsolete|| --- Comment #3 from Sam James --- Created attachment 61474 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61474&action=edit tst_qstringtokenizer.cpp.ii.xz
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Andrew Pinski changed: What|Removed |Added Ever confirmed|0 |1 Last reconfirmed||2025-05-19 Status|UNCONFIRMED |WAITING --- Comment #2 from Andrew Pinski --- (In reply to Sam James from comment #0) > Created attachment 61472 [details] > tst_qstringtokenizer.cpp.ii.xz Is there a way to regenerate this preprocessed source with a more recent GCC 15? AVX512ER support has been removed so we get errors.
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 Andrew Pinski changed: What|Removed |Added Target Milestone|--- |15.2 Keywords||alias
[Bug tree-optimization/120358] [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358 --- Comment #1 from Sam James --- Created attachment 61473 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61473&action=edit build.sh
