Skip to content

Commit 1acfb8a

Browse files
bors[bot]ptersilievext01
authored
38: Insertsmcalls r=ltratt a=vext01 Co-authored-by: Lukas Diekmann <[email protected]> Co-authored-by: Edd Barrett <[email protected]>
2 parents acc9ec5 + 1cb7bc1 commit 1acfb8a

File tree

7 files changed

+315
-146
lines changed

7 files changed

+315
-146
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef __YK_LIVENESS_H
2+
#define __YK_LIVENESS_H
3+
4+
#include "llvm/IR/Instructions.h"
5+
6+
#include <map>
7+
#include <set>
8+
9+
using namespace llvm;
10+
11+
namespace llvm {
12+
13+
// A liveness analysis for LLVM IR.
14+
//
15+
// This is based on the algorithm shown in Chapter 10 of the book:
16+
//
17+
// Modern Compiler Implementation in Java (2nd edition)
18+
// by Andrew W. Appel
19+
class LivenessAnalysis {
20+
std::map<Instruction *, std::set<Value *>> In;
21+
22+
/// Find the successor instructions of the specified instruction.
23+
std::set<Instruction *> getSuccessorInstructions(Instruction *I);
24+
25+
/// Replaces the set `S` with the set `R`, returning if the set changed.
26+
bool updateValueSet(std::set<Value *> &S, const std::set<Value *> &R);
27+
28+
public:
29+
LivenessAnalysis(Function *Func);
30+
31+
/// Returns the set of live variables immediately before the specified
32+
/// instruction.
33+
std::set<Value *> getLiveVarsBefore(Instruction *I);
34+
};
35+
36+
} // namespace llvm
37+
38+
#endif
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef LLVM_TRANSFORMS_YK_STACKMAPS_H
2+
#define LLVM_TRANSFORMS_YK_STACKMAPS_H
3+
4+
#include "llvm/Pass.h"
5+
6+
namespace llvm {
7+
ModulePass *createYkStackmapsPass();
8+
} // namespace llvm
9+
10+
#endif

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "llvm/Transforms/Utils.h"
5151
#include "llvm/Transforms/Yk/BlockDisambiguate.h"
5252
#include "llvm/Transforms/Yk/ControlPoint.h"
53+
#include "llvm/Transforms/Yk/Stackmaps.h"
5354
#include <cassert>
5455
#include <string>
5556

@@ -274,6 +275,10 @@ static cl::opt<bool> YkPatchCtrlPoint("yk-patch-control-point", cl::init(false),
274275
cl::NotHidden,
275276
cl::desc("Patch yk_mt_control_point()"));
276277

278+
static cl::opt<bool>
279+
YkInsertStackMaps("yk-insert-stackmaps", cl::init(false), cl::NotHidden,
280+
cl::desc("Insert stackmaps for JIT deoptimisation"));
281+
277282
/// Allow standard passes to be disabled by command line options. This supports
278283
/// simple binary flags that either suppress the pass or do nothing.
279284
/// i.e. -disable-mypass=false has no effect.
@@ -1143,6 +1148,9 @@ bool TargetPassConfig::addISelPasses() {
11431148
if (YkPatchCtrlPoint)
11441149
addPass(createYkControlPointPass());
11451150

1151+
if (YkInsertStackMaps)
1152+
addPass(createYkStackmapsPass());
1153+
11461154
addISelPrepare();
11471155
return addCoreISelPasses();
11481156
}

llvm/lib/Transforms/Yk/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
add_llvm_component_library(LLVMYkPasses
22
BlockDisambiguate.cpp
33
ControlPoint.cpp
4+
LivenessAnalysis.cpp
5+
StackMaps.cpp
46

57
DEPENDS
68
intrinsics_gen

llvm/lib/Transforms/Yk/ControlPoint.cpp

Lines changed: 3 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "llvm/IR/Verifier.h"
5959
#include "llvm/InitializePasses.h"
6060
#include "llvm/Pass.h"
61+
#include "llvm/Transforms/Yk/LivenessAnalysis.h"
6162
#include <map>
6263

6364
#define DEBUG_TYPE "yk-control-point"
@@ -83,158 +84,14 @@ CallInst *findControlPointCall(Module &M) {
8384
return nullptr;
8485

8586
// 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();
8788
if (U == CtrlPoint->user_end())
8889
return nullptr;
8990

9091
return cast<CallInst>(*U);
9192
}
9293

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-
11194
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-
23895
void initializeYkControlPointPass(PassRegistry &);
23996
} // namespace llvm
24097

@@ -273,7 +130,7 @@ class YkControlPoint : public ModulePass {
273130

274131
// Find all live variables just before the call to the control point.
275132
LivenessAnalysis LA(OldCtrlPointCall->getFunction());
276-
std::set<Value *> LiveVals = LA.getLiveVarsBefore(OldCtrlPointCall);
133+
const std::set<Value *> LiveVals = LA.getLiveVarsBefore(OldCtrlPointCall);
277134
if (LiveVals.size() == 0) {
278135
Context.emitError(
279136
"The interpreter loop has no live variables!\n"

0 commit comments

Comments
 (0)