+  type predicates = pred list LiveMap.map
+
+  (* val number : pseudoasm -> numasm
+   * numbers the instructions!
+   *)
+
+  fun number instrs =
+    let
+      val nums = List.tabulate (List.length instrs, (fn i => i))
+    in
+      foldr
+        LiveMap.insert'
+        LiveMap.empty
+        (ListPair.zip (nums,instrs))
+    end
+
+  (* val defusesucc : numasm -> (ident * pred list) list
+   * generates def/use/succ predicates according to rules
+   *)
+  fun defusesucc l =
+    let
+      val labelmap = LiveMap.foldri
+        (fn (n, a, b) => LabelMap.insert(b, a, n))
+        (LabelMap.empty)
+        (LiveMap.mapPartial (fn (X.LABEL lb) => SOME(lb) | _ => NONE) l)
+
+      fun findlabel (lb) = valOf (LabelMap.find (labelmap, lb))
+
+      (* val defhit/usehit : X.oper -> pred list
+       * helper functions to discard constant operands *)
+      fun defhit (X.REG X.PC) = raise ErrorMsg.InternalError "cannot define PC"
+        | defhit (X.REG a) = [DEF(X.REG a)]
+        | defhit (X.TEMP a) = [DEF(X.TEMP a)]
+        | defhit (_) = nil
+    
+      and usehit (X.REG a) = [USE(X.REG a)]
+        | usehit (X.TEMP a) = [USE(X.TEMP a)]
+        | usehit (_) = nil
+
+      fun callhit 0 = nil
+        | callhit 1 = USE(X.REG(X.R0))::(callhit 0)
+        | callhit 2 = USE(X.REG(X.R1))::(callhit 1)
+        | callhit 3 = USE(X.REG(X.R2))::(callhit 2)
+        | callhit 4 = USE(X.REG(X.R3))::(callhit 3)
+        | callhit _ = callhit 4
+
+      (* val gendef : ident * X.insn -> ident * pred list
+       * generates the def/use/succ predicates for a single insn
+       *)
+      fun gendef (n, X.DIRECTIVE(_))           = ([SUCC (n+1)])
+        | gendef (n, X.COMMENT(_))             = ([SUCC (n+1)])
+        | gendef (n, X.LIVEIGN (_))            = ([SUCC (n+1)])
+        | gendef (n, X.LABEL l)                = ([SUCC (n+1)])
+        | gendef (n, X.INSN(X.NV, _))          = ([SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.MOVLIT(dest, _))) = (defhit dest @ [SUCC(n+1), ISMOVE])
+        | gendef (n, X.INSN(_, X.MOVSYM(dest, sym))) = (defhit dest @ [SUCC(n+1), ISMOVE])
+        | gendef (n, X.INSN(_, X.MOVSTR(dest, str))) = (defhit dest @ [SUCC(n+1), ISMOVE])
+        | gendef (n, X.INSN(X.AL, X.MOVLBL(X.REG X.PC, l))) = ([SUCC (findlabel l)])
+        | gendef (n, X.INSN(_, X.MOVLBL(X.REG X.PC, l))) = ([SUCC (n+1), SUCC (findlabel l)])
+        | gendef (n, X.INSN(_, X.MOVLBL(_, _))) = raise ErrorMsg.InternalError "MOVLBL with target neq PC"
+        | gendef (n, X.INSN(_, X.LDR(dest, src))) = (defhit dest @ usehit src @ [SUCC (n+1), ISMOVE])
+        | gendef (n, X.INSN(_, X.STO(dest, src))) = (usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.MOV(dest, src))) = (defhit dest @ usehit src @ [SUCC (n+1), ISMOVE])
+        | gendef (n, X.INSN(_, X.MOVS(dest, src))) = (usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.ADD(dest, src))) = (defhit dest @ usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.ADDS(dest, src))) = (usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.SUB(dest, src))) = (defhit dest @ usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.SUBS(dest, src))) = (usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.AND(dest, src))) = (defhit dest @ usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.ANDS(dest, src))) = (usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.NOT(dest, src))) = (defhit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.NOTS(dest, src))) = (usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.PUSH(X.REG X.SP, src))) = (usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.PUSH(_, _))) = raise ErrorMsg.InternalError "PUSH with sp != SP"
+        | gendef (n, X.INSN(X.AL, X.POP(X.REG X.SP, X.REG X.PC))) = ([USE (X.REG X.R0)]) (* kind of like 'ret' *)
+        | gendef (n, X.INSN(_, X.POP(X.REG X.SP, X.REG X.PC))) = ([USE (X.REG X.R0), SUCC(n+1)])
+        | gendef (n, X.INSN(_, X.POP(X.REG X.SP, src))) = (defhit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.POP(_, _))) = raise ErrorMsg.InternalError "POP with sp != SP"
+        | gendef (n, X.INSN(_, X.CALL(X.REG X.SP, src, a))) = (callhit a @
+                                                               usehit src @
+                                                               [DEF(X.REG(X.R0)), DEF(X.REG(X.R1)), DEF(X.REG(X.R2)), DEF(X.REG(X.R3)),
+                                                                DEF(X.REG(X.R4)), DEF(X.REG(X.R5)),
+                                                                SUCC(n+1)]
+                                                              )
+        | gendef (n, X.INSN(_, X.CALL(_, _, _))) = raise ErrorMsg.InternalError "CALL with sp != SP"
+        | gendef (n, X.INSN(_, X.SHR(dest, src))) = (defhit dest @ usehit dest @ usehit src @ [SUCC (n+1)])
+        | gendef (n, X.INSN(_, X.SHL(dest, src))) = (defhit dest @ usehit dest @ usehit src @ [SUCC (n+1)])
+    in
+        LiveMap.mapi gendef l
+    end
+
+  (* val uselive : (int * pred list) list -> OperSet.set LiveMap.map
+   * generates liveness for 'use' rules to get the iterative analyzer started
+   *)
+  fun uselive preds =
+    LiveMap.mapi
+      (fn (n, pl) =>
+         foldr
+           (fn (USE (l), set) => OperSet.add (set, l)
+             | (_, set) => set)
+           OperSet.empty
+           pl
+      )
+      preds
+
+  (* val subsetlive : OperSet.set LiveMap.map * OperSet.set LiveMap.map -> bool
+   * true if first is subset of second
+   *)
+
+  fun subsetlive (l1,l2) =
+    LiveMap.foldri
+      (fn (_, _, false) => false
+        | (n, set1, _) => case LiveMap.find (l2, n)
+            of NONE => false
+             | SOME set2 => OperSet.isSubset (set1, set2))
+      true
+      l1
+  
+  (* val succs : pred list -> int list
+   * generates a list of lines that succeed a line given the predicates
+   * for that line
+   *)
+  fun succs (SUCC(a)::l') = a::(succs l')
+    | succs (_::l') = succs l'
+    | succs nil = nil
+
+  fun defs (DEF(a)::l) = a::(defs l)
+    | defs (_::l) = defs l
+    | defs nil = nil
+  
+  fun uses (USE(a)::l) = a::(defs l)
+    | uses (_::l) = defs l
+    | uses nil = nil
+  
+  fun ismove l = List.exists (fn ISMOVE => true | _ => false) l
+
+  (* val liveiter : OperSet.set LiveMap.map -> (int * pred list) list -> OperSet.set LiveMap.map
+   * iteratively generates livenesses from def/use/succ rules
+   * it must be fed a liveness list generated from the use rule as it only
+   * processes the second rule :