Hi All,<div><br></div><div> (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:</div>
<div><br></div><div><div>goodPrimeAtLeast: lowerLimit</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"Answer the next good prime >= lowerlimit.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>If lowerLimit is larger than the largest known good prime,</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>just make it odd."</div><div><span class="Apple-tab-span" style="white-space:pre">        </span></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| primes low mid high prime |</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>primes := self goodPrimes.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>low := 1.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>high := primes size.</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>lowerLimit > (primes at: high) ifTrue: [</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>^lowerLimit bitOr: 1 ].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>[ high - low <= 1 ] whileFalse: [</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>mid := high + low // 2.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>prime := primes at: mid.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>prime = lowerLimit ifTrue: [ ^prime ].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span><b>prime < lowerLimit</b></div><div><b><span class="Apple-tab-span" style="white-space:pre">                        </span>ifTrue: [ low := mid ]</b></div><div><b><span class="Apple-tab-span" style="white-space:pre">                        </span>ifFalse: [ high := mid ]</b> ].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>(primes at: low) >= lowerLimit ifTrue: [ ^primes at: low ].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^primes at: high</div>
<div><br></div><div>The code for this sequence is</div><div><div><span class="Apple-tab-span" style="white-space:pre">        </span>58 <15> pushTemp: 5</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>59 <10> pushTemp: 0</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>60 <B2> send: <</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>61 <9B> jumpFalse: 66</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>62 <13> pushTemp: 3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span><b>63 <81 42> storeIntoTemp: 2</b></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>65 <92> jumpTo: 69</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>66 <13> pushTemp: 3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span><b>67 <81 44> storeIntoTemp: 4</b></div><div><span class="Apple-tab-span" style="white-space:pre">        </span><b>69 <87> pop</b></div></div><div><br>
</div><div>where-as the following would be better:</div><div><br></div><div><div><span class="Apple-tab-span" style="white-space:pre">        </span>58 <15> pushTemp: 5</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>59 <10> pushTemp: 0</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>60 <B2> send: <</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>61 <9B> jumpFalse: 66</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>62 <13> pushTemp: 3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>63 <82 42> popIntoTemp: 2</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>65 <92> jumpTo: 69</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>66 <13> pushTemp: 3</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>67 <82 44> popIntoTemp: 4</div></div><div><br></div><div>The reason is that the code generator favours using a single pop for both arms of the if:</div>
<div><br></div><div>MessageNode>>sizeCodeForIf: encoder value: forValue</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| thenExpr elseExpr branchSize thenSize elseSize |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>thenExpr := arguments at: 1.</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>elseExpr := arguments at: 2.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(forValue</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> or: [(thenExpr isJust: NodeNil)</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> or: [elseExpr isJust: NodeNil]]) not</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>"(...not ifTrue: avoids using ifFalse: alone during this compile)"</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: <b>"Two-armed IFs forEffect share a single pop"</b></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[^super sizeCodeForEffect: encoder].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>...</div><div><br></div><div>MessageNode>>emitCodeForIf: stack encoder: encoder value: forValue</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| thenExpr thenSize elseExpr elseSize |</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>thenSize := sizes at: 1.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>elseSize := sizes at: 2.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(forValue not and: [elseSize * thenSize > 0]) ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span><b>"Two-armed IFs forEffect share a single pop"</b></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[^super emitCodeForEffect: stack encoder: encoder].</div>
<div><br></div><div>It would be nice if this only happened if doing so actually reduced the size of the generated code.</div>-- <br>best,<div>Eliot</div><br>
</div>