Skip to content

Instantly share code, notes, and snippets.

@tomsmeding
Last active April 28, 2020 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomsmeding/cd35e70c962fad5094e1a1fd315de4d4 to your computer and use it in GitHub Desktop.
Save tomsmeding/cd35e70c962fad5094e1a1fd315de4d4 to your computer and use it in GitHub Desktop.

For people who wonder even more about taking the maximum of two floats: let's compare fmax(a,b), fmaxf(a,b), std::max(a,b) and if (a < b) return b; else return a; in gcc, clang, icc and msvc.

Look at the assembler outputs here: gcc and clang (https://godbolt.org/z/a1pb5N), icc and mscv (https://godbolt.org/z/FoH15I).

Results:

. CLANG GCC ICC MSVC
fmax double, wtf, maxsd double, call fmax double, call fmax call fmaxf
fmaxf wtf, maxss call fmaxf call fmaxf call fmaxf
std::max maxss maxss maxss maxss
if(<) maxss maxss maxss conditional

Discussion of the four implementations:

  • fmax() has signature double fmax(double, double), and only MSVC is sneaky enough to ignore that. However, since you're working with floats, not doubles, please just use fmaxf().
  • fmaxf() results in a function call (!) in all but clang, but clang uses something weird with cmpunordss; see below.
  • std::max() uses the optimal single maxss instruction in all compilers. Please use this one.
  • The if-condition is recognised and converted to the optimal maxss instruction by all the smart compilers in the bunch; only msvc outputs an actual branch.

Further remarks:

  • Clang is the only compiler that inlines fmax() and fmaxf(), and it shows that these functions are paranoid: the cmpunordss is an instruction that allows it to deal correctly with NaN values. Indeed, the specification of the functions states that NaN is treated as -inf. The std::max() and if(<) implementations don't have this particular behaviour with NaN's.
  • MSVC is not smart enough to recognise the conditional and convert it to a maximum instruction. Poor msvc.
  • Clang may actually be the best compiler in this micro-test: for all four implementations, it's as good or better than the rest. (Note that a function call is always undesirable in hot code.)

Conclusion: use std::max().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment