[<<][meta][>>][..]
Mon Aug 1 18:38:14 CEST 2011

Sharing

f3 x = let xx = x * x in xx * xx

*Main> f3 1 :: SSA Tfloat
R0 = fmul 1.0 1.0
R1 = fmul 1.0 1.0
R2 = fmul R0 R1
R2


Why isn't "fmul 1.0 1.0" shared?  Or, a bit more obvious:


f4 x = let x1 = x  * x  in
       let x2 = x1 * x1 in
       let x3 = x2 * x2 in
                x3 * x3

*Main> f4 1 :: SSA Tfloat
R0 = fmul 1.0 1.0
R1 = fmul 1.0 1.0
R2 = fmul R0 R1
R3 = fmul 1.0 1.0
R4 = fmul 1.0 1.0
R5 = fmul R3 R4
R6 = fmul R2 R5
R7 = fmul 1.0 1.0
R8 = fmul 1.0 1.0
R9 = fmul R7 R8
R10 = fmul 1.0 1.0
R11 = fmul 1.0 1.0
R12 = fmul R10 R11
R13 = fmul R9 R12
R14 = fmul R6 R13
R14


Why doesn't this share anything, while there is threading going on?

f5 x = let_ (x  * x)  $ \x1 ->
       let_ (x1 * x1) $ \x2 ->             
       let_ (x2 * x2) $ \x3 ->             
             x3 * x3
*Main> f5 1 :: SSA Tfloat
R0 = fmul 1.0 1.0
R1 = let R0
R2 = let R0
R3 = fmul R1 R2
R4 = let R3
R5 = let R3
R6 = fmul R4 R5
R7 = let R6
R8 = let R6
R9 = fmul R7 R8

This is correct apart from the copying of variables.

The right implementation of let_ seems to be:


let' (SSA x) body = SSA $ do
  vx <- x
  lowerSSA body $ return vx
  

Or with wrapping expanded:

let' (SSA x) body = SSA $ do
  vx <- x
  unSSA $ body $ SSA $ return vx


Is all that wrapping/unwrapping necessary?  It might be simpler to
define SSA as a monad.

I came to the following explanation, which could be worded better but
I believe does hint at what's going on:

    The idea is that in let' the monadic variable x is only
    "dereferenced" once, which would not be the case for an ordinary
    let expression which would run a computation multiple times.



[Reply][About]
[<<][meta][>>][..]