@@ -263,37 +263,39 @@ static InstructionCost ComputeSpeculationCost(const Instruction *I,
263
263
bool SpeculativeExecutionPass::considerHoistingFromTo (
264
264
BasicBlock &FromBlock, BasicBlock &ToBlock) {
265
265
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)) {
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))
287
270
if (NotHoisted.contains (I))
288
271
return false ;
289
- }
290
272
}
291
273
return true ;
292
274
};
275
+ auto AllPrecedingUsesFromBlockHoisted =
276
+ [&HasNoUnhoistedInstr](const User *U) {
277
+ // Debug variable has special operand to check it's not hoisted.
278
+ if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U))
279
+ return HasNoUnhoistedInstr (DVI->location_ops ());
280
+
281
+ // Usially debug label intrinsic corresponds to label in LLVM IR. In
282
+ // these cases we should not move it here.
283
+ // TODO: Possible special processing needed to detect it is related to a
284
+ // hoisted instruction.
285
+ if (isa<DbgLabelInst>(U))
286
+ return false ;
287
+
288
+ return HasNoUnhoistedInstr (U->operand_values ());
289
+ };
293
290
294
291
InstructionCost TotalSpeculationCost = 0 ;
295
292
unsigned NotHoistedInstCount = 0 ;
296
293
for (const auto &I : FromBlock) {
294
+ // Make note of any DPValues that need hoisting.
295
+ for (DPValue &DPV : I.getDbgValueRange ())
296
+ if (HasNoUnhoistedInstr (DPV.location_ops ()))
297
+ DPValuesToHoist[DPV.getInstruction ()].push_back (&DPV);
298
+
297
299
const InstructionCost Cost = ComputeSpeculationCost (&I, *TTI);
298
300
if (Cost.isValid () && isSafeToSpeculativelyExecute (&I) &&
299
301
AllPrecedingUsesFromBlockHoisted (&I)) {
@@ -311,12 +313,22 @@ bool SpeculativeExecutionPass::considerHoistingFromTo(
311
313
}
312
314
313
315
for (auto I = FromBlock.begin (); I != FromBlock.end ();) {
316
+ // If any DPValues attached to this instruction should be hoisted, hoist
317
+ // them now - they will end up attached to either the next hoisted
318
+ // instruction or the ToBlock terminator.
319
+ if (DPValuesToHoist.contains (&*I)) {
320
+ for (auto *DPV : DPValuesToHoist[&*I]) {
321
+ DPV->removeFromParent ();
322
+ ToBlock.insertDPValueBefore (DPV,
323
+ ToBlock.getTerminator ()->getIterator ());
324
+ }
325
+ }
314
326
// We have to increment I before moving Current as moving Current
315
327
// changes the list that I is iterating through.
316
328
auto Current = I;
317
329
++I;
318
330
if (!NotHoisted.count (&*Current)) {
319
- Current->moveBeforePreserving (ToBlock.getTerminator ());
331
+ Current->moveBefore (ToBlock.getTerminator ());
320
332
}
321
333
}
322
334
return true ;
0 commit comments