https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127177

--- Comment #9 from Matthias Kretz (Vir) <mkretz at gcc dot gnu.org> ---
I did some benchmarking.

TL;DR: If fpclass* is available, it doesn't hurt to use it, and it can be
better. For vectorization, the integer compare seems to be the general
preference. For scalar, the current solution seems best. But it won't hurt to
use integer compare for scalar isinf and always be correct with
-fsignaling-nans.


The benchmark is basically this loop:

for (int i = 0; i < 1'000'000; ++i)
  {
    float y = 1;
    if (isinf(x)) x = 0;
    x += y;
  }

This puts isinf into the critical path and its latency directly influences the
measurement.

With -march=x86-64-v4 I get the following asm:

BENCHMARK(scalar_latency<scalar_abs_gt_max>);
  40cab0:       vandps xmm0,xmm1,xmm3
  40cab4:       vucomiss xmm0,DWORD PTR [rip+0x46558]        # 453014
<_IO_stdin_used+0x14>
  40cabc:       vmovaps xmm0,xmm2
  40cac0:       jbe    40cac6 <void
scalar_latency<&(scalar_abs_gt_max(float))>(benchmark::State&)+0x96>
  40cac2:       vxorps xmm0,xmm0,xmm0
  40cac6:       vaddss xmm1,xmm1,xmm0
  40caca:       sub    eax,0x1
  40cacd:       jne    40cab0 <void
scalar_latency<&(scalar_abs_gt_max(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_abs_eq_inf>);
  40c9f0:       vandps xmm0,xmm1,xmm3
  40c9f4:       vucomiss xmm0,DWORD PTR [rip+0x46614]        # 453010
<_IO_stdin_used+0x10>
  40c9fc:       vmovaps xmm0,xmm2
  40ca00:       jp     40ca08 <void
scalar_latency<&(scalar_abs_eq_inf(float))>(benchmark::State&)+0x98>
  40ca02:       jne    40ca08 <void
scalar_latency<&(scalar_abs_eq_inf(float))>(benchmark::State&)+0x98>
  40ca04:       vxorps xmm0,xmm0,xmm0
  40ca08:       vaddss xmm1,xmm1,xmm0
  40ca0c:       sub    eax,0x1
  40ca0f:       jne    40c9f0 <void
scalar_latency<&(scalar_abs_eq_inf(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_eq_ninf_fpcmp>);
  40c930:       vorps  xmm0,xmm1,xmm2
  40c934:       vucomiss xmm0,DWORD PTR [rip+0x466d0]        # 45300c
<_IO_stdin_used+0xc>
  40c93c:       vmovaps xmm0,xmm3
  40c940:       jp     40c948 <void
scalar_latency<&(scalar_eq_ninf_fpcmp(float))>(benchmark::State&)+0x98>
  40c942:       jne    40c948 <void
scalar_latency<&(scalar_eq_ninf_fpcmp(float))>(benchmark::State&)+0x98>
  40c944:       vxorps xmm0,xmm0,xmm0
  40c948:       vaddss xmm1,xmm1,xmm0
  40c94c:       sub    eax,0x1
  40c94f:       jne    40c930 <void
scalar_latency<&(scalar_eq_ninf_fpcmp(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_eq_ninf_intcmp>);
  40c870:       vmovd  edx,xmm1
  40c874:       vmovaps xmm0,xmm2
  40c878:       or     edx,0x80000000
  40c87e:       cmp    edx,0xff800000
  40c884:       jne    40c88a <void
scalar_latency<&(scalar_eq_ninf_intcmp(float))>(benchmark::State&)+0x9a>
  40c886:       vxorps xmm0,xmm0,xmm0
  40c88a:       vaddss xmm1,xmm1,xmm0
  40c88e:       sub    eax,0x1
  40c891:       jne    40c870 <void
scalar_latency<&(scalar_eq_ninf_intcmp(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_fpclass>);
  40c710:       vfpclassss k0,xmm1,0x18
  40c717:       vmovaps xmm0,xmm2
  40c71b:       kortestd k0,k0
  40c720:       je     40c726 <void
scalar_latency<&(scalar_fpclass(float))>(benchmark::State&)+0x86>
  40c722:       vxorps xmm0,xmm0,xmm0
  40c726:       vaddss xmm1,xmm1,xmm0
  40c72a:       sub    eax,0x1
  40c72d:       jne    40c710 <void
scalar_latency<&(scalar_fpclass(float))>(benchmark::State&)+0x70>

BENCHMARK(vector_latency<vec_abs_gt_max>);
  40c660:       vandps zmm1,zmm0,zmm3
  40c666:       vcmpltps k1,zmm4,zmm1
  40c66d:       vmovaps zmm1{k1}{z},zmm2
  40c673:       vaddps zmm0,zmm0,zmm1
  40c679:       sub    eax,0x1
  40c67c:       jne    40c660 <void
vector_latency<&(vec_abs_gt_max(std::simd::basic_vec<float, std::simd::_Abi<16,
1, 1ull> >))>(benchmark::State&)+0xc0>

BENCHMARK(vector_latency<vec_abs_eq_inf>);
  40c560:       vandps zmm1,zmm0,zmm4
  40c566:       vcmpeqps k1,zmm1,zmm3
  40c56d:       vmovaps zmm1{k1}{z},zmm2
  40c573:       vaddps zmm0,zmm0,zmm1
  40c579:       sub    eax,0x1
  40c57c:       jne    40c560 <void
vector_latency<&(vec_abs_eq_inf(std::simd::basic_vec<float, std::simd::_Abi<16,
1, 1ull> >))>(benchmark::State&)+0xc0>

BENCHMARK(vector_latency<vec_eq_ninf_fpcmp>);
  40c460:       vorps  zmm1,zmm0,zmm4
  40c466:       vcmpeqps k1,zmm1,zmm3
  40c46d:       vmovaps zmm1{k1}{z},zmm2
  40c473:       vaddps zmm0,zmm0,zmm1
  40c479:       sub    eax,0x1
  40c47c:       jne    40c460 <void
vector_latency<&(vec_eq_ninf_fpcmp(std::simd::basic_vec<float,
std::simd::_Abi<16, 1, 1ull> >))>(benchmark::State&)+0xc0>

BENCHMARK(vector_latency<vec_eq_ninf_intcmp>);
  40c360:       vorps  zmm1,zmm0,zmm4
  40c366:       vpcmpeqd k1,zmm1,zmm2
  40c36c:       vmovaps zmm1{k1}{z},zmm3
  40c372:       vaddps zmm0,zmm0,zmm1
  40c378:       sub    eax,0x1
  40c37b:       jne    40c360 <void
vector_latency<&(vec_eq_ninf_intcmp(std::simd::basic_vec<float,
std::simd::_Abi<16, 1, 1ull> >))>(benchmark::State&)+0xc0>

BENCHMARK(vector_latency<vec_fpclass_mask>);
  40c1a0:       vfpclassps k1,zmm0,0x18
  40c1a7:       vmovaps zmm1{k1}{z},zmm2
  40c1ad:       vaddps zmm0,zmm0,zmm1
  40c1b3:       sub    eax,0x1
  40c1b6:       jne    40c1a0 <void
vector_latency<&(vec_fpclass_mask(std::simd::basic_vec<float,
std::simd::_Abi<16, 1, 1ull> >))>(benchmark::State&)+0x80>


With -march=x86-64-v3 I get:

BENCHMARK(scalar_latency<scalar_abs_gt_max>);
  40c9b0:       vandps xmm0,xmm1,xmm3
  40c9b4:       vucomiss xmm0,DWORD PTR [rip+0x46654]        # 453010
<_IO_stdin_used+0x10>
  40c9bc:       vmovaps xmm0,xmm2
  40c9c0:       jbe    40c9c6 <void
scalar_latency<&(scalar_abs_gt_max(float))>(benchmark::State&)+0x96>
  40c9c2:       vxorps xmm0,xmm0,xmm0
  40c9c6:       sub    eax,0x1
  40c9c9:       vaddss xmm1,xmm1,xmm0
  40c9cd:       jne    40c9b0 <void
scalar_latency<&(scalar_abs_gt_max(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_abs_eq_inf>);
  40c8f0:       vandps xmm0,xmm1,xmm3
  40c8f4:       vucomiss xmm0,DWORD PTR [rip+0x46710]        # 45300c
<_IO_stdin_used+0xc>
  40c8fc:       vmovaps xmm0,xmm2
  40c900:       jp     40c908 <void
scalar_latency<&(scalar_abs_eq_inf(float))>(benchmark::State&)+0x98>
  40c902:       jne    40c908 <void
scalar_latency<&(scalar_abs_eq_inf(float))>(benchmark::State&)+0x98>
  40c904:       vxorps xmm0,xmm0,xmm0
  40c908:       sub    eax,0x1
  40c90b:       vaddss xmm1,xmm1,xmm0
  40c90f:       jne    40c8f0 <void
scalar_latency<&(scalar_abs_eq_inf(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_eq_ninf_fpcmp>);
  40c830:       vorps  xmm0,xmm1,xmm2
  40c834:       vucomiss xmm0,DWORD PTR [rip+0x467cc]        # 453008
<_IO_stdin_used+0x8>
  40c83c:       vmovaps xmm0,xmm3
  40c840:       jp     40c848 <void
scalar_latency<&(scalar_eq_ninf_fpcmp(float))>(benchmark::State&)+0x98>
  40c842:       jne    40c848 <void
scalar_latency<&(scalar_eq_ninf_fpcmp(float))>(benchmark::State&)+0x98>
  40c844:       vxorps xmm0,xmm0,xmm0
  40c848:       sub    eax,0x1
  40c84b:       vaddss xmm1,xmm1,xmm0
  40c84f:       jne    40c830 <void
scalar_latency<&(scalar_eq_ninf_fpcmp(float))>(benchmark::State&)+0x80>

BENCHMARK(scalar_latency<scalar_eq_ninf_intcmp>);
  40c778:       vmovd  edx,xmm1
  40c77c:       vmovaps xmm0,xmm2
  40c780:       or     edx,0x80000000
  40c786:       cmp    edx,0xff800000
  40c78c:       jne    40c792 <void
scalar_latency<&(scalar_eq_ninf_intcmp(float))>(benchmark::State&)+0x92>
  40c78e:       vxorps xmm0,xmm0,xmm0
  40c792:       sub    eax,0x1
  40c795:       vaddss xmm1,xmm1,xmm0
  40c799:       jne    40c778 <void
scalar_latency<&(scalar_eq_ninf_intcmp(float))>(benchmark::State&)+0x78>

BENCHMARK(vector_latency<vec_abs_gt_max>);
  40c580:       vandps ymm0,ymm1,ymm4
  40c584:       sub    eax,0x1
  40c587:       vcmpltps ymm0,ymm3,ymm0
  40c58c:       vpand  ymm0,ymm2,ymm0
  40c590:       vaddps ymm1,ymm1,ymm0
  40c594:       jne    40c580 <void
vector_latency<&(vec_abs_gt_max(std::simd::basic_vec<float, std::simd::_Abi<8,
1, 0ull> >))>(benchmark::State&)+0xa0>

BENCHMARK(vector_latency<vec_abs_eq_inf>);
  40c4a0:       vandps ymm0,ymm1,ymm4
  40c4a4:       sub    eax,0x1
  40c4a7:       vcmpeqps ymm0,ymm0,ymm3
  40c4ac:       vpand  ymm0,ymm2,ymm0
  40c4b0:       vaddps ymm1,ymm1,ymm0
  40c4b4:       jne    40c4a0 <void
vector_latency<&(vec_abs_eq_inf(std::simd::basic_vec<float, std::simd::_Abi<8,
1, 0ull> >))>(benchmark::State&)+0xa0>

BENCHMARK(vector_latency<vec_eq_ninf_fpcmp>);
  40c3c0:       vorps  ymm0,ymm1,ymm4
  40c3c4:       sub    eax,0x1
  40c3c7:       vcmpeqps ymm0,ymm0,ymm3
  40c3cc:       vpand  ymm0,ymm2,ymm0
  40c3d0:       vaddps ymm1,ymm1,ymm0
  40c3d4:       jne    40c3c0 <void
vector_latency<&(vec_eq_ninf_fpcmp(std::simd::basic_vec<float,
std::simd::_Abi<8, 1, 0ull> >))>(benchmark::State&)+0xa0>

BENCHMARK(vector_latency<vec_eq_ninf_intcmp>);
  40c2e0:       vorps  ymm0,ymm1,ymm4
  40c2e4:       sub    eax,0x1
  40c2e7:       vpcmpeqd ymm0,ymm0,ymm3
  40c2eb:       vpand  ymm0,ymm0,ymm2
  40c2ef:       vaddps ymm1,ymm1,ymm0
  40c2f3:       jne    40c2e0 <void
vector_latency<&(vec_eq_ninf_intcmp(std::simd::basic_vec<float,
std::simd::_Abi<8, 1, 0ull> >))>(benchmark::State&)+0xa0>

On an Intel(R) Xeon(R) W-2145 CPU @ 3.70GHz system

-march=x86-64-v3:
-------------------------------------------------------------------------------------------------------------------
Benchmark                                      Time             CPU  
Iterations     CYCLES INSTRUCTIONS        IPC
-------------------------------------------------------------------------------------------------------------------
scalar_latency<scalar_abs_gt_max>         901170 ns       901140 ns         
742   4.00241M     7.00001M    1.74895
scalar_latency<scalar_abs_eq_inf>        1082323 ns      1082119 ns         
700   4.81333M     8.00001M    1.66205
scalar_latency<scalar_eq_ninf_fpcmp>     1014561 ns      1014085 ns         
714   4.44968M     8.00001M    1.79788
scalar_latency<scalar_eq_ninf_intcmp>     970507 ns       970330 ns         
724   4.24098M     8.00001M    1.88636
vector_latency<vec_abs_gt_max>           2711088 ns      2710493 ns         
259   11.8666M     6.00001M   0.505624
vector_latency<vec_abs_eq_inf>           2714891 ns      2713491 ns         
259   11.8659M     6.00001M   0.505651
vector_latency<vec_eq_ninf_fpcmp>        2697500 ns      2697030 ns         
259   11.8666M     6.00001M   0.505624
vector_latency<vec_eq_ninf_intcmp>       1832236 ns      1831533 ns         
383   8.12751M     6.00001M   0.738234

-march=x86-64-v4:
-------------------------------------------------------------------------------------------------------------------
Benchmark                                      Time             CPU  
Iterations     CYCLES INSTRUCTIONS        IPC
-------------------------------------------------------------------------------------------------------------------
scalar_latency<scalar_abs_gt_max>         901364 ns       901227 ns         
751   4.00131M     7.00001M    1.74943
scalar_latency<scalar_abs_eq_inf>         936893 ns       936732 ns         
764   4.16215M     8.00001M    1.92208
scalar_latency<scalar_eq_ninf_fpcmp>     1038307 ns      1038038 ns         
665   4.60913M     8.00001M    1.73569
scalar_latency<scalar_eq_ninf_intcmp>     903080 ns       902915 ns         
779   4.00141M     8.00001M     1.9993
scalar_latency<scalar_fpclass>            913609 ns       913298 ns         
744    4.0032M     7.00001M    1.74861
vector_latency<vec_abs_gt_max>           2766369 ns      2765630 ns         
254   10.9426M     6.00001M   0.548316
vector_latency<vec_abs_eq_inf>           2795032 ns      2794206 ns         
251   10.9459M     6.00001M    0.54815
vector_latency<vec_eq_ninf_fpcmp>        2769082 ns      2768627 ns         
254    10.943M     6.00001M   0.548298
vector_latency<vec_eq_ninf_intcmp>       2793158 ns      2792376 ns         
251   10.9455M     6.00001M   0.548173
vector_latency<vec_fpclass_mask>         2299563 ns      2299045 ns         
303   9.02547M     5.00001M   0.553989


On an Intel(R) Core(TM) Ultra 7 165U laptop:

-march=x86-64-v3:
-------------------------------------------------------------------------------------------------------------------
Benchmark                                      Time             CPU  
Iterations     CYCLES INSTRUCTIONS        IPC
-------------------------------------------------------------------------------------------------------------------
scalar_latency<scalar_abs_gt_max>         565470 ns       565475 ns        
1265   2.07347M     7.00001M    3.37599
scalar_latency<scalar_abs_eq_inf>         515747 ns       515645 ns        
1257   2.05566M     8.00001M     3.8917
scalar_latency<scalar_eq_ninf_fpcmp>      564059 ns       564065 ns        
1427   2.12581M     8.00001M    3.76328
scalar_latency<scalar_eq_ninf_intcmp>     570534 ns       570358 ns        
1058   2.16697M     8.00001M    3.69179
vector_latency<vec_abs_gt_max>           2428999 ns      2428794 ns         
281   10.4335M     6.00001M   0.575072
vector_latency<vec_abs_eq_inf>           2477083 ns      2476535 ns         
252   10.4275M     6.00001M     0.5754
vector_latency<vec_eq_ninf_fpcmp>        2352268 ns      2352001 ns         
290   10.4265M     6.00001M   0.575456
vector_latency<vec_eq_ninf_intcmp>       1553970 ns      1553645 ns         
482   6.15973M     6.00001M   0.974069


AMD EPYC 9654 96-Core Processor:

-march=x86-64-v3:
-------------------------------------------------------------------------------------------------------------------
Benchmark                                      Time             CPU  
Iterations     CYCLES INSTRUCTIONS        IPC
-------------------------------------------------------------------------------------------------------------------
scalar_latency<scalar_abs_gt_max>        1334837 ns      1329645 ns         
529   3.18514M     7.00001M    2.19771
scalar_latency<scalar_abs_eq_inf>        1257570 ns      1252693 ns         
559   3.00086M     8.00001M     2.6659
scalar_latency<scalar_eq_ninf_fpcmp>     1257765 ns      1252755 ns         
559   3.00077M     8.00001M    2.66598
scalar_latency<scalar_eq_ninf_intcmp>    1257623 ns      1252687 ns         
559   3.00073M     8.00001M    2.66602
vector_latency<vec_abs_gt_max>           2933985 ns      2922812 ns         
239    7.0015M     6.00001M   0.856961
vector_latency<vec_abs_eq_inf>           2934460 ns      2922794 ns         
239   7.00149M     6.00001M   0.856962
vector_latency<vec_eq_ninf_fpcmp>        2935047 ns      2922894 ns         
239   7.00153M     6.00001M   0.856957
vector_latency<vec_eq_ninf_intcmp>       2515700 ns      2505271 ns         
279   6.00129M     6.00001M   0.999786

-march=x86-64-v4:
-------------------------------------------------------------------------------------------------------------------
Benchmark                                      Time             CPU  
Iterations     CYCLES INSTRUCTIONS        IPC
-------------------------------------------------------------------------------------------------------------------
scalar_latency<scalar_abs_gt_max>        1258043 ns      1252814 ns         
559   3.00096M     7.00001M    2.33259
scalar_latency<scalar_abs_eq_inf>        1258571 ns      1253424 ns         
559   3.00236M     8.00001M    2.66457
scalar_latency<scalar_eq_ninf_fpcmp>     1258308 ns      1253125 ns         
559   3.00144M     8.00001M    2.66539
scalar_latency<scalar_eq_ninf_intcmp>    1257910 ns      1252718 ns         
559   3.00075M     8.00001M    2.66601
scalar_latency<scalar_fpclass>           1258088 ns      1252849 ns         
559   3.00098M     7.00001M    2.33257
vector_latency<vec_abs_gt_max>           4193035 ns      4176038 ns         
168    10.003M     6.00001M   0.599822
vector_latency<vec_abs_eq_inf>           4192833 ns      4175791 ns         
168   10.0025M     6.00001M   0.599851
vector_latency<vec_eq_ninf_fpcmp>        4192588 ns      4175999 ns         
168   10.0028M     6.00001M   0.599831
vector_latency<vec_eq_ninf_intcmp>       4192538 ns      4175702 ns         
168   10.0027M     6.00001M   0.599841
vector_latency<vec_fpclass_mask>         3773481 ns      3758034 ns         
186   9.00195M     5.00001M   0.555436

Reply via email to