SCM Repository
[diderot] / branches / pure-cfg / src / compiler / mid-to-low / mid-to-low.sml |
View of /branches/pure-cfg/src/compiler/mid-to-low/mid-to-low.sml
Parent Directory
|
Revision Log
Revision 493 -
(download)
(annotate)
Thu Jan 27 16:40:50 2011 UTC (11 years, 4 months ago) by jhr
File size: 9118 byte(s)
Thu Jan 27 16:40:50 2011 UTC (11 years, 4 months ago) by jhr
File size: 9118 byte(s)
Working on porting to new IL
(* mid-to-low.sml * * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu) * All rights reserved. * * Translation from MidIL to LowIL representations. *) structure MidToLow : sig val translate : MidIL.program -> LowIL.program end = struct structure SrcIL = MidIL structure SrcOp = MidOps structure VTbl = SrcIL.Var.Tbl structure DstIL = LowIL structure DstTy = LowILTypes structure DstOp = LowOps type var_env = DstIL.var VTbl.hash_table fun rename (env : var_env, x) = (case VTbl.find env x of SOME x' => x' | NONE => let val x' = DstIL.Var.new (SrcIL.Var.name x, SrcIL.Var.ty x) in VTbl.insert env (x, x'); x' end (* end case *)) fun renameList (env, xs) = List.map (fn x => rename(env, x)) xs (* convert a rational to a FloatLit.float value. We do this by long division * with a cutoff when we get to 12 digits. *) fun ratToFloat r = (case Rational.explode r of {sign=0, ...} => FloatLit.zero false | {sign, num, denom=1} => FloatLit.fromInt(sign * IntInf.toInt num) | {sign, num, denom} => let (* normalize so that num <= denom *) val (denom, exp) = let fun lp (n, denom) = if (denom < num) then lp(n+1, denom*10) else (denom, n) in lp (1, denom) end (* normalize so that num <= denom < 10*num *) val (num, exp) = let fun lp (n, num) = if (10*num < denom) then lp(n-1, 10*num) else (num, n) in lp (exp, num) end (* divide num/denom, computing the resulting digits *) fun divLp (n, a) = let val (q, r) = IntInf.divMod(a, denom) in if (r = 0) then (q, []) else if (n < 12) then let val (d, dd) = divLp(n+1, 10*r) in if (d < 10) then (q, (IntInf.toInt d)::dd) else (q+1, 0::dd) end else if (IntInf.div(10*r, denom) < 5) then (q, []) else (q+1, []) (* round up *) end val digits = let val (d, dd) = divLp (0, num) in (IntInf.toInt d)::dd end in FloatLit.fromDigits{isNeg=(sign < 0), digits=digits, exp=exp} end (* end case *)) (* expand the EvalKernel operations into vector operations. The parameters * are * result -- the lhs variable to store the result * d -- the vector width of the operation, which should be equal * to twice the support of the kernel * h -- the kernel * k -- the derivative of the kernel to evaluate * * The generated code is computing * * result = a_0 + x*(a_1 + x*(a_2 + ... x*a_n) ... ) * * as a d-wide vector operation, where n is the degree of the kth derivative * of h and the a_i are coefficient vectors that have an element for each * piece of h. The computation is implemented as follows * * m_n = x * a_n * s_{n-1} = a_{n-1} + m_n * m_{n-1} = x * s_{n-1} * s_{n-2} = a_{n-2} + m_{n-1} * m_{n-2} = x * s_{n-2} * ... * s_1 = a_1 + m_2 * m_1 = x * s_1 * result = a_0 + m_1 *) fun expandEvalKernel (result, d, h, k, [x]) = let val {isCont, segs} = Kernel.curve (h, k) (* degree of polynomial *) val deg = List.length(hd segs) - 1 (* convert to a vector of vectors to give fast access *) val segs = Vector.fromList (List.map Vector.fromList segs) (* get the kernel coefficient value for the d'th term of the i'th * segment. *) fun coefficient d i = Literal.Float(ratToFloat (Vector.sub (Vector.sub(segs, i), d))) val ty = DstTy.VecTy d val coeffs = List.tabulate (deg+1, fn i => DstIL.Var.new("a"^Int.toString i, ty)) (* code to define the coefficient vectors *) val coeffVecs = let fun mk (x, (i, code)) = let val lits = List.tabulate(d, coefficient i) val vars = List.tabulate(d, fn _ => DstIL.Var.new("_f", DstTy.realTy)) val code = ListPair.map (fn (x, lit) => (x, DstIL.LIT lit)) (vars, lits) @ (x, DstIL.CONS vars) :: code in (i-1, code) end in #2 (List.foldr mk (deg, []) coeffs) end (* build the evaluation of the polynomials in reverse order *) fun pTmp i = DstIL.Var.new("prod" ^ Int.toString i, ty) fun sTmp i = DstIL.Var.new("sum" ^ Int.toString i, ty) fun eval (i, [coeff]) = let val m = pTmp i in (m, [(m, DstIL.OP(DstOp.Mul ty, [x, coeff]))]) end | eval (i, coeff::r) = let val (m, stms) = eval(i+1, r) val s = sTmp i val m' = pTmp i val stms = (m', DstIL.OP(DstOp.Mul ty, [x, s])) :: (s, DstIL.OP(DstOp.Add ty, [coeff, m])) :: stms in (m', stms) end val evalCode = let val a0::r = coeffs val (m, stms) = eval (1, r) in List.rev ((result, DstIL.OP(DstOp.Add ty, [a0, m]))::stms) end in coeffVecs @ evalCode end (* compute the load address for a given set of voxels indices. For the * operation * * VoxelAddress<info>(i_1, ..., i_d) * * the address is given by * * base + szb * (i_1 + N_2 * (i_2 + N_3 * (... + N_d * i_d) ...)) * * where * base -- base address of the image data * szb -- image-element size in bytes * N_i -- size of ith axis in elements *) fun expandVoxelAddress (result, info, indices) = raise Fail "unimplemented" fun expandOp (env, y, rator, args) = let val args' = renameList(env, args) fun assign rator' = [(y, DstIL.OP(rator', args'))] in case rator of SrcOp.Add ty => assign (DstOp.Add ty) | SrcOp.Sub ty => assign (DstOp.Sub ty) | SrcOp.Mul ty => assign (DstOp.Mul ty) | SrcOp.Div ty => assign (DstOp.Div ty) | SrcOp.Neg ty => assign (DstOp.Neg ty) | SrcOp.LT ty => assign (DstOp.LT ty) | SrcOp.LTE ty => assign (DstOp.LTE ty) | SrcOp.EQ ty => assign (DstOp.EQ ty) | SrcOp.NEQ ty => assign (DstOp.NEQ ty) | SrcOp.GT ty => assign (DstOp.GT ty) | SrcOp.GTE ty => assign (DstOp.GTE ty) | SrcOp.Not => assign (DstOp.Not) | SrcOp.Max => assign (DstOp.Max) | SrcOp.Min => assign (DstOp.Min) | SrcOp.Sin => assign (DstOp.Sin) | SrcOp.Cos => assign (DstOp.Cos) | SrcOp.Pow => assign (DstOp.Pow) | SrcOp.Dot d => assign (DstOp.Dot d) | SrcOp.Cross => assign (DstOp.Cross) | SrcOp.Select(ty, i)=> assign (DstOp.Select(ty, i)) | SrcOp.Norm d => assign (DstOp.Norm d) | SrcOp.Scale d => assign (DstOp.Scale d) | SrcOp.InvScale d => assign (DstOp.InvScale d) | SrcOp.CL => assign (DstOp.CL) | SrcOp.PrincipleEvec ty => assign (DstOp.PrincipleEvec ty) | SrcOp.Subscript ty => assign (DstOp.Subscript ty) | SrcOp.Floor d => assign (DstOp.Floor d) | SrcOp.IntToReal => assign (DstOp.IntToReal) | SrcOp.TruncToInt d => assign (DstOp.TruncToInt d) | SrcOp.RoundToInt d => assign (DstOp.RoundToInt d) | SrcOp.CeilToInt d => assign (DstOp.CeilToInt d) | SrcOp.FloorToInt d => assign (DstOp.FloorToInt d) | SrcOp.VoxelAddress info => expandVoxelAddress (y, info, args') | SrcOp.LoadVoxels(rty, d) => assign (DstOp.LoadVoxels(rty, d)) | SrcOp.PosToImgSpace info => assign (DstOp.PosToImgSpace info) | SrcOp.GradToWorldSpace info => assign (DstOp.GradToWorldSpace info) | SrcOp.EvalKernel(d, h, k) => expandEvalKernel(y, d, h, k, args') | SrcOp.LoadImage info => assign (DstOp.LoadImage info) | SrcOp.Inside info => assign (DstOp.Inside info) | SrcOp.Input(ty, name) => assign (DstOp.Input(ty, name)) | SrcOp.InputWithDefault(ty, name) => assign (DstOp.InputWithDefault(ty, name)) (* end case *) end (* expand a SrcIL assignment to a DstIL CFG *) fun expand (env, (y, rhs)) = let val y' = rename (env, y) fun assign rhs = [(y', rhs)] in case rhs of SrcIL.VAR x => assign (DstIL.VAR(rename(env, x))) | SrcIL.LIT lit => assign (DstIL.LIT lit) | SrcIL.OP(rator, args) => expandOp (env, y', rator, args) | SrcIL.CONS args => assign (DstIL.CONS(renameList(env, args))) (* end case *) end structure Trans = TranslateFn ( struct structure SrcIL = SrcIL structure DstIL = DstIL type var_env = var_env val rename = rename val expand = DstIL.CFG.assignsToCFG o expand end) fun translate (SrcIL.Program{globals, globalInit, actors}) = let val env = VTbl.mkTable (256, Fail "env") fun transMethod (SrcIL.Method{name, stateIn, stateOut, body}) = DstIL.Method{ name = name, stateIn = renameList (env, stateIn), stateOut = renameList (env, stateOut), body = Trans.translate (env, body) } fun transActor (SrcIL.Actor{name, params, state, stateInit, methods}) = DstIL.Actor{ name = name, params = renameList (env, params), state = renameList (env, state), stateInit = Trans.translate (env, stateInit), methods = List.map transMethod methods } in DstIL.Program{ globals = renameList (env, globals), globalInit = Trans.translate (env, globalInit), actors = List.map transActor actors } end end
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |