-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathBasicBlock.java
More file actions
281 lines (266 loc) · 8.87 KB
/
BasicBlock.java
File metadata and controls
281 lines (266 loc) · 8.87 KB
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
package com.compilerprogramming.ezlang.compiler;
import java.util.*;
public class BasicBlock {
public final int bid;
public final boolean loopHead;
public final List<BasicBlock> successors = new ArrayList<>(); // successors
public final List<BasicBlock> predecessors = new ArrayList<>();
public final List<Instruction> instructions = new ArrayList<>();
/**
* The preorder traversal number, also acts as a flag indicating whether the
* BB is yet to be visited (_pre==0 means not yet visited).
*/
int pre;
/**
* The depth of the BB in the dominator tree
*/
int domDepth;
/**
* Reverse post order traversal number;
* Sort node list in ascending order by this to traverse graph in reverse post order.
* In RPO order if an edge exists from A to B we visit A followed by B, but cycles have to
* be dealt with in another way.
*/
int rpo;
/**
* Immediate dominator is the closest strict dominator.
* @see DominatorTree
*/
public BasicBlock idom;
/**
* Nodes for whom this node is the immediate dominator,
* thus the dominator tree.
*/
public List<BasicBlock> dominatedChildren = new ArrayList<>();
/**
* Dominance frontier
*/
public Set<BasicBlock> dominationFrontier = new HashSet<>();
/**
* Nearest Loop to which this BB belongs
*/
public LoopNest loop;
// Liveness computation
/**
* VarKill contains all the variables that are defined
* in the block. This is often called defs in literature, but
* we use the name in Engineering a Compiler.
*/
LiveSet varKill;
/**
* UEVar contains upward-exposed variables in the block,
* i.e. those variables that are used in the block prior to
* any redefinition in the block.
*
* This is often called uses in Literature but we use the
* name in Engineering a Compiler.
*/
LiveSet UEVar;
/**
* LiveOut is the union of variables that are live at the
* head of some block that is a successor of this block.
*/
LiveSet liveOut;
/**
* phiUses(B) is the set of variables used in a phi-operation at entry of a block successor of the block B
* That is, inputs to successor block's phi functions.
*/
LiveSet phiUses;
/**
* phiDefs(B) the variables defined by phi-operations at entry of the block B
*/
LiveSet phiDefs;
/**
* Live in set
*/
LiveSet liveIn;
// -----------------------
public BasicBlock(int bid, boolean loopHead) {
this.bid = bid;
this.loopHead = loopHead;
}
public BasicBlock(int bid) {
this(bid, false);
}
// For testing only
public BasicBlock(int bid, BasicBlock... preds) {
this.bid = bid;
this.loopHead = false;
for (BasicBlock bb : preds)
bb.addSuccessor(this);
}
public void add(Instruction instruction) {
instructions.add(instruction);
instruction.block = this;
}
public void add(int pos, Instruction instruction) {
instructions.add(pos, instruction);
instruction.block = this;
}
public void update(int pos, Instruction instruction) {
instructions.set(pos, instruction);
instruction.block = this;
}
public void deleteInstruction(Instruction instruction) {
instructions.remove(instruction);
}
public void addSuccessor(BasicBlock successor) {
if (!successors.contains(successor)) {
successors.add(successor);
successor.predecessors.add(this);
}
}
public void removeSuccessor(BasicBlock successor) {
successors.remove(successor);
successor.predecessors.remove(this);
}
/**
* Initially the phi has the form
* v = phi(v,v,...)
*/
public void insertPhiFor(Register var) {
for (Instruction i: instructions) {
if (i instanceof Instruction.Phi phi) {
if (phi.value().nonSSAId() == var.nonSSAId())
// already added
return;
}
else break;
}
List<Register> inputs = new ArrayList<>();
for (int i = 0; i < predecessors.size(); i++)
inputs.add(var);
Instruction.Phi phi = new Instruction.Phi(var, inputs);
add(0, phi);
}
public List<Instruction.Phi> phis() {
List<Instruction.Phi> list = new ArrayList<>();
for (Instruction i: instructions) {
if (i instanceof Instruction.Phi phi)
list.add(phi);
else break;
}
return list;
}
public int whichPred(BasicBlock pred) {
int i = 0;
for (BasicBlock p: predecessors) {
if (p == pred)
return i;
i++;
}
throw new IllegalStateException();
}
public BasicBlock predecessor(int i) {
if (i >= predecessors.size())
return null;
return predecessors.get(i);
}
public int whichSucc(BasicBlock succ) {
int i = 0;
for (BasicBlock s: successors) {
if (s == succ)
return i;
i++;
}
throw new IllegalStateException();
}
public void replaceInstruction(Instruction instruction, List<Instruction> replacements) {
int i;
for (i = 0; i < instructions.size(); i++)
if (instructions.get(i) == instruction)
break;
assert i < instructions.size();
for (int j = replacements.size()-1; j >= 0; j--) {
instructions.add(i+1, replacements.get(j));
}
instructions.remove(i);
}
public static StringBuilder toStr(StringBuilder sb, BasicBlock bb, BitSet visited, boolean dumpLiveness)
{
if (visited.get(bb.bid))
return sb;
visited.set(bb.bid);
sb.append("L").append(bb.bid).append(":\n");
for (Instruction n: bb.instructions) {
sb.append(" ");
n.toStr(sb).append("\n");
}
if (dumpLiveness) {
if (bb.phiDefs != null) sb.append(" #PHIDEFS = ").append(bb.phiDefs.toString()).append("\n");
if (bb.phiUses != null) sb.append(" #PHIUSES = ").append(bb.phiUses.toString()).append("\n");
if (bb.UEVar != null) sb.append(" #UEVAR = ").append(bb.UEVar.toString()).append("\n");
if (bb.varKill != null) sb.append(" #VARKILL = ").append(bb.varKill.toString()).append("\n");
if (bb.liveIn != null) sb.append(" #LIVEIN = ").append(bb.liveIn.toString()).append("\n");
if (bb.liveOut != null) sb.append(" #LIVEOUT = ").append(bb.liveOut.toString()).append("\n");
}
for (BasicBlock succ: bb.successors) {
toStr(sb, succ, visited, dumpLiveness);
}
return sb;
}
private String escapeHtmlChars(String s) {
if (s.contains(">"))
s = s.replaceAll(">", " > ");
if (s.contains(">="))
s = s.replaceAll(">=", " ≥ ");
if (s.contains("<"))
s = s.replaceAll("<", " < ");
if (s.contains("<="))
s = s.replaceAll("<=", " ≤ ");
return s;
}
public StringBuilder toDot(StringBuilder sb, boolean verbose) {
sb.append("<TABLE BORDER=\"1\" CELLBORDER=\"0\">\n");
sb.append("<TR><TD><B>L").append(bid).append("</B></TD></TR>\n");
for (Instruction i: instructions) {
sb.append("<TR><TD>");
sb.append(escapeHtmlChars(i.toStr(new StringBuilder()).toString()));
sb.append("</TD></TR>\n");
}
sb.append("</TABLE>");
return sb;
}
public StringBuilder listDomFrontiers(StringBuilder sb) {
sb.append("L").append(this.bid).append(":");
for (BasicBlock bb: dominationFrontier) {
sb.append(" L").append(bb.bid);
}
sb.append("\n");
return sb;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BasicBlock that = (BasicBlock) o;
return bid == that.bid;
}
@Override
public int hashCode() {
return bid;
}
public String label() {
return "BB(" + bid + ")";
}
public String uniqueName() {
return "BB_" + bid;
}
//////////////// dominator calculations /////////////////////
public void resetDomInfo() {
domDepth = 0;
idom = null;
dominatedChildren.clear();
dominationFrontier.clear();
}
public void resetRPO() {
pre = 0;
rpo = 0;
}
public boolean dominates(BasicBlock other) {
if (this == other) return true;
while (other.domDepth > domDepth) other = other.idom;
return this == other;
}
/////////////////// End of dominator calculations //////////////////////////////////
}