What is the purpose of replacing expressions, used as limits in a For example:to:do: call with by a new temporary variable? OCOpalExamples>>#exampleToDoArgumentLimitIsExpression exampleToDoArgumentLimitIsExpression | count sum | count := 10. sum := 0. 1 to: count - 1 do: [ :each | sum := sum + each]. ^sum exampleToDoArgumentLimitIsExpression | tmp1 tmp2 tmp3 | tmp1 := 10. tmp2 := 0. tmp3 := tmp1 - 1. 1 to: tmp3 do: [ :tmp4 | tmp2 := tmp2 + tmp4 ]. ^ tmp2 |
SSA form?
Le 19/11/15 22:14, Nicolai Hess a écrit : > What is the purpose of replacing expressions, used as limits in a > to:do: call with by a new temporary variable? > > For example: > > OCOpalExamples>>#exampleToDoArgumentLimitIsExpression > the code is > > exampleToDoArgumentLimitIsExpression > | count sum | > count := 10. > sum := 0. > 1 to: count - 1 do: [ :each | sum := sum + each]. > ^sum > > the decompiled bytecode : > > exampleToDoArgumentLimitIsExpression > | tmp1 tmp2 tmp3 | > tmp1 := 10. > tmp2 := 0. > tmp3 := tmp1 - 1. > 1 to: tmp3 do: [ :tmp4 | tmp2 := tmp2 + tmp4 ]. > ^ tmp2 > > So, the expression (count - 1) in the to:do: loop is replaced by a new > temporay (tmp3). > > Ok, but why ? |
2015-11-19 22:29 GMT+01:00 stepharo <[hidden email]>: SSA form? and for method arguments? foo: count | sum | sum := 0. 1 to: count do: [ :ku | sum := sum + ku ]. ^ sum transforms to: "foo: arg1 | tmp1 tmp2 | tmp1 := 0. tmp2 := arg1. 1 to: tmp2 do: [ :tmp3 | tmp1 := tmp1 + tmp3 ]. ^ tmp1" Le 19/11/15 22:14, Nicolai Hess a écrit : |
In reply to this post by Nicolai Hess-3-2
Because were to:do: not inlined the expression passed as the to: actual argument would be evaluated exactly once (bound to the formal argument for to:) and so assigning to a temporary preserves the semantics in the most direct way. If the expression has side effects then those side effects must occur only once.
Note that were the to: expression merely another variable then the compiler could only substitute the original variable if it's value could not change, e.g. in exampleToDoArgumentLimitIsExpression | count sum | count := 10. sum := 0. 1 to: count do: [ :each | sum := sum + each]. ^sum It is ok to use count directly as the limit variable, but in this it is not: exampleToDoArgumentLimitIsExpression | count sum | count := 10. sum := 0. 1 to: count do: [ :each | sum := sum + each. count := #somethingElseEntirely]. ^sum _,,,^..^,,,_ (phone) > On Nov 19, 2015, at 1:14 PM, Nicolai Hess <[hidden email]> wrote: > > What is the purpose of replacing expressions, used as limits in a > to:do: call with by a new temporary variable? > > For example: > > OCOpalExamples>>#exampleToDoArgumentLimitIsExpression > the code is > > exampleToDoArgumentLimitIsExpression > | count sum | > count := 10. > sum := 0. > 1 to: count - 1 do: [ :each | sum := sum + each]. > ^sum > > the decompiled bytecode : > > exampleToDoArgumentLimitIsExpression > | tmp1 tmp2 tmp3 | > tmp1 := 10. > tmp2 := 0. > tmp3 := tmp1 - 1. > 1 to: tmp3 do: [ :tmp4 | tmp2 := tmp2 + tmp4 ]. > ^ tmp2 > > So, the expression (count - 1) in the to:do: loop is replaced by a new > temporay (tmp3). > > Ok, but why ? |
You can use whileTrue: if it's a problem for you not to evaluate the limit at each iteration of the loop. If you look at OrderedCollection for example, there are implemented differently in Pharo/VW and Squeak. Pharo and VW use to:do: whereas Squeak uses whileTrue: to iterate over the collection. Hence, if you remove elements from the OrderedCollection while iterating over it, the behavior is different. 2015-11-20 1:34 GMT+01:00 Eliot Miranda <[hidden email]>: Because were to:do: not inlined the expression passed as the to: actual argument would be evaluated exactly once (bound to the formal argument for to:) and so assigning to a temporary preserves the semantics in the most direct way. If the expression has side effects then those side effects must occur only once. |
Thanks eliot, Clement, but if the argument for to:do: is not an expression but one of the method argument, this2015-11-20 8:31 GMT+01:00 Clément Bera <[hidden email]>:
I don't need this. I just compared some compiled methods bytecodes after the latest fix for the wrong frame size calculation. For this, I compared opal compilers result with that of the old compiler. And I noticed that some methods compiled with opal had some "hidden" temps and couldn't explain way:)
|
Hi Nicolai,
(* and with the right preference, block)
_,,,^..^,,,_ (phone)
|
2015-11-20 9:58 GMT+01:00 Eliot Miranda <[hidden email]>:
I don't know, but I don't think so. Recompiling all ~90000 compiled methods, once with opal and once with the other compiler and comparing the numbers of tempVars gives a difference of about 400 methods. Not all 400 differences came from the extra tempvars for the to:do: transform, and sometimes opal generates code with less temp vars. Anyway, adding extra tempvars for accessing the method arguments seems to be a bug.
|
Hi Nicolai,
On Sat, Nov 21, 2015 at 10:40 AM, Nicolai Hess <[hidden email]> wrote:
Well it's a nice surprise to find out that the Squeak compiler does use a variable directly if it's not assigned to in the block. Thanks to your observation I've simplified the test a little, not scanning for assignments if the variable is a method argument or a block argument and the assignment to block arg preference is not in effect.
Agreed ;-)
_,,,^..^,,,_ best, Eliot |
In reply to this post by Clément Béra
On Fri, 20 Nov 2015, Clément Bera wrote:
> You can use whileTrue: if it's a problem for you not to evaluate the limit at each iteration of the loop. > If you look at OrderedCollection for example, there are implemented differently in Pharo/VW and Squeak. Pharo and VW use to:do: whereas Squeak uses whileTrue: to iterate over the collection. Hence, if you remove elements from the OrderedCollection while iterating > over it, the behavior is different. One should refrain from modifying collections during iteration. In case of OrderedCollection there's #removeAllSuchThat: to let one safely remove elements from the collection while iterating over it. Levente |
Free forum by Nabble | Edit this page |