unsigned O);
/// Transfer debug values from one node to another, while optionally
- /// generating fragment expressions for split-up values.
+ /// generating fragment expressions for split-up values. If \p InvalidateDbg
+ /// is set, debug values are invalidated after they are transferred.
void transferDbgValues(SDValue From, SDValue To, unsigned OffsetInBits = 0,
- unsigned SizeInBits = 0);
+ unsigned SizeInBits = 0, bool InvalidateDbg = true);
/// Remove the specified node from the system. If any of its
/// operands then becomes dead, remove them as well. Inform UpdateListener
return DbgInfo->getSDDbgValues(SD);
}
-private:
- /// Transfer SDDbgValues. Called via ReplaceAllUses{OfValue}?With
- void TransferDbgValues(SDValue From, SDValue To);
-
public:
/// Return true if there are any SDDbgValue nodes associated
/// with this SelectionDAG.
AnalyzeNewValue(Lo);
AnalyzeNewValue(Hi);
- // Transfer debug values.
+ // Transfer debug values. Don't invalidate the source debug value until it's
+ // been transferred to the high and low bits.
if (DAG.getDataLayout().isBigEndian()) {
- DAG.transferDbgValues(Op, Hi, 0, Hi.getValueSizeInBits());
+ DAG.transferDbgValues(Op, Hi, 0, Hi.getValueSizeInBits(), false);
DAG.transferDbgValues(Op, Lo, Hi.getValueSizeInBits(),
Lo.getValueSizeInBits());
} else {
- DAG.transferDbgValues(Op, Lo, 0, Lo.getValueSizeInBits());
+ DAG.transferDbgValues(Op, Lo, 0, Lo.getValueSizeInBits(), false);
DAG.transferDbgValues(Op, Hi, Lo.getValueSizeInBits(),
Hi.getValueSizeInBits());
}
}
void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
- unsigned OffsetInBits,
- unsigned SizeInBits) {
+ unsigned OffsetInBits, unsigned SizeInBits,
+ bool InvalidateDbg) {
SDNode *FromNode = From.getNode();
SDNode *ToNode = To.getNode();
- assert(FromNode != ToNode);
+ assert(FromNode && ToNode && "Can't modify dbg values");
+
+ // PR35338
+ // TODO: assert(From != To && "Redundant dbg value transfer");
+ // TODO: assert(FromNode != ToNode && "Intranode dbg value transfer");
+ if (From == To || FromNode == ToNode)
+ return;
+
+ if (!FromNode->getHasDebugValue())
+ return;
SmallVector<SDDbgValue *, 2> ClonedDVs;
for (SDDbgValue *Dbg : GetDbgValues(FromNode)) {
- if (Dbg->getKind() != SDDbgValue::SDNODE)
- break;
+ if (Dbg->getKind() != SDDbgValue::SDNODE || Dbg->isInvalidated())
+ continue;
+
+ // TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value");
+
+ // Just transfer the dbg value attached to From.
+ if (Dbg->getResNo() != From.getResNo())
+ continue;
DIVariable *Var = Dbg->getVariable();
auto *Expr = Dbg->getExpression();
getDbgValue(Var, Expr, ToNode, To.getResNo(), Dbg->isIndirect(),
Dbg->getDebugLoc(), Dbg->getOrder());
ClonedDVs.push_back(Clone);
- Dbg->setIsInvalidated();
+
+ if (InvalidateDbg)
+ Dbg->setIsInvalidated();
}
for (SDDbgValue *Dbg : ClonedDVs)
assert(From != To.getNode() && "Cannot replace uses of with self");
// Preserve Debug Values
- TransferDbgValues(FromN, To);
+ transferDbgValues(FromN, To);
// Iterate over all the existing uses of From. New uses will be added
// to the beginning of the use list, which we avoid visiting.
for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
if (From->hasAnyUseOfValue(i)) {
assert((i < To->getNumValues()) && "Invalid To location");
- TransferDbgValues(SDValue(From, i), SDValue(To, i));
+ transferDbgValues(SDValue(From, i), SDValue(To, i));
}
// Iterate over just the existing users of From. See the comments in
// Preserve Debug Info.
for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
- TransferDbgValues(SDValue(From, i), *To);
+ transferDbgValues(SDValue(From, i), *To);
// Iterate over just the existing users of From. See the comments in
// the ReplaceAllUsesWith above.
}
// Preserve Debug Info.
- TransferDbgValues(From, To);
+ transferDbgValues(From, To);
// Iterate over just the existing users of From. See the comments in
// the ReplaceAllUsesWith above.
if (Num == 1)
return ReplaceAllUsesOfValueWith(*From, *To);
- TransferDbgValues(*From, *To);
+ transferDbgValues(*From, *To);
// Read up all the uses and make records of them. This helps
// processing new uses that are introduced during the
DbgInfo->add(DB, SD, isParameter);
}
-/// Transfer SDDbgValues. Called in replace nodes.
-void SelectionDAG::TransferDbgValues(SDValue From, SDValue To) {
- if (From == To || !From.getNode()->getHasDebugValue())
- return;
- SDNode *FromNode = From.getNode();
- SDNode *ToNode = To.getNode();
- SmallVector<SDDbgValue *, 2> ClonedDVs;
- for (auto *Dbg : GetDbgValues(FromNode)) {
- // Only add Dbgvalues attached to same ResNo.
- if (Dbg->getKind() == SDDbgValue::SDNODE &&
- Dbg->getSDNode() == From.getNode() &&
- Dbg->getResNo() == From.getResNo() && !Dbg->isInvalidated()) {
- assert(FromNode != ToNode &&
- "Should not transfer Debug Values intranode");
- SDDbgValue *Clone = getDbgValue(Dbg->getVariable(), Dbg->getExpression(),
- ToNode, To.getResNo(), Dbg->isIndirect(),
- Dbg->getDebugLoc(), Dbg->getOrder());
- ClonedDVs.push_back(Clone);
- Dbg->setIsInvalidated();
- }
- }
- for (SDDbgValue *I : ClonedDVs)
- AddDbgValue(I, ToNode, false);
-}
-
SDValue SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad,
SDValue NewMemOp) {
assert(isa<MemSDNode>(NewMemOp.getNode()) && "Expected a memop node");