text: 
  function il2ssa_irval_var(v)
    visit:ir2(irval: v) {
       once irval {
          var -> nm
        | else -> []
       }
    }
  
  function il2ssa_use(e)
  collector(add, get) {
    iter:ir2(irexpr: e) {
       once irval {
          var -> add(nm)
        | else -> []
       }
    };
    return unifiq(get())
  }
  
  function il2ssa_term_labels(t)
  collector(add, get) {
    iter:ir2(irterm: t) {
       once irlabel : add(node);
    };
    return unifiq(get())
  }
  
  function il2ssa_term_uses(t)
  collector(add, get) {
    iter:ir2(irterm: t) {
      once irval {
          var -> add(nm)
        | else -> []
      }
    };
    return unifiq(get())
  }
  
  function il2ssa_genssa(code)
  collector(add, get) {
    consts = mkhash(); otyps = mkhash();
    return [ /* A list: [consts; gencode; allocas; otyps] */
     // consts:
     consts;
     // gencode:
     visit:ir2(ircode: code) {
      deep irbblock {
         bblock -> {
          <tuses:tl> = t;
           'b'(name, c::[[%Sm<<(name,"__EXIT");'use'(@tuses)]], tl)
         }
      };
      once irterm : forall {
        il2ssa_term_uses(node):il2ssa_term_labels(node);
      };
      once irexpr {
         load -> { p = il2ssa_irval_var(ptr);
                   if(p) 'load'(p) else 'use'() }
      |  store -> { d1 = il2ssa_irval_var(ptr);
                    e0 = il2ssa_irval_var(e);
                    e1 = if(e0) e0 else {
                       nm = gensym();
                       ohashput(consts, nm, e);
                       return nm
                    };
                    if(d1) {
                       'store'(d1,e1)
                    } else { 'use'(@il2ssa_use(node)) }
                  }
      |  alloca -> {
            add(caar(stack));
            ohashput(otyps, caar(stack), t);
            return 'store'(caar(stack),'_UNDEF')
         }
      |  else -> 'use'(@il2ssa_use(node))
      };
      deep irpair : {
         if(nm) node else [gensym(); e]
      };
     };
     // allocas:
     get();
     // otyps:
     otyps]
  }
  
  function il2ssa_dossa(code) {
   // Prepare the genssa form
   <[consts; gencode; allocas; otyps]> = il2ssa_genssa(code);
   // Refine the list of allocas
   noalloc = mkhash();
   donotalloc(ns) = {
      iter n in ns do if n {
        ohashput(noalloc, n, true)
      }
   };
   visit:ir2(ircode: code) {
     once irexpr {
       | load -> []
       | store -> donotalloc([il2ssa_irval_var(e)])
       | else -> donotalloc(il2ssa_use(node))
     }
   };
   // Perform the genssa mumbo-jumbo
   nallocas = filter a in allocas as not(ohashget(noalloc, a));
   nssa = ssa_transform(gencode, nallocas);
   return [consts; nallocas; nssa; otyps]
  }
  
  function il2ssa_fullssa(code) 
  {
   <[consts; nallocas; nssa; otyps]> = il2ssa_dossa(code);
   <[vmap;ngen;DT]> = nssa;
    loops = ssa_find_loops(ngen, DT);
  
    origtype(nm) = ohashget(otyps, nm);
   // Decode the genssa representation: fill the hashtables
    genh = mkhash();
    remap0(n) = {
         do loop(x = ohashget(vmap, n), p = n) {
            if(x) return loop(ohashget(vmap, x), x)
            else return p }};
    remap(n) = {
       n0 = remap0(n);
       chk = ohashget(consts, n0);
       if(chk) chk else 'var'(n0)
    };
    nah = mkhash(); iter a in nallocas do ohashput(nah, a, a);
    nahp(n) = ohashget(nah, n);
    nahv(v) = {
      match v with
         var(nm) -> nahp(nm)
       | else -> []
    };
    still = mkhash();
    stillthere(k) = ohashget(still, k);
    markpresense(k) = ohashput(still, k, k);
    visit:genssa(code: ngen) {
      deep bblock { b -> iter ops do ops(name) };
      deep oppair : fun(bb) { markpresense(name); op(bb, name) };
      deep iop {
           phi -> fun(bb, tgt) {
             nphi = [tgt;'phi'(origtype(orig), @zip(map vals do remap(vals), prevs))];
             ohashput(genh, bb,
                ohashget(genh, bb)::[nphi]) }
        |  else -> fun(bb, tgt) {[]} }};
   // Apply the decoded remapping and phi insertion:
    ret = visit:ir2(ircode: code) {
      deep irbblock {
         bblock ->
            mk:node(c = ohashget(genh, name) :: map append [k;v] in c do 
                      if (v && stillthere(k)) [[k;v]] else [])
      };
      deep irexpr {
         alloca -> if(nahp(caar(stack))) [] else node
       | load -> if(nahv(ptr)) [] else node
       | store -> if(nahv(ptr)) [] else node
       | else -> node
      };
      deep irval {
         var -> {
            chk = remap(nm);
            if(chk) chk else node
         }
      |  else -> node
      };
    };
  
   return [['loops'(cadr(loops))];ret]
  }