1 | //===- llvm/unittest/IR/ConstantsTest.cpp - Constants 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/Constants.h" |
10 | #include "llvm-c/Core.h" |
11 | #include "llvm/AsmParser/Parser.h" |
12 | #include "llvm/IR/ConstantFold.h" |
13 | #include "llvm/IR/DerivedTypes.h" |
14 | #include "llvm/IR/InstrTypes.h" |
15 | #include "llvm/IR/Instruction.h" |
16 | #include "llvm/IR/LLVMContext.h" |
17 | #include "llvm/IR/Module.h" |
18 | #include "llvm/Support/SourceMgr.h" |
19 | #include "gtest/gtest.h" |
20 | |
21 | namespace llvm { |
22 | namespace { |
23 | |
24 | TEST(ConstantsTest, Integer_i1) { |
25 | LLVMContext Context; |
26 | IntegerType *Int1 = IntegerType::get(C&: Context, NumBits: 1); |
27 | Constant *One = ConstantInt::get(Ty: Int1, V: 1, IsSigned: true); |
28 | Constant *Zero = ConstantInt::get(Ty: Int1, V: 0); |
29 | Constant *NegOne = ConstantInt::get(Ty: Int1, V: static_cast<uint64_t>(-1), IsSigned: true); |
30 | EXPECT_EQ(NegOne, ConstantInt::getSigned(Int1, -1)); |
31 | Constant *Poison = PoisonValue::get(T: Int1); |
32 | |
33 | // Input: @b = constant i1 add(i1 1 , i1 1) |
34 | // Output: @b = constant i1 false |
35 | EXPECT_EQ(Zero, ConstantExpr::getAdd(One, One)); |
36 | |
37 | // @c = constant i1 add(i1 -1, i1 1) |
38 | // @c = constant i1 false |
39 | EXPECT_EQ(Zero, ConstantExpr::getAdd(NegOne, One)); |
40 | |
41 | // @d = constant i1 add(i1 -1, i1 -1) |
42 | // @d = constant i1 false |
43 | EXPECT_EQ(Zero, ConstantExpr::getAdd(NegOne, NegOne)); |
44 | |
45 | // @e = constant i1 sub(i1 -1, i1 1) |
46 | // @e = constant i1 false |
47 | EXPECT_EQ(Zero, ConstantExpr::getSub(NegOne, One)); |
48 | |
49 | // @f = constant i1 sub(i1 1 , i1 -1) |
50 | // @f = constant i1 false |
51 | EXPECT_EQ(Zero, ConstantExpr::getSub(One, NegOne)); |
52 | |
53 | // @g = constant i1 sub(i1 1 , i1 1) |
54 | // @g = constant i1 false |
55 | EXPECT_EQ(Zero, ConstantExpr::getSub(One, One)); |
56 | |
57 | // @h = constant i1 shl(i1 1 , i1 1) ; poison |
58 | // @h = constant i1 poison |
59 | EXPECT_EQ(Poison, ConstantExpr::getShl(One, One)); |
60 | |
61 | // @i = constant i1 shl(i1 1 , i1 0) |
62 | // @i = constant i1 true |
63 | EXPECT_EQ(One, ConstantExpr::getShl(One, Zero)); |
64 | |
65 | // @n = constant i1 mul(i1 -1, i1 1) |
66 | // @n = constant i1 true |
67 | EXPECT_EQ(One, ConstantExpr::getMul(NegOne, One)); |
68 | |
69 | // @o = constant i1 sdiv(i1 -1, i1 1) ; overflow |
70 | // @o = constant i1 true |
71 | EXPECT_EQ(One, ConstantFoldBinaryInstruction(Instruction::SDiv, NegOne, One)); |
72 | |
73 | // @p = constant i1 sdiv(i1 1 , i1 -1); overflow |
74 | // @p = constant i1 true |
75 | EXPECT_EQ(One, ConstantFoldBinaryInstruction(Instruction::SDiv, One, NegOne)); |
76 | |
77 | // @q = constant i1 udiv(i1 -1, i1 1) |
78 | // @q = constant i1 true |
79 | EXPECT_EQ(One, ConstantFoldBinaryInstruction(Instruction::UDiv, NegOne, One)); |
80 | |
81 | // @r = constant i1 udiv(i1 1, i1 -1) |
82 | // @r = constant i1 true |
83 | EXPECT_EQ(One, ConstantFoldBinaryInstruction(Instruction::UDiv, One, NegOne)); |
84 | |
85 | // @s = constant i1 srem(i1 -1, i1 1) ; overflow |
86 | // @s = constant i1 false |
87 | EXPECT_EQ(Zero, |
88 | ConstantFoldBinaryInstruction(Instruction::SRem, NegOne, One)); |
89 | |
90 | // @u = constant i1 srem(i1 1, i1 -1) ; overflow |
91 | // @u = constant i1 false |
92 | EXPECT_EQ(Zero, |
93 | ConstantFoldBinaryInstruction(Instruction::SRem, One, NegOne)); |
94 | } |
95 | |
96 | TEST(ConstantsTest, IntSigns) { |
97 | LLVMContext Context; |
98 | IntegerType *Int8Ty = Type::getInt8Ty(C&: Context); |
99 | EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, false)->getSExtValue()); |
100 | EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, true)->getSExtValue()); |
101 | EXPECT_EQ(100, ConstantInt::getSigned(Int8Ty, 100)->getSExtValue()); |
102 | EXPECT_EQ(-50, ConstantInt::get(Int8Ty, 206)->getSExtValue()); |
103 | EXPECT_EQ(-50, ConstantInt::getSigned(Int8Ty, -50)->getSExtValue()); |
104 | EXPECT_EQ(206U, ConstantInt::getSigned(Int8Ty, -50)->getZExtValue()); |
105 | |
106 | // Overflow is handled by truncation. |
107 | EXPECT_EQ(0x3b, ConstantInt::get(Int8Ty, 0x13b)->getSExtValue()); |
108 | } |
109 | |
110 | TEST(ConstantsTest, PointerCast) { |
111 | LLVMContext C; |
112 | Type *PtrTy = PointerType::get(C, AddressSpace: 0); |
113 | Type *Int64Ty = Type::getInt64Ty(C); |
114 | VectorType *PtrVecTy = FixedVectorType::get(ElementType: PtrTy, NumElts: 4); |
115 | VectorType *Int64VecTy = FixedVectorType::get(ElementType: Int64Ty, NumElts: 4); |
116 | VectorType *PtrScalableVecTy = ScalableVectorType::get(ElementType: PtrTy, MinNumElts: 4); |
117 | VectorType *Int64ScalableVecTy = ScalableVectorType::get(ElementType: Int64Ty, MinNumElts: 4); |
118 | |
119 | // ptrtoint ptr to i64 |
120 | EXPECT_EQ( |
121 | Constant::getNullValue(Int64Ty), |
122 | ConstantExpr::getPointerCast(Constant::getNullValue(PtrTy), Int64Ty)); |
123 | |
124 | // bitcast ptr to ptr |
125 | EXPECT_EQ(Constant::getNullValue(PtrTy), |
126 | ConstantExpr::getPointerCast(Constant::getNullValue(PtrTy), PtrTy)); |
127 | |
128 | // ptrtoint <4 x ptr> to <4 x i64> |
129 | EXPECT_EQ(Constant::getNullValue(Int64VecTy), |
130 | ConstantExpr::getPointerCast(Constant::getNullValue(PtrVecTy), |
131 | Int64VecTy)); |
132 | |
133 | // ptrtoint <vscale x 4 x ptr> to <vscale x 4 x i64> |
134 | EXPECT_EQ(Constant::getNullValue(Int64ScalableVecTy), |
135 | ConstantExpr::getPointerCast( |
136 | Constant::getNullValue(PtrScalableVecTy), Int64ScalableVecTy)); |
137 | |
138 | // bitcast <4 x ptr> to <4 x ptr> |
139 | EXPECT_EQ( |
140 | Constant::getNullValue(PtrVecTy), |
141 | ConstantExpr::getPointerCast(Constant::getNullValue(PtrVecTy), PtrVecTy)); |
142 | |
143 | // bitcast <vscale x 4 x ptr> to <vscale x 4 x ptr> |
144 | EXPECT_EQ(Constant::getNullValue(PtrScalableVecTy), |
145 | ConstantExpr::getPointerCast( |
146 | Constant::getNullValue(PtrScalableVecTy), PtrScalableVecTy)); |
147 | |
148 | Type *Ptr1Ty = PointerType::get(C, AddressSpace: 1); |
149 | ConstantInt *K = ConstantInt::get(Ty: Type::getInt64Ty(C), V: 1234); |
150 | |
151 | // Make sure that addrspacecast of inttoptr is not folded away. |
152 | EXPECT_NE(K, ConstantExpr::getAddrSpaceCast( |
153 | ConstantExpr::getIntToPtr(K, PtrTy), Ptr1Ty)); |
154 | EXPECT_NE(K, ConstantExpr::getAddrSpaceCast( |
155 | ConstantExpr::getIntToPtr(K, Ptr1Ty), PtrTy)); |
156 | |
157 | Constant *NullPtr0 = Constant::getNullValue(Ty: PtrTy); |
158 | Constant *NullPtr1 = Constant::getNullValue(Ty: Ptr1Ty); |
159 | |
160 | // Make sure that addrspacecast of null is not folded away. |
161 | EXPECT_NE(Constant::getNullValue(PtrTy), |
162 | ConstantExpr::getAddrSpaceCast(NullPtr0, Ptr1Ty)); |
163 | |
164 | EXPECT_NE(Constant::getNullValue(Ptr1Ty), |
165 | ConstantExpr::getAddrSpaceCast(NullPtr1, PtrTy)); |
166 | } |
167 | |
168 | #define CHECK(x, y) \ |
169 | { \ |
170 | std::string __s; \ |
171 | raw_string_ostream __o(__s); \ |
172 | Instruction *__I = cast<ConstantExpr>(x)->getAsInstruction(); \ |
173 | __I->print(__o); \ |
174 | __I->deleteValue(); \ |
175 | __o.flush(); \ |
176 | EXPECT_EQ(std::string(" <badref> = " y), __s); \ |
177 | } |
178 | |
179 | TEST(ConstantsTest, AsInstructionsTest) { |
180 | LLVMContext Context; |
181 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
182 | |
183 | Type *Int64Ty = Type::getInt64Ty(C&: Context); |
184 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
185 | Type *Int16Ty = Type::getInt16Ty(C&: Context); |
186 | |
187 | Constant *Global = |
188 | M->getOrInsertGlobal(Name: "dummy" , Ty: PointerType::getUnqual(ElementType: Int32Ty)); |
189 | Constant *Global2 = |
190 | M->getOrInsertGlobal(Name: "dummy2" , Ty: PointerType::getUnqual(ElementType: Int32Ty)); |
191 | |
192 | Constant *P0 = ConstantExpr::getPtrToInt(C: Global, Ty: Int32Ty); |
193 | Constant *P4 = ConstantExpr::getPtrToInt(C: Global2, Ty: Int32Ty); |
194 | Constant *P6 = ConstantExpr::getBitCast(C: P4, Ty: FixedVectorType::get(ElementType: Int16Ty, NumElts: 2)); |
195 | |
196 | Constant *One = ConstantInt::get(Ty: Int32Ty, V: 1); |
197 | Constant *Two = ConstantInt::get(Ty: Int64Ty, V: 2); |
198 | Constant *Big = ConstantInt::get(Context, V: APInt{256, uint64_t(-1), true}); |
199 | Constant *Elt = ConstantInt::get(Ty: Int16Ty, V: 2015); |
200 | Constant *Poison16 = PoisonValue::get(T: Int16Ty); |
201 | Constant *Undef64 = UndefValue::get(T: Int64Ty); |
202 | Constant *PoisonV16 = PoisonValue::get(T: P6->getType()); |
203 | |
204 | #define P0STR "ptrtoint (ptr @dummy to i32)" |
205 | #define P3STR "ptrtoint (ptr @dummy to i1)" |
206 | #define P4STR "ptrtoint (ptr @dummy2 to i32)" |
207 | #define P6STR "bitcast (i32 ptrtoint (ptr @dummy2 to i32) to <2 x i16>)" |
208 | |
209 | CHECK(ConstantExpr::getNeg(P0), "sub i32 0, " P0STR); |
210 | CHECK(ConstantExpr::getNot(P0), "xor i32 " P0STR ", -1" ); |
211 | CHECK(ConstantExpr::getAdd(P0, P0), "add i32 " P0STR ", " P0STR); |
212 | CHECK(ConstantExpr::getAdd(P0, P0, false, true), |
213 | "add nsw i32 " P0STR ", " P0STR); |
214 | CHECK(ConstantExpr::getAdd(P0, P0, true, true), |
215 | "add nuw nsw i32 " P0STR ", " P0STR); |
216 | CHECK(ConstantExpr::getSub(P0, P0), "sub i32 " P0STR ", " P0STR); |
217 | CHECK(ConstantExpr::getMul(P0, P0), "mul i32 " P0STR ", " P0STR); |
218 | CHECK(ConstantExpr::getXor(P0, P0), "xor i32 " P0STR ", " P0STR); |
219 | CHECK(ConstantExpr::getShl(P0, P0), "shl i32 " P0STR ", " P0STR); |
220 | CHECK(ConstantExpr::getShl(P0, P0, true), "shl nuw i32 " P0STR ", " P0STR); |
221 | CHECK(ConstantExpr::getShl(P0, P0, false, true), |
222 | "shl nsw i32 " P0STR ", " P0STR); |
223 | |
224 | CHECK(ConstantExpr::getICmp(CmpInst::ICMP_EQ, P0, P4), |
225 | "icmp eq i32 " P0STR ", " P4STR); |
226 | |
227 | std::vector<Constant *> V; |
228 | V.push_back(x: One); |
229 | // FIXME: getGetElementPtr() actually creates an inbounds ConstantGEP, |
230 | // not a normal one! |
231 | // CHECK(ConstantExpr::getGetElementPtr(Global, V, false), |
232 | // "getelementptr i32*, i32** @dummy, i32 1"); |
233 | CHECK(ConstantExpr::getInBoundsGetElementPtr(PointerType::getUnqual(Int32Ty), |
234 | Global, V), |
235 | "getelementptr inbounds ptr, ptr @dummy, i32 1" ); |
236 | |
237 | CHECK(ConstantExpr::getExtractElement(P6, One), |
238 | "extractelement <2 x i16> " P6STR ", i32 1" ); |
239 | |
240 | EXPECT_EQ(Poison16, ConstantExpr::getExtractElement(P6, Two)); |
241 | EXPECT_EQ(Poison16, ConstantExpr::getExtractElement(P6, Big)); |
242 | EXPECT_EQ(Poison16, ConstantExpr::getExtractElement(P6, Undef64)); |
243 | |
244 | EXPECT_EQ(Elt, ConstantExpr::getExtractElement( |
245 | ConstantExpr::getInsertElement(P6, Elt, One), One)); |
246 | EXPECT_EQ(PoisonV16, ConstantExpr::getInsertElement(P6, Elt, Two)); |
247 | EXPECT_EQ(PoisonV16, ConstantExpr::getInsertElement(P6, Elt, Big)); |
248 | EXPECT_EQ(PoisonV16, ConstantExpr::getInsertElement(P6, Elt, Undef64)); |
249 | } |
250 | |
251 | #ifdef GTEST_HAS_DEATH_TEST |
252 | #ifndef NDEBUG |
253 | TEST(ConstantsTest, ReplaceWithConstantTest) { |
254 | LLVMContext Context; |
255 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
256 | |
257 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
258 | Constant *One = ConstantInt::get(Ty: Int32Ty, V: 1); |
259 | |
260 | Constant *Global = |
261 | M->getOrInsertGlobal(Name: "dummy" , Ty: PointerType::getUnqual(ElementType: Int32Ty)); |
262 | Constant *GEP = ConstantExpr::getGetElementPtr( |
263 | Ty: PointerType::getUnqual(ElementType: Int32Ty), C: Global, Idx: One); |
264 | EXPECT_DEATH(Global->replaceAllUsesWith(GEP), |
265 | "this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!" ); |
266 | } |
267 | |
268 | #endif |
269 | #endif |
270 | |
271 | #undef CHECK |
272 | |
273 | TEST(ConstantsTest, ConstantArrayReplaceWithConstant) { |
274 | LLVMContext Context; |
275 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
276 | |
277 | Type *IntTy = Type::getInt8Ty(C&: Context); |
278 | ArrayType *ArrayTy = ArrayType::get(ElementType: IntTy, NumElements: 2); |
279 | Constant *A01Vals[2] = {ConstantInt::get(Ty: IntTy, V: 0), |
280 | ConstantInt::get(Ty: IntTy, V: 1)}; |
281 | Constant *A01 = ConstantArray::get(T: ArrayTy, V: A01Vals); |
282 | |
283 | Constant *Global = new GlobalVariable(*M, IntTy, false, |
284 | GlobalValue::ExternalLinkage, nullptr); |
285 | Constant *GlobalInt = ConstantExpr::getPtrToInt(C: Global, Ty: IntTy); |
286 | Constant *A0GVals[2] = {ConstantInt::get(Ty: IntTy, V: 0), GlobalInt}; |
287 | Constant *A0G = ConstantArray::get(T: ArrayTy, V: A0GVals); |
288 | ASSERT_NE(A01, A0G); |
289 | |
290 | GlobalVariable *RefArray = |
291 | new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G); |
292 | ASSERT_EQ(A0G, RefArray->getInitializer()); |
293 | |
294 | GlobalInt->replaceAllUsesWith(V: ConstantInt::get(Ty: IntTy, V: 1)); |
295 | ASSERT_EQ(A01, RefArray->getInitializer()); |
296 | } |
297 | |
298 | TEST(ConstantsTest, ConstantExprReplaceWithConstant) { |
299 | LLVMContext Context; |
300 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
301 | |
302 | Type *IntTy = Type::getInt8Ty(C&: Context); |
303 | Constant *G1 = new GlobalVariable(*M, IntTy, false, |
304 | GlobalValue::ExternalLinkage, nullptr); |
305 | Constant *G2 = new GlobalVariable(*M, IntTy, false, |
306 | GlobalValue::ExternalLinkage, nullptr); |
307 | ASSERT_NE(G1, G2); |
308 | |
309 | Constant *Int1 = ConstantExpr::getPtrToInt(C: G1, Ty: IntTy); |
310 | Constant *Int2 = ConstantExpr::getPtrToInt(C: G2, Ty: IntTy); |
311 | ASSERT_NE(Int1, Int2); |
312 | |
313 | GlobalVariable *Ref = |
314 | new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1); |
315 | ASSERT_EQ(Int1, Ref->getInitializer()); |
316 | |
317 | G1->replaceAllUsesWith(V: G2); |
318 | ASSERT_EQ(Int2, Ref->getInitializer()); |
319 | } |
320 | |
321 | TEST(ConstantsTest, GEPReplaceWithConstant) { |
322 | LLVMContext Context; |
323 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
324 | |
325 | Type *IntTy = Type::getInt32Ty(C&: Context); |
326 | Type *PtrTy = PointerType::get(ElementType: IntTy, AddressSpace: 0); |
327 | auto *C1 = ConstantInt::get(Ty: IntTy, V: 1); |
328 | auto *Placeholder = new GlobalVariable( |
329 | *M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr); |
330 | auto *GEP = ConstantExpr::getGetElementPtr(Ty: IntTy, C: Placeholder, Idx: C1); |
331 | ASSERT_EQ(GEP->getOperand(0), Placeholder); |
332 | |
333 | auto *Ref = |
334 | new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP); |
335 | ASSERT_EQ(GEP, Ref->getInitializer()); |
336 | |
337 | auto *Global = new GlobalVariable(*M, IntTy, false, |
338 | GlobalValue::ExternalLinkage, nullptr); |
339 | auto *Alias = GlobalAlias::create(Ty: IntTy, AddressSpace: 0, Linkage: GlobalValue::ExternalLinkage, |
340 | Name: "alias" , Aliasee: Global, Parent: M.get()); |
341 | Placeholder->replaceAllUsesWith(V: Alias); |
342 | ASSERT_EQ(GEP, Ref->getInitializer()); |
343 | ASSERT_EQ(GEP->getOperand(0), Alias); |
344 | } |
345 | |
346 | TEST(ConstantsTest, AliasCAPI) { |
347 | LLVMContext Context; |
348 | SMDiagnostic Error; |
349 | std::unique_ptr<Module> M = |
350 | parseAssemblyString(AsmString: "@g = global i32 42" , Err&: Error, Context); |
351 | GlobalVariable *G = M->getGlobalVariable(Name: "g" ); |
352 | Type *I16Ty = Type::getInt16Ty(C&: Context); |
353 | Type *I16PTy = PointerType::get(ElementType: I16Ty, AddressSpace: 0); |
354 | Constant *Aliasee = ConstantExpr::getBitCast(C: G, Ty: I16PTy); |
355 | LLVMValueRef AliasRef = |
356 | LLVMAddAlias2(M: wrap(P: M.get()), ValueTy: wrap(P: I16Ty), AddrSpace: 0, Aliasee: wrap(P: Aliasee), Name: "a" ); |
357 | ASSERT_EQ(unwrap<GlobalAlias>(AliasRef)->getAliasee(), Aliasee); |
358 | } |
359 | |
360 | static std::string getNameOfType(Type *T) { |
361 | std::string S; |
362 | raw_string_ostream RSOS(S); |
363 | T->print(O&: RSOS); |
364 | return S; |
365 | } |
366 | |
367 | TEST(ConstantsTest, BuildConstantDataArrays) { |
368 | LLVMContext Context; |
369 | |
370 | for (Type *T : {Type::getInt8Ty(C&: Context), Type::getInt16Ty(C&: Context), |
371 | Type::getInt32Ty(C&: Context), Type::getInt64Ty(C&: Context)}) { |
372 | ArrayType *ArrayTy = ArrayType::get(ElementType: T, NumElements: 2); |
373 | Constant *Vals[] = {ConstantInt::get(Ty: T, V: 0), ConstantInt::get(Ty: T, V: 1)}; |
374 | Constant *CA = ConstantArray::get(T: ArrayTy, V: Vals); |
375 | ASSERT_TRUE(isa<ConstantDataArray>(CA)) << " T = " << getNameOfType(T); |
376 | auto *CDA = cast<ConstantDataArray>(Val: CA); |
377 | Constant *CA2 = ConstantDataArray::getRaw( |
378 | Data: CDA->getRawDataValues(), NumElements: CDA->getNumElements(), ElementTy: CDA->getElementType()); |
379 | ASSERT_TRUE(CA == CA2) << " T = " << getNameOfType(T); |
380 | } |
381 | |
382 | for (Type *T : {Type::getHalfTy(C&: Context), Type::getBFloatTy(C&: Context), |
383 | Type::getFloatTy(C&: Context), Type::getDoubleTy(C&: Context)}) { |
384 | ArrayType *ArrayTy = ArrayType::get(ElementType: T, NumElements: 2); |
385 | Constant *Vals[] = {ConstantFP::get(Ty: T, V: 0), ConstantFP::get(Ty: T, V: 1)}; |
386 | Constant *CA = ConstantArray::get(T: ArrayTy, V: Vals); |
387 | ASSERT_TRUE(isa<ConstantDataArray>(CA)) << " T = " << getNameOfType(T); |
388 | auto *CDA = cast<ConstantDataArray>(Val: CA); |
389 | Constant *CA2 = ConstantDataArray::getRaw( |
390 | Data: CDA->getRawDataValues(), NumElements: CDA->getNumElements(), ElementTy: CDA->getElementType()); |
391 | ASSERT_TRUE(CA == CA2) << " T = " << getNameOfType(T); |
392 | } |
393 | } |
394 | |
395 | TEST(ConstantsTest, BuildConstantDataVectors) { |
396 | LLVMContext Context; |
397 | |
398 | for (Type *T : {Type::getInt8Ty(C&: Context), Type::getInt16Ty(C&: Context), |
399 | Type::getInt32Ty(C&: Context), Type::getInt64Ty(C&: Context)}) { |
400 | Constant *Vals[] = {ConstantInt::get(Ty: T, V: 0), ConstantInt::get(Ty: T, V: 1)}; |
401 | Constant *CV = ConstantVector::get(V: Vals); |
402 | ASSERT_TRUE(isa<ConstantDataVector>(CV)) << " T = " << getNameOfType(T); |
403 | auto *CDV = cast<ConstantDataVector>(Val: CV); |
404 | Constant *CV2 = ConstantDataVector::getRaw( |
405 | Data: CDV->getRawDataValues(), NumElements: CDV->getNumElements(), ElementTy: CDV->getElementType()); |
406 | ASSERT_TRUE(CV == CV2) << " T = " << getNameOfType(T); |
407 | } |
408 | |
409 | for (Type *T : {Type::getHalfTy(C&: Context), Type::getBFloatTy(C&: Context), |
410 | Type::getFloatTy(C&: Context), Type::getDoubleTy(C&: Context)}) { |
411 | Constant *Vals[] = {ConstantFP::get(Ty: T, V: 0), ConstantFP::get(Ty: T, V: 1)}; |
412 | Constant *CV = ConstantVector::get(V: Vals); |
413 | ASSERT_TRUE(isa<ConstantDataVector>(CV)) << " T = " << getNameOfType(T); |
414 | auto *CDV = cast<ConstantDataVector>(Val: CV); |
415 | Constant *CV2 = ConstantDataVector::getRaw( |
416 | Data: CDV->getRawDataValues(), NumElements: CDV->getNumElements(), ElementTy: CDV->getElementType()); |
417 | ASSERT_TRUE(CV == CV2) << " T = " << getNameOfType(T); |
418 | } |
419 | } |
420 | |
421 | TEST(ConstantsTest, BitcastToGEP) { |
422 | LLVMContext Context; |
423 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
424 | |
425 | auto *i32 = Type::getInt32Ty(C&: Context); |
426 | auto *U = StructType::create(Context, Name: "Unsized" ); |
427 | Type *EltTys[] = {i32, U}; |
428 | auto *S = StructType::create(Elements: EltTys); |
429 | |
430 | auto *G = |
431 | new GlobalVariable(*M, S, false, GlobalValue::ExternalLinkage, nullptr); |
432 | auto *PtrTy = PointerType::get(ElementType: i32, AddressSpace: 0); |
433 | auto *C = ConstantExpr::getBitCast(C: G, Ty: PtrTy); |
434 | /* With opaque pointers, no cast is necessary. */ |
435 | EXPECT_EQ(C, G); |
436 | } |
437 | |
438 | bool foldFuncPtrAndConstToNull(LLVMContext &Context, Module *TheModule, |
439 | uint64_t AndValue, |
440 | MaybeAlign FunctionAlign = std::nullopt) { |
441 | Type *VoidType(Type::getVoidTy(C&: Context)); |
442 | FunctionType *FuncType(FunctionType::get(Result: VoidType, isVarArg: false)); |
443 | Function *Func( |
444 | Function::Create(Ty: FuncType, Linkage: GlobalValue::ExternalLinkage, N: "" , M: TheModule)); |
445 | |
446 | if (FunctionAlign) |
447 | Func->setAlignment(*FunctionAlign); |
448 | |
449 | IntegerType *ConstantIntType(Type::getInt32Ty(C&: Context)); |
450 | ConstantInt *TheConstant(ConstantInt::get(Ty: ConstantIntType, V: AndValue)); |
451 | |
452 | Constant *TheConstantExpr(ConstantExpr::getPtrToInt(C: Func, Ty: ConstantIntType)); |
453 | |
454 | Constant *C = ConstantFoldBinaryInstruction(Opcode: Instruction::And, V1: TheConstantExpr, |
455 | V2: TheConstant); |
456 | bool Result = C && C->isNullValue(); |
457 | |
458 | if (!TheModule) { |
459 | // If the Module exists then it will delete the Function. |
460 | delete Func; |
461 | } |
462 | |
463 | return Result; |
464 | } |
465 | |
466 | TEST(ConstantsTest, FoldFunctionPtrAlignUnknownAnd2) { |
467 | LLVMContext Context; |
468 | Module TheModule("TestModule" , Context); |
469 | // When the DataLayout doesn't specify a function pointer alignment we |
470 | // assume in this case that it is 4 byte aligned. This is a bug but we can't |
471 | // fix it directly because it causes a code size regression on X86. |
472 | // FIXME: This test should be changed once existing targets have |
473 | // appropriate defaults. See associated FIXME in ConstantFoldBinaryInstruction |
474 | ASSERT_TRUE(foldFuncPtrAndConstToNull(Context, &TheModule, 2)); |
475 | } |
476 | |
477 | TEST(ConstantsTest, DontFoldFunctionPtrAlignUnknownAnd4) { |
478 | LLVMContext Context; |
479 | Module TheModule("TestModule" , Context); |
480 | ASSERT_FALSE(foldFuncPtrAndConstToNull(Context, &TheModule, 4)); |
481 | } |
482 | |
483 | TEST(ConstantsTest, FoldFunctionPtrAlign4) { |
484 | LLVMContext Context; |
485 | Module TheModule("TestModule" , Context); |
486 | const char *AlignmentStrings[] = {"Fi32" , "Fn32" }; |
487 | |
488 | for (unsigned AndValue = 1; AndValue <= 2; ++AndValue) { |
489 | for (const char *AlignmentString : AlignmentStrings) { |
490 | TheModule.setDataLayout(AlignmentString); |
491 | ASSERT_TRUE(foldFuncPtrAndConstToNull(Context, &TheModule, AndValue)); |
492 | } |
493 | } |
494 | } |
495 | |
496 | TEST(ConstantsTest, DontFoldFunctionPtrAlign1) { |
497 | LLVMContext Context; |
498 | Module TheModule("TestModule" , Context); |
499 | const char *AlignmentStrings[] = {"Fi8" , "Fn8" }; |
500 | |
501 | for (const char *AlignmentString : AlignmentStrings) { |
502 | TheModule.setDataLayout(AlignmentString); |
503 | ASSERT_FALSE(foldFuncPtrAndConstToNull(Context, &TheModule, 2)); |
504 | } |
505 | } |
506 | |
507 | TEST(ConstantsTest, FoldFunctionAlign4PtrAlignMultiple) { |
508 | LLVMContext Context; |
509 | Module TheModule("TestModule" , Context); |
510 | TheModule.setDataLayout("Fn8" ); |
511 | ASSERT_TRUE(foldFuncPtrAndConstToNull(Context, &TheModule, 2, Align(4))); |
512 | } |
513 | |
514 | TEST(ConstantsTest, DontFoldFunctionAlign4PtrAlignIndependent) { |
515 | LLVMContext Context; |
516 | Module TheModule("TestModule" , Context); |
517 | TheModule.setDataLayout("Fi8" ); |
518 | ASSERT_FALSE(foldFuncPtrAndConstToNull(Context, &TheModule, 2, Align(4))); |
519 | } |
520 | |
521 | TEST(ConstantsTest, DontFoldFunctionPtrIfNoModule) { |
522 | LLVMContext Context; |
523 | // Even though the function is explicitly 4 byte aligned, in the absence of a |
524 | // DataLayout we can't assume that the function pointer is aligned. |
525 | ASSERT_FALSE(foldFuncPtrAndConstToNull(Context, nullptr, 2, Align(4))); |
526 | } |
527 | |
528 | TEST(ConstantsTest, FoldGlobalVariablePtr) { |
529 | LLVMContext Context; |
530 | |
531 | IntegerType *IntType(Type::getInt32Ty(C&: Context)); |
532 | |
533 | std::unique_ptr<GlobalVariable> Global( |
534 | new GlobalVariable(IntType, true, GlobalValue::ExternalLinkage)); |
535 | |
536 | Global->setAlignment(Align(4)); |
537 | |
538 | ConstantInt *TheConstant(ConstantInt::get(Ty: IntType, V: 2)); |
539 | |
540 | Constant *TheConstantExpr(ConstantExpr::getPtrToInt(C: Global.get(), Ty: IntType)); |
541 | |
542 | ASSERT_TRUE(ConstantFoldBinaryInstruction(Instruction::And, TheConstantExpr, |
543 | TheConstant) |
544 | ->isNullValue()); |
545 | } |
546 | |
547 | // Check that containsUndefOrPoisonElement and containsPoisonElement is working |
548 | // great |
549 | |
550 | TEST(ConstantsTest, containsUndefElemTest) { |
551 | LLVMContext Context; |
552 | |
553 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
554 | Constant *CU = UndefValue::get(T: Int32Ty); |
555 | Constant *CP = PoisonValue::get(T: Int32Ty); |
556 | Constant *C1 = ConstantInt::get(Ty: Int32Ty, V: 1); |
557 | Constant *C2 = ConstantInt::get(Ty: Int32Ty, V: 2); |
558 | |
559 | { |
560 | Constant *V1 = ConstantVector::get(V: {C1, C2}); |
561 | EXPECT_FALSE(V1->containsUndefOrPoisonElement()); |
562 | EXPECT_FALSE(V1->containsPoisonElement()); |
563 | } |
564 | |
565 | { |
566 | Constant *V2 = ConstantVector::get(V: {C1, CU}); |
567 | EXPECT_TRUE(V2->containsUndefOrPoisonElement()); |
568 | EXPECT_FALSE(V2->containsPoisonElement()); |
569 | } |
570 | |
571 | { |
572 | Constant *V3 = ConstantVector::get(V: {C1, CP}); |
573 | EXPECT_TRUE(V3->containsUndefOrPoisonElement()); |
574 | EXPECT_TRUE(V3->containsPoisonElement()); |
575 | } |
576 | |
577 | { |
578 | Constant *V4 = ConstantVector::get(V: {CU, CP}); |
579 | EXPECT_TRUE(V4->containsUndefOrPoisonElement()); |
580 | EXPECT_TRUE(V4->containsPoisonElement()); |
581 | } |
582 | } |
583 | |
584 | // Check that poison elements in vector constants are matched |
585 | // correctly for both integer and floating-point types. Just don't |
586 | // crash on vectors of pointers (could be handled?). |
587 | |
588 | TEST(ConstantsTest, isElementWiseEqual) { |
589 | LLVMContext Context; |
590 | |
591 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
592 | Constant *CU = UndefValue::get(T: Int32Ty); |
593 | Constant *CP = PoisonValue::get(T: Int32Ty); |
594 | Constant *C1 = ConstantInt::get(Ty: Int32Ty, V: 1); |
595 | Constant *C2 = ConstantInt::get(Ty: Int32Ty, V: 2); |
596 | |
597 | Constant *C1211 = ConstantVector::get(V: {C1, C2, C1, C1}); |
598 | Constant *C12U1 = ConstantVector::get(V: {C1, C2, CU, C1}); |
599 | Constant *C12U2 = ConstantVector::get(V: {C1, C2, CU, C2}); |
600 | Constant *C12U21 = ConstantVector::get(V: {C1, C2, CU, C2, C1}); |
601 | Constant *C12P1 = ConstantVector::get(V: {C1, C2, CP, C1}); |
602 | Constant *C12P2 = ConstantVector::get(V: {C1, C2, CP, C2}); |
603 | Constant *C12P21 = ConstantVector::get(V: {C1, C2, CP, C2, C1}); |
604 | |
605 | EXPECT_FALSE(C1211->isElementWiseEqual(C12U1)); |
606 | EXPECT_FALSE(C12U1->isElementWiseEqual(C1211)); |
607 | EXPECT_FALSE(C12U2->isElementWiseEqual(C12U1)); |
608 | EXPECT_FALSE(C12U1->isElementWiseEqual(C12U2)); |
609 | EXPECT_FALSE(C12U21->isElementWiseEqual(C12U2)); |
610 | |
611 | EXPECT_TRUE(C1211->isElementWiseEqual(C12P1)); |
612 | EXPECT_TRUE(C12P1->isElementWiseEqual(C1211)); |
613 | EXPECT_FALSE(C12P2->isElementWiseEqual(C12P1)); |
614 | EXPECT_FALSE(C12P1->isElementWiseEqual(C12P2)); |
615 | EXPECT_FALSE(C12P21->isElementWiseEqual(C12P2)); |
616 | |
617 | Type *FltTy = Type::getFloatTy(C&: Context); |
618 | Constant *CFU = UndefValue::get(T: FltTy); |
619 | Constant *CFP = PoisonValue::get(T: FltTy); |
620 | Constant *CF1 = ConstantFP::get(Ty: FltTy, V: 1.0); |
621 | Constant *CF2 = ConstantFP::get(Ty: FltTy, V: 2.0); |
622 | |
623 | Constant *CF1211 = ConstantVector::get(V: {CF1, CF2, CF1, CF1}); |
624 | Constant *CF12U1 = ConstantVector::get(V: {CF1, CF2, CFU, CF1}); |
625 | Constant *CF12U2 = ConstantVector::get(V: {CF1, CF2, CFU, CF2}); |
626 | Constant *CFUU1U = ConstantVector::get(V: {CFU, CFU, CF1, CFU}); |
627 | Constant *CF12P1 = ConstantVector::get(V: {CF1, CF2, CFP, CF1}); |
628 | Constant *CF12P2 = ConstantVector::get(V: {CF1, CF2, CFP, CF2}); |
629 | Constant *CFPP1P = ConstantVector::get(V: {CFP, CFP, CF1, CFP}); |
630 | |
631 | EXPECT_FALSE(CF1211->isElementWiseEqual(CF12U1)); |
632 | EXPECT_FALSE(CF12U1->isElementWiseEqual(CF1211)); |
633 | EXPECT_FALSE(CFUU1U->isElementWiseEqual(CF12U1)); |
634 | EXPECT_FALSE(CF12U2->isElementWiseEqual(CF12U1)); |
635 | EXPECT_FALSE(CF12U1->isElementWiseEqual(CF12U2)); |
636 | |
637 | EXPECT_TRUE(CF1211->isElementWiseEqual(CF12P1)); |
638 | EXPECT_TRUE(CF12P1->isElementWiseEqual(CF1211)); |
639 | EXPECT_TRUE(CFPP1P->isElementWiseEqual(CF12P1)); |
640 | EXPECT_FALSE(CF12P2->isElementWiseEqual(CF12P1)); |
641 | EXPECT_FALSE(CF12P1->isElementWiseEqual(CF12P2)); |
642 | |
643 | PointerType *PtrTy = PointerType::get(C&: Context, AddressSpace: 0); |
644 | Constant *CPU = UndefValue::get(T: PtrTy); |
645 | Constant *CPP = PoisonValue::get(T: PtrTy); |
646 | Constant *CP0 = ConstantPointerNull::get(T: PtrTy); |
647 | |
648 | Constant *CP0000 = ConstantVector::get(V: {CP0, CP0, CP0, CP0}); |
649 | Constant *CP00U0 = ConstantVector::get(V: {CP0, CP0, CPU, CP0}); |
650 | Constant *CP00U = ConstantVector::get(V: {CP0, CP0, CPU}); |
651 | Constant *CP00P0 = ConstantVector::get(V: {CP0, CP0, CPP, CP0}); |
652 | Constant *CP00P = ConstantVector::get(V: {CP0, CP0, CPP}); |
653 | |
654 | EXPECT_FALSE(CP0000->isElementWiseEqual(CP00U0)); |
655 | EXPECT_FALSE(CP00U0->isElementWiseEqual(CP0000)); |
656 | EXPECT_FALSE(CP0000->isElementWiseEqual(CP00U)); |
657 | EXPECT_FALSE(CP00U->isElementWiseEqual(CP00U0)); |
658 | EXPECT_FALSE(CP0000->isElementWiseEqual(CP00P0)); |
659 | EXPECT_FALSE(CP00P0->isElementWiseEqual(CP0000)); |
660 | EXPECT_FALSE(CP0000->isElementWiseEqual(CP00P)); |
661 | EXPECT_FALSE(CP00P->isElementWiseEqual(CP00P0)); |
662 | } |
663 | |
664 | // Check that vector/aggregate constants correctly store undef and poison |
665 | // elements. |
666 | |
667 | TEST(ConstantsTest, CheckElementWiseUndefPoison) { |
668 | LLVMContext Context; |
669 | |
670 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
671 | StructType *STy = StructType::get(elt1: Int32Ty, elts: Int32Ty); |
672 | ArrayType *ATy = ArrayType::get(ElementType: Int32Ty, NumElements: 2); |
673 | Constant *CU = UndefValue::get(T: Int32Ty); |
674 | Constant *CP = PoisonValue::get(T: Int32Ty); |
675 | |
676 | { |
677 | Constant *CUU = ConstantVector::get(V: {CU, CU}); |
678 | Constant *CPP = ConstantVector::get(V: {CP, CP}); |
679 | Constant *CUP = ConstantVector::get(V: {CU, CP}); |
680 | Constant *CPU = ConstantVector::get(V: {CP, CU}); |
681 | EXPECT_EQ(CUU, UndefValue::get(CUU->getType())); |
682 | EXPECT_EQ(CPP, PoisonValue::get(CPP->getType())); |
683 | EXPECT_NE(CUP, UndefValue::get(CUP->getType())); |
684 | EXPECT_NE(CPU, UndefValue::get(CPU->getType())); |
685 | } |
686 | |
687 | { |
688 | Constant *CUU = ConstantStruct::get(T: STy, V: {CU, CU}); |
689 | Constant *CPP = ConstantStruct::get(T: STy, V: {CP, CP}); |
690 | Constant *CUP = ConstantStruct::get(T: STy, V: {CU, CP}); |
691 | Constant *CPU = ConstantStruct::get(T: STy, V: {CP, CU}); |
692 | EXPECT_EQ(CUU, UndefValue::get(CUU->getType())); |
693 | EXPECT_EQ(CPP, PoisonValue::get(CPP->getType())); |
694 | EXPECT_NE(CUP, UndefValue::get(CUP->getType())); |
695 | EXPECT_NE(CPU, UndefValue::get(CPU->getType())); |
696 | } |
697 | |
698 | { |
699 | Constant *CUU = ConstantArray::get(T: ATy, V: {CU, CU}); |
700 | Constant *CPP = ConstantArray::get(T: ATy, V: {CP, CP}); |
701 | Constant *CUP = ConstantArray::get(T: ATy, V: {CU, CP}); |
702 | Constant *CPU = ConstantArray::get(T: ATy, V: {CP, CU}); |
703 | EXPECT_EQ(CUU, UndefValue::get(CUU->getType())); |
704 | EXPECT_EQ(CPP, PoisonValue::get(CPP->getType())); |
705 | EXPECT_NE(CUP, UndefValue::get(CUP->getType())); |
706 | EXPECT_NE(CPU, UndefValue::get(CPU->getType())); |
707 | } |
708 | } |
709 | |
710 | TEST(ConstantsTest, GetSplatValueRoundTrip) { |
711 | LLVMContext Context; |
712 | |
713 | Type *FloatTy = Type::getFloatTy(C&: Context); |
714 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
715 | Type *Int8Ty = Type::getInt8Ty(C&: Context); |
716 | |
717 | for (unsigned Min : {1, 2, 8}) { |
718 | auto ScalableEC = ElementCount::getScalable(MinVal: Min); |
719 | auto FixedEC = ElementCount::getFixed(MinVal: Min); |
720 | |
721 | for (auto EC : {ScalableEC, FixedEC}) { |
722 | for (auto *Ty : {FloatTy, Int32Ty, Int8Ty}) { |
723 | Constant *Zero = Constant::getNullValue(Ty); |
724 | Constant *One = Constant::getAllOnesValue(Ty); |
725 | |
726 | for (auto *C : {Zero, One}) { |
727 | Constant *Splat = ConstantVector::getSplat(EC, Elt: C); |
728 | ASSERT_NE(nullptr, Splat); |
729 | |
730 | Constant *SplatVal = Splat->getSplatValue(); |
731 | EXPECT_NE(nullptr, SplatVal); |
732 | EXPECT_EQ(SplatVal, C); |
733 | } |
734 | } |
735 | } |
736 | } |
737 | } |
738 | |
739 | TEST(ConstantsTest, ComdatUserTracking) { |
740 | LLVMContext Context; |
741 | Module M("MyModule" , Context); |
742 | |
743 | Comdat *C = M.getOrInsertComdat(Name: "comdat" ); |
744 | const SmallPtrSetImpl<GlobalObject *> &Users = C->getUsers(); |
745 | EXPECT_TRUE(Users.size() == 0); |
746 | |
747 | Type *Ty = Type::getInt8Ty(C&: Context); |
748 | GlobalVariable *GV1 = cast<GlobalVariable>(Val: M.getOrInsertGlobal(Name: "gv1" , Ty)); |
749 | GV1->setComdat(C); |
750 | EXPECT_TRUE(Users.size() == 1); |
751 | EXPECT_TRUE(Users.contains(GV1)); |
752 | |
753 | GlobalVariable *GV2 = cast<GlobalVariable>(Val: M.getOrInsertGlobal(Name: "gv2" , Ty)); |
754 | GV2->setComdat(C); |
755 | EXPECT_TRUE(Users.size() == 2); |
756 | EXPECT_TRUE(Users.contains(GV2)); |
757 | |
758 | GV1->eraseFromParent(); |
759 | EXPECT_TRUE(Users.size() == 1); |
760 | EXPECT_TRUE(Users.contains(GV2)); |
761 | |
762 | GV2->eraseFromParent(); |
763 | EXPECT_TRUE(Users.size() == 0); |
764 | } |
765 | |
766 | // Verify that the C API getters for BlockAddress work |
767 | TEST(ConstantsTest, BlockAddressCAPITest) { |
768 | const char *BlockAddressIR = R"( |
769 | define void @test_block_address_func() { |
770 | entry: |
771 | br label %block_bb_0 |
772 | block_bb_0: |
773 | ret void |
774 | } |
775 | )" ; |
776 | |
777 | LLVMContext Context; |
778 | SMDiagnostic Error; |
779 | std::unique_ptr<Module> M = |
780 | parseAssemblyString(AsmString: BlockAddressIR, Err&: Error, Context); |
781 | |
782 | EXPECT_TRUE(M.get() != nullptr); |
783 | |
784 | // Get the function |
785 | auto *Func = M->getFunction(Name: "test_block_address_func" ); |
786 | EXPECT_TRUE(Func != nullptr); |
787 | |
788 | // Get the second basic block, since we can't use the entry one |
789 | const BasicBlock &BB = *(++Func->begin()); |
790 | EXPECT_EQ(BB.getName(), "block_bb_0" ); |
791 | |
792 | // Construct the C API values |
793 | LLVMValueRef BlockAddr = LLVMBlockAddress(F: wrap(P: Func), BB: wrap(P: &BB)); |
794 | EXPECT_TRUE(LLVMIsABlockAddress(BlockAddr)); |
795 | |
796 | // Get the Function/BasicBlock values back out |
797 | auto *OutFunc = unwrap(P: LLVMGetBlockAddressFunction(BlockAddr)); |
798 | auto *OutBB = unwrap(P: LLVMGetBlockAddressBasicBlock(BlockAddr)); |
799 | |
800 | // Verify that they round-tripped properly |
801 | EXPECT_EQ(Func, OutFunc); |
802 | EXPECT_EQ(&BB, OutBB); |
803 | } |
804 | |
805 | } // end anonymous namespace |
806 | } // end namespace llvm |
807 | |