Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/charisee/src/compiler/mid-to-low/ein-to-low-set.sml
ViewVC logotype

View of /branches/charisee/src/compiler/mid-to-low/ein-to-low-set.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3624 - (download) (annotate)
Fri Jan 29 17:49:01 2016 UTC (4 years, 2 months ago) by jhr
File size: 11566 byte(s)
adding header comments in prep for merge
(* ein-to-low-set.sml
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2016 The University of Chicago
 * All rights reserved.
 *)

(*
* genfn-Does preliminary scan of the body of EIN.EIN for vectorization potential
* If there is a field then passes to FieldToLow
* If there is a tensor then passes to handle*() functions to check if indices match
* i.e. <A_ij+B_ij>_ij vs.<A_ji+B_ij>_ij
*
*     (1) If indices match then passes to Iter->VecToLow functions.
*            Creates LowIL vector operators.
*     (2) Iter->ScaToLow
*           Creates Low-IL scalar operators
* Note. The Iter function creates LowIL.CONS and therefore binds the indices in the EIN.body 
*)
structure EinToLow = struct
    local

    structure Var = LowIL.Var
    structure E = Ein
    structure P = Printer
    structure Iter = Iter
    structure EtoSca = ScaToLow
    structure EtoVec = VecToLow
    structure H = Helper
    structure Op = LowOps

    in

    fun iter e = Iter.prodIter e
    fun intToReal n = H.intToReal n
    
    (*dropIndex: a list-> int*a*alist
    * alpha::i->returns  length of list-1, i, alpha
    *)
    fun dropIndex alpha = let
        val (e1::es) = List.rev(alpha)
        in (length alpha-1, e1, List.rev es)
        end

    (*matchLast:E.alpha*int -> (E.alpha) Option
    * Is the last index of alpha E.V n.
    * If so, return the rest of the list 
    *)
    fun matchLast (alpha, n) = 
        case List.rev(alpha)
            of (E.V v)::es => (case (n = v)
                of true => SOME(List.rev es)
                | _ =>   NONE
                (*end case*))
            | _ => NONE

    (*matchFindLast:E.alpha *int -> E.alpha option* E.mu option
    * Is the last index of alpha = n.
    * is n anywhere else?
    *)
    fun matchFindLast (alpha, n) = let
        val es = List.tl(List.rev(alpha))
        val f = List.find(fn E.V e => e = n | _ => false) es
        in
            (matchLast(alpha, n), f)
        end 

    (*runGeneralCase:Var*E.EIN*Var-> Var*LowIL.ASSN list
    * does not do vector projections
    * instead approach like a general EIN
    *)
    fun runGeneralCase (e:Ein.ein, args:LowIL.var list) = let
        val index = Ein.index e
        in
            iter(AvailRHS.new(), index, index, EtoSca.generalfn, (e, args))
        end

    fun createP((E.EIN{params ,...}, args), vecIndex, id, ix) =
        VecToLow.Param(id, List.nth (args, id), H.getTensorTy (params, id), ix, VecToLow.Proj vecIndex)
        
    fun createI((E.EIN{params ,...}, args), id, ix) =
        VecToLow.Param(id, List.nth (args, id), H.getTensorTy (params, id), ix, VecToLow.Indx)
        
    (*handleNeg:.body* int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for scaling a vector with negative 1.
    *)
    fun handleNeg (E.Op1(E.Neg, E.Tensor(id , alpha)), index, info) = let
        val (n, vecIX, index') = dropIndex index
        in case (matchLast(alpha, n))
            of SOME ix1 => let
                val avail = AvailRHS.new()
                val (avail, vA) = intToReal(avail, ~1)
                val vecB = createP(info, vecIX, id, ix1)
                val nextfnargs = (vA, vecIX, vecB)
                in
                    iter(avail, index, index', EtoVec.negV, nextfnargs)
                end
            | NONE => runGeneralCase info
        end

    (*handleSub:E.body*int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for subtracting two vectors
    *)
    fun handleSub (E.Op2(E.Sub, E.Tensor(id1, alpha), E.Tensor(id2, beta)), index, info) = let
        val (n, vecIX, index') = dropIndex index
        in case(matchLast(alpha, n) , matchLast(beta, n)) of
            (SOME ix1, SOME ix2) =>let
                val avail = AvailRHS.new()
                val vecA = createP(info, vecIX, id1, ix1)
                val vecB = createP(info, vecIX, id2, ix2)
                val nextfnargs = (vecIX, Op.subVec vecIX, vecA, vecB)
                in
                    iter(avail, index, index', EtoVec.op2, nextfnargs)
                end 
            | _   => runGeneralCase info
        end

    (*handleAdd:E.body*int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for adding two vectors
    *)
    fun handleAdd (E.Opn(E.Add, es), index, info) = let
        val (n, vecIX, index') = dropIndex index
        (*check that each tensor in addition list has matching indices*)
        fun sample ([], rest) = let
            val avail = AvailRHS.new()
            val nextfnargs = (vecIX, List.rev rest)
            in
                iter(avail, index, index', EtoVec.addV, nextfnargs)
            end 
        | sample (E.Tensor(id1, alpha)::ts, rest) = (case (matchLast(alpha, n))
            of SOME ix1    => sample(ts, createP(info, vecIX, id1, ix1)::rest)
            | _            => runGeneralCase info
            (*end case*))
        | sample _ = runGeneralCase info
        in
            sample(es, [])
        end
        
    (*handleScale:E.tensor_id*E.tensor_id*E.alpha*int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for adding scaling a vector
    *)
    fun handleScale (id1, id2, alpha2, index, info) = let
        val (n, vecIX, index') = dropIndex index
        in case matchLast(alpha2, n)
            of SOME ix2 =>  let
                val avail = AvailRHS.new()
                val vecA = createI(info, id1, [])
                val vecB = createP(info, vecIX, id2, ix2)
                val nextfnargs = (vecIX, Op.prodScaV vecIX, vecA, vecB)
                in
                    iter(avail, index, index', EtoVec.op2, nextfnargs)
                end
            | _ =>runGeneralCase info
        end

    (*handleProd:E.body*int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for vector product
    *)
    fun handleProd (E.Opn(E.Prod, [E.Tensor(id1 , alpha), E.Tensor(id2, beta)]), index, info) = let
        val (e, args) = info
        val (n, vecIX, index') = dropIndex index
        val avail = AvailRHS.new()
        in case(matchFindLast(alpha, n), matchFindLast(beta, n))
            of ((SOME ix1, NONE), (SOME ix2, NONE)) => let
                (*n is the last index of alpha, beta and nowhere else, possible modulate*)
                val vecA = createP(info, vecIX, id1, ix1)
                val vecB = createP(info, vecIX, id2, ix2)
                val nextfnargs = (vecIX, Op.prodVec vecIX, vecA, vecB)
                in
                    iter(avail, index, index', EtoVec.op2, nextfnargs)
                end
            | ((NONE, NONE), (SOME ix2, NONE)) =>let
                (*n is the last index of beta and nowhere else, possible scaleVector*)
                val vecA = createI(info, id1, alpha)
                val vecB = createP(info, vecIX, id2, ix2)
                val nextfnargs = (vecIX, Op.prodScaV vecIX, vecA, vecB)
                in
                    iter(avail, index, index', EtoVec.op2 , nextfnargs)
                end
            | ((SOME ix1, NONE), (NONE, NONE)) =>let
                (*n is the last index of alpha and nowhere else, ossile scaleVector*)
                val vecA = createI(info, id2, beta)
                val vecB = createP(info, vecIX, id1, ix1)
                val nextfnargs = (vecIX, Op.prodScaV vecIX, vecA, vecB)
                
                in
                    iter(avail, index, index', EtoVec.op2, nextfnargs)
                end
            | _ => runGeneralCase info
        end
    
    (*handleSumProd:E.body*int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for dot product
    *)
    fun handleSumProd1 (E.Sum([(E.V v, _, ub)], E.Opn(E.Prod, [E.Tensor(id1 , alpha), E.Tensor(id2, beta)])), index, info) = 
        case(matchFindLast(alpha, v), matchFindLast(beta, v))
            of ((SOME ix1, NONE), (SOME ix2, NONE)) => let
                (*v is the last index of alpha, beta and nowhere else, possible sumProd*)
                val avail = AvailRHS.new()
                val vecIX= ub+1
                val vecA = createP(info, vecIX, id1, ix1)
                val vecB = createP(info, vecIX, id2, ix2)
                val nextfnargs = (vecIX, vecA, vecB)
                in
                    iter(avail, index, index, EtoVec.dotV, nextfnargs)
                end
        | _ => runGeneralCase info

    
    (*handleSumProd:E.body*int list*info ->Var*LowIL.ASSN list
    * info:(string*E.EIN*Var list)
    * low-IL code for double dot product
    * Sigma_{i, j} A_ij B_ij
    *)
    fun handleSumProd2 (body, index, info) = let
        val E.Sum([(E.V v1, lb1, ub1), (E.V v2, lb2, ub2)], E.Opn(E.Prod, [E.Tensor(id1 , alpha), E.Tensor(id2, beta)])) = body
        fun check(v, ub, sx) = (case (matchFindLast(alpha, v), matchFindLast(beta, v))
            of ((SOME ix1, NONE), (SOME ix2, NONE)) => let
                (*v is the last index of alpha, beta and nowhere else, possible sumProd*)
                val avail = AvailRHS.new()
                (*val nextfnargs = (Ein.params e, args, sx, ub+1, id1, ix1, id2, ix2)*)
                val vecIX= ub+1
                val vecA = createP(info, vecIX, id1, ix1)
                val vecB = createP(info, vecIX, id2, ix2)
                val nextfnargs = (sx, vecIX, vecA, vecB)
                in
                    SOME(iter(avail, index, index, EtoVec.sumDotV, nextfnargs))
                end
            | _ => NONE
            (*end case*))
        in (case check(v1, ub1, (E.V v2, lb2, ub2))
            of SOME e =>e
            | _ => (case check(v2, ub2, (E.V v1, lb1, ub1))
                of SOME e => e
                |_ => runGeneralCase info
                (*end case*))
            (*end case*))
        end

    (*scan:var*E.Ein*Var list * Var list-> Var*LowIL.Assgn list
    *scans body  for vectorization potential
    *)
    fun scan (y, e:Ein.ein, args:LowIL.var list) = let
        val b = Ein.body e
        val index = Ein.index e
        val info = (e, args)
        val all = (b, index, info)

        (*any result type*)
        fun gen() = case b
            of E.Sum([_], E.Opn(E.Prod, [E.Tensor(_ , i::ix), E.Tensor(_, j::jx)])) => handleSumProd1 all
            | E.Sum([_, _], E.Opn(E.Prod, [E.Tensor(_ , i::ix), E.Tensor(_, j::jx)])) => handleSumProd2 all
            |  _ => runGeneralCase info
        (*non scalar result for sure*)
        fun nonScalar() = case b
            of E.Op2(E.Sub, E.Tensor(_, _::_), E.Tensor(_, _::_)) => handleSub all
            | E.Opn(E.Add, (E.Tensor(_, _::_)::_)) => handleAdd all
            | E.Op1(E.Neg, E.Tensor(_ , _::_)) => handleNeg all
            | E.Opn(E.Prod, [E.Tensor(s, []), E.Tensor(v, j::jx)]) => handleScale(s, v, j::jx, index, info)
            | E.Opn(E.Prod, [E.Tensor(v, j::jx), E.Tensor(s , [])]) => handleScale(s, v, j::jx, index, info)
            | E.Opn(E.Prod, [E.Tensor(_ , _::_), E.Tensor(_, _::_)]) => handleProd all
            |  _ => gen()

          val (avail, _) = case index
            of [3, 3] => runGeneralCase info
            | [3, 3, 3] => runGeneralCase info
            | _::_ => nonScalar()
            | _ => gen()
        in  case AvailRHS.getAssignments avail
            of (x, A)::rest =>  let (*need to reassign the last assgn*)
                val code = List.rev((x, A)::rest)
                val rtn = code@[(y, A)]
                in List.map (fn e =>LowIL.ASSGN(e)) rtn end
        end
        

end (* local *)

end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0