Skip to content

Commit bbd2af5

Browse files
committed
Fix multiple locations in stackmaps
When fixing a bug in our control point pass (which split blocks at the wrong instruction) this shook out another bug in stackmaps. So far we were only able to store one additional location per register. However, there can be cases were we need to store 2 additional locations. We get away with this fix for now but may have to revisit this in the future if even more locations are needed and implement a more general approach.
1 parent be26a55 commit bbd2af5

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)