[Bug tree-optimization/126384] New: [17 Regression] Miscompare by SPEC CPU 2006 astar (-ffast-math) since r17-2654-gfb0838bc1073aa

"pheeck at gcc dot gnu.org via Gcc-bugs" <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.