diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/Local.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 305 |
1 files changed, 19 insertions, 286 deletions
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index ccdaca9..72bc094 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -428,10 +428,6 @@ bool llvm::wouldInstructionBeTriviallyDead(const Instruction *I, if (I->isEHPad()) return false; - // We don't want debug info removed by anything this general. - if (isa<DbgVariableIntrinsic>(I)) - return false; - if (const DbgLabelInst *DLI = dyn_cast<DbgLabelInst>(I)) { if (DLI->getLabel()) return false; @@ -1632,33 +1628,6 @@ static bool PhiHasDebugValue(DILocalVariable *DIVar, /// describes an alloca'd variable, so we need to use the alloc size of the /// value when doing the comparison. E.g. an i1 value will be identified as /// covering an n-bit fragment, if the store size of i1 is at least n bits. -static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) { - const DataLayout &DL = DII->getDataLayout(); - TypeSize ValueSize = DL.getTypeAllocSizeInBits(ValTy); - if (std::optional<uint64_t> FragmentSize = - DII->getExpression()->getActiveBits(DII->getVariable())) - return TypeSize::isKnownGE(ValueSize, TypeSize::getFixed(*FragmentSize)); - - // We can't always calculate the size of the DI variable (e.g. if it is a - // VLA). Try to use the size of the alloca that the dbg intrinsic describes - // instead. - if (DII->isAddressOfVariable()) { - // DII should have exactly 1 location when it is an address. - assert(DII->getNumVariableLocationOps() == 1 && - "address of variable must have exactly 1 location operand."); - if (auto *AI = - dyn_cast_or_null<AllocaInst>(DII->getVariableLocationOp(0))) { - if (std::optional<TypeSize> FragmentSize = - AI->getAllocationSizeInBits(DL)) { - return TypeSize::isKnownGE(ValueSize, *FragmentSize); - } - } - } - // Could not determine size of variable. Conservatively return false. - return false; -} -// RemoveDIs: duplicate implementation of the above, using DbgVariableRecords, -// the replacement for dbg.values. static bool valueCoversEntireFragment(Type *ValTy, DbgVariableRecord *DVR) { const DataLayout &DL = DVR->getModule()->getDataLayout(); TypeSize ValueSize = DL.getTypeAllocSizeInBits(ValTy); @@ -1703,98 +1672,12 @@ static void insertDbgValueOrDbgVariableRecordAfter( insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, NextIt); } -/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value -/// that has an associated llvm.dbg.declare intrinsic. -void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, - StoreInst *SI, DIBuilder &Builder) { - assert(DII->isAddressOfVariable() || isa<DbgAssignIntrinsic>(DII)); - auto *DIVar = DII->getVariable(); - assert(DIVar && "Missing variable"); - auto *DIExpr = DII->getExpression(); - Value *DV = SI->getValueOperand(); - - DebugLoc NewLoc = getDebugValueLoc(DII); - - // If the alloca describes the variable itself, i.e. the expression in the - // dbg.declare doesn't start with a dereference, we can perform the - // conversion if the value covers the entire fragment of DII. - // If the alloca describes the *address* of DIVar, i.e. DIExpr is - // *just* a DW_OP_deref, we use DV as is for the dbg.value. - // We conservatively ignore other dereferences, because the following two are - // not equivalent: - // dbg.declare(alloca, ..., !Expr(deref, plus_uconstant, 2)) - // dbg.value(DV, ..., !Expr(deref, plus_uconstant, 2)) - // The former is adding 2 to the address of the variable, whereas the latter - // is adding 2 to the value of the variable. As such, we insist on just a - // deref expression. - bool CanConvert = - DIExpr->isDeref() || (!DIExpr->startsWithDeref() && - valueCoversEntireFragment(DV->getType(), DII)); - if (CanConvert) { - insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, - SI->getIterator()); - return; - } - - // FIXME: If storing to a part of the variable described by the dbg.declare, - // then we want to insert a dbg.value for the corresponding fragment. - LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to dbg.value: " << *DII - << '\n'); - // For now, when there is a store to parts of the variable (but we do not - // know which part) we insert an dbg.value intrinsic to indicate that we - // know nothing about the variable's content. - DV = PoisonValue::get(DV->getType()); - insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, - SI->getIterator()); -} - static DIExpression *dropInitialDeref(const DIExpression *DIExpr) { int NumEltDropped = DIExpr->getElements()[0] == dwarf::DW_OP_LLVM_arg ? 3 : 1; return DIExpression::get(DIExpr->getContext(), DIExpr->getElements().drop_front(NumEltDropped)); } -void llvm::InsertDebugValueAtStoreLoc(DbgVariableIntrinsic *DII, StoreInst *SI, - DIBuilder &Builder) { - auto *DIVar = DII->getVariable(); - assert(DIVar && "Missing variable"); - auto *DIExpr = DII->getExpression(); - DIExpr = dropInitialDeref(DIExpr); - Value *DV = SI->getValueOperand(); - - DebugLoc NewLoc = getDebugValueLoc(DII); - - insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, - SI->getIterator()); -} - -/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value -/// that has an associated llvm.dbg.declare intrinsic. -void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, - LoadInst *LI, DIBuilder &Builder) { - auto *DIVar = DII->getVariable(); - auto *DIExpr = DII->getExpression(); - assert(DIVar && "Missing variable"); - - if (!valueCoversEntireFragment(LI->getType(), DII)) { - // FIXME: If only referring to a part of the variable described by the - // dbg.declare, then we want to insert a dbg.value for the corresponding - // fragment. - LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to dbg.value: " - << *DII << '\n'); - return; - } - - DebugLoc NewLoc = getDebugValueLoc(DII); - - // We are now tracking the loaded value instead of the address. In the - // future if multi-location support is added to the IR, it might be - // preferable to keep tracking both the loaded value and the original - // address in case the alloca can not be elided. - insertDbgValueOrDbgVariableRecordAfter(Builder, LI, DIVar, DIExpr, NewLoc, - LI); -} - void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, StoreInst *SI, DIBuilder &Builder) { assert(DVR->isAddressOfVariable() || DVR->isDbgAssign()); @@ -1855,40 +1738,6 @@ void llvm::InsertDebugValueAtStoreLoc(DbgVariableRecord *DVR, StoreInst *SI, SI->getIterator()); } -/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated -/// llvm.dbg.declare intrinsic. -void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, - PHINode *APN, DIBuilder &Builder) { - auto *DIVar = DII->getVariable(); - auto *DIExpr = DII->getExpression(); - assert(DIVar && "Missing variable"); - - if (PhiHasDebugValue(DIVar, DIExpr, APN)) - return; - - if (!valueCoversEntireFragment(APN->getType(), DII)) { - // FIXME: If only referring to a part of the variable described by the - // dbg.declare, then we want to insert a dbg.value for the corresponding - // fragment. - LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to dbg.value: " - << *DII << '\n'); - return; - } - - BasicBlock *BB = APN->getParent(); - auto InsertionPt = BB->getFirstInsertionPt(); - - DebugLoc NewLoc = getDebugValueLoc(DII); - - // The block may be a catchswitch block, which does not have a valid - // insertion point. - // FIXME: Insert dbg.value markers in the successors when appropriate. - if (InsertionPt != BB->end()) { - insertDbgValueOrDbgVariableRecord(Builder, APN, DIVar, DIExpr, NewLoc, - InsertionPt); - } -} - void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, LoadInst *LI, DIBuilder &Builder) { auto *DIVar = DVR->getVariable(); @@ -1981,7 +1830,7 @@ bool llvm::LowerDbgDeclare(Function &F) { if (Dbgs.empty() && DVRs.empty()) return Changed; - auto LowerOne = [&](auto *DDI) { + auto LowerOne = [&](DbgVariableRecord *DDI) { AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DDI->getVariableLocationOp(0)); // If this is an alloca for a scalar variable, insert a dbg.value @@ -2036,7 +1885,6 @@ bool llvm::LowerDbgDeclare(Function &F) { Changed = true; }; - for_each(Dbgs, LowerOne); for_each(DVRs, LowerOne); if (Changed) @@ -2046,12 +1894,9 @@ bool llvm::LowerDbgDeclare(Function &F) { return Changed; } -// RemoveDIs: re-implementation of insertDebugValuesForPHIs, but which pulls the -// debug-info out of the block's DbgVariableRecords rather than dbg.value -// intrinsics. -static void -insertDbgVariableRecordsForPHIs(BasicBlock *BB, - SmallVectorImpl<PHINode *> &InsertedPHIs) { +/// Propagate dbg.value records through the newly inserted PHIs. +void llvm::insertDebugValuesForPHIs(BasicBlock *BB, + SmallVectorImpl<PHINode *> &InsertedPHIs) { assert(BB && "No BasicBlock to clone DbgVariableRecord(s) from."); if (InsertedPHIs.size() == 0) return; @@ -2113,76 +1958,12 @@ insertDbgVariableRecordsForPHIs(BasicBlock *BB, } } -/// Propagate dbg.value intrinsics through the newly inserted PHIs. -void llvm::insertDebugValuesForPHIs(BasicBlock *BB, - SmallVectorImpl<PHINode *> &InsertedPHIs) { - assert(BB && "No BasicBlock to clone dbg.value(s) from."); - if (InsertedPHIs.size() == 0) - return; - - insertDbgVariableRecordsForPHIs(BB, InsertedPHIs); - - // Map existing PHI nodes to their dbg.values. - ValueToValueMapTy DbgValueMap; - for (auto &I : *BB) { - if (auto DbgII = dyn_cast<DbgVariableIntrinsic>(&I)) { - for (Value *V : DbgII->location_ops()) - if (auto *Loc = dyn_cast_or_null<PHINode>(V)) - DbgValueMap.insert({Loc, DbgII}); - } - } - if (DbgValueMap.size() == 0) - return; - - // Map a pair of the destination BB and old dbg.value to the new dbg.value, - // so that if a dbg.value is being rewritten to use more than one of the - // inserted PHIs in the same destination BB, we can update the same dbg.value - // with all the new PHIs instead of creating one copy for each. - MapVector<std::pair<BasicBlock *, DbgVariableIntrinsic *>, - DbgVariableIntrinsic *> - NewDbgValueMap; - // Then iterate through the new PHIs and look to see if they use one of the - // previously mapped PHIs. If so, create a new dbg.value intrinsic that will - // propagate the info through the new PHI. If we use more than one new PHI in - // a single destination BB with the same old dbg.value, merge the updates so - // that we get a single new dbg.value with all the new PHIs. - for (auto *PHI : InsertedPHIs) { - BasicBlock *Parent = PHI->getParent(); - // Avoid inserting an intrinsic into an EH block. - if (Parent->getFirstNonPHIIt()->isEHPad()) - continue; - for (auto *VI : PHI->operand_values()) { - auto V = DbgValueMap.find(VI); - if (V != DbgValueMap.end()) { - auto *DbgII = cast<DbgVariableIntrinsic>(V->second); - auto [NewDI, Inserted] = NewDbgValueMap.try_emplace({Parent, DbgII}); - if (Inserted) - NewDI->second = cast<DbgVariableIntrinsic>(DbgII->clone()); - DbgVariableIntrinsic *NewDbgII = NewDI->second; - // If PHI contains VI as an operand more than once, we may - // replaced it in NewDbgII; confirm that it is present. - if (is_contained(NewDbgII->location_ops(), VI)) - NewDbgII->replaceVariableLocationOp(VI, PHI); - } - } - } - // Insert thew new dbg.values into their destination blocks. - for (auto DI : NewDbgValueMap) { - BasicBlock *Parent = DI.first.first; - auto *NewDbgII = DI.second; - auto InsertionPt = Parent->getFirstInsertionPt(); - assert(InsertionPt != Parent->end() && "Ill-formed basic block"); - NewDbgII->insertBefore(InsertionPt); - } -} - bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress, DIBuilder &Builder, uint8_t DIExprFlags, int Offset) { - TinyPtrVector<DbgDeclareInst *> DbgDeclares = findDbgDeclares(Address); TinyPtrVector<DbgVariableRecord *> DVRDeclares = findDVRDeclares(Address); - auto ReplaceOne = [&](auto *DII) { + auto ReplaceOne = [&](DbgVariableRecord *DII) { assert(DII->getVariable() && "Missing variable"); auto *DIExpr = DII->getExpression(); DIExpr = DIExpression::prepend(DIExpr, DIExprFlags, Offset); @@ -2190,10 +1971,9 @@ bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress, DII->replaceVariableLocationOp(Address, NewAddress); }; - for_each(DbgDeclares, ReplaceOne); for_each(DVRDeclares, ReplaceOne); - return !DbgDeclares.empty() || !DVRDeclares.empty(); + return !DVRDeclares.empty(); } static void updateOneDbgValueForAlloca(const DebugLoc &Loc, @@ -2645,7 +2425,6 @@ using DbgValReplacement = std::optional<DIExpression *>; /// changes are made. static bool rewriteDebugUsers( Instruction &From, Value &To, Instruction &DomPoint, DominatorTree &DT, - function_ref<DbgValReplacement(DbgVariableIntrinsic &DII)> RewriteExpr, function_ref<DbgValReplacement(DbgVariableRecord &DVR)> RewriteDVRExpr) { // Find debug users of From. SmallVector<DbgVariableIntrinsic *, 1> Users; @@ -2654,43 +2433,32 @@ static bool rewriteDebugUsers( if (Users.empty() && DPUsers.empty()) return false; + // Ignore intrinsic-users: they are no longer supported and should never + // appear. + assert(Users.empty()); + // Prevent use-before-def of To. bool Changed = false; - SmallPtrSet<DbgVariableIntrinsic *, 1> UndefOrSalvage; SmallPtrSet<DbgVariableRecord *, 1> UndefOrSalvageDVR; if (isa<Instruction>(&To)) { bool DomPointAfterFrom = From.getNextNode() == &DomPoint; - for (auto *DII : Users) { - // It's common to see a debug user between From and DomPoint. Move it - // after DomPoint to preserve the variable update without any reordering. - if (DomPointAfterFrom && DII->getNextNode() == &DomPoint) { - LLVM_DEBUG(dbgs() << "MOVE: " << *DII << '\n'); - DII->moveAfter(&DomPoint); - Changed = true; - - // Users which otherwise aren't dominated by the replacement value must - // be salvaged or deleted. - } else if (!DT.dominates(&DomPoint, DII)) { - UndefOrSalvage.insert(DII); - } - } - // DbgVariableRecord implementation of the above. for (auto *DVR : DPUsers) { Instruction *MarkedInstr = DVR->getMarker()->MarkedInstr; Instruction *NextNonDebug = MarkedInstr; - // The next instruction might still be a dbg.declare, skip over it. - if (isa<DbgVariableIntrinsic>(NextNonDebug)) - NextNonDebug = NextNonDebug->getNextNode(); + // It's common to see a debug user between From and DomPoint. Move it + // after DomPoint to preserve the variable update without any reordering. if (DomPointAfterFrom && NextNonDebug == &DomPoint) { LLVM_DEBUG(dbgs() << "MOVE: " << *DVR << '\n'); DVR->removeFromParent(); - // Ensure there's a marker. DomPoint.getParent()->insertDbgRecordAfter(DVR, &DomPoint); Changed = true; + + // Users which otherwise aren't dominated by the replacement value must + // be salvaged or deleted. } else if (!DT.dominates(&DomPoint, MarkedInstr)) { UndefOrSalvageDVR.insert(DVR); } @@ -2698,19 +2466,6 @@ static bool rewriteDebugUsers( } // Update debug users without use-before-def risk. - for (auto *DII : Users) { - if (UndefOrSalvage.count(DII)) - continue; - - DbgValReplacement DVRepl = RewriteExpr(*DII); - if (!DVRepl) - continue; - - DII->replaceVariableLocationOp(&From, &To); - DII->setExpression(*DVRepl); - LLVM_DEBUG(dbgs() << "REWRITE: " << *DII << '\n'); - Changed = true; - } for (auto *DVR : DPUsers) { if (UndefOrSalvageDVR.count(DVR)) continue; @@ -2725,7 +2480,7 @@ static bool rewriteDebugUsers( Changed = true; } - if (!UndefOrSalvage.empty() || !UndefOrSalvageDVR.empty()) { + if (!UndefOrSalvageDVR.empty()) { // Try to salvage the remaining debug users. salvageDebugInfo(From); Changed = true; @@ -2770,9 +2525,6 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, Type *FromTy = From.getType(); Type *ToTy = To.getType(); - auto Identity = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { - return DII.getExpression(); - }; auto IdentityDVR = [&](DbgVariableRecord &DVR) -> DbgValReplacement { return DVR.getExpression(); }; @@ -2781,7 +2533,7 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, Module &M = *From.getModule(); const DataLayout &DL = M.getDataLayout(); if (isBitCastSemanticsPreserving(DL, FromTy, ToTy)) - return rewriteDebugUsers(From, To, DomPoint, DT, Identity, IdentityDVR); + return rewriteDebugUsers(From, To, DomPoint, DT, IdentityDVR); // Handle integer-to-integer widening and narrowing. // FIXME: Use DW_OP_convert when it's available everywhere. @@ -2793,24 +2545,10 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, // When the width of the result grows, assume that a debugger will only // access the low `FromBits` bits when inspecting the source variable. if (FromBits < ToBits) - return rewriteDebugUsers(From, To, DomPoint, DT, Identity, IdentityDVR); + return rewriteDebugUsers(From, To, DomPoint, DT, IdentityDVR); // The width of the result has shrunk. Use sign/zero extension to describe // the source variable's high bits. - auto SignOrZeroExt = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { - DILocalVariable *Var = DII.getVariable(); - - // Without knowing signedness, sign/zero extension isn't possible. - auto Signedness = Var->getSignedness(); - if (!Signedness) - return std::nullopt; - - bool Signed = *Signedness == DIBasicType::Signedness::Signed; - return DIExpression::appendExt(DII.getExpression(), ToBits, FromBits, - Signed); - }; - // RemoveDIs: duplicate implementation working on DbgVariableRecords rather - // than on dbg.value intrinsics. auto SignOrZeroExtDVR = [&](DbgVariableRecord &DVR) -> DbgValReplacement { DILocalVariable *Var = DVR.getVariable(); @@ -2823,8 +2561,7 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, return DIExpression::appendExt(DVR.getExpression(), ToBits, FromBits, Signed); }; - return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExt, - SignOrZeroExtDVR); + return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExtDVR); } // TODO: Floating-point conversions, vectors. @@ -3800,10 +3537,6 @@ void llvm::remapDebugVariable(ValueToValueMapTy &Mapping, Instruction *Inst) { if (I != Mapping.end()) DA->setAddress(I->second); }; - if (auto DVI = dyn_cast<DbgVariableIntrinsic>(Inst)) - RemapDebugOperands(DVI, DVI->location_ops()); - if (auto DAI = dyn_cast<DbgAssignIntrinsic>(Inst)) - RemapAssignAddress(DAI); for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange())) { RemapDebugOperands(&DVR, DVR.location_ops()); if (DVR.isDbgAssign()) |