From 72ce759928e6dfee6a9efa310b966c19722352ba Mon Sep 17 00:00:00 2001 From: stozer Date: Wed, 4 Dec 2019 09:44:02 +0000 Subject: [DebugInfo] Recover debug intrinsics when killing duplicated/empty basic blocks When basic blocks are killed, either due to being empty or to being an if.then or if.else block whose complement contains identical instructions, some of the debug intrinsics in that block are lost. This patch sinks those intrinsics into the single successor block, setting them Undef if necessary to prevent debug info from falling out-of-date. Differential Revision: https://reviews.llvm.org/D70318 --- llvm/lib/Transforms/Utils/Local.cpp | 27 +++++++++++--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 59 ++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 22 deletions(-) (limited to 'llvm/lib/Transforms') diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index eaccaa1c4ac..94edf8ccab8 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -485,15 +485,19 @@ void llvm::RecursivelyDeleteTriviallyDeadInstructions( I.eraseFromParent(); } } +void llvm::setDbgVariableUndef(DbgVariableIntrinsic *DVI) { + Value *DbgValue = DVI->getVariableLocation(false); + Value *Undef = UndefValue::get(DbgValue ? DbgValue->getType() + : Type::getInt1Ty(DVI->getContext())); + DVI->setOperand( + 0, MetadataAsValue::get(DVI->getContext(), ValueAsMetadata::get(Undef))); +} bool llvm::replaceDbgUsesWithUndef(Instruction *I) { SmallVector DbgUsers; findDbgUsers(DbgUsers, I); - for (auto *DII : DbgUsers) { - Value *Undef = UndefValue::get(I->getType()); - DII->setOperand(0, MetadataAsValue::get(DII->getContext(), - ValueAsMetadata::get(Undef))); - } + for (auto *DII : DbgUsers) + setDbgVariableUndef(DII); return !DbgUsers.empty(); } @@ -1040,6 +1044,19 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB, assert(PN->use_empty() && "There shouldn't be any uses here!"); PN->eraseFromParent(); } + // If Succ has multiple predecessors, each debug intrinsic in BB may or may + // not be valid when we reach Succ, so the debug variable should be set + // undef since its value is unknown. + Instruction *DbgInsertPoint = Succ->getFirstNonPHI(); + while (DbgInfoIntrinsic *DI = dyn_cast(&BB->front())) { + if (auto DVI = cast(DI)) { + if (!isa(DVI)) + setDbgVariableUndef(DVI); + DVI->moveBefore(DbgInsertPoint); + } else { + break; + } + } } // If the unconditional branch we replaced contains llvm.loop metadata, we diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 79d4857c2c8..0e74a26987c 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetOperations.h" @@ -38,6 +39,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" @@ -1250,14 +1252,38 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, Instruction *I1 = &*BB1_Itr++, *I2 = &*BB2_Itr++; // Skip debug info if it is not identical. - DbgInfoIntrinsic *DBI1 = dyn_cast(I1); - DbgInfoIntrinsic *DBI2 = dyn_cast(I2); - if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { - while (isa(I1)) - I1 = &*BB1_Itr++; - while (isa(I2)) - I2 = &*BB2_Itr++; - } + + // If the terminator instruction is hoisted, and any variable locations have + // non-identical debug intrinsics, then those variable locations must be set + // as undef. + // FIXME: If each block contains identical debug variable intrinsics in a + // different order, they will be considered non-identical and be dropped. + MapVector UndefDVIs; + + auto SkipDbgInfo = [&UndefDVIs](Instruction *&I, + BasicBlock::iterator &BB_Itr) { + while (isa(I)) { + if (DbgVariableIntrinsic *DVI = dyn_cast(I)) + UndefDVIs.insert( + {DebugVariable(DVI->getVariable(), DVI->getExpression(), + DVI->getDebugLoc()->getInlinedAt()), + DVI}); + I = &*BB_Itr++; + } + }; + + auto SkipNonIdenticalDbgInfo = + [&BB1_Itr, &BB2_Itr, &SkipDbgInfo](Instruction *&I1, Instruction *&I2) { + DbgInfoIntrinsic *DBI1 = dyn_cast(I1); + DbgInfoIntrinsic *DBI2 = dyn_cast(I2); + if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { + SkipDbgInfo(I1, BB1_Itr); + SkipDbgInfo(I2, BB2_Itr); + } + }; + + SkipNonIdenticalDbgInfo(I1, I2); + // FIXME: Can we define a safety predicate for CallBr? if (isa(I1) || !I1->isIdenticalToWhenDefined(I2) || (isa(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2)) || @@ -1330,15 +1356,7 @@ static bool HoistThenElseCodeToIf(BranchInst *BI, I1 = &*BB1_Itr++; I2 = &*BB2_Itr++; - // Skip debug info if it is not identical. - DbgInfoIntrinsic *DBI1 = dyn_cast(I1); - DbgInfoIntrinsic *DBI2 = dyn_cast(I2); - if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { - while (isa(I1)) - I1 = &*BB1_Itr++; - while (isa(I2)) - I2 = &*BB2_Itr++; - } + SkipNonIdenticalDbgInfo(I1, I2); } while (I1->isIdenticalToWhenDefined(I2)); return true; @@ -1374,6 +1392,13 @@ HoistTerminator: } // Okay, it is safe to hoist the terminator. + for (auto DIVariableInst : UndefDVIs) { + DbgVariableIntrinsic *DVI = DIVariableInst.second; + DVI->moveBefore(BI); + if (Value *V = DVI->getVariableLocation()) + setDbgVariableUndef(DVI); + } + Instruction *NT = I1->clone(); BIParent->getInstList().insert(BI->getIterator(), NT); if (!NT->getType()->isVoidTy()) { -- cgit v1.2.3