Skip to content

Commit 0aacd44

Browse files
authored
[RemoveDIs][DebugInfo] Hoist DPValues in SpeculativeExecution (#80886)
This patch modifies `SpeculativeExecutionPass::considerHoistingFromTo` to treat DPValues the same way that it treats debug intrinsics, which is to hoist them iff all of their instruction operands within the FromBlock are also being hoisted. This is probably not the ideal behaviour, which would be to not hoist debug info at all in this case, but this patch simply ensures that DPValue behaviour is consistent with debug intrinsic behaviour rather than trying to create new functional changes.
1 parent 7ab0a87 commit 0aacd44

File tree

2 files changed

+53
-39
lines changed

2 files changed

+53
-39
lines changed

llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp

+52-39
Original file line numberDiff line numberDiff line change
@@ -263,60 +263,73 @@ static InstructionCost ComputeSpeculationCost(const Instruction *I,
263263
bool SpeculativeExecutionPass::considerHoistingFromTo(
264264
BasicBlock &FromBlock, BasicBlock &ToBlock) {
265265
SmallPtrSet<const Instruction *, 8> NotHoisted;
266-
const auto AllPrecedingUsesFromBlockHoisted = [&NotHoisted](const User *U) {
267-
// Debug variable has special operand to check it's not hoisted.
268-
if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U)) {
269-
return all_of(DVI->location_ops(), [&NotHoisted](Value *V) {
270-
if (const auto *I = dyn_cast_or_null<Instruction>(V)) {
271-
if (!NotHoisted.contains(I))
272-
return true;
273-
}
274-
return false;
275-
});
276-
}
277-
278-
// Usially debug label intrinsic corresponds to label in LLVM IR. In these
279-
// cases we should not move it here.
280-
// TODO: Possible special processing needed to detect it is related to a
281-
// hoisted instruction.
282-
if (isa<DbgLabelInst>(U))
283-
return false;
284-
285-
for (const Value *V : U->operand_values()) {
286-
if (const Instruction *I = dyn_cast<Instruction>(V)) {
287-
if (NotHoisted.contains(I))
288-
return false;
266+
SmallDenseMap<const Instruction *, SmallVector<DPValue *>> DPValuesToHoist;
267+
auto HasNoUnhoistedInstr = [&NotHoisted](auto Values) {
268+
for (const Value *V : Values) {
269+
if (const auto *I = dyn_cast_or_null<Instruction>(V)) {
270+
if (!NotHoisted.contains(I))
271+
return true;
289272
}
290273
}
291-
return true;
274+
return false;
292275
};
276+
auto AllPrecedingUsesFromBlockHoisted =
277+
[&HasNoUnhoistedInstr](const User *U) {
278+
// Debug variable has special operand to check it's not hoisted.
279+
if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U))
280+
return HasNoUnhoistedInstr(DVI->location_ops());
281+
282+
// Usially debug label intrinsic corresponds to label in LLVM IR. In
283+
// these cases we should not move it here.
284+
// TODO: Possible special processing needed to detect it is related to a
285+
// hoisted instruction.
286+
if (isa<DbgLabelInst>(U))
287+
return false;
288+
289+
return HasNoUnhoistedInstr(U->operand_values());
290+
};
293291

294292
InstructionCost TotalSpeculationCost = 0;
295293
unsigned NotHoistedInstCount = 0;
296294
for (const auto &I : FromBlock) {
297-
const InstructionCost Cost = ComputeSpeculationCost(&I, *TTI);
298-
if (Cost.isValid() && isSafeToSpeculativelyExecute(&I) &&
299-
AllPrecedingUsesFromBlockHoisted(&I)) {
300-
TotalSpeculationCost += Cost;
301-
if (TotalSpeculationCost > SpecExecMaxSpeculationCost)
302-
return false; // too much to hoist
303-
} else {
304-
// Debug info intrinsics should not be counted for threshold.
305-
if (!isa<DbgInfoIntrinsic>(I))
306-
NotHoistedInstCount++;
307-
if (NotHoistedInstCount > SpecExecMaxNotHoisted)
308-
return false; // too much left behind
309-
NotHoisted.insert(&I);
295+
// Make note of any DPValues that need hoisting.
296+
for (DPValue &DPV : I.getDbgValueRange()) {
297+
if (HasNoUnhoistedInstr(DPV.location_ops()))
298+
DPValuesToHoist[DPV.getInstruction()].push_back(&DPV);
299+
300+
const InstructionCost Cost = ComputeSpeculationCost(&I, *TTI);
301+
if (Cost.isValid() && isSafeToSpeculativelyExecute(&I) &&
302+
AllPrecedingUsesFromBlockHoisted(&I)) {
303+
TotalSpeculationCost += Cost;
304+
if (TotalSpeculationCost > SpecExecMaxSpeculationCost)
305+
return false; // too much to hoist
306+
} else {
307+
// Debug info intrinsics should not be counted for threshold.
308+
if (!isa<DbgInfoIntrinsic>(I))
309+
NotHoistedInstCount++;
310+
if (NotHoistedInstCount > SpecExecMaxNotHoisted)
311+
return false; // too much left behind
312+
NotHoisted.insert(&I);
313+
}
310314
}
311-
}
312315

313316
for (auto I = FromBlock.begin(); I != FromBlock.end();) {
317+
// If any DPValues attached to this instruction should be hoisted, hoist
318+
// them now - they will end up attached to either the next hoisted
319+
// instruction or the ToBlock terminator.
320+
if (DPValuesToHoist.contains(&*I)) {
321+
for (auto *DPV : DPValuesToHoist[&*I]) {
322+
DPV->removeFromParent();
323+
ToBlock.insertDPValueBefore(DPV,
324+
ToBlock.getTerminator()->getIterator());
325+
}
326+
}
314327
// We have to increment I before moving Current as moving Current
315328
// changes the list that I is iterating through.
316329
auto Current = I;
317330
++I;
318331
if (!NotHoisted.count(&*Current)) {
319-
Current->moveBeforePreserving(ToBlock.getTerminator());
332+
Current->moveBefore(ToBlock.getTerminator());
320333
}
321334
}
322335
return true;

llvm/test/Transforms/SpeculativeExecution/PR46267.ll

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt < %s -S -passes='speculative-execution' | FileCheck %s
2+
; RUN: opt --try-experimental-debuginfo-iterators < %s -S -passes='speculative-execution' | FileCheck %s
23

34
%class.B = type { ptr }
45

0 commit comments

Comments
 (0)