Home My Page Projects Code Snippets Project Openings 3D graphics for Standard ML
Summary Activity SCM

SCM Repository

[sml3d] View of /trunk/sml3d/src/particles/compiler/inline-block.sml
ViewVC logotype

View of /trunk/sml3d/src/particles/compiler/inline-block.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 874 - (download) (annotate)
Thu May 6 18:08:36 2010 UTC (9 years, 4 months ago) by pavelk
File size: 3393 byte(s)
Added a new property to blocks: reference count. This new property is used in an optimization where we remove unused blocks from the program, and inline blocks that only have one reference count to reduce the amount of branching that we need to do.
structure BlockEliminator :> PSYSIR_OPTIMIZATION =
  struct
   
   structure IR = PSysIR
  
   fun resetRefCountForBlock(IR.BLK{refCount, ...}) = refCount := 0
   
   fun countRefsInBlock(IR.BLK{body, ...}) = let
     fun updateRefForBlock(IR.BLK{refCount, ...}) = refCount := (!refCount) + 1
     fun stepStmt(IR.PRIM(v, p, vl, s)) = stepStmt(s)
       | stepStmt(IR.IF(v, s1, s2)) = (stepStmt(s1); stepStmt(s2))
       | stepStmt(IR.GOTO(blk, vl)) = updateRefForBlock(blk)
       | stepStmt(_) = ()
       
    in
     stepStmt(body)
    end
    
   fun inlineBlocks(IR.BLK{id, params, body, visited, refCount}) = let
     fun fixStmt(v as IR.V{scope, ...}, p, vl, s) = ((case scope
      of IR.S_LOCAL(rhs) => rhs := (p, vl)
       | _ => ()
      (* end case *));
      IR.PRIM(v, p, vl, s))

     (* Replace the instances of params with args in vl. We assume
      * that args and params have the same length, since otherwise
      * we should have caught a compilation error...
      *)      
     fun replaceArg(v, args, pms) = let
       (* Return the index into the list of our params of the given variable *)
       fun searchParams(v, p :: ps, n) = 
         if IR.compare(v, p) = EQUAL then 
          n 
         else 
          searchParams(v, ps, n + 1)
         
         | searchParams(v, [], _) = ~1
       
       val idx = searchParams(v, pms, 0)
      in
       if idx < 0 then
        v
       else
        List.nth(args, idx)
      end
      
     fun replaceArgs(vl, args, pms) = let
       fun proxyRep(v) = replaceArg(v, args, pms)
      in
       List.map proxyRep vl
      end
           
     fun replaceStmts(IR.PRIM(v, p, vl, s), args, pms) = 
         fixStmt(v, p, replaceArgs(vl, args, pms), replaceStmts(s, args, pms))
       
       | replaceStmts(IR.IF(v, s1, s2), args, pms) = 
         IR.IF(replaceArg(v, args, pms), replaceStmts(s1, args, pms), replaceStmts(s2, args, pms))
       
       | replaceStmts(IR.GOTO(blk, vl), args, pms) = IR.GOTO(blk, replaceArgs(vl, args, pms))
       
       | replaceStmts(IR.RETURN(vl), args, pms) = IR.RETURN(replaceArgs(vl, args, pms))
       
       | replaceStmts(x, _, _) = x
       
     
     fun doInline(IR.PRIM(v, p, vl, s)) = IR.PRIM(v, p, vl, doInline(s))
       | doInline(IR.IF(v, s1, s2)) = IR.IF(v, doInline(s1), doInline(s2))
       
       | doInline(IR.GOTO(blk as IR.BLK{body=stmts, refCount=rc, params=ps, ...}, vl)) =
         if (!rc) = 1 then
          replaceStmts(stmts, vl, ps)
         else
          IR.GOTO(blk, vl)
       
       | doInline(x) = x
     
    in
     IR.BLK{id=id, params=params, body=doInline(body), visited=visited, refCount=refCount}
    end
    
  fun isUsefulBlk(IR.BLK{refCount, ...}) = (!refCount) > 1
    
  fun inlineBlockList(blks) = let
    fun removeUselessNotRoot(blk :: rest) = blk :: (List.filter isUsefulBlk rest) 
      | removeUselessNotRoot([]) = []
   in
    List.app resetRefCountForBlock blks;
    List.app countRefsInBlock blks;
    removeUselessNotRoot(List.map inlineBlocks blks)
   end
    
  fun optimize (IR.PGM{emitter, physics, render}) = IR.PGM {
    (* the emitter is only ever one block, so there's nothing
     * to inline...
     *)
    emitter = emitter,
    
    physics = inlineBlockList(physics),
    render = render
  }
  
  end

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