https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126384
Bug ID: 126384
Summary: [17 Regression] Miscompare by SPEC CPU 2006 astar
(-ffast-math) since r17-2654-gfb0838bc1073aa
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: pheeck at gcc dot gnu.org
CC: rguenth at gcc dot gnu.org
Blocks: 26163
Target Milestone: ---
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
This is a case where -ffast-math leads to wrong outputs. That may not be a
miscompilation. But even if it isn't, maybe it is possible to avoid the loss
of precision? Therefore, I decided to investigate and report this.
-- How to reproduce --
Compile the SPEC CPU 2006 benchmark astar with trunk GCC using -O2 -ffast-math
(generic march).
/home/fkastl/gcc/inst/bin/g++ -c -o CreateWay_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 CreateWay_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o Places_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 Places_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o RegBounds_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 RegBounds_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o RegMng_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 RegMng_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o Way2_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 Way2_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o WayInit_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 WayInit_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o Library.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 Library.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o Random.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 Random.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o Region_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 Region_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o RegWay_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 RegWay_.cpp
/home/fkastl/gcc/inst/bin/g++ -c -o Way_.o -DSPEC_CPU -DNDEBUG
-DSPEC_CPU_LITTLE_ENDIAN -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 Way_.cpp
/home/fkastl/gcc/inst/bin/g++ -O2 -ffast-math -g -fpermissive -std=gnu++17
-DSPEC_CPU_LP64 -Wl,-rpath,/home/fkastl/gcc/inst/lib64 CreateWay_.o
Places_.o RegBounds_.o RegMng_.o Way2_.o WayInit_.o Library.o Random.o
Region_.o RegWay_.o Way_.o -o astar
Run it on the 473.astar/data/train/input/BigLakes1024.cfg input.
./astar BigLakes1024.cfg > BigLakes1024.out 2>> BigLakes1024.err
And let SPEC compare the output with the reference output.
specperl /home/fkastl/gcc/benchmarks/cpu2006/bin/specdiff -m -l 10 --reltol
0.001
/home/fkastl/gcc/benchmarks/cpu2006/benchspec/CPU2006/473.astar/data/train/output/BigLakes1024.out
BigLakes1024.out > BigLakes1024.out.cmp
You'll get this in BigLakes1024.out.cmp:
0028: Total way length : 102620
Total way length : 92310
^
0031: Reg ways quantity : 1578
Reg ways quantity : 1587
^
0032: Total reg way length : 192914
Total reg way length : 193584
^
This causes PGO builds of the benchmark to fail, because BigLakes1024.cfg is
used as a training input for the instrumented binary and the SPEC benchmarking
tools check that even the instrumented binary produces correct output.
-- What I found out --
The problem is in Random.cpp, in the function 'rnumt myrandom()' (you can
replicate the miscompare even if you use -ffast-math only for this file, and
even if you use #pragma GCC optimize("O0") on the other functions in this
file).
Here is a diff of -fdump-tree-optimize dumps:
diff -up dumps-{without,with}-ffast-math/*optimized
--- dumps-without-ffast-math/Random.cpp.272t.optimized 2026-07-24
09:47:18.242308006 +0200
+++ dumps-with-ffast-math/Random.cpp.272t.optimized 2026-07-24
09:47:24.470276941 +0200
@@ -3,9 +3,9 @@
rnumt myrandom ()
{
- rnumt x3;
+ vector(2) float vect_x3_23.10;
+ vector(2) float vect_x3_22.9;
rnumt x2;
- rnumt x1;
int y1rnd.0_1;
int _2;
int _3;
@@ -15,11 +15,14 @@ rnumt myrandom ()
int y3rnd.2_7;
int _8;
int _9;
- float _10;
- float _11;
int _12;
float _13;
rnumt _24;
+ vector(2) int _44;
+ float _47;
+ float _48;
+ float _49;
+ float _50;
<bb 2> [local count: 1073741824]:
# DEBUG BEGIN_STMT
@@ -37,13 +40,14 @@ rnumt myrandom ()
y3rnd.2_7 = y3rnd;
_8 = y3rnd.2_7 * 170;
_9 = _8 % 30323;
+ _44 = {_9, _3};
+ vect_x3_22.9_45 = (vector(2) float) _44;
+ vect_x3_23.10_46 = vect_x3_22.9_45 * {
3.297826697234995663166046142578125e-5, 3.303710036561824381351470947265625e-5
};
y3rnd = _9;
# DEBUG BEGIN_STMT
- x1_18 = (rnumt) _3;
- # DEBUG x1 => x1_18
+ # DEBUG D#2 => (rnumt) _3
# DEBUG BEGIN_STMT
- x1_19 = x1_18 * 3.303710036561824381351470947265625e-5;
- # DEBUG x1 => x1_19
+ # DEBUG x1 => D#2 * 3.303710036561824381351470947265625e-5
# DEBUG BEGIN_STMT
x2_20 = (rnumt) _6;
# DEBUG x2 => x2_20
@@ -51,17 +55,17 @@ rnumt myrandom ()
x2_21 = x2_20 * 3.299567833892069756984710693359375e-5;
# DEBUG x2 => x2_21
# DEBUG BEGIN_STMT
- x3_22 = (rnumt) _9;
- # DEBUG x3 => x3_22
+ # DEBUG D#1 => (rnumt) _9
# DEBUG BEGIN_STMT
- x3_23 = x3_22 * 3.297826697234995663166046142578125e-5;
- # DEBUG x3 => x3_23
+ # DEBUG x3 => D#1 * 3.297826697234995663166046142578125e-5
# DEBUG BEGIN_STMT
- _10 = x1_19 + x2_21;
- _11 = _10 + x3_23;
- _12 = (int) _11;
+ _47 = BIT_FIELD_REF <vect_x3_23.10_46, 32, 0>;
+ _48 = BIT_FIELD_REF <vect_x3_23.10_46, 32, 32>;
+ _49 = _47 + _48;
+ _50 = x2_21 + _49;
+ _12 = (int) _50;
_13 = (float) _12;
- _24 = _11 - _13;
+ _24 = _50 - _13;
return _24;
}
The pass tree-slp2 performs the problematic transformation. It is the pass
that inserts the BIT_FIELD_REFs, and if I do -fdisable-tree-slp2, the
miscompare disappears.
r17-2654-gfb0838bc1073aa is a recent commit that modifies slp. Indeed, if I
revert it, the miscompare also disappears.
commit fb0838bc1073aa5f22ec38e0cca2d70d625c6d71
Author: Richard Biener <[email protected]>
AuthorDate: Wed Jul 15 10:37:57 2026 +0200
Commit: Richard Biener <[email protected]>
CommitDate: Thu Jul 23 10:24:38 2026 +0200
Support two-lane vector BB reductions without target support
Here is the diff of the -fdump-tree-slp2 dumps with and without the revert:
diff -up dumps-with-revert/*slp2 dumps-with-ffast-math/*slp2
--- dumps-with-revert/Random.cpp.200t.slp2 2026-07-24 10:08:22.199021913
+0200
+++ dumps-with-ffast-math/Random.cpp.200t.slp2 2026-07-24 09:47:24.454945482
+0200
@@ -10,6 +10,8 @@
;; 2 succs { 1 }
rnumt myrandom ()
{
+ vector(2) float vect_x3_23.10;
+ vector(2) float vect_x3_22.9;
rnumt x3;
rnumt x2;
rnumt x1;
@@ -27,6 +29,11 @@ rnumt myrandom ()
int _12;
float _13;
rnumt _24;
+ vector(2) int _44;
+ float _47;
+ float _48;
+ float _49;
+ float _50;
<bb 2> [local count: 1073741824]:
# DEBUG BEGIN_STMT
@@ -44,6 +51,9 @@ rnumt myrandom ()
y3rnd.2_7 = y3rnd;
_8 = y3rnd.2_7 * 170;
_9 = _8 % 30323;
+ _44 = {_9, _3};
+ vect_x3_22.9_45 = (vector(2) float) _44;
+ vect_x3_23.10_46 = vect_x3_22.9_45 * {
3.297826697234995663166046142578125e-5, 3.303710036561824381351470947265625e-5
};
y3rnd = _9;
# DEBUG BEGIN_STMT
x1_18 = (rnumt) _3;
@@ -65,7 +75,11 @@ rnumt myrandom ()
# DEBUG x3 => x3_23
# DEBUG BEGIN_STMT
_10 = x1_19 + x2_21;
- _11 = _10 + x3_23;
+ _47 = BIT_FIELD_REF <vect_x3_23.10_46, 32, 0>;
+ _48 = BIT_FIELD_REF <vect_x3_23.10_46, 32, 32>;
+ _49 = _47 + _48;
+ _50 = _49 + x2_21;
+ _11 = _50;
_12 = (int) _11;
_13 = (float) _12;
_24 = _11 - _13;
Referenced Bugs:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26163
[Bug 26163] [meta-bug] missed optimization in SPEC (2026, 2k17, 2k and 2k6 and
95)