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

SCM Repository

[diderot] View of /branches/vis15/src/compiler/mid-to-low/load-voxels.sml
ViewVC logotype

View of /branches/vis15/src/compiler/mid-to-low/load-voxels.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3800 - (download) (annotate)
Mon May 2 23:14:26 2016 UTC (4 years, 3 months ago) by jhr
File size: 6572 byte(s)
  Fixes for building with MLton
(* load-voxels.sml
 *
 * This module handles the expansion of the Mir IR operators LoadVoxels and
 * LoadVoxelsWithCtl into Low IR code.
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2016 The University of Chicago
 * All rights reserved.
 *)

structure LoadVoxels : sig

  (* expand the assignment
   *
   *	lhs = LoadVoxels<info,s>(img, idx)
   *
   * into Low IR code.
   *)
    val expand : {
	    lhs : LowIR.var,
	    info : ImageInfo.info,
	    s : int,
	    img : LowIR.var,
	    idx : LowIR.var
	  } -> LowIR.assign list

  (* expand the assignment
   *
   *	lhs = LoadVoxelsWithCtl<info,s,ctl>(img, idx)
   *
   * into Low IR code.
   *)
    val expandWithCtl : {
	    lhs : LowIR.var,
	    info : ImageInfo.info,
	    s : int,
	    ctl : IndexCtl.ctl,
	    img : LowIR.var,
	    idx : LowIR.var
	  } -> LowIR.assign list

  end = struct

    structure IR = LowIR
    structure V = IR.Var
    structure Ty = LowTypes
    structure Op = LowOps

    fun assignOp (avail, pre, ty, opss, args) =
	  AvailRHS.addAssign(avail, pre, ty, IR.OP(opss, args))

    fun imul' (avail, pre, a, b) = assignOp (avail, pre, Ty.IntTy, Op.IMul, [a, b])
    fun iadd' (avail, pre, a, b) = assignOp (avail, pre, Ty.IntTy, Op.IAdd, [a, b])
    fun ilit' (avail, pre, n) =
	  AvailRHS.addAssign (avail, pre, Ty.IntTy, IR.LIT(Literal.Int(IntLit.fromInt n)))
    fun imul (avail, a, b) = imul' (avail, "mulRes", a, b)
    fun iadd (avail, a, b) = iadd' (avail, "addRes", a, b)
    fun ilit (avail, n) = ilit' (avail, "ilit", n)

  (* load the indices into individual variables; return the number of indices and
   * the list of variables.
   *)
    fun loadIndices (avail, idx) = (case V.ty idx
	   of Ty.IntTy => (1, [idx])
	    | ty as Ty.SeqTy(Ty.IntTy, SOME n) => let
		fun loadIdx i =
		      assignOp (avail, "idx", Ty.IntTy, Op.Subscript ty, [idx, ilit (avail, i)])
		in
		  (n, List.tabulate (n, loadIdx))
		end
	    | ty => raise Fail(concat["loadIndices: bogus type " ^ Ty.toString ty])
	  (* end case *))

  (* load the sizes of the axes into individual variables (except the slowest).
   * The result will be a list of variables holding the axis sizes ordered from
   * fastest to slowest.
   *)
    fun loadSizes (avail, info, img) = (case ImageInfo.sizes info
	   of [] => let (* no proxy, so we need load sizes from image object *)
		fun load i = assignOp (avail, "sz", Ty.IntTy, Op.ImageDim(info, i), [img])
		in
		  List.tabulate (ImageInfo.dim info - 1, load)
		end
	    | sz::szs => let
		fun load (_, [], xs) = List.rev xs (* drop last size, since it is the slowest *)
		  | load (sz, sz'::szs, xs) = load (sz', szs, ilit (avail, sz) :: xs)
		in
		  load (sz, szs, [])
		end
	  (* end case *))

(* FIXME: we will get better CSE if we structure the address computation
 * as
 *      (base + stride * (...)) + offset
 * since the lhs argument will be the same for each sample.
 *)
  (* add code to handle the offset and stride when addressing non-scalar image data *)
    fun adjustForStrideAndOffset (avail, 1, _, ix) = ix
      | adjustForStrideAndOffset (avail, stride, 0, ix) =
	  imul' (avail, "offp", ilit' (avail, "stride", stride), ix)
      | adjustForStrideAndOffset (avail, stride, offset, ix) =
	  iadd' (avail, "offp",
	    ilit' (avail, "offset", offset),
	    imul (avail, ilit' (avail, "stride", stride), ix))

  (* compute the voxel address for a sample.  For the call
   *
   *    voxelAddress (avail, info, img) (offset, [i_1, ..., i_d])
   *
   * the address is given by
   *
   *    base + offset + stride * (i_1 + N_1 * (i_2 + N_2 * (... + N_{d-1} * i_d) ...))
   *
   * where
   *    base    -- base address of the image data
   *    stride  -- number of samples per voxel
   *    offset  -- offset of sample being addressed
   *    N_i     -- size of ith axis in elements
   *
   * Note that we are following the Nrrd convention that the axes are ordered
   * in fastest to slowest order.  We are also assuming the C semantics of address
   * arithmetic, where the offset will be automatically scaled by the size of the
   * elements.
   *)
    fun voxelAddress (avail, info, img) = let
          val stride = ImageInfo.stride info
        (* get N_1 ... N_{d-1} *)
	  val sizes = loadSizes (avail, info, img)
	  fun voxelAddr (offset, [ix]) = let
		val offp = adjustForStrideAndOffset (avail, stride, offset, ix)
		in
		  assignOp (avail, "baseAddr", Ty.AddrTy info, Op.VoxelAddress info, [img, offp])
		end
	    | voxelAddr (offset, ix::ixs) = let
		fun gen ([sz], [ix]) = imul (avail, sz, ix)
		  | gen (sz::szs, ix::ixs) = imul (avail, sz, iadd (avail, ix, gen (szs, ixs)))
		  | gen _ = raise Fail "voxelAddress: sizes/indices arity mismatch"
                val t = iadd(avail, ix, gen (sizes, ixs))
		val offp = adjustForStrideAndOffset (avail, stride, offset, t)
		in
		  assignOp (avail, "baseAddr", Ty.AddrTy info, Op.VoxelAddress info, [img, offp])
		end
	  in
	    voxelAddr
	  end

  (* apply f to the integers 0 .. n-1 *)
    fun foreach n f = let
	  fun lp i = if (i < n) then (f i; lp (i+1)) else ()
	  in
	    lp 0
	  end

  (* iterate over an N-dimensional grid of s^n indices.  For each location,
   * the function f gets called with a list of integers [idx1, ..., idxn],
   * where idx1 varies the fastest and idxn varies the slowest.
   *)
    fun gridIterate (n, s, f) = let
	  fun lp (i, idxs) = if (i < n)
		then foreach s (fn idx => lp (i+1, idx::idxs))
		else f idxs
	  in
	    lp (0, [])
	  end

    fun expand {lhs, info, s, img, idx} = let
	  val avail = AvailRHS.new ()
	  val (dim, idxs) = loadIndices (avail, idx)
	  in
	    List.rev (AvailRHS.getAssignments avail)
	  end

    fun expandWithCtl {lhs, info, s, ctl, img, idx} = let
	  val avail = AvailRHS.new ()
	  val (dim, idxs) = loadIndices (avail, idx)
	  in
	    List.rev (AvailRHS.getAssignments avail)
	  end

  end

(****** from vis12 branch
    fun expandVoxelAddressWithCtl (result, info, offset, ictl, img::indices) = let
	(* wrap each index with an ControlIndex operator *)
(* FIXME: need to check the order of indices here and in the high-to-mid code!!! *)
	  fun wrap (dim, idx::idxs, revIndices, revStms) = let
		val idx' = DstIL.Var.copy idx
		val stm = (idx', DstIL.OP(DstOp.ControlIndex(info, ictl, dim), [img, idx]))
		in
		  wrap (dim+1, idxs, idx'::revIndices, stm::revStms)
		end
	    | wrap (_, [], revIndices, revStms) =
		List.revAppend (revStms,
		  expandVoxelAddress (result, info, offset, img :: List.rev revIndices))
	  in
	    wrap (0, indices, [], [])
	  end
******)

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