@@ -263,60 +263,73 @@ 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)) {
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 ;
289
272
}
290
273
}
291
- return true ;
274
+ return false ;
292
275
};
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
+ };
293
291
294
292
InstructionCost TotalSpeculationCost = 0 ;
295
293
unsigned NotHoistedInstCount = 0 ;
296
294
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
+ }
310
314
}
311
- }
312
315
313
316
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
+ }
314
327
// We have to increment I before moving Current as moving Current
315
328
// changes the list that I is iterating through.
316
329
auto Current = I;
317
330
++I;
318
331
if (!NotHoisted.count (&*Current)) {
319
- Current->moveBeforePreserving (ToBlock.getTerminator ());
332
+ Current->moveBefore (ToBlock.getTerminator ());
320
333
}
321
334
}
322
335
return true ;
0 commit comments