forked from OSchip/llvm-project
Reapply "[DebugInfo] Handle multiple variable location operands in IR"
Fixed section of code that iterated through a SmallDenseMap and added
instructions in each iteration, causing non-deterministic code; replaced
SmallDenseMap with MapVector to prevent non-determinism.
This reverts commit 01ac6d1587
.
This commit is contained in:
parent
410f09af09
commit
3bfddc2593
|
@ -203,6 +203,7 @@ public:
|
|||
Value *getVariableLocationOp(unsigned OpIdx) const;
|
||||
|
||||
void replaceVariableLocationOp(Value *OldValue, Value *NewValue);
|
||||
void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue);
|
||||
|
||||
void setVariable(DILocalVariable *NewVar) {
|
||||
setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar));
|
||||
|
|
|
@ -311,9 +311,10 @@ void salvageDebugInfoForDbgValues(Instruction &I,
|
|||
/// Given an instruction \p I and DIExpression \p DIExpr operating on it, write
|
||||
/// the effects of \p I into the returned DIExpression, or return nullptr if
|
||||
/// it cannot be salvaged. \p StackVal: whether DW_OP_stack_value should be
|
||||
/// appended to the expression.
|
||||
/// appended to the expression. \p LocNo: the index of the location operand to
|
||||
/// which \p I applies, should be 0 for debug info without a DIArgList.
|
||||
DIExpression *salvageDebugInfoImpl(Instruction &I, DIExpression *DIExpr,
|
||||
bool StackVal);
|
||||
bool StackVal, unsigned LocNo);
|
||||
|
||||
/// Point debug users of \p From to \p To or salvage them. Use this function
|
||||
/// only when replacing all uses of \p From with \p To, with a guarantee that
|
||||
|
|
|
@ -2873,11 +2873,16 @@ class TypePromotionTransaction {
|
|||
/// Keep track of the debug users.
|
||||
SmallVector<DbgValueInst *, 1> DbgValues;
|
||||
|
||||
/// Keep track of the new value so that we can undo it by replacing
|
||||
/// instances of the new value with the original value.
|
||||
Value *New;
|
||||
|
||||
using use_iterator = SmallVectorImpl<InstructionAndIdx>::iterator;
|
||||
|
||||
public:
|
||||
/// Replace all the use of \p Inst by \p New.
|
||||
UsesReplacer(Instruction *Inst, Value *New) : TypePromotionAction(Inst) {
|
||||
UsesReplacer(Instruction *Inst, Value *New)
|
||||
: TypePromotionAction(Inst), New(New) {
|
||||
LLVM_DEBUG(dbgs() << "Do: UsersReplacer: " << *Inst << " with " << *New
|
||||
<< "\n");
|
||||
// Record the original uses.
|
||||
|
@ -2903,7 +2908,7 @@ class TypePromotionTransaction {
|
|||
// the original debug uses must also be reinstated to maintain the
|
||||
// correctness and utility of debug value instructions.
|
||||
for (auto *DVI : DbgValues)
|
||||
DVI->replaceVariableLocationOp(DVI->getVariableLocationOp(0), Inst);
|
||||
DVI->replaceVariableLocationOp(New, Inst);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7903,18 +7908,21 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) {
|
|||
DbgValueInst &DVI = *cast<DbgValueInst>(I);
|
||||
|
||||
// Does this dbg.value refer to a sunk address calculation?
|
||||
Value *Location = DVI.getVariableLocationOp(0);
|
||||
WeakTrackingVH SunkAddrVH = SunkAddrs[Location];
|
||||
Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;
|
||||
if (SunkAddr) {
|
||||
// Point dbg.value at locally computed address, which should give the best
|
||||
// opportunity to be accurately lowered. This update may change the type of
|
||||
// pointer being referred to; however this makes no difference to debugging
|
||||
// information, and we can't generate bitcasts that may affect codegen.
|
||||
DVI.replaceVariableLocationOp(Location, SunkAddr);
|
||||
return true;
|
||||
bool AnyChange = false;
|
||||
for (Value *Location : DVI.getValues()) {
|
||||
WeakTrackingVH SunkAddrVH = SunkAddrs[Location];
|
||||
Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr;
|
||||
if (SunkAddr) {
|
||||
// Point dbg.value at locally computed address, which should give the best
|
||||
// opportunity to be accurately lowered. This update may change the type
|
||||
// of pointer being referred to; however this makes no difference to
|
||||
// debugging information, and we can't generate bitcasts that may affect
|
||||
// codegen.
|
||||
DVI.replaceVariableLocationOp(Location, SunkAddr);
|
||||
AnyChange = true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return AnyChange;
|
||||
}
|
||||
|
||||
// A llvm.dbg.value may be using a value before its definition, due to
|
||||
|
@ -7933,30 +7941,51 @@ bool CodeGenPrepare::placeDbgValues(Function &F) {
|
|||
if (!DVI)
|
||||
continue;
|
||||
|
||||
Instruction *VI = dyn_cast_or_null<Instruction>(DVI->getValue());
|
||||
SmallVector<Instruction *, 4> VIs;
|
||||
for (Value *V : DVI->getValues())
|
||||
if (Instruction *VI = dyn_cast_or_null<Instruction>(V))
|
||||
VIs.push_back(VI);
|
||||
|
||||
if (!VI || VI->isTerminator())
|
||||
continue;
|
||||
// This DVI may depend on multiple instructions, complicating any
|
||||
// potential sink. This block takes the defensive approach, opting to
|
||||
// "undef" the DVI if it has more than one instruction and any of them do
|
||||
// not dominate DVI.
|
||||
for (Instruction *VI : VIs) {
|
||||
if (VI->isTerminator())
|
||||
continue;
|
||||
|
||||
// If VI is a phi in a block with an EHPad terminator, we can't insert
|
||||
// after it.
|
||||
if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
|
||||
continue;
|
||||
// If VI is a phi in a block with an EHPad terminator, we can't insert
|
||||
// after it.
|
||||
if (isa<PHINode>(VI) && VI->getParent()->getTerminator()->isEHPad())
|
||||
continue;
|
||||
|
||||
// If the defining instruction dominates the dbg.value, we do not need
|
||||
// to move the dbg.value.
|
||||
if (DT.dominates(VI, DVI))
|
||||
continue;
|
||||
// If the defining instruction dominates the dbg.value, we do not need
|
||||
// to move the dbg.value.
|
||||
if (DT.dominates(VI, DVI))
|
||||
continue;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
|
||||
<< *DVI << ' ' << *VI);
|
||||
DVI->removeFromParent();
|
||||
if (isa<PHINode>(VI))
|
||||
DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
|
||||
else
|
||||
DVI->insertAfter(VI);
|
||||
MadeChange = true;
|
||||
++NumDbgValueMoved;
|
||||
// If we depend on multiple instructions and any of them doesn't
|
||||
// dominate this DVI, we probably can't salvage it: moving it to
|
||||
// after any of the instructions could cause us to lose the others.
|
||||
if (VIs.size() > 1) {
|
||||
LLVM_DEBUG(
|
||||
dbgs()
|
||||
<< "Unable to find valid location for Debug Value, undefing:\n"
|
||||
<< *DVI);
|
||||
DVI->setUndef();
|
||||
break;
|
||||
}
|
||||
|
||||
LLVM_DEBUG(dbgs() << "Moving Debug Value before :\n"
|
||||
<< *DVI << ' ' << *VI);
|
||||
DVI->removeFromParent();
|
||||
if (isa<PHINode>(VI))
|
||||
DVI->insertBefore(&*VI->getParent()->getFirstInsertionPt());
|
||||
else
|
||||
DVI->insertAfter(VI);
|
||||
MadeChange = true;
|
||||
++NumDbgValueMoved;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MadeChange;
|
||||
|
|
|
@ -1260,7 +1260,8 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
|
|||
// variable. FIXME: Further work could recover those too.
|
||||
while (isa<Instruction>(V)) {
|
||||
Instruction &VAsInst = *cast<Instruction>(V);
|
||||
DIExpression *NewExpr = salvageDebugInfoImpl(VAsInst, Expr, StackValue);
|
||||
// Temporary "0", awaiting real implementation.
|
||||
DIExpression *NewExpr = salvageDebugInfoImpl(VAsInst, Expr, StackValue, 0);
|
||||
|
||||
// If we cannot salvage any further, and haven't yet found a suitable debug
|
||||
// expression, bail out.
|
||||
|
@ -6053,7 +6054,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
|
|||
DILocalVariable *Variable = DI.getVariable();
|
||||
DIExpression *Expression = DI.getExpression();
|
||||
dropDanglingDebugInfo(Variable, Expression);
|
||||
SmallVector<Value *> Values(DI.getValues());
|
||||
SmallVector<Value *, 4> Values(DI.getValues());
|
||||
if (Values.empty())
|
||||
return;
|
||||
|
||||
|
|
|
@ -98,6 +98,24 @@ void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
|
|||
setArgOperand(
|
||||
0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
|
||||
}
|
||||
void DbgVariableIntrinsic::replaceVariableLocationOp(unsigned OpIdx,
|
||||
Value *NewValue) {
|
||||
assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index");
|
||||
if (!hasArgList()) {
|
||||
Value *NewOperand = isa<MetadataAsValue>(NewValue)
|
||||
? NewValue
|
||||
: MetadataAsValue::get(
|
||||
getContext(), ValueAsMetadata::get(NewValue));
|
||||
return setArgOperand(0, NewOperand);
|
||||
}
|
||||
SmallVector<ValueAsMetadata *, 4> MDs;
|
||||
ValueAsMetadata *NewOperand = getAsMetadata(NewValue);
|
||||
for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx)
|
||||
MDs.push_back(Idx == OpIdx ? NewOperand
|
||||
: getAsMetadata(getVariableLocationOp(Idx)));
|
||||
setArgOperand(
|
||||
0, MetadataAsValue::get(getContext(), DIArgList::get(getContext(), MDs)));
|
||||
}
|
||||
|
||||
Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
|
||||
if (auto Fragment = getExpression()->getFragmentInfo())
|
||||
|
|
|
@ -31,6 +31,10 @@ void User::replaceUsesOfWith(Value *From, Value *To) {
|
|||
// most importantly, removing "this" from the use list of "From".
|
||||
setOperand(i, To);
|
||||
}
|
||||
if (auto DVI = dyn_cast_or_null<DbgVariableIntrinsic>(this)) {
|
||||
if (is_contained(DVI->location_ops(), From))
|
||||
DVI->replaceVariableLocationOp(From, To);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -563,10 +563,9 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {
|
|||
}
|
||||
|
||||
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(I)) {
|
||||
if (auto *AI =
|
||||
dyn_cast_or_null<AllocaInst>(DVI->getVariableLocationOp(0))) {
|
||||
Allocas[AI].DbgVariableIntrinsics.push_back(DVI);
|
||||
}
|
||||
for (Value *V : DVI->location_ops())
|
||||
if (auto *AI = dyn_cast_or_null<AllocaInst>(V))
|
||||
Allocas[AI].DbgVariableIntrinsics.push_back(DVI);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -2173,7 +2173,7 @@ void coro::salvageDebugInfo(
|
|||
Storage = StInst->getOperand(0);
|
||||
} else if (auto *GEPInst = dyn_cast<GetElementPtrInst>(Storage)) {
|
||||
Expr = llvm::salvageDebugInfoImpl(*GEPInst, Expr,
|
||||
/*WithStackValue=*/false);
|
||||
/*WithStackValue=*/false, 0);
|
||||
if (!Expr)
|
||||
return;
|
||||
Storage = GEPInst->getOperand(0);
|
||||
|
|
|
@ -3586,15 +3586,6 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
|
|||
llvm::sort(DbgUsersToSink,
|
||||
[](auto *A, auto *B) { return B->comesBefore(A); });
|
||||
|
||||
// Update the arguments of a dbg.declare instruction, so that it
|
||||
// does not point into a sunk instruction.
|
||||
auto updateDbgDeclare = [](DbgVariableIntrinsic *DII) {
|
||||
if (!isa<DbgDeclareInst>(DII))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
SmallVector<DbgVariableIntrinsic *, 2> DIIClones;
|
||||
SmallSet<DebugVariable, 4> SunkVariables;
|
||||
for (auto User : DbgUsersToSink) {
|
||||
|
@ -3602,7 +3593,7 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
|
|||
// one per variable fragment. It should be left in the original place
|
||||
// because the sunk instruction is not an alloca (otherwise we could not be
|
||||
// here).
|
||||
if (updateDbgDeclare(User))
|
||||
if (isa<DbgDeclareInst>(User))
|
||||
continue;
|
||||
|
||||
DebugVariable DbgUserVariable =
|
||||
|
@ -3613,6 +3604,8 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) {
|
|||
continue;
|
||||
|
||||
DIIClones.emplace_back(cast<DbgVariableIntrinsic>(User->clone()));
|
||||
if (isa<DbgDeclareInst>(User) && isa<CastInst>(I))
|
||||
DIIClones.back()->replaceVariableLocationOp(I, I->getOperand(0));
|
||||
LLVM_DEBUG(dbgs() << "CLONE: " << *DIIClones.back() << '\n');
|
||||
}
|
||||
|
||||
|
|
|
@ -1218,10 +1218,10 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
|
|||
isa<CleanupReturnInst>(Inst))
|
||||
RetVec.push_back(&Inst);
|
||||
|
||||
if (auto *DDI = dyn_cast<DbgVariableIntrinsic>(&Inst))
|
||||
if (auto *Alloca =
|
||||
dyn_cast_or_null<AllocaInst>(DDI->getVariableLocationOp(0)))
|
||||
AllocaDbgMap[Alloca].push_back(DDI);
|
||||
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst))
|
||||
for (Value *V : DVI->location_ops())
|
||||
if (auto *Alloca = dyn_cast_or_null<AllocaInst>(V))
|
||||
AllocaDbgMap[Alloca].push_back(DVI);
|
||||
|
||||
if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
|
||||
LandingPadVec.push_back(&Inst);
|
||||
|
@ -1297,13 +1297,18 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
|
|||
}
|
||||
|
||||
if (!AllocaToPaddedAllocaMap.empty()) {
|
||||
for (auto &BB : F)
|
||||
for (auto &Inst : BB)
|
||||
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst))
|
||||
if (auto *AI =
|
||||
dyn_cast_or_null<AllocaInst>(DVI->getVariableLocationOp(0)))
|
||||
if (auto *NewAI = AllocaToPaddedAllocaMap.lookup(AI))
|
||||
DVI->replaceVariableLocationOp(AI, NewAI);
|
||||
for (auto &BB : F) {
|
||||
for (auto &Inst : BB) {
|
||||
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst)) {
|
||||
for (Value *V : DVI->location_ops()) {
|
||||
if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
|
||||
if (auto *NewAI = AllocaToPaddedAllocaMap.lookup(AI))
|
||||
DVI->replaceVariableLocationOp(V, NewAI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &P : AllocaToPaddedAllocaMap)
|
||||
P.first->eraseFromParent();
|
||||
}
|
||||
|
|
|
@ -521,10 +521,14 @@ bool AggressiveDeadCodeElimination::removeDeadInstructions() {
|
|||
// If intrinsic is pointing at a live SSA value, there may be an
|
||||
// earlier optimization bug: if we know the location of the variable,
|
||||
// why isn't the scope of the location alive?
|
||||
if (Value *V = DII->getVariableLocationOp(0))
|
||||
if (Instruction *II = dyn_cast<Instruction>(V))
|
||||
if (isLive(II))
|
||||
for (Value *V : DII->location_ops()) {
|
||||
if (Instruction *II = dyn_cast<Instruction>(V)) {
|
||||
if (isLive(II)) {
|
||||
dbgs() << "Dropping debug info for " << *DII << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5829,57 +5829,71 @@ void LoopStrengthReduce::getAnalysisUsage(AnalysisUsage &AU) const {
|
|||
AU.addPreserved<MemorySSAWrapperPass>();
|
||||
}
|
||||
|
||||
using EqualValues = SmallVector<std::tuple<WeakVH, int64_t, DIExpression *>, 4>;
|
||||
using EqualValuesMap = DenseMap<DbgValueInst *, EqualValues>;
|
||||
using EqualValues = SmallVector<std::tuple<WeakVH, int64_t>, 4>;
|
||||
using EqualValuesMap =
|
||||
DenseMap<std::pair<DbgValueInst *, unsigned>, EqualValues>;
|
||||
using ExpressionMap = DenseMap<DbgValueInst *, DIExpression *>;
|
||||
|
||||
static void DbgGatherEqualValues(Loop *L, ScalarEvolution &SE,
|
||||
EqualValuesMap &DbgValueToEqualSet) {
|
||||
EqualValuesMap &DbgValueToEqualSet,
|
||||
ExpressionMap &DbgValueToExpression) {
|
||||
for (auto &B : L->getBlocks()) {
|
||||
for (auto &I : *B) {
|
||||
auto DVI = dyn_cast<DbgValueInst>(&I);
|
||||
if (!DVI)
|
||||
continue;
|
||||
auto V = DVI->getVariableLocationOp(0);
|
||||
if (!V || !SE.isSCEVable(V->getType()))
|
||||
continue;
|
||||
auto DbgValueSCEV = SE.getSCEV(V);
|
||||
EqualValues EqSet;
|
||||
for (PHINode &Phi : L->getHeader()->phis()) {
|
||||
if (V->getType() != Phi.getType())
|
||||
for (unsigned Idx = 0; Idx < DVI->getNumVariableLocationOps(); ++Idx) {
|
||||
// TODO: We can duplicate results if the same arg appears more than
|
||||
// once.
|
||||
Value *V = DVI->getVariableLocationOp(Idx);
|
||||
if (!V || !SE.isSCEVable(V->getType()))
|
||||
continue;
|
||||
if (!SE.isSCEVable(Phi.getType()))
|
||||
continue;
|
||||
auto PhiSCEV = SE.getSCEV(&Phi);
|
||||
Optional<APInt> Offset =
|
||||
SE.computeConstantDifference(DbgValueSCEV, PhiSCEV);
|
||||
if (Offset && Offset->getMinSignedBits() <= 64)
|
||||
EqSet.emplace_back(std::make_tuple(
|
||||
&Phi, Offset.getValue().getSExtValue(), DVI->getExpression()));
|
||||
auto DbgValueSCEV = SE.getSCEV(V);
|
||||
EqualValues EqSet;
|
||||
for (PHINode &Phi : L->getHeader()->phis()) {
|
||||
if (V->getType() != Phi.getType())
|
||||
continue;
|
||||
if (!SE.isSCEVable(Phi.getType()))
|
||||
continue;
|
||||
auto PhiSCEV = SE.getSCEV(&Phi);
|
||||
Optional<APInt> Offset =
|
||||
SE.computeConstantDifference(DbgValueSCEV, PhiSCEV);
|
||||
if (Offset && Offset->getMinSignedBits() <= 64)
|
||||
EqSet.emplace_back(
|
||||
std::make_tuple(&Phi, Offset.getValue().getSExtValue()));
|
||||
}
|
||||
DbgValueToEqualSet[{DVI, Idx}] = std::move(EqSet);
|
||||
DbgValueToExpression[DVI] = DVI->getExpression();
|
||||
}
|
||||
DbgValueToEqualSet[DVI] = std::move(EqSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DbgApplyEqualValues(EqualValuesMap &DbgValueToEqualSet) {
|
||||
static void DbgApplyEqualValues(EqualValuesMap &DbgValueToEqualSet,
|
||||
ExpressionMap &DbgValueToExpression) {
|
||||
for (auto A : DbgValueToEqualSet) {
|
||||
auto DVI = A.first;
|
||||
auto DVI = A.first.first;
|
||||
auto Idx = A.first.second;
|
||||
// Only update those that are now undef.
|
||||
if (!isa_and_nonnull<UndefValue>(DVI->getVariableLocationOp(0)))
|
||||
if (!isa_and_nonnull<UndefValue>(DVI->getVariableLocationOp(Idx)))
|
||||
continue;
|
||||
for (auto EV : A.second) {
|
||||
auto V = std::get<WeakVH>(EV);
|
||||
if (!V)
|
||||
auto EVHandle = std::get<WeakVH>(EV);
|
||||
if (!EVHandle)
|
||||
continue;
|
||||
auto DbgDIExpr = std::get<DIExpression *>(EV);
|
||||
// The dbg.value may have had its value changed by LSR; refresh it from
|
||||
// the map, but continue to update the mapped expression as it may be
|
||||
// updated multiple times in this function.
|
||||
auto DbgDIExpr = DbgValueToExpression[DVI];
|
||||
auto Offset = std::get<int64_t>(EV);
|
||||
DVI->replaceVariableLocationOp(DVI->getVariableLocationOp(0), V);
|
||||
DVI->replaceVariableLocationOp(Idx, EVHandle);
|
||||
if (Offset) {
|
||||
SmallVector<uint64_t, 8> Ops;
|
||||
DIExpression::appendOffset(Ops, Offset);
|
||||
DbgDIExpr = DIExpression::prependOpcodes(DbgDIExpr, Ops, true);
|
||||
DbgDIExpr = DIExpression::appendOpsToArg(DbgDIExpr, Ops, Idx, true);
|
||||
}
|
||||
DVI->setExpression(DbgDIExpr);
|
||||
DbgValueToExpression[DVI] = DbgDIExpr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5903,7 +5917,8 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
|
|||
// Debug preservation - before we start removing anything create equivalence
|
||||
// sets for the llvm.dbg.value intrinsics.
|
||||
EqualValuesMap DbgValueToEqualSet;
|
||||
DbgGatherEqualValues(L, SE, DbgValueToEqualSet);
|
||||
ExpressionMap DbgValueToExpression;
|
||||
DbgGatherEqualValues(L, SE, DbgValueToEqualSet, DbgValueToExpression);
|
||||
|
||||
// Remove any extra phis created by processing inner loops.
|
||||
Changed |= DeleteDeadPHIs(L->getHeader(), &TLI, MSSAU.get());
|
||||
|
@ -5923,7 +5938,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
|
|||
}
|
||||
}
|
||||
|
||||
DbgApplyEqualValues(DbgValueToEqualSet);
|
||||
DbgApplyEqualValues(DbgValueToEqualSet, DbgValueToExpression);
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
|
|
@ -266,11 +266,13 @@ bool SpeculativeExecutionPass::considerHoistingFromTo(
|
|||
const auto AllPrecedingUsesFromBlockHoisted = [&NotHoisted](const User *U) {
|
||||
// Debug variable has special operand to check it's not hoisted.
|
||||
if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U)) {
|
||||
if (const auto *I =
|
||||
dyn_cast_or_null<Instruction>(DVI->getVariableLocationOp(0)))
|
||||
if (NotHoisted.count(I) == 0)
|
||||
return true;
|
||||
return false;
|
||||
return all_of(DVI->location_ops(), [&NotHoisted](Value *V) {
|
||||
if (const auto *I = dyn_cast_or_null<Instruction>(V)) {
|
||||
if (NotHoisted.count(I) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// Usially debug label instrinsic corresponds to label in LLVM IR. In these
|
||||
|
|
|
@ -407,7 +407,8 @@ static bool removeRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) {
|
|||
/// - Keep track of non-overlapping fragments.
|
||||
static bool removeRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) {
|
||||
SmallVector<DbgValueInst *, 8> ToBeRemoved;
|
||||
DenseMap<DebugVariable, std::pair<Value *, DIExpression *> > VariableMap;
|
||||
DenseMap<DebugVariable, std::pair<SmallVector<Value *, 4>, DIExpression *>>
|
||||
VariableMap;
|
||||
for (auto &I : *BB) {
|
||||
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(&I)) {
|
||||
DebugVariable Key(DVI->getVariable(),
|
||||
|
@ -416,10 +417,10 @@ static bool removeRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) {
|
|||
auto VMI = VariableMap.find(Key);
|
||||
// Update the map if we found a new value/expression describing the
|
||||
// variable, or if the variable wasn't mapped already.
|
||||
if (VMI == VariableMap.end() ||
|
||||
VMI->second.first != DVI->getValue() ||
|
||||
SmallVector<Value *, 4> Values(DVI->getValues());
|
||||
if (VMI == VariableMap.end() || VMI->second.first != Values ||
|
||||
VMI->second.second != DVI->getExpression()) {
|
||||
VariableMap[Key] = { DVI->getValue(), DVI->getExpression() };
|
||||
VariableMap[Key] = {Values, DVI->getExpression()};
|
||||
continue;
|
||||
}
|
||||
// Found an identical mapping. Remember the instruction for later removal.
|
||||
|
|
|
@ -1511,20 +1511,19 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
|
|||
continue;
|
||||
}
|
||||
|
||||
// If the location isn't a constant or an instruction, delete the
|
||||
// intrinsic.
|
||||
auto *DVI = cast<DbgVariableIntrinsic>(DII);
|
||||
Value *Location = DVI->getVariableLocationOp(0);
|
||||
if (!Location ||
|
||||
(!isa<Constant>(Location) && !isa<Instruction>(Location))) {
|
||||
DebugIntrinsicsToDelete.push_back(DVI);
|
||||
continue;
|
||||
}
|
||||
auto IsInvalidLocation = [&NewFunc](Value *Location) {
|
||||
// Location is invalid if it isn't a constant or an instruction, or is an
|
||||
// instruction but isn't in the new function.
|
||||
if (!Location ||
|
||||
(!isa<Constant>(Location) && !isa<Instruction>(Location)))
|
||||
return true;
|
||||
Instruction *LocationInst = dyn_cast<Instruction>(Location);
|
||||
return LocationInst && LocationInst->getFunction() != &NewFunc;
|
||||
};
|
||||
|
||||
// If the variable location is an instruction but isn't in the new
|
||||
// function, delete the intrinsic.
|
||||
Instruction *LocationInst = dyn_cast<Instruction>(Location);
|
||||
if (LocationInst && LocationInst->getFunction() != &NewFunc) {
|
||||
auto *DVI = cast<DbgVariableIntrinsic>(DII);
|
||||
// If any of the used locations are invalid, delete the intrinsic.
|
||||
if (any_of(DVI->location_ops(), IsInvalidLocation)) {
|
||||
DebugIntrinsicsToDelete.push_back(DVI);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -554,15 +554,16 @@ bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
|
|||
//
|
||||
// TODO: This, along with a check for non-null value operands, should be
|
||||
// promoted to verifier failures.
|
||||
Value *V = DVI->getValue();
|
||||
if (!V)
|
||||
return false;
|
||||
|
||||
// For now, don't try to interpret anything more complicated than an empty
|
||||
// DIExpression. Eventually we should try to handle OP_deref and fragments.
|
||||
if (DVI->getExpression()->getNumElements())
|
||||
return false;
|
||||
|
||||
Value *V = DVI->getVariableLocationOp(0);
|
||||
if (!V)
|
||||
return false;
|
||||
|
||||
Type *Ty = V->getType();
|
||||
uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
|
||||
Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
|
||||
|
|
|
@ -411,7 +411,7 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
|
|||
return true;
|
||||
}
|
||||
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
|
||||
if (DVI->getValue())
|
||||
if (DVI->hasArgList() || DVI->getValue(0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1360,7 +1360,7 @@ static bool PhiHasDebugValue(DILocalVariable *DIVar,
|
|||
SmallVector<DbgValueInst *, 1> DbgValues;
|
||||
findDbgValues(DbgValues, APN);
|
||||
for (auto *DVI : DbgValues) {
|
||||
assert(DVI->getValue() == APN);
|
||||
assert(is_contained(DVI->getValues(), APN));
|
||||
if ((DVI->getVariable() == DIVar) && (DVI->getExpression() == DIExpr))
|
||||
return true;
|
||||
}
|
||||
|
@ -1387,13 +1387,19 @@ static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) {
|
|||
// 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
|
||||
// intead.
|
||||
if (DII->isAddressOfVariable())
|
||||
if (auto *AI = dyn_cast_or_null<AllocaInst>(DII->getVariableLocationOp(0)))
|
||||
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 (Optional<TypeSize> FragmentSize = AI->getAllocationSizeInBits(DL)) {
|
||||
assert(ValueSize.isScalable() == FragmentSize->isScalable() &&
|
||||
"Both sizes should agree on the scalable flag.");
|
||||
return TypeSize::isKnownGE(ValueSize, *FragmentSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Could not determine size of variable. Conservatively return false.
|
||||
return false;
|
||||
}
|
||||
|
@ -1596,17 +1602,26 @@ void llvm::insertDebugValuesForPHIs(BasicBlock *BB,
|
|||
ValueToValueMapTy DbgValueMap;
|
||||
for (auto &I : *BB) {
|
||||
if (auto DbgII = dyn_cast<DbgVariableIntrinsic>(&I)) {
|
||||
if (auto *Loc =
|
||||
dyn_cast_or_null<PHINode>(DbgII->getVariableLocationOp(0)))
|
||||
DbgValueMap.insert({Loc, DbgII});
|
||||
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, insert a new dbg.value intrinsic that will
|
||||
// propagate the info through the new PHI.
|
||||
// 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.
|
||||
|
@ -1616,15 +1631,27 @@ void llvm::insertDebugValuesForPHIs(BasicBlock *BB,
|
|||
auto V = DbgValueMap.find(VI);
|
||||
if (V != DbgValueMap.end()) {
|
||||
auto *DbgII = cast<DbgVariableIntrinsic>(V->second);
|
||||
DbgVariableIntrinsic *NewDbgII =
|
||||
cast<DbgVariableIntrinsic>(DbgII->clone());
|
||||
NewDbgII->replaceVariableLocationOp(VI, PHI);
|
||||
auto InsertionPt = Parent->getFirstInsertionPt();
|
||||
assert(InsertionPt != Parent->end() && "Ill-formed basic block");
|
||||
NewDbgII->insertBefore(&*InsertionPt);
|
||||
auto NewDI = NewDbgValueMap.find({Parent, DbgII});
|
||||
if (NewDI == NewDbgValueMap.end()) {
|
||||
auto *NewDbgII = cast<DbgVariableIntrinsic>(DbgII->clone());
|
||||
NewDI = NewDbgValueMap.insert({{Parent, DbgII}, NewDbgII}).first;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds all intrinsics declaring local variables as living in the memory that
|
||||
|
@ -1665,11 +1692,25 @@ void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
|
|||
// DenseMap lookup.
|
||||
if (!V->isUsedByMetadata())
|
||||
return;
|
||||
if (auto *L = LocalAsMetadata::getIfExists(V))
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
|
||||
// TODO: If this value appears multiple times in a DIArgList, we should still
|
||||
// only add the owning DbgValueInst once; use this set to track ArgListUsers.
|
||||
// This behaviour can be removed when we can automatically remove duplicates.
|
||||
SmallPtrSet<DbgValueInst *, 4> EncounteredDbgValues;
|
||||
if (auto *L = LocalAsMetadata::getIfExists(V)) {
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L)) {
|
||||
for (User *U : MDV->users())
|
||||
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
|
||||
DbgValues.push_back(DVI);
|
||||
}
|
||||
for (Metadata *AL : L->getAllArgListUsers()) {
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), AL)) {
|
||||
for (User *U : MDV->users())
|
||||
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
|
||||
if (EncounteredDbgValues.insert(DVI).second)
|
||||
DbgValues.push_back(DVI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void llvm::findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers,
|
||||
|
@ -1678,11 +1719,25 @@ void llvm::findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers,
|
|||
// DenseMap lookup.
|
||||
if (!V->isUsedByMetadata())
|
||||
return;
|
||||
if (auto *L = LocalAsMetadata::getIfExists(V))
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
|
||||
// TODO: If this value appears multiple times in a DIArgList, we should still
|
||||
// only add the owning DbgValueInst once; use this set to track ArgListUsers.
|
||||
// This behaviour can be removed when we can automatically remove duplicates.
|
||||
SmallPtrSet<DbgVariableIntrinsic *, 4> EncounteredDbgValues;
|
||||
if (auto *L = LocalAsMetadata::getIfExists(V)) {
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L)) {
|
||||
for (User *U : MDV->users())
|
||||
if (DbgVariableIntrinsic *DII = dyn_cast<DbgVariableIntrinsic>(U))
|
||||
DbgUsers.push_back(DII);
|
||||
}
|
||||
for (Metadata *AL : L->getAllArgListUsers()) {
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), AL)) {
|
||||
for (User *U : MDV->users())
|
||||
if (DbgVariableIntrinsic *DII = dyn_cast<DbgVariableIntrinsic>(U))
|
||||
if (EncounteredDbgValues.insert(DII).second)
|
||||
DbgUsers.push_back(DII);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
|
||||
|
@ -1752,9 +1807,14 @@ void llvm::salvageDebugInfoForDbgValues(
|
|||
// are implicitly pointing out the value as a DWARF memory location
|
||||
// description.
|
||||
bool StackValue = isa<DbgValueInst>(DII);
|
||||
auto DIILocation = DII->location_ops();
|
||||
assert(
|
||||
is_contained(DIILocation, &I) &&
|
||||
"DbgVariableIntrinsic must use salvaged instruction as its location");
|
||||
unsigned LocNo = std::distance(DIILocation.begin(), find(DIILocation, &I));
|
||||
|
||||
DIExpression *DIExpr =
|
||||
salvageDebugInfoImpl(I, DII->getExpression(), StackValue);
|
||||
salvageDebugInfoImpl(I, DII->getExpression(), StackValue, LocNo);
|
||||
|
||||
// salvageDebugInfoImpl should fail on examining the first element of
|
||||
// DbgUsers, or none of them.
|
||||
|
@ -1847,7 +1907,7 @@ bool getSalvageOpsForBinOp(BinaryOperator *BI,
|
|||
|
||||
DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,
|
||||
DIExpression *SrcDIExpr,
|
||||
bool WithStackValue) {
|
||||
bool WithStackValue, unsigned LocNo) {
|
||||
auto &M = *I.getModule();
|
||||
auto &DL = M.getDataLayout();
|
||||
|
||||
|
@ -1855,7 +1915,7 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,
|
|||
auto doSalvage = [&](SmallVectorImpl<uint64_t> &Ops) -> DIExpression * {
|
||||
DIExpression *DIExpr = SrcDIExpr;
|
||||
if (!Ops.empty()) {
|
||||
DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue);
|
||||
DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, LocNo, WithStackValue);
|
||||
}
|
||||
return DIExpr;
|
||||
};
|
||||
|
|
|
@ -384,11 +384,14 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
|
|||
// possible or create a clone in the OldPreHeader if not.
|
||||
Instruction *LoopEntryBranch = OrigPreheader->getTerminator();
|
||||
|
||||
// Record all debug intrinsics preceding LoopEntryBranch to avoid duplication.
|
||||
// Record all debug intrinsics preceding LoopEntryBranch to avoid
|
||||
// duplication.
|
||||
using DbgIntrinsicHash =
|
||||
std::pair<std::pair<Value *, DILocalVariable *>, DIExpression *>;
|
||||
std::pair<std::pair<hash_code, DILocalVariable *>, DIExpression *>;
|
||||
auto makeHash = [](DbgVariableIntrinsic *D) -> DbgIntrinsicHash {
|
||||
return {{D->getVariableLocationOp(0), D->getVariable()},
|
||||
auto VarLocOps = D->location_ops();
|
||||
return {{hash_combine_range(VarLocOps.begin(), VarLocOps.end()),
|
||||
D->getVariable()},
|
||||
D->getExpression()};
|
||||
};
|
||||
SmallDenseSet<DbgIntrinsicHash, 8> DbgIntrinsics;
|
||||
|
|
|
@ -183,7 +183,8 @@ TEST(MetadataTest, DeleteInstUsedByDbgValue) {
|
|||
|
||||
// Delete %b. The dbg.value should now point to undef.
|
||||
I.eraseFromParent();
|
||||
EXPECT_TRUE(isa<UndefValue>(DVIs[0]->getValue()));
|
||||
EXPECT_EQ(DVIs[0]->getNumVariableLocationOps(), 1u);
|
||||
EXPECT_TRUE(isa<UndefValue>(DVIs[0]->getValue(0)));
|
||||
}
|
||||
|
||||
TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {
|
||||
|
|
Loading…
Reference in New Issue