Modern Compiler Implementation in ML

©1998 by Andrew W. Appel

An Alternate Graph Representation for the Tiger Compiler

Chapter 10 describes the Graph module, which presents an abstract view of directed graphs for CFG's and interference graphs. Without so much abstraction, the compiler can run faster: in particular, with the following representation of flowgraphs and interference graphs, liveness analysis and register allocation is about 10 times faster.

Flow

Structure Flow, which defines the representation of control flow graphs, need not use the Graph abstraction:
structure Flow =
struct
    datatype node = NODE of {def: Temp.temp list, 
			     use: Temp.temp list, 
			     ismove: bool,
			     succ: node list ref,
			     pred: node list ref,	
			     liveOut: Temp.temp list ref}

    type flowgraph = node list
end

MakeGraph

The flowgraph created by MakeGraph will have accurate def,use,ismove,succ,pred information, but all the liveOut lists will be empty:
structure MakeGraph : 
   sig 
       val instrs2graph : Assem.instr list -> Flow.flowgraph
   end

Liveness

Liveness analysis will fill in the liveOut information of each flow node, and will then create an interference graph in which each node has a status of INGRAPH(d), where d=length(!adj).
structure Liveness : 
sig
    structure I : sig
          datatype status = INGRAPH of int (* degree *)
			  | REMOVED
			  | COLORED of string

          datatype node = NODE of {temp: Temp.temp,
				   adj: node list ref,
				   status: status ref}

    end
    datatype igraph = IGRAPH of {graph: I.node list,
			         moves: (I.node*I.node) list}

    val interferenceGraph : Flow.flowgraph -> igraph
	                      
    val show : TextIO.outstream * igraph -> unit
end

Color

The signature COLOR doesn't change, but of course it's referring to a different igraph type than before. The status of a node in an interference graph can be any of:
INGRAPH(d)
means that the node is still in the graph, and d the number of nodes on the adj list whose status is either INGRAPH or COLORED.
REMOVED
means that the node has been removed from the graph (for efficiency, do not actually delete the nodes and edges).
COLORED(r)
means that the node has been assigned color (i.e., register name) r.
signature COLOR =
sig
  structure Frame : FRAME

  type allocation = Frame.register Temp.Table.table

  val color: {interference: Liveness.igraph,
	      initial: allocation,
	      spillCost: Temp.temp -> int,
	      registers: Frame.register list}
	       -> allocation * Temp.temp list
end