Optimized 3-way comparisons for int and float (#2250)

Previously, `caml_int_compare` and `caml_float_compare` would compute their -1/0/1 result
at type int, then widen it to type intnat.  On 64-bit platforms this causes an extra sign extension.
This commit changes the code so that the -1/0/1 result is computed directly at type intnat.
master
Stefan Muenzel 2019-03-23 22:51:59 +08:00 committed by Xavier Leroy
parent 46f901bb94
commit 6efe8fea5b
3 changed files with 19 additions and 8 deletions

View File

@ -88,8 +88,11 @@ Working version
* GPR#2240: Constify "identifier" in struct custom_operations
(Cedric Cellier, review by Xavier Leroy)
- GPR#2250: Remove extra integer sign-extension in compare functions
(Stefan Muenzel, review by Xavier Leroy)
* GPR#2293: Constify "caml_named_value"
(Stephen Dolan, review by ??)
(Stephen Dolan, review by Xavier Leroy)
### Standard library:

View File

@ -1008,8 +1008,12 @@ intnat caml_float_compare_unboxed(double f, double g)
/* If one or both of f and g is NaN, order according to the convention
NaN = NaN and NaN < x for all other floats x. */
/* This branchless implementation is from GPR#164.
Note that [f == f] if and only if f is not NaN. */
return (f > g) - (f < g) + (f == f) - (g == g);
Note that [f == f] if and only if f is not NaN.
We expand each subresult of the expression to
avoid sign-extension on 64bit. GPR#2250. */
intnat res =
(intnat)(f > g) - (intnat)(f < g) + (intnat)(f == f) - (intnat)(g == g);
return res;
}
#endif

View File

@ -25,6 +25,11 @@
#include "caml/misc.h"
#include "caml/mlvalues.h"
/* Comparison resulting in -1,0,1, with type intnat,
without extra integer width conversion (GPR#2250). */
#define COMPARE_INT(v1, v2) \
(intnat)(v1 > v2) - (intnat)(v1 < v2)
static const char * parse_sign_and_base(const char * p,
/*out*/ int * base,
/*out*/ int * signedness,
@ -126,8 +131,7 @@ CAMLprim value caml_bswap16(value v)
CAMLprim value caml_int_compare(value v1, value v2)
{
int res = (v1 > v2) - (v1 < v2);
return Val_int(res);
return Val_long(COMPARE_INT(v1, v2));
}
CAMLprim value caml_int_of_string(value s)
@ -314,7 +318,7 @@ CAMLprim value caml_int32_to_float(value v)
intnat caml_int32_compare_unboxed(int32_t i1, int32_t i2)
{
return (i1 > i2) - (i1 < i2);
return COMPARE_INT(i1, i2);
}
CAMLprim value caml_int32_compare(value v1, value v2)
@ -562,7 +566,7 @@ CAMLprim value caml_int64_to_nativeint(value v)
intnat caml_int64_compare_unboxed(int64_t i1, int64_t i2)
{
return (i1 > i2) - (i1 < i2);
return COMPARE_INT(i1, i2);
}
CAMLprim value caml_int64_compare(value v1, value v2)
@ -824,7 +828,7 @@ CAMLprim value caml_nativeint_to_int32(value v)
intnat caml_nativeint_compare_unboxed(intnat i1, intnat i2)
{
return (i1 > i2) - (i1 < i2);
return COMPARE_INT(i1, i2);
}
CAMLprim value caml_nativeint_compare(value v1, value v2)