[squeak-dev] here's a curio for compiler mavens...

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Mon Feb 13 20:38:26 UTC 2012


Le 13 février 2012 21:27, Igor Stasenko <siguctua at gmail.com> a écrit :
> On 13 February 2012 20:58, Eliot Miranda <eliot.miranda at gmail.com> wrote:
>> Hi All,
>>
>>     (whitewash alert)  I just had occasion to look at the bytecode generated
>> by the standard compiler for HashedCollection class>>#goodPrimeAtLeast:.
>>  Here's the source, with the issue in bold:
>>
>> goodPrimeAtLeast: lowerLimit
>> "Answer the next good prime >= lowerlimit.
>> If lowerLimit is larger than the largest known good prime,
>> just make it odd."
>> | primes low mid high prime |
>> primes := self goodPrimes.
>> low := 1.
>> high := primes size.
>> lowerLimit > (primes at: high) ifTrue: [
>> ^lowerLimit bitOr: 1 ].
>> [ high - low <= 1 ] whileFalse: [
>> mid := high + low // 2.
>> prime := primes at: mid.
>> prime = lowerLimit ifTrue: [ ^prime ].
>> prime < lowerLimit
>> ifTrue: [ low := mid ]
>> ifFalse: [ high := mid ] ].
>> (primes at: low) >= lowerLimit ifTrue: [ ^primes at: low ].
>> ^primes at: high
>>
>> The code for this sequence is
>> 58 <15> pushTemp: 5
>> 59 <10> pushTemp: 0
>> 60 <B2> send: <
>> 61 <9B> jumpFalse: 66
>> 62 <13> pushTemp: 3
>> 63 <81 42> storeIntoTemp: 2
>> 65 <92> jumpTo: 69
>> 66 <13> pushTemp: 3
>> 67 <81 44> storeIntoTemp: 4
>> 69 <87> pop
>>
>> where-as the following would be better:
>>
>> 58 <15> pushTemp: 5
>> 59 <10> pushTemp: 0
>> 60 <B2> send: <
>> 61 <9B> jumpFalse: 66
>> 62 <13> pushTemp: 3
>> 63 <82 42> popIntoTemp: 2
>> 65 <92> jumpTo: 69
>> 66 <13> pushTemp: 3
>> 67 <82 44> popIntoTemp: 4
>>
>
> [ (a) ifTrue:[ b] ifFalse: [c] ] value
> should answer b or c (depending on a)
> now if you use pop instead of store, it will break.
>

Yes but we always know whether we want to emit code forValue or just for effect.

> Of course in while loop, the [ loop-body closure ] value is always
> discarded, so yes we can
> eliminate extra pop.
> But you can do even more:
>
> 1. loop head
> ...
> ....
>  61 <9B> jumpFalse: 66
>  62 <13> pushTemp: 3
>  63 <82 42> popIntoTemp: 2
> ** 65 <92> jumpTo: 1
>  66 <13> pushTemp: 3
>  67 <82 44> popIntoTemp: 4
>  69  ...  jumpTo: 1
>
> so, we can have 1 less jump when code enters first branch.
>

Very good!
I think however that hacking the Decompiler will be a challenge!

>
>> The reason is that the code generator favours using a single pop for both
>> arms of the if:
>>
>> MessageNode>>sizeCodeForIf: encoder value: forValue
>> | thenExpr elseExpr branchSize thenSize elseSize |
>> thenExpr := arguments at: 1.
>> elseExpr := arguments at: 2.
>> (forValue
>> or: [(thenExpr isJust: NodeNil)
>> or: [elseExpr isJust: NodeNil]]) not
>> "(...not ifTrue: avoids using ifFalse: alone during this compile)"
>> ifTrue:  "Two-armed IFs forEffect share a single pop"
>> [^super sizeCodeForEffect: encoder].
>> ...
>>
>> MessageNode>>emitCodeForIf: stack encoder: encoder value: forValue
>> | thenExpr thenSize elseExpr elseSize |
>> thenSize := sizes at: 1.
>> elseSize := sizes at: 2.
>> (forValue not and: [elseSize * thenSize > 0]) ifTrue:
>> "Two-armed IFs forEffect share a single pop"
>> [^super emitCodeForEffect: stack encoder: encoder].
>>
>> It would be nice if this only happened if doing so actually reduced the size
>> of the generated code.
>> --
>> best,
>> Eliot
>>
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko.
>


More information about the Squeak-dev mailing list