Skip to content

Commit c861e95

Browse files
committed
Sort live operands of stackmap calls.
Sort the live variables by order of appearance using a dominator tree. The order is important for frame construction during deoptimisation: since live variables may reference other live variables they need to be proceesed in the order they appear in the module.
1 parent 8ecca06 commit c861e95

File tree

4 files changed

+28
-8
lines changed

4 files changed

+28
-8
lines changed

llvm/include/llvm/Transforms/Yk/LivenessAnalysis.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef __YK_LIVENESS_H
22
#define __YK_LIVENESS_H
33

4+
#include "llvm/IR/Dominators.h"
45
#include "llvm/IR/Instructions.h"
56

67
#include <map>
@@ -22,15 +23,18 @@ class LivenessAnalysis {
2223
/// Find the successor instructions of the specified instruction.
2324
std::set<Instruction *> getSuccessorInstructions(Instruction *I);
2425

26+
// A domniator tree used to sort the live variables.
27+
DominatorTree DT;
28+
2529
/// Replaces the set `S` with the set `R`, returning if the set changed.
2630
bool updateValueSet(std::set<Value *> &S, const std::set<Value *> &R);
2731

2832
public:
2933
LivenessAnalysis(Function *Func);
3034

31-
/// Returns the set of live variables immediately before the specified
32-
/// instruction.
33-
std::set<Value *> getLiveVarsBefore(Instruction *I);
35+
/// Returns the vector of live variables immediately before the specified
36+
/// instruction (sorted in order of appearance).
37+
std::vector<Value *> getLiveVarsBefore(Instruction *I);
3438
};
3539

3640
} // namespace llvm

llvm/lib/Transforms/Yk/ControlPoint.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ class YkControlPoint : public ModulePass {
130130

131131
// Find all live variables just before the call to the control point.
132132
LivenessAnalysis LA(OldCtrlPointCall->getFunction());
133-
const std::set<Value *> LiveVals = LA.getLiveVarsBefore(OldCtrlPointCall);
133+
const std::vector<Value *> LiveVals =
134+
LA.getLiveVarsBefore(OldCtrlPointCall);
134135
if (LiveVals.size() == 0) {
135136
Context.emitError(
136137
"The interpreter loop has no live variables!\n"

llvm/lib/Transforms/Yk/LivenessAnalysis.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ LivenessAnalysis::LivenessAnalysis(Function *Func) {
6969
// Compute defs and uses for each instruction.
7070
std::map<Instruction *, std::set<Value *>> Defs;
7171
std::map<Instruction *, std::set<Value *>> Uses;
72+
73+
// Create a domniator tree so we can later sort the live variables.
74+
DT = DominatorTree(*Func);
75+
7276
for (BasicBlock &BB : *Func) {
7377
for (Instruction &I : BB) {
7478
// Record what this instruction defines.
@@ -172,8 +176,19 @@ LivenessAnalysis::LivenessAnalysis(Function *Func) {
172176
} while (Changed); // Until a fixed-point.
173177
}
174178

175-
std::set<Value *> LivenessAnalysis::getLiveVarsBefore(Instruction *I) {
176-
return In[I];
179+
std::vector<Value *> LivenessAnalysis::getLiveVarsBefore(Instruction *I) {
180+
std::set<Value *> Res = In[I];
181+
// Sort the live variables by order of appearance using a dominator tree. The
182+
// order is important for frame construction during deoptimisation: since live
183+
// variables may reference other live variables they need to be proceesed in
184+
// the order they appear in the module.
185+
std::vector<Value *> Sorted(Res.begin(), Res.end());
186+
std::sort(Sorted.begin(), Sorted.end(), [this](Value *A, Value *B) {
187+
if (isa<Instruction>(B))
188+
return DT.dominates(A, cast<Instruction>(B));
189+
return false;
190+
});
191+
return Sorted;
177192
}
178193

179194
} // namespace llvm

llvm/lib/Transforms/Yk/StackMaps.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class YkStackmaps : public ModulePass {
4545
return false;
4646
}
4747

48-
std::map<Instruction *, std::set<Value *>> SMCalls;
48+
std::map<Instruction *, std::vector<Value *>> SMCalls;
4949
for (Function &F : M) {
5050
if (F.empty()) // skip declarations.
5151
continue;
@@ -65,7 +65,7 @@ class YkStackmaps : public ModulePass {
6565
Value *Shadow = ConstantInt::get(Type::getInt32Ty(Context), 0);
6666
for (auto It : SMCalls) {
6767
Instruction *I = cast<Instruction>(It.first);
68-
const std::set<Value *> L = It.second;
68+
const std::vector<Value *> L = It.second;
6969

7070
IRBuilder<> Bldr(I);
7171
Value *SMID = ConstantInt::get(Type::getInt64Ty(Context), Count);

0 commit comments

Comments
 (0)