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

SCM Repository

[diderot] View of /branches/vis15/src/compiler/simplify/simplify-vars.sml
ViewVC logotype

View of /branches/vis15/src/compiler/simplify/simplify-vars.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3995 - (download) (annotate)
Sat Jun 18 20:00:19 2016 UTC (3 years, 1 month ago) by jhr
File size: 6854 byte(s)
  Working on merge: fix initialization of globals
(* simplify-vars.sml
 *
 * This module analyses the use of variables in the Simple AST and rationalizes
 * their use in the following ways:
 *
 *   -- for any strand parameter that is used in a method, we create a shadow state
 *      variable
 *
 *   -- strand-invariant state variables (except outputs) and expressions are
 *      lifted to global scope. (TODO)
 *
 *   -- local variables that are bound to images and are used to define fields
 *      need to be promoted to global scope so that when the fields variables
 *      are removed in the high-to-mid phase, the image variables are still in
 *      scope. (TODO)
 *
 * We assume that contraction has already been run and that unused variables have
 * been eliminated.
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2015 The University of Chicago
 * All rights reserved.
 *)

structure SimplifyVars : sig

    val transform : Simple.program -> Simple.program

  end = struct

    structure S = Simple
    structure SV = SimpleVar
    structure VMap = SimpleVar.Map

  (* track if a strand parameter is referenced in a strand method *)
    local
      val {setFn, getFn} = SV.newFlag()
    in
      fun markUsedInMethod x = (case SV.kindOf x
	     of SV.StrandParam => setFn(x, true)
	      | _ => ()
	    (* end case *))
      fun isUsedInMethod x = getFn x
      fun clrUsedInMethodMark x = setFn(x, false)
    end (* local *)

  (* analyze a method for uses of parameters *)
    fun analyzeMethod blk = let
	  fun analyzeBlk (S.Block{code, ...}) = List.app analyzeStm code
	  and analyzeStm stm = (case stm
                 of S.S_Var(x, NONE) => ()
		  | S.S_Var(x, SOME e) => analyzeExp e
                  | S.S_Assign(x, e) => analyzeExp e
                  | S.S_IfThenElse(x, b1, b2) => (markUsedInMethod x; analyzeBlk b1; analyzeBlk b2)
		  | S.S_Foreach(x, xs, blk) => analyzeBlk blk
                  | S.S_New(strnd, xs) => List.app markUsedInMethod xs
                  | S.S_Continue => ()
                  | S.S_Die => ()
                  | S.S_Stabilize => ()
                  | S.S_Return x => markUsedInMethod x
                  | S.S_Print xs => List.app markUsedInMethod xs
		  | S.S_MapReduce{args, ...} => raise Fail "unexpected MapReduce in method"
		(* end case *))
	  and analyzeExp exp = (case exp
		 of S.E_Var x => markUsedInMethod x
		  | S.E_Lit _ => ()
		  | S.E_Select(x, fld) => markUsedInMethod x
		  | S.E_Apply(f, xs, _) => List.app markUsedInMethod xs
		  | S.E_Prim(_, _, xs, _) => List.app markUsedInMethod xs
		  | S.E_Tensor(xs, _) => List.app markUsedInMethod xs
		  | S.E_Seq(xs, _) => List.app markUsedInMethod xs
		  | S.E_Slice(x, indices, _) => markUsedInMethod x
		  | S.E_Coerce{x, ...} => markUsedInMethod x
		  | S.E_LoadSeq _ => ()
		  | S.E_LoadImage _ => ()
		(* end case *))
	  in
	    analyzeBlk blk
	  end

  (* rename the free variables in a block according to the given mapping.  Variables that are
   * not in the domain of the map are unchanged.
   *)
    fun renameBlock env = let
          fun rename x = (case VMap.find(env, x)
                 of SOME x' => x'
                  | NONE => x
                (* end case *))
	  val renameList = List.map rename
	  fun renameBlk (S.Block{props, code}) = S.Block{props = props, code = List.map renameStm code}
	  and renameStm stm = (case stm
                 of S.S_Var(x, NONE) => stm
		  | S.S_Var(x, SOME e) => S.S_Var(x, SOME(renameExp e))
                  | S.S_Assign(x, e) => S.S_Assign(rename x, renameExp e)
                  | S.S_IfThenElse(x, b1, b2) =>
                      S.S_IfThenElse(rename x, renameBlk b1, renameBlk b2)
		  | S.S_Foreach(x, xs, blk) =>
		      S.S_Foreach(rename x, rename xs, renameBlk blk)
                  | S.S_New(strnd, xs) => S.S_New(strnd, renameList xs)
                  | S.S_Continue => stm
                  | S.S_Die => stm
                  | S.S_Stabilize => stm
                  | S.S_Return x => S.S_Return(rename x)
                  | S.S_Print xs => S.S_Print(renameList xs)
		  | S.S_MapReduce{results, reductions, body, args, source} => S.S_MapReduce{
			results = results,
			reductions = reductions,
			body = body,
			args = renameList args,
			source = source
		      }
		(* end case *))
	  and renameExp exp = (case exp
                 of S.E_Var x => S.E_Var(rename x)
		  | S.E_Select(x, fld) => S.E_Select(rename x, fld)
                  | S.E_Lit _ => exp
                  | S.E_Apply(f, xs, ty) => S.E_Apply(f, renameList xs, ty)
                  | S.E_Prim(f, tys, xs, ty) =>
                      S.E_Prim(f, tys, renameList xs, ty)
                  | S.E_Tensor(xs, ty) => S.E_Tensor(renameList xs, ty)
                  | S.E_Seq(xs, ty) => S.E_Seq(renameList xs, ty)
                  | S.E_Slice(x, idxs, ty) => S.E_Slice(rename x, idxs, ty)
                  | S.E_Coerce{srcTy, dstTy, x} =>
                      S.E_Coerce{srcTy=srcTy, dstTy=dstTy, x=rename x}
                  | S.E_LoadSeq _ => exp
                  | S.E_LoadImage _ => exp
		(* end case *))
	  in
	    renameBlk
	  end

  (* transform a strand definition by introducing shadow state variables for
   * parameters.
   *)
    fun doStrand (S.Strand{name, params, state, stateInit, initM, updateM, stabilizeM}) = let
	(* analyze the methods *)
	  val () = (
		Option.app analyzeMethod initM;
		analyzeMethod updateM;
		Option.app analyzeMethod stabilizeM)
	(* identify parameters that need to be shadowed *)
	  val shadowParams = List.filter (not o isUsedInMethod) params
	  in
	    case List.filter isUsedInMethod params
	     of [] => NONE
	      | used => let
		  val (shadowParams, initStms, env) = let
			fun f (x, (xs, stms, env)) = let
				val x' = SV.copy(x, SV.StrandStateVar)
				val stm = S.S_Assign(x', S.E_Var x)
				in
				  (x'::xs, stm::stms, VMap.insert(env, x, x'))
				end
			in
			  List.foldr f ([], [], VMap.empty) used
			end
		  val rename = renameBlock env
		  in
		    SOME(S.Strand{
			name = name, params = params,
			state = state @ shadowParams,
			stateInit = let
			  val S.Block{props, code} = stateInit
			  in
			    S.Block{props = props, code = code @ initStms}
			  end,
			initM = Option.map rename initM,
			updateM = rename updateM,
			stabilizeM = Option.map rename stabilizeM
		      })
		  end
	    (* end case *)
	  end

    fun transform prog = let
	  val S.Program{
		  props, consts, inputs, constInit, globals, funcs,
		  globInit, strand, create, init, update
		} = prog
	  in
	    case doStrand strand
	     of NONE => prog
	      | SOME strand => S.Program{
		    props = props, consts = consts, inputs = inputs, constInit = constInit,
		    globals = globals, funcs = funcs, globInit = globInit, strand = strand,
		    create = create, init = init, update = update
		  }
	    (* end case *)
	  end

  end

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