Skip to content

Commit eb33453

Browse files
bors[bot]ptersilie
andauthored
68: Fix multiple locations in stackmaps r=ltratt a=ptersilie Co-authored-by: Lukas Diekmann <[email protected]>
2 parents be26a55 + bbd2af5 commit eb33453

File tree

5 files changed

+482
-28
lines changed

5 files changed

+482
-28
lines changed

llvm/include/llvm/CodeGen/StackMaps.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,11 @@ class StackMaps {
195195
unsigned Size = 0;
196196
unsigned Reg = 0;
197197
int64_t Offset = 0;
198+
unsigned ExtraReg = 0;
198199

199200
Location() = default;
200-
Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset)
201-
: Type(Type), Size(Size), Reg(Reg), Offset(Offset) {}
201+
Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset, unsigned ExtraReg = 0)
202+
: Type(Type), Size(Size), Reg(Reg), Offset(Offset), ExtraReg(ExtraReg) {}
202203
};
203204

204205
struct LiveOutReg {

llvm/lib/CodeGen/StackMaps.cpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -286,21 +286,46 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
286286

287287

288288
signed Offset = 0;
289-
// Check if there are any mappings for this register in the spillmap. If so,
290-
// encode the additional location in the offset field of the stackmap record
291-
// (which is unused for register locations). Note that this assumes that
292-
// there can only be one additional location for each value, which may turn
293-
// out to be false.
289+
int RHS = 0;
290+
// Check for any additional mappings in the spillmap and add them to his
291+
// location to be later encoded into stackmaps. A typical case where we need
292+
// to record multiple sources is the following (annotated with SpillMap
293+
// info):
294+
//
295+
// %rcx = load %rbp, -8 // SpillMap[rcx] = -8
296+
// %rbx = %rcx // SpillMap[rbx] = rcx
297+
// STACKMAP(%rbx) or STACKMAP(%rcx)
298+
//
299+
// First a value is loaded from the stack into %rcx and then immediately
300+
// moved into %rbx. This means there are three sources for the same value,
301+
// and during deoptimisation we need to make sure we write the value back to
302+
// each one of them. Note, that the stackmap may track either of %rbx or
303+
// %rcx, resulting in different ways below to retrieve the mappings.
304+
int ExtraReg = 0;
294305
if (MOI->isReg()) {
295306
Register R = MOI->getReg();
296307
if (SpillOffsets.count(R) > 0) {
297-
Offset = SpillOffsets[R];
308+
RHS = SpillOffsets[R];
298309
assert(SpillOffsets[R] != 0);
299-
if (Offset > 0) {
300-
// If the additional location is another register encode its DWARF id.
301-
// Also temporarily add 1 since 0 is used to mean there is no
302-
// additional location.
303-
Offset = getDwarfRegNum(Offset, TRI) + 1;
310+
if (RHS > 0) {
311+
// The additional location is another register: encode its DWARF id.
312+
// Also temporarily add 1 since 0 means there is no additional
313+
// location.
314+
ExtraReg = getDwarfRegNum(RHS, TRI) + 1;
315+
// Check if the other register also has a mapping and add it.
316+
if (SpillOffsets.count(RHS) > 0) {
317+
Offset = SpillOffsets[RHS];
318+
}
319+
} else {
320+
// The other location is an offset.
321+
Offset = RHS;
322+
// Find any additional mappings where the current register appears on
323+
// the right hand side.
324+
for (auto I = SpillOffsets.begin(); I != SpillOffsets.end(); I++) {
325+
if (I->second == R) {
326+
ExtraReg = getDwarfRegNum(I->first, TRI) + 1;
327+
}
328+
}
304329
}
305330
}
306331
}
@@ -312,7 +337,7 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
312337
Offset = TRI->getSubRegIdxOffset(SubRegIdx);
313338

314339
Locs.emplace_back(Location::Register, TRI->getSpillSize(*RC), DwarfRegNum,
315-
Offset);
340+
Offset, ExtraReg);
316341
return ++MOI;
317342
}
318343

@@ -813,7 +838,7 @@ void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
813838
OS.emitIntValue(0, 1); // Reserved
814839
OS.emitInt16(Loc.Size);
815840
OS.emitInt16(Loc.Reg);
816-
OS.emitInt16(0); // Reserved
841+
OS.emitInt16(Loc.ExtraReg); // Reserved
817842
OS.emitInt32(Loc.Offset);
818843
}
819844
LiveIdx++;

llvm/lib/Target/X86/X86AsmPrinter.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,7 @@ void processInstructions(
9797
const MachineOperand Rhs = Instr.getOperand(1);
9898
assert(Lhs.isReg() && "Is register.");
9999
assert(Rhs.isReg() && "Is register.");
100-
if (SpillMap.count(Rhs.getReg()) > 0) {
101-
// If the RHS has a mapping, apply the same mapping to the new register.
102-
// This means, that stack spills moved into one register and then into
103-
// another will continued to be tracked.
104-
SpillMap[Lhs.getReg()] = SpillMap[Rhs.getReg()];
105-
} else {
106-
SpillMap[Lhs.getReg()] = Rhs.getReg();
107-
}
100+
SpillMap[Lhs.getReg()] = Rhs.getReg();
108101
// YKFIXME: If the `mov` instruction has a killed-flag, remove the
109102
// register from the map.
110103

llvm/lib/Transforms/Yk/ControlPoint.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,13 @@ class YkControlPoint : public ModulePass {
231231
Builder.CreateCall(YKFR, {NewCtrlPointCallInst});
232232
Builder.CreateUnreachable();
233233

234-
// To do so we need to first split up the current block and then
235-
// insert a conditional branch that either continues or returns.
236-
234+
// Split up the current block and then insert a conditional branch that
235+
// either continues after the control point or invokes frame reconstruction.
237236
BasicBlock *BB = NewCtrlPointCallInst->getParent();
238-
BasicBlock *ContBB = BB->splitBasicBlock(New);
239-
237+
BasicBlock *ContBB = BB->splitBasicBlock(New->getNextNonDebugInstruction());
240238
Instruction &OldBr = BB->back();
239+
assert(OldBr.getPrevNonDebugInstruction() == New &&
240+
"Split block at the wrong spot.");
241241
OldBr.eraseFromParent();
242242
Builder.SetInsertPoint(BB);
243243
// The return value of the control point tells us whether a guard has failed

0 commit comments

Comments
 (0)