Assignment

Mutation of existing variables is also quite simple. We’ll add a special case to our code generator for the “=” operator to add internal logic for looking up the LHS variable and assign it the right hand side using the store operation.

  1. cgen (S.BinaryOp "=" (S.Var var) val) = do
  2. a <- getvar var
  3. cval <- cgen val
  4. store a cval
  5. return cval

Testing this out for a trivial example we find that we can now update variables.

  1. ready> def main(x) x = 1;
  2. ; ModuleID = 'my cool jit'
  3. define double @main(double %x) {
  4. entry:
  5. %0 = alloca double
  6. store double %x, double* %0
  7. store double 1.000000e+00, double* %0
  8. ret double 1.000000e+00
  9. }
  10. Evaluated to: 1.0

Finally we can write down our Fibonacci example using mutable updates.

  1. def fibi(x)
  2. var a = 1, b = 1, c = 0 in
  3. (for i = 3, i < x, 1.0 in
  4. c = (a + b) :
  5. a = b :
  6. b = c
  7. ): b;
  8. fibi(10);

With this, we completed what we set out to do. Our nice iterative fib example from the intro compiles and runs just fine. The mem2reg pass optimizes all of our stack variables into SSA registers, inserting PHI nodes where needed, and our front-end remains simple: no “iterated dominance frontier” computation anywhere in sight.

  1. define double @fibi(double %x) #0 {
  2. entry:
  3. br label %for.loop
  4. for.loop: ; preds = %for.loop, %entry
  5. %0 = phi double [ %4, %for.loop ], [ 3.000000e+00, %entry ]
  6. %1 = phi double [ %3, %for.loop ], [ 1.000000e+00, %entry ]
  7. %2 = phi double [ %1, %for.loop ], [ 1.000000e+00, %entry ]
  8. %3 = fadd double %2, %1
  9. %4 = fadd double %0, 1.000000e+00
  10. %5 = fcmp ult double %4, %x
  11. br i1 %5, label %for.loop, label %for.exit
  12. for.exit: ; preds = %for.loop
  13. %6 = call double @"binary:"(double 0.000000e+00, double %3)
  14. ret double %6
  15. }

Running the optimizations we see that we get nicely optimal assembly code for our loop. The auto-vectorizer pass has also rewriten our naive code to used SIMD instructions which yield much faster execution.

  1. fibi: # @fibi
  2. # BB#0: # %entry
  3. vmovsd .LCPI2_0(%rip), %xmm2
  4. vmovsd .LCPI2_1(%rip), %xmm3
  5. vmovaps %xmm2, %xmm1
  6. vmovaps %xmm2, %xmm4
  7. .align 16, 0x90
  8. .LBB2_1: # %for.loop
  9. vmovaps %xmm1, %xmm5
  10. vaddsd %xmm4, %xmm5, %xmm1
  11. vaddsd %xmm2, %xmm3, %xmm3
  12. vucomisd %xmm0, %xmm3
  13. vmovaps %xmm5, %xmm4
  14. jb .LBB2_1
  15. # BB#2: # %for.exit
  16. vmovaps %xmm1, %xmm0
  17. ret