// If any of the SDDbgValue nodes refer to this SDNode, invalidate
// them and forget about that node.
DbgInfo->erase(N);
+
+ // Invalidate extra info.
+ SDEI.erase(N);
}
#ifndef NDEBUG
// Preserve Debug Values
transferDbgValues(FromN, To);
+ // Preserve extra info.
+ copyExtraInfo(From, To.getNode());
// Iterate over all the existing uses of From. New uses will be added
// to the beginning of the use list, which we avoid visiting.
assert((i < To->getNumValues()) && "Invalid To location");
transferDbgValues(SDValue(From, i), SDValue(To, i));
}
+ // Preserve extra info.
+ copyExtraInfo(From, To);
// Iterate over just the existing users of From. See the comments in
// the ReplaceAllUsesWith above.
if (From->getNumValues() == 1) // Handle the simple case efficiently.
return ReplaceAllUsesWith(SDValue(From, 0), To[0]);
- // Preserve Debug Info.
- for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
+ for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
+ // Preserve Debug Info.
transferDbgValues(SDValue(From, i), To[i]);
+ // Preserve extra info.
+ copyExtraInfo(From, To[i].getNode());
+ }
// Iterate over just the existing users of From. See the comments in
// the ReplaceAllUsesWith above.
// Preserve Debug Info.
transferDbgValues(From, To);
+ copyExtraInfo(From.getNode(), To.getNode());
// Iterate over just the existing users of From. See the comments in
// the ReplaceAllUsesWith above.
return ReplaceAllUsesOfValueWith(*From, *To);
transferDbgValues(*From, *To);
+ copyExtraInfo(From->getNode(), To->getNode());
// Read up all the uses and make records of them. This helps
// processing new uses that are introduced during the
}
}
+void SelectionDAG::copyExtraInfo(SDNode *From, SDNode *To) {
+ assert(From && To && "Invalid SDNode; empty source SDValue?");
+ auto I = SDEI.find(From);
+ if (I == SDEI.end())
+ return;
+ SDEI[To] = I->second;
+}
+
#ifndef NDEBUG
static void checkForCyclesHelper(const SDNode *N,
SmallPtrSetImpl<const SDNode*> &Visited,
EXPECT_EQ(Op.getOpcode(), ISD::SPLAT_VECTOR);
}
+TEST_F(AArch64SelectionDAGTest, ReplaceAllUsesWith) {
+ SDLoc Loc;
+ EVT IntVT = EVT::getIntegerVT(Context, 8);
+
+ SDValue N0 = DAG->getConstant(0x42, Loc, IntVT);
+ SDValue N1 = DAG->getRegister(0, IntVT);
+ // Construct node to fill arbitrary ExtraInfo.
+ SDValue N2 = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1);
+ EXPECT_FALSE(DAG->getHeapAllocSite(N2.getNode()));
+ EXPECT_FALSE(DAG->getNoMergeSiteInfo(N2.getNode()));
+ MDNode *MD = MDNode::get(Context, None);
+ DAG->addHeapAllocSite(N2.getNode(), MD);
+ DAG->addNoMergeSiteInfo(N2.getNode(), true);
+ EXPECT_EQ(DAG->getHeapAllocSite(N2.getNode()), MD);
+ EXPECT_TRUE(DAG->getNoMergeSiteInfo(N2.getNode()));
+
+ SDValue Root = DAG->getNode(ISD::ADD, Loc, IntVT, N2, N2);
+ EXPECT_EQ(Root->getOperand(0)->getOpcode(), ISD::SUB);
+ // Create new node and check that ExtraInfo is propagated on RAUW.
+ SDValue New = DAG->getNode(ISD::ADD, Loc, IntVT, N1, N1);
+ EXPECT_FALSE(DAG->getHeapAllocSite(New.getNode()));
+ EXPECT_FALSE(DAG->getNoMergeSiteInfo(New.getNode()));
+
+ DAG->ReplaceAllUsesWith(N2, New);
+ EXPECT_EQ(Root->getOperand(0), New);
+ EXPECT_EQ(DAG->getHeapAllocSite(New.getNode()), MD);
+ EXPECT_TRUE(DAG->getNoMergeSiteInfo(New.getNode()));
+}
+
} // end namespace llvm