File: ssa.sig

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (247 lines) | stat: -rw-r--r-- 12,267 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
(* 
 * Machine SSA representation.
 *
 * Some conventions
 * ----------------
 *  1.  Each machine instruction is mapped into an ssa_op.  Some exceptions:
 *      a.  live-out and live-in for each entry and exit are represented as 
 *          SINK and SOURCE nodes.
 *      b.  PHI functions may be inserted
 *      c.  COPYs may be propagated during construction of the ssa graph. 
 *  2.  Each instruction set must provide the pseudo instructions SINK, SOURCE
 *      and PHI.
 *  3.  Each ssa_op is numbered with its own ssa_id, starting from 0.
 *  4.  Each definition is given a unique (non-negative) value id
 *      IMPORTANT: ssa_id <> value.  Each instructions may define multiple
 *      values, even zero.   But each instruction is given its own unique id.
 *  5.  Negative value ids are immediate constants.   These are value numbered
 *      so that the each distinct constant is given unique (negative) id.
 *      These constants are entered into the operandTbl.
 *  6.  In-edges of the graph are use-def chains.  These are computed on the
 *      fly.
 *      Out-edges are def-use chains.  Both type of edges have the following
 *      form:
 *              (source id, dst id, register)
 *      Of course, immedidate operands have no edges associated with them.
 *  7.  The graph interface has high overhead.  So in order to allow faster
 *      implementation, we allow direct access to the internal data structures.
 *      These are:
 *         Name          Mapping             Description
 *         ---------------------------------------------------------------
 *         defSiteTbl   value -> ssa_id      Definition site of a value
 *                                           (i.e. use/def chains)
 *         blockTbl     ssa_id -> block      Block id of an instruction
 *         defsTbl      ssa_id -> value list Definitions of an ssa_op
 *         usesTbl      ssa_id -> value list Uses of an ssa_op
 *         rtlTbl       ssa_id -> rtl        RTL of an ssa_op
 *         succTbl      ssa_id -> outedges   Out edges of an ssa_op
 *                                           (i.e. def/use chains)
 *         ssaOpTbl     ssa_id -> ssa_op     ssa_op table
 *         cellKindTbl  value -> ssa_id      cellkind of a value
 *         operandTbl   value -> operand     operand table
 * 
 *     But in general, you should use the graph interface for traversal
 *     if are not sure how the internal tables work.
 * 
 * -- Allen (leunga@cs.nyu.edu)
 * 
 *)
signature SSA =
sig

   structure I          : INSTRUCTIONS
   structure C          : CELLS
   structure SP         : SSA_PROPERTIES
   structure RTL        : MLTREE_RTL
   structure CFG        : SSA_FLOWGRAPH
   structure Dom        : DOMINATOR_TREE
   structure DJ         : DJ_GRAPH
   structure GCMap      : GC_MAP
   structure MLTreeComp : MLTREECOMP
   structure W          : FREQ
      sharing SP.I = CFG.I = MLTreeComp.I = I
      sharing SP.RTL = RTL
      sharing MLTreeComp.T = RTL.T
      sharing I.C = SP.C = C 
      sharing Dom = DJ.Dom
      sharing CFG.W = W

   (*------------------------------------------------------------------------
    * Basic type definitions used in the SSA form
    *------------------------------------------------------------------------*)
   type value  = int             (* value id *)
   type pos    = int             (* position within a block *)
   type block  = Graph.node_id   (* block id *)
   type ssa_id = Graph.node_id   (* ssa id *)
   type rtl    = RTL.rtl         (* RTL *)
   type const  = SP.OT.const     (* constants *)
   type cfg    = CFG.cfg         (* control flow graph *)
                  (* dominator tree *)
   type dom    = (CFG.block,CFG.edge_info,CFG.info) Dom.dominator_tree 
   type nameTbl = {oldName:C.cell, index:int} IntHashTable.hash_table 

   (*------------------------------------------------------------------------
    * An SSA op is an instruction 
    *------------------------------------------------------------------------*)
   type ssa_op = I.instruction

   (*------------------------------------------------------------------------
    * Information about the SSA graph 
    *------------------------------------------------------------------------*)
   type ssa_info 

   (*------------------------------------------------------------------------
    * The graph structure
    *------------------------------------------------------------------------*)
   type ssa = (ssa_op,value,ssa_info) Graph.graph

   (*------------------------------------------------------------------------
    * How to create a new SSA graph
    *------------------------------------------------------------------------*)
                  (* create an empty SSA graph *)
   val newSSA : {cfg:     cfg, 
                 dom:     cfg -> dom, 
                 gcmap:   GCMap.gcmap option,
                 nameTbl: nameTbl option
                } -> ssa  
   val newRenamedVar : ssa -> C.cell -> value   (* generate renamed variable *)
   val newVar    : ssa -> C.cell -> C.cell      

   (* create a new op; but does not add edges *)
   val newOp     : ssa -> {id   : ssa_id,        
                           instr: I.instruction, 
                           rtl  : rtl, 
                           defs : value list,
                           uses : value list,
                           block: block,
                           pos  : pos
                          } -> unit
   val reserve   : ssa -> int -> unit           (* reserve n nodes *)
   val immed     : ssa -> int -> value          (* lookup immed value *)
   val operand   : ssa -> I.operand -> value    (* lookup perand *)
   val computeDefUseChains : ssa -> unit

   (*------------------------------------------------------------------------
    * Extract info from the SSA graph
    *------------------------------------------------------------------------*)
   val dom       : ssa -> dom                 (* extracts the dominator *)
   val cfg       : ssa -> cfg                 (* extracts the CFG *)
   val maxVar    : ssa -> int                 (* maximum number of ssa names *)
   val numberOfOperands : ssa -> int          (* number of operands *)
   val const     : ssa -> value -> const      (* lookup const values *)

   (*------------------------------------------------------------------------
    * Extract the raw tables.  
    * These should only be used when the optimization guarantees that
    * no new ssa ops are added to the graph, since that may involve resizing
    * these tables, rendering them obsolete.  
    *------------------------------------------------------------------------*)
   val defSiteTbl : ssa -> ssa_id Array.array    
   val blockTbl   : ssa -> block Array.array
   val posTbl     : ssa -> pos Array.array
   val defsTbl    : ssa -> value list Array.array 
   val usesTbl    : ssa -> value list Array.array 
   val rtlTbl     : ssa -> rtl Array.array
   val succTbl    : ssa -> value Graph.edge list Array.array (* out edges *)
   val ssaOpTbl   : ssa -> ssa_op Array.array                (* node table *) 
   val cellKindTbl: ssa -> C.cellkind IntHashTable.hash_table
                              (* cellkind table *)
   val operandTbl : ssa -> SP.OT.operandTable       
   val minPos     : ssa -> int ref
   val maxPos     : ssa -> int ref

   (*------------------------------------------------------------------------
    * Zero registers, pinned registers
    *------------------------------------------------------------------------*)
   val zeroRegs     : Word8Array.array
   val pinnedUseTbl : Word8Array.array
   val pinnedDefTbl : Word8Array.array

   (*------------------------------------------------------------------------
    * Lookup information (the safe way)
    *------------------------------------------------------------------------*)
   val defSite   : ssa -> value -> ssa_id          (* lookup definition site *)
   val block     : ssa -> ssa_id -> block          (* lookup block id *)
   val rtl       : ssa -> ssa_id -> rtl            (* lookup rtl *)
   val uses      : ssa -> ssa_id -> value list
   val defs      : ssa -> ssa_id -> value list

       (* nodes linearized and indexed by block id *)
   val nodes     : ssa -> {sources : ssa_id list Array.array,
                           phis    : ssa_id list Array.array,
                           ops     : ssa_id list Array.array,
                           sinks   : ssa_id list Array.array
                          }
   val freqTbl   : ssa -> W.freq Array.array  (* frequency indexed by block *)
   val noResize  : ssa -> ('a -> 'b) -> 'a -> 'b
   (*------------------------------------------------------------------------
    *  Iterators
    *------------------------------------------------------------------------*)
   val forallNodes : ssa -> (ssa_id -> unit) -> unit
   val foldNodes   : ssa -> (ssa_id * 'a -> 'a) -> 'a -> 'a 

   (*------------------------------------------------------------------------
    * Remove all useless phi-functions from the graph.  
    * Useless phi-functions are self-loops of the form
    *    t <- phi(t, t, ..., t, s, t, ..., t)
    * This transformation removes this phi-function and replace all uses
    * of t by s.  This process is worklist driven; removing a useless 
    * phi-function can introduce other useless phi-functions. 
    *------------------------------------------------------------------------*)
   val removeUselessPhiFunctions : ssa -> unit
 
   (*------------------------------------------------------------------------
    * Remove all nodes from the graph.  Note that no uses should be
    * present after this transformation.
    *------------------------------------------------------------------------*)
   val removeAllNodes : ssa -> ssa_id list -> unit

   (*------------------------------------------------------------------------
    * Replace all use of one value with another.  Return true iff
    * all uses of "from" has been replaced by "to".
    * Note: The definition of "from" must dominate all uses of "to", as
    * required by the SSA form.
    *------------------------------------------------------------------------*)
   val replaceAllUses : ssa -> {from:value, to:value, vn:value} -> bool

   (*------------------------------------------------------------------------
    * Replace the definition of value by const.  Return true iff
    * this operation is successful.
    *------------------------------------------------------------------------*)
   val foldConstant : ssa -> {value:value, const:value} -> bool

   (*------------------------------------------------------------------------
    * Move an instruction from one block to another
    *------------------------------------------------------------------------*)
   val moveOp : ssa -> {id:ssa_id, block:block} -> unit

   (*------------------------------------------------------------------------
    * Set the target of a conditional branch as true or false.
    * This removes the branch and eliminates all unreachable code.
    *------------------------------------------------------------------------*)
   val setBranch : ssa -> {id:ssa_id, cond:bool} -> unit

   (*------------------------------------------------------------------------
    * Signal that an SSA has been changed.   This uncaches all data structures.
    *------------------------------------------------------------------------*)
   val changed : ssa -> unit

   (*------------------------------------------------------------------------
    *  Pretty printing 
    *------------------------------------------------------------------------*)
   val showOp  : ssa -> ssa_id -> string
   val showVal : ssa -> value -> string
   val showRTL : ssa -> rtl -> string

   (*------------------------------------------------------------------------
    *  Graphical viewing 
    *------------------------------------------------------------------------*)
   val viewAsCFG : ssa -> GraphLayout.layout
   val viewAsSSA : ssa -> GraphLayout.layout

   (*------------------------------------------------------------------------
    *  Check whether the ssa graph is consistent
    *------------------------------------------------------------------------*)
   val consistencyCheck : ssa -> unit
end