@@ -4313,12 +4313,31 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
4313
4313
// mark the location undef: we know it was supposed to receive a new location
4314
4314
// here, but that computation has been sunk.
4315
4315
SmallVector<DbgVariableIntrinsic *, 2 > DbgUsers;
4316
- findDbgUsers (DbgUsers, I);
4316
+ SmallVector<DPValue *, 2 > DPValues;
4317
+ findDbgUsers (DbgUsers, I, &DPValues);
4318
+ if (!DbgUsers.empty ())
4319
+ tryToSinkInstructionDbgValues (I, InsertPos, SrcBlock, DestBlock, DbgUsers);
4320
+ if (!DPValues.empty ())
4321
+ tryToSinkInstructionDPValues (I, InsertPos, SrcBlock, DestBlock, DPValues);
4322
+
4323
+ // PS: there are numerous flaws with this behaviour, not least that right now
4324
+ // assignments can be re-ordered past other assignments to the same variable
4325
+ // if they use different Values. Creating more undef assignements can never be
4326
+ // undone. And salvaging all users outside of this block can un-necessarily
4327
+ // alter the lifetime of the live-value that the variable refers to.
4328
+ // Some of these things can be resolved by tolerating debug use-before-defs in
4329
+ // LLVM-IR, however it depends on the instruction-referencing CodeGen backend
4330
+ // being used for more architectures.
4317
4331
4332
+ return true ;
4333
+ }
4334
+
4335
+ void InstCombinerImpl::tryToSinkInstructionDbgValues (
4336
+ Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
4337
+ BasicBlock *DestBlock, SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers) {
4318
4338
// For all debug values in the destination block, the sunk instruction
4319
4339
// will still be available, so they do not need to be dropped.
4320
4340
SmallVector<DbgVariableIntrinsic *, 2 > DbgUsersToSalvage;
4321
- SmallVector<DPValue *, 2 > DPValuesToSalvage;
4322
4341
for (auto &DbgUser : DbgUsers)
4323
4342
if (DbgUser->getParent () != DestBlock)
4324
4343
DbgUsersToSalvage.push_back (DbgUser);
@@ -4362,19 +4381,140 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I,
4362
4381
4363
4382
// Perform salvaging without the clones, then sink the clones.
4364
4383
if (!DIIClones.empty ()) {
4365
- // RemoveDIs: pass in empty vector of DPValues until we get to instrumenting
4366
- // this pass.
4367
- SmallVector<DPValue *, 1 > DummyDPValues;
4368
- salvageDebugInfoForDbgValues (*I, DbgUsersToSalvage, DummyDPValues);
4384
+ salvageDebugInfoForDbgValues (*I, DbgUsersToSalvage, {});
4369
4385
// The clones are in reverse order of original appearance, reverse again to
4370
4386
// maintain the original order.
4371
4387
for (auto &DIIClone : llvm::reverse (DIIClones)) {
4372
4388
DIIClone->insertBefore (&*InsertPos);
4373
4389
LLVM_DEBUG (dbgs () << " SINK: " << *DIIClone << ' \n ' );
4374
4390
}
4375
4391
}
4392
+ }
4376
4393
4377
- return true ;
4394
+ void InstCombinerImpl::tryToSinkInstructionDPValues (
4395
+ Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
4396
+ BasicBlock *DestBlock, SmallVectorImpl<DPValue *> &DPValues) {
4397
+ // Implementation of tryToSinkInstructionDbgValues, but for the DPValue of
4398
+ // variable assignments rather than dbg.values.
4399
+
4400
+ // Fetch all DPValues not already in the destination.
4401
+ SmallVector<DPValue *, 2 > DPValuesToSalvage;
4402
+ for (auto &DPV : DPValues)
4403
+ if (DPV->getParent () != DestBlock)
4404
+ DPValuesToSalvage.push_back (DPV);
4405
+
4406
+ // Fetch a second collection, of DPValues in the source block that we're going
4407
+ // to sink.
4408
+ SmallVector<DPValue *> DPValuesToSink;
4409
+ for (DPValue *DPV : DPValuesToSalvage)
4410
+ if (DPV->getParent () == SrcBlock)
4411
+ DPValuesToSink.push_back (DPV);
4412
+
4413
+ // Sort DPValues according to their position in the block. This is a partial
4414
+ // order: DPValues attached to different instructions will be ordered by the
4415
+ // instruction order, but DPValues attached to the same instruction won't
4416
+ // have an order.
4417
+ auto Order = [](DPValue *A, DPValue *B) -> bool {
4418
+ return B->getInstruction ()->comesBefore (A->getInstruction ());
4419
+ };
4420
+ llvm::stable_sort (DPValuesToSink, Order);
4421
+
4422
+ // If there are two assignments to the same variable attached to the same
4423
+ // instruction, the ordering between the two assignments is important. Scan
4424
+ // for this (rare) case and establish which is the last assignment.
4425
+ using InstVarPair = std::pair<const Instruction *, DebugVariable>;
4426
+ SmallDenseMap<InstVarPair, DPValue *> FilterOutMap;
4427
+ if (DPValuesToSink.size () > 1 ) {
4428
+ SmallDenseMap<InstVarPair, unsigned > CountMap;
4429
+ // Count how many assignments to each variable there is per instruction.
4430
+ for (DPValue *DPV : DPValuesToSink) {
4431
+ DebugVariable DbgUserVariable =
4432
+ DebugVariable (DPV->getVariable (), DPV->getExpression (),
4433
+ DPV->getDebugLoc ()->getInlinedAt ());
4434
+ CountMap[std::make_pair (DPV->getInstruction (), DbgUserVariable)] += 1 ;
4435
+ }
4436
+
4437
+ // If there are any instructions with two assignments, add them to the
4438
+ // FilterOutMap to record that they need extra filtering.
4439
+ SmallPtrSet<const Instruction *, 4 > DupSet;
4440
+ for (auto It : CountMap) {
4441
+ if (It.second > 1 ) {
4442
+ FilterOutMap[It.first ] = nullptr ;
4443
+ DupSet.insert (It.first .first );
4444
+ }
4445
+ }
4446
+
4447
+ // For all instruction/variable pairs needing extra filtering, find the
4448
+ // latest assignment.
4449
+ for (const Instruction *Inst : DupSet) {
4450
+ for (DPValue &DPV : llvm::reverse (Inst->getDbgValueRange ())) {
4451
+ DebugVariable DbgUserVariable =
4452
+ DebugVariable (DPV.getVariable (), DPV.getExpression (),
4453
+ DPV.getDebugLoc ()->getInlinedAt ());
4454
+ auto FilterIt =
4455
+ FilterOutMap.find (std::make_pair (Inst, DbgUserVariable));
4456
+ if (FilterIt == FilterOutMap.end ())
4457
+ continue ;
4458
+ if (FilterIt->second != nullptr )
4459
+ continue ;
4460
+ FilterIt->second = &DPV;
4461
+ }
4462
+ }
4463
+ }
4464
+
4465
+ // Perform cloning of the DPValues that we plan on sinking, filter out any
4466
+ // duplicate assignments identified above.
4467
+ SmallVector<DPValue *, 2 > DPVClones;
4468
+ SmallSet<DebugVariable, 4 > SunkVariables;
4469
+ for (DPValue *DPV : DPValuesToSink) {
4470
+ if (DPV->Type == DPValue::LocationType::Declare)
4471
+ continue ;
4472
+
4473
+ DebugVariable DbgUserVariable =
4474
+ DebugVariable (DPV->getVariable (), DPV->getExpression (),
4475
+ DPV->getDebugLoc ()->getInlinedAt ());
4476
+
4477
+ // For any variable where there were multiple assignments in the same place,
4478
+ // ignore all but the last assignment.
4479
+ if (!FilterOutMap.empty ()) {
4480
+ InstVarPair IVP = std::make_pair (DPV->getInstruction (), DbgUserVariable);
4481
+ auto It = FilterOutMap.find (IVP);
4482
+
4483
+ // Filter out.
4484
+ if (It != FilterOutMap.end () && It->second != DPV)
4485
+ continue ;
4486
+ }
4487
+
4488
+ if (!SunkVariables.insert (DbgUserVariable).second )
4489
+ continue ;
4490
+
4491
+ if (DPV->isDbgAssign ())
4492
+ continue ;
4493
+
4494
+ DPVClones.emplace_back (DPV->clone ());
4495
+ LLVM_DEBUG (dbgs () << " CLONE: " << *DPVClones.back () << ' \n ' );
4496
+ }
4497
+
4498
+ // Perform salvaging without the clones, then sink the clones.
4499
+ if (DPVClones.empty ())
4500
+ return ;
4501
+
4502
+ salvageDebugInfoForDbgValues (*I, {}, DPValuesToSalvage);
4503
+
4504
+ // The clones are in reverse order of original appearance. Assert that the
4505
+ // head bit is set on the iterator as we _should_ have received it via
4506
+ // getFirstInsertionPt. Inserting like this will reverse the clone order as
4507
+ // we'll repeatedly insert at the head, such as:
4508
+ // DPV-3 (third insertion goes here)
4509
+ // DPV-2 (second insertion goes here)
4510
+ // DPV-1 (first insertion goes here)
4511
+ // Any-Prior-DPVs
4512
+ // InsertPtInst
4513
+ assert (InsertPos.getHeadBit ());
4514
+ for (DPValue *DPVClone : DPVClones) {
4515
+ InsertPos->getParent ()->insertDPValueBefore (DPVClone, InsertPos);
4516
+ LLVM_DEBUG (dbgs () << " SINK: " << *DPVClone << ' \n ' );
4517
+ }
4378
4518
}
4379
4519
4380
4520
bool InstCombinerImpl::run () {
0 commit comments