diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index b82564c9d68..8850ffe3bee 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -462,6 +462,9 @@ public: /// expected to compare two \a Use references. template void sortUseList(Compare Cmp); + /// \brief Reverse the use-list. + void reverseUseList(); + private: /// \brief Merge two lists together. /// diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 1ab2183b656..555823b3f28 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -614,6 +614,25 @@ Value *Value::DoPHITranslation(const BasicBlock *CurBB, LLVMContext &Value::getContext() const { return VTy->getContext(); } +void Value::reverseUseList() { + if (!UseList || !UseList->Next) + // No need to reverse 0 or 1 uses. + return; + + Use *Head = UseList; + Use *Current = UseList->Next; + Head->Next = nullptr; + while (Current) { + Use *Next = Current->Next; + Current->Next = Head; + Head->setPrev(&Current->Next); + Head = Current; + Current = Next; + } + UseList = Head; + Head->setPrev(&UseList); +} + //===----------------------------------------------------------------------===// // ValueHandleBase Class //===----------------------------------------------------------------------===// diff --git a/unittests/IR/UseTest.cpp b/unittests/IR/UseTest.cpp index 980175c3e8c..fa73fe77bd3 100644 --- a/unittests/IR/UseTest.cpp +++ b/unittests/IR/UseTest.cpp @@ -66,4 +66,47 @@ TEST(UseTest, sort) { ASSERT_EQ(8u, I); } +TEST(UseTest, reverse) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.reverseUseList(); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + } // end anonymous namespace