[squeak-dev] The Inbox: Collections-nice.807.mcz
leves at caesar.elte.hu
Tue Sep 18 15:20:58 UTC 2018
On Mon, 17 Sep 2018, Eliot Miranda wrote:
> Hi All,
> On Sat, Sep 15, 2018 at 6:36 PM Bert Freudenberg <bert at freudenbergs.de> wrote:
> On Sat, Sep 15, 2018 at 4:58 PM Levente Uzonyi <leves at caesar.elte.hu> wrote:
> Hi Eliot,
> Here is a very simple test case:
> [ 1 to: 500000000 do: [ :i | i = 1 ifTrue: [ true ] ifFalse: [ false ] ] ] timeToRun.
> [ 1 to: 500000000 do: [ :i | i = 1 ] ] timeToRun.
> On my machine it gives #(992 1436).
> Huh, interesting.
> Eliot, if you figure this out, please let us know what it was ...
> hmmm. It's my fault. It is to do with the criteria the StackToRegisterMappingCogit uses to decide whether to inline comparison operations. The code I wrote in genSpecialSelectorComparison says
> "Only interested in inlining if followed by a conditional branch."
> inlineCAB := branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse].
> "Further, only interested in inlining = and ~= if there's a SmallInteger constant involved.
> The relational operators successfully statically predict SmallIntegers; the equality operators do not."
> (inlineCAB and: [primDescriptor opcode = JumpZero or: [primDescriptor opcode = JumpNonZero]]) ifTrue:
> [inlineCAB := argIsIntConst or: [rcvrIsInt]].
> inlineCAB ifFalse:
> [^self genSpecialSelectorSend].
> So the Cogit inlines the = 1 in the first case because it is followed by the branch for the ifTrue: [true] ifFalse: [false], but does not inline = 1 in the second case. So the second case is a true
> send, and the true send code (load a register with i, another with 1, another with the SmallInteger tag, call the checked entry point of SmallInteger>>#=, tag test the receiver, tag test the argument,
> compare, reify as true or false, return) is more costly, essentially because it has a call/return. I'll discuss with Clément and Sophie we'll think about measuring this tradeoff. This is perhaps a
> good student project.
> If anyone has good arguments why the heuristics above are bogus or good measurements please post. In the mean time sorry for the late reply; I was airborne on the way back from Cagliari, or sleeping
I see no reason to limit inlining when the result is used. When it's not
used, then the program is probably incorrect.
But if you want specific situations when such expressions should be
jitted, then here's a quick list:
- when the resulting boolean is returned. E.g.:
^tally = 0
- when the resulting boolean is the value returned by a block:
array select: [ :each | each > 0 ]
- when the resulting boolean is part of a larger boolean expression
(don't know how this can be detected):
(x = 1 or: [ y = 2 ]) ifTrue: [ ... ]
All in all, I think it's easier to always inline it than not. And I can't
really find a reason not to inline it.
> in the terminal in Rome and was none too fresh. ESUG was glorious though. Thanks to all the organisers!!
> best, Eliot
More information about the Squeak-dev