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)

Reply via email to