Implicit float/1 much faster than explicit float/1

Funny observation. The (=:=)/2 and friends does already
a float conversion on its own, right? Now I get a speed up
using this implicit float conversion, instead of an

explicit float/1 evaluable function. So before I had
in swi_perf this code and performance on Windows:

  write('case, swi: '), time((between(1,20000,_),
        case(_, X, Y), Y =\= float(X), fail; true)),

% case, swi:
% % 2,040,001 inferences, 0.969 CPU in 0.968 seconds (100% CPU, 2105807 Lips)

And now I have this code and performance on Windows,
with the implicit float conversion in (=:=)/2 and friends:

   write('case, swi: '), time((between(1,20000,_),
        case(_, X, Y, G), (G=1 -> Y =\= X; Y =:= X), fail; true)),

case, swi: 
% 4,700,001 inferences, 0.453 CPU in 0.440 seconds (103% CPU, 10372416 Lips)

On my systems its rather the other way around, the additinal
if-then-else makes it slower. But here removing the float/1
call makes it twice as fast, speeds it up tremendously?

This are the new test cases and new harness:

cases.p.log (39,1 KB)
swi.p.log (4,0 KB)

Does (=:=)/2 have access to a faster float/1 ?

Surprise surprise, Trealla Prolog doesn’t do the implicit conversion:

/* Trealla Prolog 2.4.24 */
?- 1.17920676571692e+30 =:= 1179206765716919932371622592985.
   error(type_error(evaluable,1179206765716919932371622592985/0),(=:=)/2).

?- 1.17920676571692e+30 =\= 1179206765716919932371622592985.
   error(type_error(evaluable,1179206765716919932371622592985/0),(=\=)/2).

Now I am preparing a list of Prolog systems, where the implicit conversion
is faster, and where the implicit conversion is slower, I guess because
of the surrounding if-then-else.

But for those Prolog systems where the implicit conversion is faster
I have the very strong suspicion that they have a horrible evaluation
function overrhead, that removing a float/1 is such a drastic impact.

Maybe the impact is amplified, in that removing the float/1 evaluable
function call also changes the generate Prolog interpreter code for
(=:=)/2 or (==)/2, since it sees the arguments are only variables?

Neverthless that speed-up seems a little drastic, since I do only
20’000 iterations in the test case.

Edit 20.10.2022
Ok, here is a list with Prolog systems, where removing float/1 has
drastic impact or not. Difference between explicit float/1 and implict float
plus even a little if-then-else around it:

System Explicit Implicit and if-then-else Delta
jekejeke 270 534 98%
ciao 344 692 101%
eclipse 883 381 -57%
trealla 553 n/a n/a
swi 989 440 -56%
scryer 889 1449 63%
sicstus 1087 475 -56%
dogelog 1171 1657 42%

I would say where it goes down, calling an evaluable function
is a challenge. For ECLiPSe Prolog, SWI Prolog and SICStus Prolog
maybe? Or maybe they are so fast in everything else, that a rather

negligible overhead in evaluable functions becomes visible?

As for SWI, meta-calling never optimizes arithmetic and thus it simply creates a terms float(X) and Y and then starts evaluating these. If the expression appears compiled code and the optimise flag is true (set by the user or start Prolog as swipl -O), arithmetic is compiled to a stack, and Y =\= float(X) becomes

- push Y
- push X
- eval float/1
- eval =\=/2.

Where references to functions are resolved at compile time. That makes a quite drastic difference on programs that use a lot of arithmetic, but in most applications the impact is neglectable and sometimes even negative.