diff options
-rw-r--r-- | llvm/include/llvm/ADT/ilist.h | 9 | ||||
-rw-r--r-- | llvm/include/llvm/CodeGen/MachineFunction.h | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineBasicBlock.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/IR/SymbolTableListTraitsImpl.h | 3 | ||||
-rw-r--r-- | llvm/unittests/ADT/IListTest.cpp | 30 |
5 files changed, 43 insertions, 9 deletions
diff --git a/llvm/include/llvm/ADT/ilist.h b/llvm/include/llvm/ADT/ilist.h index 62e434010dd..06c7abff965 100644 --- a/llvm/include/llvm/ADT/ilist.h +++ b/llvm/include/llvm/ADT/ilist.h @@ -65,9 +65,8 @@ template <typename NodeTy> struct ilist_callback_traits { void addNodeToList(NodeTy *) {} void removeNodeFromList(NodeTy *) {} - /// Callback before transferring nodes to this list. - /// - /// \pre \c this!=&OldList + /// Callback before transferring nodes to this list. The nodes may already be + /// in this same list. template <class Iterator> void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/, Iterator /*last*/) { @@ -286,8 +285,8 @@ private: if (position == last) return; - if (this != &L2) // Notify traits we moved the nodes... - this->transferNodesFromList(L2, first, last); + // Notify traits we moved the nodes... + this->transferNodesFromList(L2, first, last); base_list_type::splice(position, L2, first, last); } diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index a3b13fb2438..670b2d501af 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -85,7 +85,7 @@ template <> struct ilist_callback_traits<MachineBasicBlock> { template <class Iterator> void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) { - llvm_unreachable("Never transfer between lists"); + assert(this == &OldList && "never transfer MBBs between functions"); } }; diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp index df4762088c1..c3e9c185be9 100644 --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -132,8 +132,12 @@ void ilist_traits<MachineInstr>::transferNodesFromList(ilist_traits &FromList, instr_iterator First, instr_iterator Last) { assert(Parent->getParent() == FromList.Parent->getParent() && - "MachineInstr parent mismatch!"); - assert(this != &FromList && "Called without a real transfer..."); + "cannot transfer MachineInstrs between MachineFunctions"); + + // If it's within the same BB, there's nothing to do. + if (this == &FromList) + return; + assert(Parent != FromList.Parent && "Two lists have the same parent?"); // If splicing between two blocks within the same function, just update the diff --git a/llvm/lib/IR/SymbolTableListTraitsImpl.h b/llvm/lib/IR/SymbolTableListTraitsImpl.h index a74ac8a960f..f399c823d6f 100644 --- a/llvm/lib/IR/SymbolTableListTraitsImpl.h +++ b/llvm/lib/IR/SymbolTableListTraitsImpl.h @@ -83,7 +83,8 @@ void SymbolTableListTraits<ValueSubClass>::transferNodesFromList( SymbolTableListTraits &L2, iterator first, iterator last) { // We only have to do work here if transferring instructions between BBs ItemParentClass *NewIP = getListOwner(), *OldIP = L2.getListOwner(); - assert(NewIP != OldIP && "Expected different list owners"); + if (NewIP == OldIP) + return; // We only have to update symbol table entries if we are transferring the // instructions to a different symtab object... diff --git a/llvm/unittests/ADT/IListTest.cpp b/llvm/unittests/ADT/IListTest.cpp index 3992a235403..18f6c41a648 100644 --- a/llvm/unittests/ADT/IListTest.cpp +++ b/llvm/unittests/ADT/IListTest.cpp @@ -207,6 +207,12 @@ struct NodeWithCallback : ilist_node<NodeWithCallback> { } // end namespace namespace llvm { +// These nodes are stack-allocated for testing purposes, so don't let the ilist +// own or delete them. +template <> struct ilist_alloc_traits<NodeWithCallback> { + static void deleteNode(NodeWithCallback *) {} +}; + template <> struct ilist_callback_traits<NodeWithCallback> { void addNodeToList(NodeWithCallback *N) { N->IsInList = true; } void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; } @@ -247,6 +253,30 @@ TEST(IListTest, addNodeToList) { ASSERT_TRUE(N.WasTransferred); } +TEST(IListTest, sameListSplice) { + NodeWithCallback N1(1); + NodeWithCallback N2(2); + ASSERT_FALSE(N1.WasTransferred); + ASSERT_FALSE(N2.WasTransferred); + + ilist<NodeWithCallback> L1; + L1.insert(L1.end(), &N1); + L1.insert(L1.end(), &N2); + ASSERT_EQ(2u, L1.size()); + ASSERT_EQ(&N1, &L1.front()); + ASSERT_FALSE(N1.WasTransferred); + ASSERT_FALSE(N2.WasTransferred); + + // Swap the nodes with splice inside the same list. Check that we get the + // transfer callback. + L1.splice(L1.begin(), L1, std::next(L1.begin()), L1.end()); + ASSERT_EQ(2u, L1.size()); + ASSERT_EQ(&N1, &L1.back()); + ASSERT_EQ(&N2, &L1.front()); + ASSERT_FALSE(N1.WasTransferred); + ASSERT_TRUE(N2.WasTransferred); +} + struct PrivateNode : private ilist_node<PrivateNode> { friend struct llvm::ilist_detail::NodeAccess; |