1 | //===- llvm/unittest/IR/UserTest.cpp - User unit tests --------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/IR/User.h" |
10 | #include "llvm/AsmParser/Parser.h" |
11 | #include "llvm/IR/Function.h" |
12 | #include "llvm/IR/Instructions.h" |
13 | #include "llvm/IR/LLVMContext.h" |
14 | #include "llvm/IR/Module.h" |
15 | #include "llvm/Support/SourceMgr.h" |
16 | #include "gtest/gtest.h" |
17 | using namespace llvm; |
18 | |
19 | namespace { |
20 | |
21 | TEST(UserTest, ValueOpIteration) { |
22 | LLVMContext C; |
23 | |
24 | const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n" |
25 | "entry:\n" |
26 | " switch i32 undef, label %s0\n" |
27 | " [ i32 1, label %s1\n" |
28 | " i32 2, label %s2\n" |
29 | " i32 3, label %s3\n" |
30 | " i32 4, label %s4\n" |
31 | " i32 5, label %s5\n" |
32 | " i32 6, label %s6\n" |
33 | " i32 7, label %s7\n" |
34 | " i32 8, label %s8\n" |
35 | " i32 9, label %s9 ]\n" |
36 | "\n" |
37 | "s0:\n" |
38 | " br label %exit\n" |
39 | "s1:\n" |
40 | " br label %exit\n" |
41 | "s2:\n" |
42 | " br label %exit\n" |
43 | "s3:\n" |
44 | " br label %exit\n" |
45 | "s4:\n" |
46 | " br label %exit\n" |
47 | "s5:\n" |
48 | " br label %exit\n" |
49 | "s6:\n" |
50 | " br label %exit\n" |
51 | "s7:\n" |
52 | " br label %exit\n" |
53 | "s8:\n" |
54 | " br label %exit\n" |
55 | "s9:\n" |
56 | " br label %exit\n" |
57 | "\n" |
58 | "exit:\n" |
59 | " %phi = phi i32 [ 0, %s0 ], [ 1, %s1 ],\n" |
60 | " [ 2, %s2 ], [ 3, %s3 ],\n" |
61 | " [ 4, %s4 ], [ 5, %s5 ],\n" |
62 | " [ 6, %s6 ], [ 7, %s7 ],\n" |
63 | " [ 8, %s8 ], [ 9, %s9 ]\n" |
64 | " ret void\n" |
65 | "}\n" ; |
66 | SMDiagnostic Err; |
67 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: ModuleString, Err, Context&: C); |
68 | |
69 | Function *F = M->getFunction(Name: "f" ); |
70 | BasicBlock &ExitBB = F->back(); |
71 | PHINode &P = cast<PHINode>(Val&: ExitBB.front()); |
72 | EXPECT_TRUE(P.value_op_begin() == P.value_op_begin()); |
73 | EXPECT_FALSE(P.value_op_begin() == P.value_op_end()); |
74 | EXPECT_TRUE(P.value_op_begin() != P.value_op_end()); |
75 | EXPECT_FALSE(P.value_op_end() != P.value_op_end()); |
76 | EXPECT_TRUE(P.value_op_begin() < P.value_op_end()); |
77 | EXPECT_FALSE(P.value_op_begin() < P.value_op_begin()); |
78 | EXPECT_TRUE(P.value_op_end() > P.value_op_begin()); |
79 | EXPECT_FALSE(P.value_op_begin() > P.value_op_begin()); |
80 | EXPECT_TRUE(P.value_op_begin() <= P.value_op_begin()); |
81 | EXPECT_FALSE(P.value_op_end() <= P.value_op_begin()); |
82 | EXPECT_TRUE(P.value_op_begin() >= P.value_op_begin()); |
83 | EXPECT_FALSE(P.value_op_begin() >= P.value_op_end()); |
84 | EXPECT_EQ(10, std::distance(P.value_op_begin(), P.value_op_end())); |
85 | |
86 | // const value op iteration |
87 | const PHINode *IP = &P; |
88 | EXPECT_TRUE(IP->value_op_begin() == IP->value_op_begin()); |
89 | EXPECT_FALSE(IP->value_op_begin() == IP->value_op_end()); |
90 | EXPECT_TRUE(IP->value_op_begin() != IP->value_op_end()); |
91 | EXPECT_FALSE(IP->value_op_end() != IP->value_op_end()); |
92 | EXPECT_TRUE(IP->value_op_begin() < IP->value_op_end()); |
93 | EXPECT_FALSE(IP->value_op_begin() < IP->value_op_begin()); |
94 | EXPECT_TRUE(IP->value_op_end() > IP->value_op_begin()); |
95 | EXPECT_FALSE(IP->value_op_begin() > IP->value_op_begin()); |
96 | EXPECT_TRUE(IP->value_op_begin() <= IP->value_op_begin()); |
97 | EXPECT_FALSE(IP->value_op_end() <= IP->value_op_begin()); |
98 | EXPECT_TRUE(IP->value_op_begin() >= IP->value_op_begin()); |
99 | EXPECT_FALSE(IP->value_op_begin() >= IP->value_op_end()); |
100 | EXPECT_EQ(10, std::distance(IP->value_op_begin(), IP->value_op_end())); |
101 | |
102 | User::value_op_iterator I = P.value_op_begin(); |
103 | I += 3; |
104 | EXPECT_EQ(std::next(P.value_op_begin(), 3), I); |
105 | EXPECT_EQ(P.getOperand(3), *I); |
106 | I++; |
107 | EXPECT_EQ(P.getOperand(6), I[2]); |
108 | EXPECT_EQ(P.value_op_end(), (I - 2) + 8); |
109 | |
110 | // const value op |
111 | User::const_value_op_iterator CI = IP->value_op_begin(); |
112 | CI += 3; |
113 | EXPECT_EQ(std::next(IP->value_op_begin(), 3), CI); |
114 | EXPECT_EQ(IP->getOperand(3), *CI); |
115 | CI++; |
116 | EXPECT_EQ(IP->getOperand(6), CI[2]); |
117 | EXPECT_EQ(IP->value_op_end(), (CI - 2) + 8); |
118 | } |
119 | |
120 | TEST(UserTest, replaceUseOfWith) { |
121 | LLVMContext C; |
122 | |
123 | const char *ModuleString = "define void @f(i32 %x) {\n" |
124 | "entry:\n" |
125 | " %v0 = add i32 1, 1\n" |
126 | " %v1 = add i32 %x, 2\n" |
127 | " ret void\n" |
128 | "}\n" ; |
129 | SMDiagnostic Err; |
130 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: ModuleString, Err, Context&: C); |
131 | Function *F = M->getFunction(Name: "f" ); |
132 | EXPECT_TRUE(F); |
133 | EXPECT_TRUE(F->arg_begin() != F->arg_end()); |
134 | BasicBlock& entryBB = F->front(); |
135 | Instruction& I0 = *(entryBB.begin()); |
136 | Instruction& I1 = *(++(entryBB.begin())); |
137 | |
138 | Argument &X = *F->arg_begin(); |
139 | EXPECT_EQ("x" , X.getName()); |
140 | EXPECT_NE(X.user_begin() ,X.user_end()); |
141 | EXPECT_EQ(I0.user_begin() ,I0.user_end()); |
142 | |
143 | |
144 | auto XUser = find(Range: X.users(), Val: &(I1)); |
145 | EXPECT_NE(XUser, X.user_end()); |
146 | |
147 | EXPECT_TRUE(XUser->replaceUsesOfWith(&X, &I0)); |
148 | EXPECT_EQ(X.user_begin(), X.user_end()); |
149 | EXPECT_NE(I0.user_begin(), I0.user_end()); |
150 | |
151 | // All uses have already been replaced, nothing more to do. |
152 | EXPECT_FALSE(XUser->replaceUsesOfWith(&X, &I0)); |
153 | } |
154 | |
155 | TEST(UserTest, PersonalityUser) { |
156 | LLVMContext Context; |
157 | Module M("" , Context); |
158 | FunctionType *RetVoidTy = FunctionType::get(Result: Type::getVoidTy(C&: Context), isVarArg: false); |
159 | Function *PersonalityF = Function::Create( |
160 | Ty: RetVoidTy, Linkage: GlobalValue::ExternalLinkage, N: "PersonalityFn" , M: &M); |
161 | Function *TestF = |
162 | Function::Create(Ty: RetVoidTy, Linkage: GlobalValue::ExternalLinkage, N: "TestFn" , M: &M); |
163 | |
164 | // Set up the personality function |
165 | TestF->setPersonalityFn(PersonalityF); |
166 | auto PersonalityUsers = PersonalityF->user_begin(); |
167 | |
168 | // One user and that user is the Test function |
169 | EXPECT_EQ(*PersonalityUsers, TestF); |
170 | EXPECT_EQ(++PersonalityUsers, PersonalityF->user_end()); |
171 | |
172 | // Reset the personality function |
173 | TestF->setPersonalityFn(nullptr); |
174 | |
175 | // No users should remain |
176 | EXPECT_TRUE(TestF->user_empty()); |
177 | } |
178 | |
179 | } // end anonymous namespace |
180 | |