58
58
#include " llvm/IR/Verifier.h"
59
59
#include " llvm/InitializePasses.h"
60
60
#include " llvm/Pass.h"
61
+ #include " llvm/Transforms/Yk/LivenessAnalysis.h"
61
62
#include < map>
62
63
63
64
#define DEBUG_TYPE " yk-control-point"
@@ -83,158 +84,14 @@ CallInst *findControlPointCall(Module &M) {
83
84
return nullptr ;
84
85
85
86
// Find the call site of `yk_mt_control_point()`.
86
- Value::user_iterator U = CtrlPoint->user_begin ();
87
+ const Value::user_iterator U = CtrlPoint->user_begin ();
87
88
if (U == CtrlPoint->user_end ())
88
89
return nullptr ;
89
90
90
91
return cast<CallInst>(*U);
91
92
}
92
93
93
- // / Wrapper to make `std::set_difference` more concise.
94
- // /
95
- // / Store the difference between `S1` and `S2` into `Into`.
96
- void vset_difference (const std::set<Value *> &S1, const std::set<Value *> &S2,
97
- std::set<Value *> &Into) {
98
- std::set_difference (S1.begin (), S1.end (), S2.begin (), S2.end (),
99
- std::inserter (Into, Into.begin ()));
100
- }
101
-
102
- // / Wrapper to make `std::set_union` more concise.
103
- // /
104
- // / Store the union of `S1` and `S2` into `Into`.
105
- void vset_union (const std::set<Value *> &S1, const std::set<Value *> &S2,
106
- std::set<Value *> &Into) {
107
- std::set_union (S1.begin (), S1.end (), S2.begin (), S2.end (),
108
- std::inserter (Into, Into.begin ()));
109
- }
110
-
111
94
namespace llvm {
112
- // A liveness analysis for LLVM IR.
113
- //
114
- // This is based on the algorithm shown in Chapter 10 of the book:
115
- //
116
- // Modern Compiler Implementation in Java (2nd edition)
117
- // by Andrew W. Appel
118
- class LivenessAnalysis {
119
- std::map<Instruction *, std::set<Value *>> In;
120
-
121
- // / Find the successor instructions of the specified instruction.
122
- std::set<Instruction *> getSuccessorInstructions (Instruction *I) {
123
- Instruction *Term = I->getParent ()->getTerminator ();
124
- std::set<Instruction *> SuccInsts;
125
- if (I != Term) {
126
- // Non-terminating instruction: the sole successor instruction is the
127
- // next instruction in the block.
128
- SuccInsts.insert (I->getNextNode ());
129
- } else {
130
- // Terminating instruction: successor instructions are the first
131
- // instructions of all successor blocks.
132
- for (unsigned SuccIdx = 0 ; SuccIdx < Term->getNumSuccessors (); SuccIdx++)
133
- SuccInsts.insert (&*Term->getSuccessor (SuccIdx)->begin ());
134
- }
135
- return SuccInsts;
136
- }
137
-
138
- // / Replaces the value set behind the pointer `S` with the value set `R` and
139
- // / returns whether the set behind `S` changed.
140
- bool updateValueSet (std::set<Value *> *S, const std::set<Value *> R) {
141
- bool Changed = (*S != R);
142
- *S = R;
143
- return Changed;
144
- }
145
-
146
- public:
147
- LivenessAnalysis (Function *Func) {
148
- // Compute defs and uses for each instruction.
149
- std::map<Instruction *, std::set<Value *>> Defs;
150
- std::map<Instruction *, std::set<Value *>> Uses;
151
- for (BasicBlock &BB : *Func) {
152
- for (Instruction &I : BB) {
153
- // Record what this instruction defines.
154
- if (!I.getType ()->isVoidTy ())
155
- Defs[&I].insert (cast<Value>(&I));
156
-
157
- // Record what this instruction uses.
158
- //
159
- // Note that Phi nodes are special and must be skipped. If we consider
160
- // their operands as uses, then Phi nodes in loops may use variables
161
- // before they are defined, and this messes with the algorithm.
162
- //
163
- // The book doesn't cover this quirk, as it explains liveness for
164
- // non-SSA form, and thus doesn't need to worry about Phi nodes.
165
- if (isa<PHINode>(I))
166
- continue ;
167
-
168
- for (auto *U = I.op_begin (); U < I.op_end (); U++) {
169
- if ((!isa<Constant>(U)) && (!isa<BasicBlock>(U)) &&
170
- (!isa<MetadataAsValue>(U)) && (!isa<InlineAsm>(U))) {
171
- Uses[&I].insert (*U);
172
- }
173
- }
174
- }
175
- }
176
-
177
- // A function implicitly defines its arguments.
178
- //
179
- // To propagate the arguments properly we pretend that the first instruction
180
- // in the entry block defines the arguments.
181
- Instruction *FirstInst = &*Func->getEntryBlock ().begin ();
182
- for (auto &Arg : Func->args ())
183
- Defs[FirstInst].insert (&Arg);
184
-
185
- // Compute the live sets for each instruction.
186
- //
187
- // This is the fixed-point of the following data-flow equations (page 206
188
- // in the book referenced above):
189
- //
190
- // in[I] = use[I] ∪ (out[I] - def[I])
191
- //
192
- // out[I] = ∪
193
- // (S in succ[I]) in[S]
194
- //
195
- // Note that only the `In` map is kept after this constructor ends, so
196
- // only `In` is a field.
197
- std::map<Instruction *, std::set<Value *>> Out;
198
- bool Changed;
199
- do {
200
- Changed = false ;
201
- // As the book explains, fixed-points are reached quicker if we process
202
- // control flow in "approximately reverse direction" and if we compute
203
- // `out[I]` before `in[I]`.
204
- //
205
- // Because the alrogithm works by propagating liveness from use sites
206
- // backwards to def sites (where liveness is killed), by working
207
- // backwards we are able to propagate long runs of liveness in one
208
- // iteration of the algorithm.
209
- for (BasicBlock *BB : post_order (&*Func)) {
210
- for (BasicBlock::reverse_iterator II = BB->rbegin (); II != BB->rend ();
211
- II++) {
212
- Instruction *I = &*II;
213
- // Update out[I].
214
- std::set<Instruction *> SuccInsts = getSuccessorInstructions (I);
215
- std::set<Value *> NewOut;
216
- for (Instruction *SI : SuccInsts) {
217
- NewOut.insert (In[SI].begin (), In[SI].end ());
218
- }
219
- Changed |= updateValueSet (&Out[I], std::move (NewOut));
220
-
221
- // Update in[I].
222
- std::set<Value *> OutMinusDef;
223
- vset_difference (Out[I], Defs[I], OutMinusDef);
224
-
225
- std::set<Value *> NewIn;
226
- vset_union (Uses[I], OutMinusDef, NewIn);
227
- Changed |= updateValueSet (&In[I], std::move (NewIn));
228
- }
229
- }
230
- } while (Changed); // Until a fixed-point.
231
- }
232
-
233
- // / Returns the set of live variables immediately before the specified
234
- // / instruction.
235
- std::set<Value *> getLiveVarsBefore (Instruction *I) { return In[I]; }
236
- };
237
-
238
95
void initializeYkControlPointPass (PassRegistry &);
239
96
} // namespace llvm
240
97
@@ -273,7 +130,7 @@ class YkControlPoint : public ModulePass {
273
130
274
131
// Find all live variables just before the call to the control point.
275
132
LivenessAnalysis LA (OldCtrlPointCall->getFunction ());
276
- std::set<Value *> LiveVals = LA.getLiveVarsBefore (OldCtrlPointCall);
133
+ const std::set<Value *> LiveVals = LA.getLiveVarsBefore (OldCtrlPointCall);
277
134
if (LiveVals.size () == 0 ) {
278
135
Context.emitError (
279
136
" The interpreter loop has no live variables!\n "
0 commit comments