I played around with VM parameter 75. It does indeed show a change for the float-based primitives (i.e., 541, 542, ...) but not the integer-based primitives (i.e., 1, 2, 3, ...).
Is this expected behavior? In the VMMaker sources, it looks like it should work at least for comparisons (i.e., 3 to 8):
```Smalltalk genPrimitiveLessThan ^coInterpreter primitiveDoMixedArithmetic ifTrue: [self genSmallIntegerComparison: JumpLess orDoubleComparison: #JumpFPGreater: invert: true] ifFalse: [self genSmallIntegerComparison: JumpLess] ```
Is `genPrimitiveLessThan` not the one in charge here? Hm....
I don't remember, there are any possible path, what if not Jitted ? Certainly a case for exercising VM Simulator skills, or learn them...
Note that the primitiveLessThan should fail: it only handle SmallInteger argument (and receiver).<br> It's bytecodePrimLessThan that eventually handle the automatic int -> float conversion.<br> Remember that we (the stack interpreter) short-circuit some message sends for some specialSelectors when we can recognize known operand types.
It appears that the JIT does thing differently than the (stack) interpreter.
The interpreter will try things in this order when interpreting the send of a special selector for arithmetic or comparison - for example in `bytecodePrimAdd` - if both receiver and argument are SmallInteger, then perform the operation immediately - else try to perform corresponding float primitive (`primitiveFloatAdd:toArg:`) that will eventually attempt a conversion sqInt -> double through `loadFloatOrIntFrom:` - if it fails, then fallback to a message send, which will normally call primitiveAdd if receiver is a SmallInteger (and fail for the same reason as first case)
In this scheme, if we add handling of conversions in SmallInteger primitives, we will just duplicate the work done in the 2nd stage of bytecodePrimAdd for no added value, but just a few more wasted cycles.
The JIT will only try to handle the case of both SmallIntegers - in `genSpecialSelectorArithmetic` which is invoked for some of the specialSelectors (+ - bitAnd: bitOr:) - and `genSpecialSelectorComparison` (< > <= >= = ~=)
Then it will fallback to a message send which goes through the primitives.<br> and the integer primitives effectively do not handle conversion.
The other way around, `Float op: Integer`, the float primitives do handle the conversion, and the JIT appears to be faster than `Integer op: Float`. The irony is that Jitted `Float op: Integer` is slower than interpreted code.
I let Eliot explain while the second stage was skipped, but it might be that it consumes two many instructions: remember than the purpose is to inline the specialSelectors send, so we might end up with lot of instructions... If it doesn't pay statistically (except in micro benchmarks), then it's not worth it, because it will exhaust the space devoted to jitted code more rapidly (and remember, specialSelectors are sent from many places !).
We saw that adding conversions in integer primitives is not ideal, at least for the interpreted code.<br> So welcome to brighter ideas for having your cake and eat it too...
vm-dev@lists.squeakfoundation.org