llvm.org GIT mirror llvm / e49dfa7
IRMover: Steal arguments when moving functions, NFC Instead of copying arguments from the source function to the destination, steal them. This has a few advantages. - The ValueMap doesn't need to be seeded with (or cleared of) Arguments. - Often the destination function won't have created any arguments yet, so this avoids malloc traffic. - Argument names don't need to be copied. Because argument lists are lazy, this required a new Function::stealArgumentListFrom helper. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265519 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 3 years ago
5 changed file(s) with 144 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
8787 /// built on demand, so that the list isn't allocated until the first client
8888 /// needs it. The hasLazyArguments predicate returns true if the arg list
8989 /// hasn't been set up yet.
90 public:
9091 bool hasLazyArguments() const {
9192 return getSubclassDataFromValue() & (1<<0);
9293 }
94
95 private:
9396 void CheckLazyArguments() const {
9497 if (hasLazyArguments())
9598 BuildLazyArguments();
441444 ///
442445 void eraseFromParent() override;
443446
447 /// Steal arguments from another function.
448 ///
449 /// Drop this function's arguments and splice in the ones from \c Src.
450 /// Requires that this has no function body.
451 void stealArgumentListFrom(Function &Src);
452
444453 /// Get the underlying elements of the Function... the basic block list is
445454 /// empty for external functions.
446455 ///
299299 // Clear the lazy arguments bit.
300300 unsigned SDC = getSubclassDataFromValue();
301301 const_cast(this)->setValueSubclassData(SDC &= ~(1<<0));
302 }
303
304 void Function::stealArgumentListFrom(Function &Src) {
305 assert(isDeclaration() && "Expected no references to current arguments");
306
307 // Drop the current arguments, if any, and set the lazy argument bit.
308 if (!hasLazyArguments()) {
309 assert(llvm::all_of(ArgumentList,
310 [](const Argument &A) { return A.use_empty(); }) &&
311 "Expected arguments to be unused in declaration");
312 ArgumentList.clear();
313 setValueSubclassData(getSubclassDataFromValue() | (1 << 0));
314 }
315
316 // Nothing to steal if Src has lazy arguments.
317 if (Src.hasLazyArguments())
318 return;
319
320 // Steal arguments from Src, and fix the lazy argument bits.
321 ArgumentList.splice(ArgumentList.end(), Src.ArgumentList);
322 setValueSubclassData(getSubclassDataFromValue() & ~(1 << 0));
323 Src.setValueSubclassData(Src.getSubclassDataFromValue() | (1 << 0));
302324 }
303325
304326 size_t Function::arg_size() const {
979979 ValueMapperFlags, &TypeMap,
980980 &GValMaterializer));
981981
982 // Go through and convert function arguments over, remembering the mapping.
983 Function::arg_iterator DI = Dst.arg_begin();
984 for (Argument &Arg : Src.args()) {
985 DI->setName(Arg.getName()); // Copy the name over.
986
987 // Add a mapping to our mapping.
988 ValueMap[&Arg] = &*DI;
989 ++DI;
990 }
991
992982 // Copy over the metadata attachments.
993983 SmallVector, 8> MDs;
994984 Src.getAllMetadata(MDs);
996986 Dst.setMetadata(I.first, MapMetadata(I.second, ValueMap, ValueMapperFlags,
997987 &TypeMap, &GValMaterializer));
998988
999 // Splice the body of the source function into the dest function.
989 // Steal arguments and splice the body of Src into Dst.
990 Dst.stealArgumentListFrom(Src);
1000991 Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
1001992
1002 // At this point, all of the instructions and values of the function are now
1003 // copied over. The only problem is that they are still referencing values in
1004 // the Source function as operands. Loop through all of the operands of the
1005 // functions and patch them up to point to the local versions.
993 // At this point, everything has been moved over, but the types and non-local
994 // operands will be wrong. Loop through everything and patch it up.
995 for (Argument &A : Dst.args())
996 A.mutateType(TypeMap.get(A.getType()));
1006997 for (BasicBlock &BB : Dst)
1007998 for (Instruction &I : BB)
1008999 RemapInstruction(&I, ValueMap, RF_IgnoreMissingEntries | ValueMapperFlags,
10091000 &TypeMap, &GValMaterializer);
1010
1011 // There is no need to map the arguments anymore.
1012 for (Argument &Arg : Src.args())
1013 ValueMap.erase(&Arg);
10141001
10151002 return false;
10161003 }
1111 ConstantsTest.cpp
1212 DebugInfoTest.cpp
1313 DominatorTreeTest.cpp
14 FunctionTest.cpp
1415 IRBuilderTest.cpp
1516 InstructionsTest.cpp
1617 IntrinsicsTest.cpp
0 //===- FunctionTest.cpp - Function unit tests -----------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/IR/Function.h"
10 #include "gtest/gtest.h"
11 using namespace llvm;
12
13 namespace {
14
15 TEST(FunctionTest, hasLazyArguments) {
16 LLVMContext C;
17
18 Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};
19 FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false);
20
21 // Functions start out with lazy arguments.
22 std::unique_ptr F(
23 Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
24 EXPECT_TRUE(F->hasLazyArguments());
25
26 // Checking for empty or size shouldn't force arguments to be instantiated.
27 EXPECT_FALSE(F->arg_empty());
28 EXPECT_TRUE(F->hasLazyArguments());
29 EXPECT_EQ(2u, F->arg_size());
30 EXPECT_TRUE(F->hasLazyArguments());
31
32 // The argument list should be populated at first access.
33 (void)F->arg_begin();
34 EXPECT_FALSE(F->hasLazyArguments());
35 }
36
37 TEST(FunctionTest, stealArgumentListFrom) {
38 LLVMContext C;
39
40 Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};
41 FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false);
42 std::unique_ptr F1(
43 Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));
44 std::unique_ptr F2(
45 Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));
46 EXPECT_TRUE(F1->hasLazyArguments());
47 EXPECT_TRUE(F2->hasLazyArguments());
48
49 // Steal arguments before they've been accessed. Nothing should change; both
50 // functions should still have lazy arguments.
51 //
52 // steal(empty); drop (empty)
53 F1->stealArgumentListFrom(*F2);
54 EXPECT_TRUE(F1->hasLazyArguments());
55 EXPECT_TRUE(F2->hasLazyArguments());
56
57 // Save arguments from F1 for later assertions. F1 won't have lazy arguments
58 // anymore.
59 SmallVector Args;
60 for (Argument &A : F1->args())
61 Args.push_back(&A);
62 EXPECT_EQ(2u, Args.size());
63 EXPECT_FALSE(F1->hasLazyArguments());
64
65 // Steal arguments from F1 to F2. F1's arguments should be lazy again.
66 //
67 // steal(real); drop (empty)
68 F2->stealArgumentListFrom(*F1);
69 EXPECT_TRUE(F1->hasLazyArguments());
70 EXPECT_FALSE(F2->hasLazyArguments());
71 unsigned I = 0;
72 for (Argument &A : F2->args())
73 EXPECT_EQ(Args[I++], &A);
74 EXPECT_EQ(2u, I);
75
76 // Check that arguments in F1 don't have pointer equality with the saved ones.
77 // This also instantiates F1's arguments.
78 I = 0;
79 for (Argument &A : F1->args())
80 EXPECT_NE(Args[I++], &A);
81 EXPECT_EQ(2u, I);
82 EXPECT_FALSE(F1->hasLazyArguments());
83 EXPECT_FALSE(F2->hasLazyArguments());
84
85 // Steal back from F2. F2's arguments should be lazy again.
86 //
87 // steal(real); drop (real)
88 F1->stealArgumentListFrom(*F2);
89 EXPECT_FALSE(F1->hasLazyArguments());
90 EXPECT_TRUE(F2->hasLazyArguments());
91 I = 0;
92 for (Argument &A : F1->args())
93 EXPECT_EQ(Args[I++], &A);
94 EXPECT_EQ(2u, I);
95
96 // Steal from F2 a second time. Now both functions should have lazy
97 // arguments.
98 //
99 // steal(empty); drop (real)
100 F1->stealArgumentListFrom(*F2);
101 EXPECT_TRUE(F1->hasLazyArguments());
102 EXPECT_TRUE(F2->hasLazyArguments());
103 }
104
105 } // end namespace