1 | //===- llvm/unittest/IR/InstructionsTest.cpp - Instructions 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/Instructions.h" |
10 | #include "llvm/ADT/CombinationGenerator.h" |
11 | #include "llvm/ADT/STLExtras.h" |
12 | #include "llvm/Analysis/ValueTracking.h" |
13 | #include "llvm/Analysis/VectorUtils.h" |
14 | #include "llvm/AsmParser/Parser.h" |
15 | #include "llvm/IR/BasicBlock.h" |
16 | #include "llvm/IR/Constants.h" |
17 | #include "llvm/IR/DataLayout.h" |
18 | #include "llvm/IR/DebugInfoMetadata.h" |
19 | #include "llvm/IR/DerivedTypes.h" |
20 | #include "llvm/IR/FPEnv.h" |
21 | #include "llvm/IR/Function.h" |
22 | #include "llvm/IR/IRBuilder.h" |
23 | #include "llvm/IR/LLVMContext.h" |
24 | #include "llvm/IR/MDBuilder.h" |
25 | #include "llvm/IR/Module.h" |
26 | #include "llvm/IR/NoFolder.h" |
27 | #include "llvm/IR/Operator.h" |
28 | #include "llvm/Support/SourceMgr.h" |
29 | #include "llvm-c/Core.h" |
30 | #include "gmock/gmock-matchers.h" |
31 | #include "gtest/gtest.h" |
32 | #include <memory> |
33 | |
34 | namespace llvm { |
35 | namespace { |
36 | |
37 | static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { |
38 | SMDiagnostic Err; |
39 | std::unique_ptr<Module> Mod = parseAssemblyString(AsmString: IR, Err, Context&: C); |
40 | if (!Mod) |
41 | Err.print(ProgName: "InstructionsTests" , S&: errs()); |
42 | return Mod; |
43 | } |
44 | |
45 | TEST(InstructionsTest, ReturnInst) { |
46 | LLVMContext C; |
47 | |
48 | // test for PR6589 |
49 | const ReturnInst* r0 = ReturnInst::Create(C); |
50 | EXPECT_EQ(r0->getNumOperands(), 0U); |
51 | EXPECT_EQ(r0->op_begin(), r0->op_end()); |
52 | |
53 | IntegerType* Int1 = IntegerType::get(C, NumBits: 1); |
54 | Constant* One = ConstantInt::get(Ty: Int1, V: 1, IsSigned: true); |
55 | const ReturnInst* r1 = ReturnInst::Create(C, retVal: One); |
56 | EXPECT_EQ(1U, r1->getNumOperands()); |
57 | User::const_op_iterator b(r1->op_begin()); |
58 | EXPECT_NE(r1->op_end(), b); |
59 | EXPECT_EQ(One, *b); |
60 | EXPECT_EQ(One, r1->getOperand(0)); |
61 | ++b; |
62 | EXPECT_EQ(r1->op_end(), b); |
63 | |
64 | // clean up |
65 | delete r0; |
66 | delete r1; |
67 | } |
68 | |
69 | // Test fixture that provides a module and a single function within it. Useful |
70 | // for tests that need to refer to the function in some way. |
71 | class ModuleWithFunctionTest : public testing::Test { |
72 | protected: |
73 | ModuleWithFunctionTest() : M(new Module("MyModule" , Ctx)) { |
74 | FArgTypes.push_back(Elt: Type::getInt8Ty(C&: Ctx)); |
75 | FArgTypes.push_back(Elt: Type::getInt32Ty(C&: Ctx)); |
76 | FArgTypes.push_back(Elt: Type::getInt64Ty(C&: Ctx)); |
77 | FunctionType *FTy = |
78 | FunctionType::get(Result: Type::getVoidTy(C&: Ctx), Params: FArgTypes, isVarArg: false); |
79 | F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "" , M: M.get()); |
80 | } |
81 | |
82 | LLVMContext Ctx; |
83 | std::unique_ptr<Module> M; |
84 | SmallVector<Type *, 3> FArgTypes; |
85 | Function *F; |
86 | }; |
87 | |
88 | TEST_F(ModuleWithFunctionTest, CallInst) { |
89 | Value *Args[] = {ConstantInt::get(Ty: Type::getInt8Ty(C&: Ctx), V: 20), |
90 | ConstantInt::get(Ty: Type::getInt32Ty(C&: Ctx), V: 9999), |
91 | ConstantInt::get(Ty: Type::getInt64Ty(C&: Ctx), V: 42)}; |
92 | std::unique_ptr<CallInst> Call(CallInst::Create(Func: F, Args)); |
93 | |
94 | // Make sure iteration over a call's arguments works as expected. |
95 | unsigned Idx = 0; |
96 | for (Value *Arg : Call->args()) { |
97 | EXPECT_EQ(FArgTypes[Idx], Arg->getType()); |
98 | EXPECT_EQ(Call->getArgOperand(Idx)->getType(), Arg->getType()); |
99 | Idx++; |
100 | } |
101 | |
102 | Call->addRetAttr(Attr: Attribute::get(Context&: Call->getContext(), Kind: "test-str-attr" )); |
103 | EXPECT_TRUE(Call->hasRetAttr("test-str-attr" )); |
104 | EXPECT_FALSE(Call->hasRetAttr("not-on-call" )); |
105 | |
106 | Call->addFnAttr(Attr: Attribute::get(Context&: Call->getContext(), Kind: "test-str-fn-attr" )); |
107 | ASSERT_TRUE(Call->hasFnAttr("test-str-fn-attr" )); |
108 | Call->removeFnAttr(Kind: "test-str-fn-attr" ); |
109 | EXPECT_FALSE(Call->hasFnAttr("test-str-fn-attr" )); |
110 | } |
111 | |
112 | TEST_F(ModuleWithFunctionTest, InvokeInst) { |
113 | BasicBlock *BB1 = BasicBlock::Create(Context&: Ctx, Name: "" , Parent: F); |
114 | BasicBlock *BB2 = BasicBlock::Create(Context&: Ctx, Name: "" , Parent: F); |
115 | |
116 | Value *Args[] = {ConstantInt::get(Ty: Type::getInt8Ty(C&: Ctx), V: 20), |
117 | ConstantInt::get(Ty: Type::getInt32Ty(C&: Ctx), V: 9999), |
118 | ConstantInt::get(Ty: Type::getInt64Ty(C&: Ctx), V: 42)}; |
119 | std::unique_ptr<InvokeInst> Invoke(InvokeInst::Create(Func: F, IfNormal: BB1, IfException: BB2, Args)); |
120 | |
121 | // Make sure iteration over invoke's arguments works as expected. |
122 | unsigned Idx = 0; |
123 | for (Value *Arg : Invoke->args()) { |
124 | EXPECT_EQ(FArgTypes[Idx], Arg->getType()); |
125 | EXPECT_EQ(Invoke->getArgOperand(Idx)->getType(), Arg->getType()); |
126 | Idx++; |
127 | } |
128 | } |
129 | |
130 | TEST(InstructionsTest, BranchInst) { |
131 | LLVMContext C; |
132 | |
133 | // Make a BasicBlocks |
134 | BasicBlock* bb0 = BasicBlock::Create(Context&: C); |
135 | BasicBlock* bb1 = BasicBlock::Create(Context&: C); |
136 | |
137 | // Mandatory BranchInst |
138 | const BranchInst* b0 = BranchInst::Create(IfTrue: bb0); |
139 | |
140 | EXPECT_TRUE(b0->isUnconditional()); |
141 | EXPECT_FALSE(b0->isConditional()); |
142 | EXPECT_EQ(1U, b0->getNumSuccessors()); |
143 | |
144 | // check num operands |
145 | EXPECT_EQ(1U, b0->getNumOperands()); |
146 | |
147 | EXPECT_NE(b0->op_begin(), b0->op_end()); |
148 | EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); |
149 | |
150 | EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); |
151 | |
152 | IntegerType* Int1 = IntegerType::get(C, NumBits: 1); |
153 | Constant* One = ConstantInt::get(Ty: Int1, V: 1, IsSigned: true); |
154 | |
155 | // Conditional BranchInst |
156 | BranchInst* b1 = BranchInst::Create(IfTrue: bb0, IfFalse: bb1, Cond: One); |
157 | |
158 | EXPECT_FALSE(b1->isUnconditional()); |
159 | EXPECT_TRUE(b1->isConditional()); |
160 | EXPECT_EQ(2U, b1->getNumSuccessors()); |
161 | |
162 | // check num operands |
163 | EXPECT_EQ(3U, b1->getNumOperands()); |
164 | |
165 | User::const_op_iterator b(b1->op_begin()); |
166 | |
167 | // check COND |
168 | EXPECT_NE(b, b1->op_end()); |
169 | EXPECT_EQ(One, *b); |
170 | EXPECT_EQ(One, b1->getOperand(0)); |
171 | EXPECT_EQ(One, b1->getCondition()); |
172 | ++b; |
173 | |
174 | // check ELSE |
175 | EXPECT_EQ(bb1, *b); |
176 | EXPECT_EQ(bb1, b1->getOperand(1)); |
177 | EXPECT_EQ(bb1, b1->getSuccessor(1)); |
178 | ++b; |
179 | |
180 | // check THEN |
181 | EXPECT_EQ(bb0, *b); |
182 | EXPECT_EQ(bb0, b1->getOperand(2)); |
183 | EXPECT_EQ(bb0, b1->getSuccessor(0)); |
184 | ++b; |
185 | |
186 | EXPECT_EQ(b1->op_end(), b); |
187 | |
188 | // clean up |
189 | delete b0; |
190 | delete b1; |
191 | |
192 | delete bb0; |
193 | delete bb1; |
194 | } |
195 | |
196 | TEST(InstructionsTest, CastInst) { |
197 | LLVMContext C; |
198 | |
199 | Type *Int8Ty = Type::getInt8Ty(C); |
200 | Type *Int16Ty = Type::getInt16Ty(C); |
201 | Type *Int32Ty = Type::getInt32Ty(C); |
202 | Type *Int64Ty = Type::getInt64Ty(C); |
203 | Type *V8x8Ty = FixedVectorType::get(ElementType: Int8Ty, NumElts: 8); |
204 | Type *V8x64Ty = FixedVectorType::get(ElementType: Int64Ty, NumElts: 8); |
205 | Type *X86MMXTy = Type::getX86_MMXTy(C); |
206 | |
207 | Type *HalfTy = Type::getHalfTy(C); |
208 | Type *FloatTy = Type::getFloatTy(C); |
209 | Type *DoubleTy = Type::getDoubleTy(C); |
210 | |
211 | Type *V2Int32Ty = FixedVectorType::get(ElementType: Int32Ty, NumElts: 2); |
212 | Type *V2Int64Ty = FixedVectorType::get(ElementType: Int64Ty, NumElts: 2); |
213 | Type *V4Int16Ty = FixedVectorType::get(ElementType: Int16Ty, NumElts: 4); |
214 | Type *V1Int16Ty = FixedVectorType::get(ElementType: Int16Ty, NumElts: 1); |
215 | |
216 | Type *VScaleV2Int32Ty = ScalableVectorType::get(ElementType: Int32Ty, MinNumElts: 2); |
217 | Type *VScaleV2Int64Ty = ScalableVectorType::get(ElementType: Int64Ty, MinNumElts: 2); |
218 | Type *VScaleV4Int16Ty = ScalableVectorType::get(ElementType: Int16Ty, MinNumElts: 4); |
219 | Type *VScaleV1Int16Ty = ScalableVectorType::get(ElementType: Int16Ty, MinNumElts: 1); |
220 | |
221 | Type *Int32PtrTy = PointerType::get(ElementType: Int32Ty, AddressSpace: 0); |
222 | Type *Int64PtrTy = PointerType::get(ElementType: Int64Ty, AddressSpace: 0); |
223 | |
224 | Type *Int32PtrAS1Ty = PointerType::get(ElementType: Int32Ty, AddressSpace: 1); |
225 | Type *Int64PtrAS1Ty = PointerType::get(ElementType: Int64Ty, AddressSpace: 1); |
226 | |
227 | Type *V2Int32PtrAS1Ty = FixedVectorType::get(ElementType: Int32PtrAS1Ty, NumElts: 2); |
228 | Type *V2Int64PtrAS1Ty = FixedVectorType::get(ElementType: Int64PtrAS1Ty, NumElts: 2); |
229 | Type *V4Int32PtrAS1Ty = FixedVectorType::get(ElementType: Int32PtrAS1Ty, NumElts: 4); |
230 | Type *VScaleV4Int32PtrAS1Ty = ScalableVectorType::get(ElementType: Int32PtrAS1Ty, MinNumElts: 4); |
231 | Type *V4Int64PtrAS1Ty = FixedVectorType::get(ElementType: Int64PtrAS1Ty, NumElts: 4); |
232 | |
233 | Type *V2Int64PtrTy = FixedVectorType::get(ElementType: Int64PtrTy, NumElts: 2); |
234 | Type *V2Int32PtrTy = FixedVectorType::get(ElementType: Int32PtrTy, NumElts: 2); |
235 | Type *VScaleV2Int32PtrTy = ScalableVectorType::get(ElementType: Int32PtrTy, MinNumElts: 2); |
236 | Type *V4Int32PtrTy = FixedVectorType::get(ElementType: Int32PtrTy, NumElts: 4); |
237 | Type *VScaleV4Int32PtrTy = ScalableVectorType::get(ElementType: Int32PtrTy, MinNumElts: 4); |
238 | Type *VScaleV4Int64PtrTy = ScalableVectorType::get(ElementType: Int64PtrTy, MinNumElts: 4); |
239 | |
240 | const Constant* c8 = Constant::getNullValue(Ty: V8x8Ty); |
241 | const Constant* c64 = Constant::getNullValue(Ty: V8x64Ty); |
242 | |
243 | const Constant *v2ptr32 = Constant::getNullValue(Ty: V2Int32PtrTy); |
244 | |
245 | EXPECT_EQ(CastInst::Trunc, CastInst::getCastOpcode(c64, true, V8x8Ty, true)); |
246 | EXPECT_EQ(CastInst::SExt, CastInst::getCastOpcode(c8, true, V8x64Ty, true)); |
247 | |
248 | EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, X86MMXTy)); |
249 | EXPECT_FALSE(CastInst::isBitCastable(X86MMXTy, V8x8Ty)); |
250 | EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, X86MMXTy)); |
251 | EXPECT_FALSE(CastInst::isBitCastable(V8x64Ty, V8x8Ty)); |
252 | EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, V8x64Ty)); |
253 | |
254 | // Check address space casts are rejected since we don't know the sizes here |
255 | EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, Int32PtrAS1Ty)); |
256 | EXPECT_FALSE(CastInst::isBitCastable(Int32PtrAS1Ty, Int32PtrTy)); |
257 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, V2Int32PtrAS1Ty)); |
258 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrTy)); |
259 | EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int64PtrAS1Ty)); |
260 | EXPECT_EQ(CastInst::AddrSpaceCast, CastInst::getCastOpcode(v2ptr32, true, |
261 | V2Int32PtrAS1Ty, |
262 | true)); |
263 | |
264 | // Test mismatched number of elements for pointers |
265 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int64PtrAS1Ty)); |
266 | EXPECT_FALSE(CastInst::isBitCastable(V4Int64PtrAS1Ty, V2Int32PtrAS1Ty)); |
267 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int32PtrAS1Ty)); |
268 | EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, V2Int32PtrTy)); |
269 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int32PtrTy)); |
270 | |
271 | EXPECT_TRUE(CastInst::isBitCastable(Int32PtrTy, Int64PtrTy)); |
272 | EXPECT_FALSE(CastInst::isBitCastable(DoubleTy, FloatTy)); |
273 | EXPECT_FALSE(CastInst::isBitCastable(FloatTy, DoubleTy)); |
274 | EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy)); |
275 | EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy)); |
276 | EXPECT_TRUE(CastInst::isBitCastable(FloatTy, Int32Ty)); |
277 | EXPECT_TRUE(CastInst::isBitCastable(Int16Ty, HalfTy)); |
278 | EXPECT_TRUE(CastInst::isBitCastable(Int32Ty, FloatTy)); |
279 | EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, Int64Ty)); |
280 | |
281 | EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, V4Int16Ty)); |
282 | EXPECT_FALSE(CastInst::isBitCastable(Int32Ty, Int64Ty)); |
283 | EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, Int32Ty)); |
284 | |
285 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int64Ty)); |
286 | EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, V2Int32PtrTy)); |
287 | EXPECT_TRUE(CastInst::isBitCastable(V2Int64PtrTy, V2Int32PtrTy)); |
288 | EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrTy, V2Int64PtrTy)); |
289 | EXPECT_FALSE(CastInst::isBitCastable(V2Int32Ty, V2Int64Ty)); |
290 | EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty)); |
291 | |
292 | |
293 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
294 | Constant::getNullValue(V4Int32PtrTy), |
295 | V2Int32PtrTy)); |
296 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
297 | Constant::getNullValue(V2Int32PtrTy), |
298 | V4Int32PtrTy)); |
299 | |
300 | EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, |
301 | Constant::getNullValue(V4Int32PtrAS1Ty), |
302 | V2Int32PtrTy)); |
303 | EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, |
304 | Constant::getNullValue(V2Int32PtrTy), |
305 | V4Int32PtrAS1Ty)); |
306 | |
307 | // Address space cast of fixed/scalable vectors of pointers to scalable/fixed |
308 | // vector of pointers. |
309 | EXPECT_FALSE(CastInst::castIsValid( |
310 | Instruction::AddrSpaceCast, Constant::getNullValue(VScaleV4Int32PtrAS1Ty), |
311 | V4Int32PtrTy)); |
312 | EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, |
313 | Constant::getNullValue(V4Int32PtrTy), |
314 | VScaleV4Int32PtrAS1Ty)); |
315 | // Address space cast of scalable vectors of pointers to scalable vector of |
316 | // pointers. |
317 | EXPECT_FALSE(CastInst::castIsValid( |
318 | Instruction::AddrSpaceCast, Constant::getNullValue(VScaleV4Int32PtrAS1Ty), |
319 | VScaleV2Int32PtrTy)); |
320 | EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, |
321 | Constant::getNullValue(VScaleV2Int32PtrTy), |
322 | VScaleV4Int32PtrAS1Ty)); |
323 | EXPECT_TRUE(CastInst::castIsValid(Instruction::AddrSpaceCast, |
324 | Constant::getNullValue(VScaleV4Int64PtrTy), |
325 | VScaleV4Int32PtrAS1Ty)); |
326 | // Same number of lanes, different address space. |
327 | EXPECT_TRUE(CastInst::castIsValid( |
328 | Instruction::AddrSpaceCast, Constant::getNullValue(VScaleV4Int32PtrAS1Ty), |
329 | VScaleV4Int32PtrTy)); |
330 | // Same number of lanes, same address space. |
331 | EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, |
332 | Constant::getNullValue(VScaleV4Int64PtrTy), |
333 | VScaleV4Int32PtrTy)); |
334 | |
335 | // Bit casting fixed/scalable vector to scalable/fixed vectors. |
336 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
337 | Constant::getNullValue(V2Int32Ty), |
338 | VScaleV2Int32Ty)); |
339 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
340 | Constant::getNullValue(V2Int64Ty), |
341 | VScaleV2Int64Ty)); |
342 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
343 | Constant::getNullValue(V4Int16Ty), |
344 | VScaleV4Int16Ty)); |
345 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
346 | Constant::getNullValue(VScaleV2Int32Ty), |
347 | V2Int32Ty)); |
348 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
349 | Constant::getNullValue(VScaleV2Int64Ty), |
350 | V2Int64Ty)); |
351 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
352 | Constant::getNullValue(VScaleV4Int16Ty), |
353 | V4Int16Ty)); |
354 | |
355 | // Bit casting scalable vectors to scalable vectors. |
356 | EXPECT_TRUE(CastInst::castIsValid(Instruction::BitCast, |
357 | Constant::getNullValue(VScaleV4Int16Ty), |
358 | VScaleV2Int32Ty)); |
359 | EXPECT_TRUE(CastInst::castIsValid(Instruction::BitCast, |
360 | Constant::getNullValue(VScaleV2Int32Ty), |
361 | VScaleV4Int16Ty)); |
362 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
363 | Constant::getNullValue(VScaleV2Int64Ty), |
364 | VScaleV2Int32Ty)); |
365 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
366 | Constant::getNullValue(VScaleV2Int32Ty), |
367 | VScaleV2Int64Ty)); |
368 | |
369 | // Bitcasting to/from <vscale x 1 x Ty> |
370 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
371 | Constant::getNullValue(VScaleV1Int16Ty), |
372 | V1Int16Ty)); |
373 | EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, |
374 | Constant::getNullValue(V1Int16Ty), |
375 | VScaleV1Int16Ty)); |
376 | |
377 | // Check that assertion is not hit when creating a cast with a vector of |
378 | // pointers |
379 | // First form |
380 | BasicBlock *BB = BasicBlock::Create(Context&: C); |
381 | Constant *NullV2I32Ptr = Constant::getNullValue(Ty: V2Int32PtrTy); |
382 | auto Inst1 = CastInst::CreatePointerCast(S: NullV2I32Ptr, Ty: V2Int32Ty, Name: "foo" , InsertAtEnd: BB); |
383 | |
384 | Constant *NullVScaleV2I32Ptr = Constant::getNullValue(Ty: VScaleV2Int32PtrTy); |
385 | auto Inst1VScale = CastInst::CreatePointerCast( |
386 | S: NullVScaleV2I32Ptr, Ty: VScaleV2Int32Ty, Name: "foo.vscale" , InsertAtEnd: BB); |
387 | |
388 | // Second form |
389 | auto Inst2 = CastInst::CreatePointerCast(S: NullV2I32Ptr, Ty: V2Int32Ty); |
390 | auto Inst2VScale = |
391 | CastInst::CreatePointerCast(S: NullVScaleV2I32Ptr, Ty: VScaleV2Int32Ty); |
392 | |
393 | delete Inst2; |
394 | delete Inst2VScale; |
395 | Inst1->eraseFromParent(); |
396 | Inst1VScale->eraseFromParent(); |
397 | delete BB; |
398 | } |
399 | |
400 | TEST(InstructionsTest, CastCAPI) { |
401 | LLVMContext C; |
402 | |
403 | Type *Int8Ty = Type::getInt8Ty(C); |
404 | Type *Int32Ty = Type::getInt32Ty(C); |
405 | Type *Int64Ty = Type::getInt64Ty(C); |
406 | |
407 | Type *FloatTy = Type::getFloatTy(C); |
408 | Type *DoubleTy = Type::getDoubleTy(C); |
409 | |
410 | Type *Int8PtrTy = PointerType::get(ElementType: Int8Ty, AddressSpace: 0); |
411 | Type *Int32PtrTy = PointerType::get(ElementType: Int32Ty, AddressSpace: 0); |
412 | |
413 | const Constant *C8 = Constant::getNullValue(Ty: Int8Ty); |
414 | const Constant *C64 = Constant::getNullValue(Ty: Int64Ty); |
415 | |
416 | EXPECT_EQ(LLVMBitCast, |
417 | LLVMGetCastOpcode(wrap(C64), true, wrap(Int64Ty), true)); |
418 | EXPECT_EQ(LLVMTrunc, LLVMGetCastOpcode(wrap(C64), true, wrap(Int8Ty), true)); |
419 | EXPECT_EQ(LLVMSExt, LLVMGetCastOpcode(wrap(C8), true, wrap(Int64Ty), true)); |
420 | EXPECT_EQ(LLVMZExt, LLVMGetCastOpcode(wrap(C8), false, wrap(Int64Ty), true)); |
421 | |
422 | const Constant *CF32 = Constant::getNullValue(Ty: FloatTy); |
423 | const Constant *CF64 = Constant::getNullValue(Ty: DoubleTy); |
424 | |
425 | EXPECT_EQ(LLVMFPToUI, |
426 | LLVMGetCastOpcode(wrap(CF32), true, wrap(Int8Ty), false)); |
427 | EXPECT_EQ(LLVMFPToSI, |
428 | LLVMGetCastOpcode(wrap(CF32), true, wrap(Int8Ty), true)); |
429 | EXPECT_EQ(LLVMUIToFP, |
430 | LLVMGetCastOpcode(wrap(C8), false, wrap(FloatTy), true)); |
431 | EXPECT_EQ(LLVMSIToFP, LLVMGetCastOpcode(wrap(C8), true, wrap(FloatTy), true)); |
432 | EXPECT_EQ(LLVMFPTrunc, |
433 | LLVMGetCastOpcode(wrap(CF64), true, wrap(FloatTy), true)); |
434 | EXPECT_EQ(LLVMFPExt, |
435 | LLVMGetCastOpcode(wrap(CF32), true, wrap(DoubleTy), true)); |
436 | |
437 | const Constant *CPtr8 = Constant::getNullValue(Ty: Int8PtrTy); |
438 | |
439 | EXPECT_EQ(LLVMPtrToInt, |
440 | LLVMGetCastOpcode(wrap(CPtr8), true, wrap(Int8Ty), true)); |
441 | EXPECT_EQ(LLVMIntToPtr, |
442 | LLVMGetCastOpcode(wrap(C8), true, wrap(Int8PtrTy), true)); |
443 | |
444 | Type *V8x8Ty = FixedVectorType::get(ElementType: Int8Ty, NumElts: 8); |
445 | Type *V8x64Ty = FixedVectorType::get(ElementType: Int64Ty, NumElts: 8); |
446 | const Constant *CV8 = Constant::getNullValue(Ty: V8x8Ty); |
447 | const Constant *CV64 = Constant::getNullValue(Ty: V8x64Ty); |
448 | |
449 | EXPECT_EQ(LLVMTrunc, LLVMGetCastOpcode(wrap(CV64), true, wrap(V8x8Ty), true)); |
450 | EXPECT_EQ(LLVMSExt, LLVMGetCastOpcode(wrap(CV8), true, wrap(V8x64Ty), true)); |
451 | |
452 | Type *Int32PtrAS1Ty = PointerType::get(ElementType: Int32Ty, AddressSpace: 1); |
453 | Type *V2Int32PtrAS1Ty = FixedVectorType::get(ElementType: Int32PtrAS1Ty, NumElts: 2); |
454 | Type *V2Int32PtrTy = FixedVectorType::get(ElementType: Int32PtrTy, NumElts: 2); |
455 | const Constant *CV2ptr32 = Constant::getNullValue(Ty: V2Int32PtrTy); |
456 | |
457 | EXPECT_EQ(LLVMAddrSpaceCast, LLVMGetCastOpcode(wrap(CV2ptr32), true, |
458 | wrap(V2Int32PtrAS1Ty), true)); |
459 | } |
460 | |
461 | TEST(InstructionsTest, VectorGep) { |
462 | LLVMContext C; |
463 | |
464 | // Type Definitions |
465 | Type *I8Ty = IntegerType::get(C, NumBits: 8); |
466 | Type *I32Ty = IntegerType::get(C, NumBits: 32); |
467 | PointerType *Ptri8Ty = PointerType::get(ElementType: I8Ty, AddressSpace: 0); |
468 | PointerType *Ptri32Ty = PointerType::get(ElementType: I32Ty, AddressSpace: 0); |
469 | |
470 | VectorType *V2xi8PTy = FixedVectorType::get(ElementType: Ptri8Ty, NumElts: 2); |
471 | VectorType *V2xi32PTy = FixedVectorType::get(ElementType: Ptri32Ty, NumElts: 2); |
472 | |
473 | // Test different aspects of the vector-of-pointers type |
474 | // and GEPs which use this type. |
475 | ConstantInt *Ci32a = ConstantInt::get(Context&: C, V: APInt(32, 1492)); |
476 | ConstantInt *Ci32b = ConstantInt::get(Context&: C, V: APInt(32, 1948)); |
477 | std::vector<Constant*> ConstVa(2, Ci32a); |
478 | std::vector<Constant*> ConstVb(2, Ci32b); |
479 | Constant *C2xi32a = ConstantVector::get(V: ConstVa); |
480 | Constant *C2xi32b = ConstantVector::get(V: ConstVb); |
481 | |
482 | CastInst *PtrVecA = new IntToPtrInst(C2xi32a, V2xi32PTy); |
483 | CastInst *PtrVecB = new IntToPtrInst(C2xi32b, V2xi32PTy); |
484 | |
485 | ICmpInst *ICmp0 = new ICmpInst(ICmpInst::ICMP_SGT, PtrVecA, PtrVecB); |
486 | ICmpInst *ICmp1 = new ICmpInst(ICmpInst::ICMP_ULT, PtrVecA, PtrVecB); |
487 | EXPECT_NE(ICmp0, ICmp1); // suppress warning. |
488 | |
489 | BasicBlock* BB0 = BasicBlock::Create(Context&: C); |
490 | // Test InsertAtEnd ICmpInst constructor. |
491 | ICmpInst *ICmp2 = new ICmpInst(BB0, ICmpInst::ICMP_SGE, PtrVecA, PtrVecB); |
492 | EXPECT_NE(ICmp0, ICmp2); // suppress warning. |
493 | |
494 | GetElementPtrInst *Gep0 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: PtrVecA, IdxList: C2xi32a); |
495 | GetElementPtrInst *Gep1 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: PtrVecA, IdxList: C2xi32b); |
496 | GetElementPtrInst *Gep2 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: PtrVecB, IdxList: C2xi32a); |
497 | GetElementPtrInst *Gep3 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: PtrVecB, IdxList: C2xi32b); |
498 | |
499 | CastInst *BTC0 = new BitCastInst(Gep0, V2xi8PTy); |
500 | CastInst *BTC1 = new BitCastInst(Gep1, V2xi8PTy); |
501 | CastInst *BTC2 = new BitCastInst(Gep2, V2xi8PTy); |
502 | CastInst *BTC3 = new BitCastInst(Gep3, V2xi8PTy); |
503 | |
504 | Value *S0 = BTC0->stripPointerCasts(); |
505 | Value *S1 = BTC1->stripPointerCasts(); |
506 | Value *S2 = BTC2->stripPointerCasts(); |
507 | Value *S3 = BTC3->stripPointerCasts(); |
508 | |
509 | EXPECT_NE(S0, Gep0); |
510 | EXPECT_NE(S1, Gep1); |
511 | EXPECT_NE(S2, Gep2); |
512 | EXPECT_NE(S3, Gep3); |
513 | |
514 | int64_t Offset; |
515 | DataLayout TD("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3" |
516 | "2:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-s:64:64-f80" |
517 | ":128:128-n8:16:32:64-S128" ); |
518 | // Make sure we don't crash |
519 | GetPointerBaseWithConstantOffset(Ptr: Gep0, Offset, DL: TD); |
520 | GetPointerBaseWithConstantOffset(Ptr: Gep1, Offset, DL: TD); |
521 | GetPointerBaseWithConstantOffset(Ptr: Gep2, Offset, DL: TD); |
522 | GetPointerBaseWithConstantOffset(Ptr: Gep3, Offset, DL: TD); |
523 | |
524 | // Gep of Geps |
525 | GetElementPtrInst *GepII0 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: Gep0, IdxList: C2xi32b); |
526 | GetElementPtrInst *GepII1 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: Gep1, IdxList: C2xi32a); |
527 | GetElementPtrInst *GepII2 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: Gep2, IdxList: C2xi32b); |
528 | GetElementPtrInst *GepII3 = GetElementPtrInst::Create(PointeeType: I32Ty, Ptr: Gep3, IdxList: C2xi32a); |
529 | |
530 | EXPECT_EQ(GepII0->getNumIndices(), 1u); |
531 | EXPECT_EQ(GepII1->getNumIndices(), 1u); |
532 | EXPECT_EQ(GepII2->getNumIndices(), 1u); |
533 | EXPECT_EQ(GepII3->getNumIndices(), 1u); |
534 | |
535 | EXPECT_FALSE(GepII0->hasAllZeroIndices()); |
536 | EXPECT_FALSE(GepII1->hasAllZeroIndices()); |
537 | EXPECT_FALSE(GepII2->hasAllZeroIndices()); |
538 | EXPECT_FALSE(GepII3->hasAllZeroIndices()); |
539 | |
540 | delete GepII0; |
541 | delete GepII1; |
542 | delete GepII2; |
543 | delete GepII3; |
544 | |
545 | delete BTC0; |
546 | delete BTC1; |
547 | delete BTC2; |
548 | delete BTC3; |
549 | |
550 | delete Gep0; |
551 | delete Gep1; |
552 | delete Gep2; |
553 | delete Gep3; |
554 | |
555 | ICmp2->eraseFromParent(); |
556 | delete BB0; |
557 | |
558 | delete ICmp0; |
559 | delete ICmp1; |
560 | delete PtrVecA; |
561 | delete PtrVecB; |
562 | } |
563 | |
564 | TEST(InstructionsTest, FPMathOperator) { |
565 | LLVMContext Context; |
566 | IRBuilder<> Builder(Context); |
567 | MDBuilder MDHelper(Context); |
568 | Instruction *I = Builder.CreatePHI(Ty: Builder.getDoubleTy(), NumReservedValues: 0); |
569 | MDNode *MD1 = MDHelper.createFPMath(Accuracy: 1.0); |
570 | Value *V1 = Builder.CreateFAdd(L: I, R: I, Name: "" , FPMD: MD1); |
571 | EXPECT_TRUE(isa<FPMathOperator>(V1)); |
572 | FPMathOperator *O1 = cast<FPMathOperator>(Val: V1); |
573 | EXPECT_EQ(O1->getFPAccuracy(), 1.0); |
574 | V1->deleteValue(); |
575 | I->deleteValue(); |
576 | } |
577 | |
578 | TEST(InstructionTest, ConstrainedTrans) { |
579 | LLVMContext Context; |
580 | std::unique_ptr<Module> M(new Module("MyModule" , Context)); |
581 | FunctionType *FTy = |
582 | FunctionType::get(Result: Type::getVoidTy(C&: Context), |
583 | Params: {Type::getFloatTy(C&: Context), Type::getFloatTy(C&: Context), |
584 | Type::getInt32Ty(C&: Context)}, |
585 | isVarArg: false); |
586 | auto *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "" , M: M.get()); |
587 | auto *BB = BasicBlock::Create(Context, Name: "bb" , Parent: F); |
588 | IRBuilder<> Builder(Context); |
589 | Builder.SetInsertPoint(BB); |
590 | auto *Arg0 = F->arg_begin(); |
591 | auto *Arg1 = F->arg_begin() + 1; |
592 | |
593 | { |
594 | auto *I = cast<Instruction>(Val: Builder.CreateFAdd(L: Arg0, R: Arg1)); |
595 | EXPECT_EQ(Intrinsic::experimental_constrained_fadd, |
596 | getConstrainedIntrinsicID(*I)); |
597 | } |
598 | |
599 | { |
600 | auto *I = cast<Instruction>( |
601 | Val: Builder.CreateFPToSI(V: Arg0, DestTy: Type::getInt32Ty(C&: Context))); |
602 | EXPECT_EQ(Intrinsic::experimental_constrained_fptosi, |
603 | getConstrainedIntrinsicID(*I)); |
604 | } |
605 | |
606 | { |
607 | auto *I = cast<Instruction>(Builder.CreateIntrinsic( |
608 | Intrinsic::ceil, {Type::getFloatTy(Context)}, {Arg0})); |
609 | EXPECT_EQ(Intrinsic::experimental_constrained_ceil, |
610 | getConstrainedIntrinsicID(*I)); |
611 | } |
612 | |
613 | { |
614 | auto *I = cast<Instruction>(Val: Builder.CreateFCmpOEQ(LHS: Arg0, RHS: Arg1)); |
615 | EXPECT_EQ(Intrinsic::experimental_constrained_fcmp, |
616 | getConstrainedIntrinsicID(*I)); |
617 | } |
618 | |
619 | { |
620 | auto *Arg2 = F->arg_begin() + 2; |
621 | auto *I = cast<Instruction>(Val: Builder.CreateAdd(LHS: Arg2, RHS: Arg2)); |
622 | EXPECT_EQ(Intrinsic::not_intrinsic, getConstrainedIntrinsicID(*I)); |
623 | } |
624 | |
625 | { |
626 | auto *I = cast<Instruction>(Builder.CreateConstrainedFPBinOp( |
627 | Intrinsic::experimental_constrained_fadd, Arg0, Arg0)); |
628 | EXPECT_EQ(Intrinsic::not_intrinsic, getConstrainedIntrinsicID(*I)); |
629 | } |
630 | } |
631 | |
632 | TEST(InstructionsTest, isEliminableCastPair) { |
633 | LLVMContext C; |
634 | |
635 | Type* Int16Ty = Type::getInt16Ty(C); |
636 | Type* Int32Ty = Type::getInt32Ty(C); |
637 | Type* Int64Ty = Type::getInt64Ty(C); |
638 | Type *Int64PtrTy = PointerType::get(C, AddressSpace: 0); |
639 | |
640 | // Source and destination pointers have same size -> bitcast. |
641 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, |
642 | CastInst::IntToPtr, |
643 | Int64PtrTy, Int64Ty, Int64PtrTy, |
644 | Int32Ty, nullptr, Int32Ty), |
645 | CastInst::BitCast); |
646 | |
647 | // Source and destination have unknown sizes, but the same address space and |
648 | // the intermediate int is the maximum pointer size -> bitcast |
649 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, |
650 | CastInst::IntToPtr, |
651 | Int64PtrTy, Int64Ty, Int64PtrTy, |
652 | nullptr, nullptr, nullptr), |
653 | CastInst::BitCast); |
654 | |
655 | // Source and destination have unknown sizes, but the same address space and |
656 | // the intermediate int is not the maximum pointer size -> nothing |
657 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt, |
658 | CastInst::IntToPtr, |
659 | Int64PtrTy, Int32Ty, Int64PtrTy, |
660 | nullptr, nullptr, nullptr), |
661 | 0U); |
662 | |
663 | // Middle pointer big enough -> bitcast. |
664 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, |
665 | CastInst::PtrToInt, |
666 | Int64Ty, Int64PtrTy, Int64Ty, |
667 | nullptr, Int64Ty, nullptr), |
668 | CastInst::BitCast); |
669 | |
670 | // Middle pointer too small -> fail. |
671 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, |
672 | CastInst::PtrToInt, |
673 | Int64Ty, Int64PtrTy, Int64Ty, |
674 | nullptr, Int32Ty, nullptr), |
675 | 0U); |
676 | |
677 | // Test that we don't eliminate bitcasts between different address spaces, |
678 | // or if we don't have available pointer size information. |
679 | DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16" |
680 | "-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64" |
681 | "-v128:128:128-a:0:64-s:64:64-f80:128:128-n8:16:32:64-S128" ); |
682 | |
683 | Type *Int64PtrTyAS1 = PointerType::get(C, AddressSpace: 1); |
684 | Type *Int64PtrTyAS2 = PointerType::get(C, AddressSpace: 2); |
685 | |
686 | IntegerType *Int16SizePtr = DL.getIntPtrType(C, AddressSpace: 1); |
687 | IntegerType *Int64SizePtr = DL.getIntPtrType(C, AddressSpace: 2); |
688 | |
689 | // Cannot simplify inttoptr, addrspacecast |
690 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, |
691 | CastInst::AddrSpaceCast, |
692 | Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2, |
693 | nullptr, Int16SizePtr, Int64SizePtr), |
694 | 0U); |
695 | |
696 | // Cannot simplify addrspacecast, ptrtoint |
697 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::AddrSpaceCast, |
698 | CastInst::PtrToInt, |
699 | Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty, |
700 | Int64SizePtr, Int16SizePtr, nullptr), |
701 | 0U); |
702 | |
703 | // Pass since the bitcast address spaces are the same |
704 | EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr, |
705 | CastInst::BitCast, |
706 | Int16Ty, Int64PtrTyAS1, Int64PtrTyAS1, |
707 | nullptr, nullptr, nullptr), |
708 | CastInst::IntToPtr); |
709 | |
710 | } |
711 | |
712 | TEST(InstructionsTest, CloneCall) { |
713 | LLVMContext C; |
714 | Type *Int32Ty = Type::getInt32Ty(C); |
715 | Type *ArgTys[] = {Int32Ty, Int32Ty, Int32Ty}; |
716 | FunctionType *FnTy = FunctionType::get(Result: Int32Ty, Params: ArgTys, /*isVarArg=*/false); |
717 | Value *Callee = Constant::getNullValue(Ty: PointerType::getUnqual(C)); |
718 | Value *Args[] = { |
719 | ConstantInt::get(Ty: Int32Ty, V: 1), |
720 | ConstantInt::get(Ty: Int32Ty, V: 2), |
721 | ConstantInt::get(Ty: Int32Ty, V: 3) |
722 | }; |
723 | std::unique_ptr<CallInst> Call( |
724 | CallInst::Create(Ty: FnTy, Func: Callee, Args, NameStr: "result" )); |
725 | |
726 | // Test cloning the tail call kind. |
727 | CallInst::TailCallKind Kinds[] = {CallInst::TCK_None, CallInst::TCK_Tail, |
728 | CallInst::TCK_MustTail}; |
729 | for (CallInst::TailCallKind TCK : Kinds) { |
730 | Call->setTailCallKind(TCK); |
731 | std::unique_ptr<CallInst> Clone(cast<CallInst>(Val: Call->clone())); |
732 | EXPECT_EQ(Call->getTailCallKind(), Clone->getTailCallKind()); |
733 | } |
734 | Call->setTailCallKind(CallInst::TCK_None); |
735 | |
736 | // Test cloning an attribute. |
737 | { |
738 | AttrBuilder AB(C); |
739 | AB.addAttribute(Attribute::NoUnwind); |
740 | Call->setAttributes( |
741 | AttributeList::get(C, Index: AttributeList::FunctionIndex, B: AB)); |
742 | std::unique_ptr<CallInst> Clone(cast<CallInst>(Val: Call->clone())); |
743 | EXPECT_TRUE(Clone->doesNotThrow()); |
744 | } |
745 | } |
746 | |
747 | TEST(InstructionsTest, AlterCallBundles) { |
748 | LLVMContext C; |
749 | Type *Int32Ty = Type::getInt32Ty(C); |
750 | FunctionType *FnTy = FunctionType::get(Result: Int32Ty, Params: Int32Ty, /*isVarArg=*/false); |
751 | Value *Callee = Constant::getNullValue(Ty: PointerType::getUnqual(C)); |
752 | Value *Args[] = {ConstantInt::get(Ty: Int32Ty, V: 42)}; |
753 | OperandBundleDef OldBundle("before" , UndefValue::get(T: Int32Ty)); |
754 | std::unique_ptr<CallInst> Call( |
755 | CallInst::Create(Ty: FnTy, Func: Callee, Args, Bundles: OldBundle, NameStr: "result" )); |
756 | Call->setTailCallKind(CallInst::TailCallKind::TCK_NoTail); |
757 | AttrBuilder AB(C); |
758 | AB.addAttribute(Attribute::Cold); |
759 | Call->setAttributes(AttributeList::get(C, Index: AttributeList::FunctionIndex, B: AB)); |
760 | Call->setDebugLoc(DebugLoc(MDNode::get(Context&: C, MDs: std::nullopt))); |
761 | |
762 | OperandBundleDef NewBundle("after" , ConstantInt::get(Ty: Int32Ty, V: 7)); |
763 | std::unique_ptr<CallInst> Clone(CallInst::Create(CI: Call.get(), Bundles: NewBundle)); |
764 | EXPECT_EQ(Call->arg_size(), Clone->arg_size()); |
765 | EXPECT_EQ(Call->getArgOperand(0), Clone->getArgOperand(0)); |
766 | EXPECT_EQ(Call->getCallingConv(), Clone->getCallingConv()); |
767 | EXPECT_EQ(Call->getTailCallKind(), Clone->getTailCallKind()); |
768 | EXPECT_TRUE(Clone->hasFnAttr(Attribute::AttrKind::Cold)); |
769 | EXPECT_EQ(Call->getDebugLoc(), Clone->getDebugLoc()); |
770 | EXPECT_EQ(Clone->getNumOperandBundles(), 1U); |
771 | EXPECT_TRUE(Clone->getOperandBundle("after" )); |
772 | } |
773 | |
774 | TEST(InstructionsTest, AlterInvokeBundles) { |
775 | LLVMContext C; |
776 | Type *Int32Ty = Type::getInt32Ty(C); |
777 | FunctionType *FnTy = FunctionType::get(Result: Int32Ty, Params: Int32Ty, /*isVarArg=*/false); |
778 | Value *Callee = Constant::getNullValue(Ty: PointerType::getUnqual(C)); |
779 | Value *Args[] = {ConstantInt::get(Ty: Int32Ty, V: 42)}; |
780 | std::unique_ptr<BasicBlock> NormalDest(BasicBlock::Create(Context&: C)); |
781 | std::unique_ptr<BasicBlock> UnwindDest(BasicBlock::Create(Context&: C)); |
782 | OperandBundleDef OldBundle("before" , UndefValue::get(T: Int32Ty)); |
783 | std::unique_ptr<InvokeInst> Invoke( |
784 | InvokeInst::Create(Ty: FnTy, Func: Callee, IfNormal: NormalDest.get(), IfException: UnwindDest.get(), Args, |
785 | Bundles: OldBundle, NameStr: "result" )); |
786 | AttrBuilder AB(C); |
787 | AB.addAttribute(Attribute::Cold); |
788 | Invoke->setAttributes( |
789 | AttributeList::get(C, Index: AttributeList::FunctionIndex, B: AB)); |
790 | Invoke->setDebugLoc(DebugLoc(MDNode::get(Context&: C, MDs: std::nullopt))); |
791 | |
792 | OperandBundleDef NewBundle("after" , ConstantInt::get(Ty: Int32Ty, V: 7)); |
793 | std::unique_ptr<InvokeInst> Clone( |
794 | InvokeInst::Create(II: Invoke.get(), Bundles: NewBundle)); |
795 | EXPECT_EQ(Invoke->getNormalDest(), Clone->getNormalDest()); |
796 | EXPECT_EQ(Invoke->getUnwindDest(), Clone->getUnwindDest()); |
797 | EXPECT_EQ(Invoke->arg_size(), Clone->arg_size()); |
798 | EXPECT_EQ(Invoke->getArgOperand(0), Clone->getArgOperand(0)); |
799 | EXPECT_EQ(Invoke->getCallingConv(), Clone->getCallingConv()); |
800 | EXPECT_TRUE(Clone->hasFnAttr(Attribute::AttrKind::Cold)); |
801 | EXPECT_EQ(Invoke->getDebugLoc(), Clone->getDebugLoc()); |
802 | EXPECT_EQ(Clone->getNumOperandBundles(), 1U); |
803 | EXPECT_TRUE(Clone->getOperandBundle("after" )); |
804 | } |
805 | |
806 | TEST_F(ModuleWithFunctionTest, DropPoisonGeneratingFlags) { |
807 | auto *OnlyBB = BasicBlock::Create(Context&: Ctx, Name: "bb" , Parent: F); |
808 | auto *Arg0 = &*F->arg_begin(); |
809 | |
810 | IRBuilder<NoFolder> B(Ctx); |
811 | B.SetInsertPoint(OnlyBB); |
812 | |
813 | { |
814 | auto *UI = |
815 | cast<Instruction>(Val: B.CreateUDiv(LHS: Arg0, RHS: Arg0, Name: "" , /*isExact*/ true)); |
816 | ASSERT_TRUE(UI->isExact()); |
817 | UI->dropPoisonGeneratingFlags(); |
818 | ASSERT_FALSE(UI->isExact()); |
819 | } |
820 | |
821 | { |
822 | auto *ShrI = |
823 | cast<Instruction>(Val: B.CreateLShr(LHS: Arg0, RHS: Arg0, Name: "" , /*isExact*/ true)); |
824 | ASSERT_TRUE(ShrI->isExact()); |
825 | ShrI->dropPoisonGeneratingFlags(); |
826 | ASSERT_FALSE(ShrI->isExact()); |
827 | } |
828 | |
829 | { |
830 | auto *AI = cast<Instruction>( |
831 | Val: B.CreateAdd(LHS: Arg0, RHS: Arg0, Name: "" , /*HasNUW*/ true, /*HasNSW*/ false)); |
832 | ASSERT_TRUE(AI->hasNoUnsignedWrap()); |
833 | AI->dropPoisonGeneratingFlags(); |
834 | ASSERT_FALSE(AI->hasNoUnsignedWrap()); |
835 | ASSERT_FALSE(AI->hasNoSignedWrap()); |
836 | } |
837 | |
838 | { |
839 | auto *SI = cast<Instruction>( |
840 | Val: B.CreateAdd(LHS: Arg0, RHS: Arg0, Name: "" , /*HasNUW*/ false, /*HasNSW*/ true)); |
841 | ASSERT_TRUE(SI->hasNoSignedWrap()); |
842 | SI->dropPoisonGeneratingFlags(); |
843 | ASSERT_FALSE(SI->hasNoUnsignedWrap()); |
844 | ASSERT_FALSE(SI->hasNoSignedWrap()); |
845 | } |
846 | |
847 | { |
848 | auto *ShlI = cast<Instruction>( |
849 | Val: B.CreateShl(LHS: Arg0, RHS: Arg0, Name: "" , /*HasNUW*/ true, /*HasNSW*/ true)); |
850 | ASSERT_TRUE(ShlI->hasNoSignedWrap()); |
851 | ASSERT_TRUE(ShlI->hasNoUnsignedWrap()); |
852 | ShlI->dropPoisonGeneratingFlags(); |
853 | ASSERT_FALSE(ShlI->hasNoUnsignedWrap()); |
854 | ASSERT_FALSE(ShlI->hasNoSignedWrap()); |
855 | } |
856 | |
857 | { |
858 | Value *GEPBase = Constant::getNullValue(Ty: B.getPtrTy()); |
859 | auto *GI = cast<GetElementPtrInst>( |
860 | Val: B.CreateInBoundsGEP(Ty: B.getInt8Ty(), Ptr: GEPBase, IdxList: Arg0)); |
861 | ASSERT_TRUE(GI->isInBounds()); |
862 | GI->dropPoisonGeneratingFlags(); |
863 | ASSERT_FALSE(GI->isInBounds()); |
864 | } |
865 | } |
866 | |
867 | TEST(InstructionsTest, GEPIndices) { |
868 | LLVMContext Context; |
869 | IRBuilder<NoFolder> Builder(Context); |
870 | Type *ElementTy = Builder.getInt8Ty(); |
871 | Type *ArrTy = ArrayType::get(ElementType: ArrayType::get(ElementType: ElementTy, NumElements: 64), NumElements: 64); |
872 | Value *Indices[] = { |
873 | Builder.getInt32(C: 0), |
874 | Builder.getInt32(C: 13), |
875 | Builder.getInt32(C: 42) }; |
876 | |
877 | Value *V = Builder.CreateGEP(Ty: ArrTy, Ptr: UndefValue::get(T: PointerType::getUnqual(ElementType: ArrTy)), |
878 | IdxList: Indices); |
879 | ASSERT_TRUE(isa<GetElementPtrInst>(V)); |
880 | |
881 | auto *GEPI = cast<GetElementPtrInst>(Val: V); |
882 | ASSERT_NE(GEPI->idx_begin(), GEPI->idx_end()); |
883 | ASSERT_EQ(GEPI->idx_end(), std::next(GEPI->idx_begin(), 3)); |
884 | EXPECT_EQ(Indices[0], GEPI->idx_begin()[0]); |
885 | EXPECT_EQ(Indices[1], GEPI->idx_begin()[1]); |
886 | EXPECT_EQ(Indices[2], GEPI->idx_begin()[2]); |
887 | EXPECT_EQ(GEPI->idx_begin(), GEPI->indices().begin()); |
888 | EXPECT_EQ(GEPI->idx_end(), GEPI->indices().end()); |
889 | |
890 | const auto *CGEPI = GEPI; |
891 | ASSERT_NE(CGEPI->idx_begin(), CGEPI->idx_end()); |
892 | ASSERT_EQ(CGEPI->idx_end(), std::next(CGEPI->idx_begin(), 3)); |
893 | EXPECT_EQ(Indices[0], CGEPI->idx_begin()[0]); |
894 | EXPECT_EQ(Indices[1], CGEPI->idx_begin()[1]); |
895 | EXPECT_EQ(Indices[2], CGEPI->idx_begin()[2]); |
896 | EXPECT_EQ(CGEPI->idx_begin(), CGEPI->indices().begin()); |
897 | EXPECT_EQ(CGEPI->idx_end(), CGEPI->indices().end()); |
898 | |
899 | delete GEPI; |
900 | } |
901 | |
902 | TEST(InstructionsTest, SwitchInst) { |
903 | LLVMContext C; |
904 | |
905 | std::unique_ptr<BasicBlock> BB1, BB2, BB3; |
906 | BB1.reset(p: BasicBlock::Create(Context&: C)); |
907 | BB2.reset(p: BasicBlock::Create(Context&: C)); |
908 | BB3.reset(p: BasicBlock::Create(Context&: C)); |
909 | |
910 | // We create block 0 after the others so that it gets destroyed first and |
911 | // clears the uses of the other basic blocks. |
912 | std::unique_ptr<BasicBlock> BB0(BasicBlock::Create(Context&: C)); |
913 | |
914 | auto *Int32Ty = Type::getInt32Ty(C); |
915 | |
916 | SwitchInst *SI = |
917 | SwitchInst::Create(Value: UndefValue::get(T: Int32Ty), Default: BB0.get(), NumCases: 3, InsertAtEnd: BB0.get()); |
918 | SI->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 1), Dest: BB1.get()); |
919 | SI->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 2), Dest: BB2.get()); |
920 | SI->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 3), Dest: BB3.get()); |
921 | |
922 | auto CI = SI->case_begin(); |
923 | ASSERT_NE(CI, SI->case_end()); |
924 | EXPECT_EQ(1, CI->getCaseValue()->getSExtValue()); |
925 | EXPECT_EQ(BB1.get(), CI->getCaseSuccessor()); |
926 | EXPECT_EQ(2, (CI + 1)->getCaseValue()->getSExtValue()); |
927 | EXPECT_EQ(BB2.get(), (CI + 1)->getCaseSuccessor()); |
928 | EXPECT_EQ(3, (CI + 2)->getCaseValue()->getSExtValue()); |
929 | EXPECT_EQ(BB3.get(), (CI + 2)->getCaseSuccessor()); |
930 | EXPECT_EQ(CI + 1, std::next(CI)); |
931 | EXPECT_EQ(CI + 2, std::next(CI, 2)); |
932 | EXPECT_EQ(CI + 3, std::next(CI, 3)); |
933 | EXPECT_EQ(SI->case_end(), CI + 3); |
934 | EXPECT_EQ(0, CI - CI); |
935 | EXPECT_EQ(1, (CI + 1) - CI); |
936 | EXPECT_EQ(2, (CI + 2) - CI); |
937 | EXPECT_EQ(3, SI->case_end() - CI); |
938 | EXPECT_EQ(3, std::distance(CI, SI->case_end())); |
939 | |
940 | auto CCI = const_cast<const SwitchInst *>(SI)->case_begin(); |
941 | SwitchInst::ConstCaseIt CCE = SI->case_end(); |
942 | ASSERT_NE(CCI, SI->case_end()); |
943 | EXPECT_EQ(1, CCI->getCaseValue()->getSExtValue()); |
944 | EXPECT_EQ(BB1.get(), CCI->getCaseSuccessor()); |
945 | EXPECT_EQ(2, (CCI + 1)->getCaseValue()->getSExtValue()); |
946 | EXPECT_EQ(BB2.get(), (CCI + 1)->getCaseSuccessor()); |
947 | EXPECT_EQ(3, (CCI + 2)->getCaseValue()->getSExtValue()); |
948 | EXPECT_EQ(BB3.get(), (CCI + 2)->getCaseSuccessor()); |
949 | EXPECT_EQ(CCI + 1, std::next(CCI)); |
950 | EXPECT_EQ(CCI + 2, std::next(CCI, 2)); |
951 | EXPECT_EQ(CCI + 3, std::next(CCI, 3)); |
952 | EXPECT_EQ(CCE, CCI + 3); |
953 | EXPECT_EQ(0, CCI - CCI); |
954 | EXPECT_EQ(1, (CCI + 1) - CCI); |
955 | EXPECT_EQ(2, (CCI + 2) - CCI); |
956 | EXPECT_EQ(3, CCE - CCI); |
957 | EXPECT_EQ(3, std::distance(CCI, CCE)); |
958 | |
959 | // Make sure that the const iterator is compatible with a const auto ref. |
960 | const auto &Handle = *CCI; |
961 | EXPECT_EQ(1, Handle.getCaseValue()->getSExtValue()); |
962 | EXPECT_EQ(BB1.get(), Handle.getCaseSuccessor()); |
963 | } |
964 | |
965 | TEST(InstructionsTest, SwitchInstProfUpdateWrapper) { |
966 | LLVMContext C; |
967 | |
968 | std::unique_ptr<BasicBlock> BB1, BB2, BB3; |
969 | BB1.reset(p: BasicBlock::Create(Context&: C)); |
970 | BB2.reset(p: BasicBlock::Create(Context&: C)); |
971 | BB3.reset(p: BasicBlock::Create(Context&: C)); |
972 | |
973 | // We create block 0 after the others so that it gets destroyed first and |
974 | // clears the uses of the other basic blocks. |
975 | std::unique_ptr<BasicBlock> BB0(BasicBlock::Create(Context&: C)); |
976 | |
977 | auto *Int32Ty = Type::getInt32Ty(C); |
978 | |
979 | SwitchInst *SI = |
980 | SwitchInst::Create(Value: UndefValue::get(T: Int32Ty), Default: BB0.get(), NumCases: 4, InsertAtEnd: BB0.get()); |
981 | SI->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 1), Dest: BB1.get()); |
982 | SI->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 2), Dest: BB2.get()); |
983 | SI->setMetadata(KindID: LLVMContext::MD_prof, |
984 | Node: MDBuilder(C).createBranchWeights(Weights: { 9, 1, 22 })); |
985 | |
986 | { |
987 | SwitchInstProfUpdateWrapper SIW(*SI); |
988 | EXPECT_EQ(*SIW.getSuccessorWeight(0), 9u); |
989 | EXPECT_EQ(*SIW.getSuccessorWeight(1), 1u); |
990 | EXPECT_EQ(*SIW.getSuccessorWeight(2), 22u); |
991 | SIW.setSuccessorWeight(idx: 0, W: 99u); |
992 | SIW.setSuccessorWeight(idx: 1, W: 11u); |
993 | EXPECT_EQ(*SIW.getSuccessorWeight(0), 99u); |
994 | EXPECT_EQ(*SIW.getSuccessorWeight(1), 11u); |
995 | EXPECT_EQ(*SIW.getSuccessorWeight(2), 22u); |
996 | } |
997 | |
998 | { // Create another wrapper and check that the data persist. |
999 | SwitchInstProfUpdateWrapper SIW(*SI); |
1000 | EXPECT_EQ(*SIW.getSuccessorWeight(0), 99u); |
1001 | EXPECT_EQ(*SIW.getSuccessorWeight(1), 11u); |
1002 | EXPECT_EQ(*SIW.getSuccessorWeight(2), 22u); |
1003 | } |
1004 | } |
1005 | |
1006 | TEST(InstructionsTest, CommuteShuffleMask) { |
1007 | SmallVector<int, 16> Indices({-1, 0, 7}); |
1008 | ShuffleVectorInst::commuteShuffleMask(Mask: Indices, InVecNumElts: 4); |
1009 | EXPECT_THAT(Indices, testing::ContainerEq(ArrayRef<int>({-1, 4, 3}))); |
1010 | } |
1011 | |
1012 | TEST(InstructionsTest, ShuffleMaskQueries) { |
1013 | // Create the elements for various constant vectors. |
1014 | LLVMContext Ctx; |
1015 | Type *Int32Ty = Type::getInt32Ty(C&: Ctx); |
1016 | Constant *CU = UndefValue::get(T: Int32Ty); |
1017 | Constant *C0 = ConstantInt::get(Ty: Int32Ty, V: 0); |
1018 | Constant *C1 = ConstantInt::get(Ty: Int32Ty, V: 1); |
1019 | Constant *C2 = ConstantInt::get(Ty: Int32Ty, V: 2); |
1020 | Constant *C3 = ConstantInt::get(Ty: Int32Ty, V: 3); |
1021 | Constant *C4 = ConstantInt::get(Ty: Int32Ty, V: 4); |
1022 | Constant *C5 = ConstantInt::get(Ty: Int32Ty, V: 5); |
1023 | Constant *C6 = ConstantInt::get(Ty: Int32Ty, V: 6); |
1024 | Constant *C7 = ConstantInt::get(Ty: Int32Ty, V: 7); |
1025 | |
1026 | Constant *Identity = ConstantVector::get(V: {C0, CU, C2, C3, C4}); |
1027 | EXPECT_TRUE(ShuffleVectorInst::isIdentityMask( |
1028 | Identity, cast<FixedVectorType>(Identity->getType())->getNumElements())); |
1029 | EXPECT_FALSE(ShuffleVectorInst::isSelectMask( |
1030 | Identity, |
1031 | cast<FixedVectorType>(Identity->getType()) |
1032 | ->getNumElements())); // identity is distinguished from select |
1033 | EXPECT_FALSE(ShuffleVectorInst::isReverseMask( |
1034 | Identity, cast<FixedVectorType>(Identity->getType())->getNumElements())); |
1035 | EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask( |
1036 | Identity, cast<FixedVectorType>(Identity->getType()) |
1037 | ->getNumElements())); // identity is always single source |
1038 | EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask( |
1039 | Identity, cast<FixedVectorType>(Identity->getType())->getNumElements())); |
1040 | EXPECT_FALSE(ShuffleVectorInst::isTransposeMask( |
1041 | Identity, cast<FixedVectorType>(Identity->getType())->getNumElements())); |
1042 | |
1043 | Constant *Select = ConstantVector::get(V: {CU, C1, C5}); |
1044 | EXPECT_FALSE(ShuffleVectorInst::isIdentityMask( |
1045 | Select, cast<FixedVectorType>(Select->getType())->getNumElements())); |
1046 | EXPECT_TRUE(ShuffleVectorInst::isSelectMask( |
1047 | Select, cast<FixedVectorType>(Select->getType())->getNumElements())); |
1048 | EXPECT_FALSE(ShuffleVectorInst::isReverseMask( |
1049 | Select, cast<FixedVectorType>(Select->getType())->getNumElements())); |
1050 | EXPECT_FALSE(ShuffleVectorInst::isSingleSourceMask( |
1051 | Select, cast<FixedVectorType>(Select->getType())->getNumElements())); |
1052 | EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask( |
1053 | Select, cast<FixedVectorType>(Select->getType())->getNumElements())); |
1054 | EXPECT_FALSE(ShuffleVectorInst::isTransposeMask( |
1055 | Select, cast<FixedVectorType>(Select->getType())->getNumElements())); |
1056 | |
1057 | Constant *Reverse = ConstantVector::get(V: {C3, C2, C1, CU}); |
1058 | EXPECT_FALSE(ShuffleVectorInst::isIdentityMask( |
1059 | Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements())); |
1060 | EXPECT_FALSE(ShuffleVectorInst::isSelectMask( |
1061 | Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements())); |
1062 | EXPECT_TRUE(ShuffleVectorInst::isReverseMask( |
1063 | Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements())); |
1064 | EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask( |
1065 | Reverse, cast<FixedVectorType>(Reverse->getType()) |
1066 | ->getNumElements())); // reverse is always single source |
1067 | EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask( |
1068 | Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements())); |
1069 | EXPECT_FALSE(ShuffleVectorInst::isTransposeMask( |
1070 | Reverse, cast<FixedVectorType>(Reverse->getType())->getNumElements())); |
1071 | |
1072 | Constant *SingleSource = ConstantVector::get(V: {C2, C2, C0, CU}); |
1073 | EXPECT_FALSE(ShuffleVectorInst::isIdentityMask( |
1074 | SingleSource, |
1075 | cast<FixedVectorType>(SingleSource->getType())->getNumElements())); |
1076 | EXPECT_FALSE(ShuffleVectorInst::isSelectMask( |
1077 | SingleSource, |
1078 | cast<FixedVectorType>(SingleSource->getType())->getNumElements())); |
1079 | EXPECT_FALSE(ShuffleVectorInst::isReverseMask( |
1080 | SingleSource, |
1081 | cast<FixedVectorType>(SingleSource->getType())->getNumElements())); |
1082 | EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask( |
1083 | SingleSource, |
1084 | cast<FixedVectorType>(SingleSource->getType())->getNumElements())); |
1085 | EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask( |
1086 | SingleSource, |
1087 | cast<FixedVectorType>(SingleSource->getType())->getNumElements())); |
1088 | EXPECT_FALSE(ShuffleVectorInst::isTransposeMask( |
1089 | SingleSource, |
1090 | cast<FixedVectorType>(SingleSource->getType())->getNumElements())); |
1091 | |
1092 | Constant *ZeroEltSplat = ConstantVector::get(V: {C0, C0, CU, C0}); |
1093 | EXPECT_FALSE(ShuffleVectorInst::isIdentityMask( |
1094 | ZeroEltSplat, |
1095 | cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements())); |
1096 | EXPECT_FALSE(ShuffleVectorInst::isSelectMask( |
1097 | ZeroEltSplat, |
1098 | cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements())); |
1099 | EXPECT_FALSE(ShuffleVectorInst::isReverseMask( |
1100 | ZeroEltSplat, |
1101 | cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements())); |
1102 | EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask( |
1103 | ZeroEltSplat, cast<FixedVectorType>(ZeroEltSplat->getType()) |
1104 | ->getNumElements())); // 0-splat is always single source |
1105 | EXPECT_TRUE(ShuffleVectorInst::isZeroEltSplatMask( |
1106 | ZeroEltSplat, |
1107 | cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements())); |
1108 | EXPECT_FALSE(ShuffleVectorInst::isTransposeMask( |
1109 | ZeroEltSplat, |
1110 | cast<FixedVectorType>(ZeroEltSplat->getType())->getNumElements())); |
1111 | |
1112 | Constant *Transpose = ConstantVector::get(V: {C0, C4, C2, C6}); |
1113 | EXPECT_FALSE(ShuffleVectorInst::isIdentityMask( |
1114 | Transpose, |
1115 | cast<FixedVectorType>(Transpose->getType())->getNumElements())); |
1116 | EXPECT_FALSE(ShuffleVectorInst::isSelectMask( |
1117 | Transpose, |
1118 | cast<FixedVectorType>(Transpose->getType())->getNumElements())); |
1119 | EXPECT_FALSE(ShuffleVectorInst::isReverseMask( |
1120 | Transpose, |
1121 | cast<FixedVectorType>(Transpose->getType())->getNumElements())); |
1122 | EXPECT_FALSE(ShuffleVectorInst::isSingleSourceMask( |
1123 | Transpose, |
1124 | cast<FixedVectorType>(Transpose->getType())->getNumElements())); |
1125 | EXPECT_FALSE(ShuffleVectorInst::isZeroEltSplatMask( |
1126 | Transpose, |
1127 | cast<FixedVectorType>(Transpose->getType())->getNumElements())); |
1128 | EXPECT_TRUE(ShuffleVectorInst::isTransposeMask( |
1129 | Transpose, |
1130 | cast<FixedVectorType>(Transpose->getType())->getNumElements())); |
1131 | |
1132 | // More tests to make sure the logic is/stays correct... |
1133 | EXPECT_TRUE(ShuffleVectorInst::isIdentityMask( |
1134 | ConstantVector::get({CU, C1, CU, C3}), 4)); |
1135 | EXPECT_TRUE(ShuffleVectorInst::isIdentityMask( |
1136 | ConstantVector::get({C4, CU, C6, CU}), 4)); |
1137 | |
1138 | EXPECT_TRUE(ShuffleVectorInst::isSelectMask( |
1139 | ConstantVector::get({C4, C1, C6, CU}), 4)); |
1140 | EXPECT_TRUE(ShuffleVectorInst::isSelectMask( |
1141 | ConstantVector::get({CU, C1, C6, C3}), 4)); |
1142 | |
1143 | EXPECT_TRUE(ShuffleVectorInst::isReverseMask( |
1144 | ConstantVector::get({C7, C6, CU, C4}), 4)); |
1145 | EXPECT_TRUE(ShuffleVectorInst::isReverseMask( |
1146 | ConstantVector::get({C3, CU, C1, CU}), 4)); |
1147 | |
1148 | EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask( |
1149 | ConstantVector::get({C7, C5, CU, C7}), 4)); |
1150 | EXPECT_TRUE(ShuffleVectorInst::isSingleSourceMask( |
1151 | ConstantVector::get({C3, C0, CU, C3}), 4)); |
1152 | |
1153 | EXPECT_TRUE(ShuffleVectorInst::isZeroEltSplatMask( |
1154 | ConstantVector::get({C4, CU, CU, C4}), 4)); |
1155 | EXPECT_TRUE(ShuffleVectorInst::isZeroEltSplatMask( |
1156 | ConstantVector::get({CU, C0, CU, C0}), 4)); |
1157 | |
1158 | EXPECT_TRUE(ShuffleVectorInst::isTransposeMask( |
1159 | ConstantVector::get({C1, C5, C3, C7}), 4)); |
1160 | EXPECT_TRUE( |
1161 | ShuffleVectorInst::isTransposeMask(ConstantVector::get({C1, C3}), 2)); |
1162 | |
1163 | // Nothing special about the values here - just re-using inputs to reduce code. |
1164 | Constant *V0 = ConstantVector::get(V: {C0, C1, C2, C3}); |
1165 | Constant *V1 = ConstantVector::get(V: {C3, C2, C1, C0}); |
1166 | |
1167 | // Identity with undef elts. |
1168 | ShuffleVectorInst *Id1 = new ShuffleVectorInst(V0, V1, |
1169 | ConstantVector::get(V: {C0, C1, CU, CU})); |
1170 | EXPECT_TRUE(Id1->isIdentity()); |
1171 | EXPECT_FALSE(Id1->isIdentityWithPadding()); |
1172 | EXPECT_FALSE(Id1->isIdentityWithExtract()); |
1173 | EXPECT_FALSE(Id1->isConcat()); |
1174 | delete Id1; |
1175 | |
1176 | // Result has less elements than operands. |
1177 | ShuffleVectorInst *Id2 = new ShuffleVectorInst(V0, V1, |
1178 | ConstantVector::get(V: {C0, C1, C2})); |
1179 | EXPECT_FALSE(Id2->isIdentity()); |
1180 | EXPECT_FALSE(Id2->isIdentityWithPadding()); |
1181 | EXPECT_TRUE(Id2->isIdentityWithExtract()); |
1182 | EXPECT_FALSE(Id2->isConcat()); |
1183 | delete Id2; |
1184 | |
1185 | // Result has less elements than operands; choose from Op1. |
1186 | ShuffleVectorInst *Id3 = new ShuffleVectorInst(V0, V1, |
1187 | ConstantVector::get(V: {C4, CU, C6})); |
1188 | EXPECT_FALSE(Id3->isIdentity()); |
1189 | EXPECT_FALSE(Id3->isIdentityWithPadding()); |
1190 | EXPECT_TRUE(Id3->isIdentityWithExtract()); |
1191 | EXPECT_FALSE(Id3->isConcat()); |
1192 | delete Id3; |
1193 | |
1194 | // Result has less elements than operands; choose from Op0 and Op1 is not identity. |
1195 | ShuffleVectorInst *Id4 = new ShuffleVectorInst(V0, V1, |
1196 | ConstantVector::get(V: {C4, C1, C6})); |
1197 | EXPECT_FALSE(Id4->isIdentity()); |
1198 | EXPECT_FALSE(Id4->isIdentityWithPadding()); |
1199 | EXPECT_FALSE(Id4->isIdentityWithExtract()); |
1200 | EXPECT_FALSE(Id4->isConcat()); |
1201 | delete Id4; |
1202 | |
1203 | // Result has more elements than operands, and extra elements are undef. |
1204 | ShuffleVectorInst *Id5 = new ShuffleVectorInst(V0, V1, |
1205 | ConstantVector::get(V: {CU, C1, C2, C3, CU, CU})); |
1206 | EXPECT_FALSE(Id5->isIdentity()); |
1207 | EXPECT_TRUE(Id5->isIdentityWithPadding()); |
1208 | EXPECT_FALSE(Id5->isIdentityWithExtract()); |
1209 | EXPECT_FALSE(Id5->isConcat()); |
1210 | delete Id5; |
1211 | |
1212 | // Result has more elements than operands, and extra elements are undef; choose from Op1. |
1213 | ShuffleVectorInst *Id6 = new ShuffleVectorInst(V0, V1, |
1214 | ConstantVector::get(V: {C4, C5, C6, CU, CU, CU})); |
1215 | EXPECT_FALSE(Id6->isIdentity()); |
1216 | EXPECT_TRUE(Id6->isIdentityWithPadding()); |
1217 | EXPECT_FALSE(Id6->isIdentityWithExtract()); |
1218 | EXPECT_FALSE(Id6->isConcat()); |
1219 | delete Id6; |
1220 | |
1221 | // Result has more elements than operands, but extra elements are not undef. |
1222 | ShuffleVectorInst *Id7 = new ShuffleVectorInst(V0, V1, |
1223 | ConstantVector::get(V: {C0, C1, C2, C3, CU, C1})); |
1224 | EXPECT_FALSE(Id7->isIdentity()); |
1225 | EXPECT_FALSE(Id7->isIdentityWithPadding()); |
1226 | EXPECT_FALSE(Id7->isIdentityWithExtract()); |
1227 | EXPECT_FALSE(Id7->isConcat()); |
1228 | delete Id7; |
1229 | |
1230 | // Result has more elements than operands; choose from Op0 and Op1 is not identity. |
1231 | ShuffleVectorInst *Id8 = new ShuffleVectorInst(V0, V1, |
1232 | ConstantVector::get(V: {C4, CU, C2, C3, CU, CU})); |
1233 | EXPECT_FALSE(Id8->isIdentity()); |
1234 | EXPECT_FALSE(Id8->isIdentityWithPadding()); |
1235 | EXPECT_FALSE(Id8->isIdentityWithExtract()); |
1236 | EXPECT_FALSE(Id8->isConcat()); |
1237 | delete Id8; |
1238 | |
1239 | // Result has twice as many elements as operands; choose consecutively from Op0 and Op1 is concat. |
1240 | ShuffleVectorInst *Id9 = new ShuffleVectorInst(V0, V1, |
1241 | ConstantVector::get(V: {C0, CU, C2, C3, CU, CU, C6, C7})); |
1242 | EXPECT_FALSE(Id9->isIdentity()); |
1243 | EXPECT_FALSE(Id9->isIdentityWithPadding()); |
1244 | EXPECT_FALSE(Id9->isIdentityWithExtract()); |
1245 | EXPECT_TRUE(Id9->isConcat()); |
1246 | delete Id9; |
1247 | |
1248 | // Result has less than twice as many elements as operands, so not a concat. |
1249 | ShuffleVectorInst *Id10 = new ShuffleVectorInst(V0, V1, |
1250 | ConstantVector::get(V: {C0, CU, C2, C3, CU, CU, C6})); |
1251 | EXPECT_FALSE(Id10->isIdentity()); |
1252 | EXPECT_FALSE(Id10->isIdentityWithPadding()); |
1253 | EXPECT_FALSE(Id10->isIdentityWithExtract()); |
1254 | EXPECT_FALSE(Id10->isConcat()); |
1255 | delete Id10; |
1256 | |
1257 | // Result has more than twice as many elements as operands, so not a concat. |
1258 | ShuffleVectorInst *Id11 = new ShuffleVectorInst(V0, V1, |
1259 | ConstantVector::get(V: {C0, CU, C2, C3, CU, CU, C6, C7, CU})); |
1260 | EXPECT_FALSE(Id11->isIdentity()); |
1261 | EXPECT_FALSE(Id11->isIdentityWithPadding()); |
1262 | EXPECT_FALSE(Id11->isIdentityWithExtract()); |
1263 | EXPECT_FALSE(Id11->isConcat()); |
1264 | delete Id11; |
1265 | |
1266 | // If an input is undef, it's not a concat. |
1267 | // TODO: IdentityWithPadding should be true here even though the high mask values are not undef. |
1268 | ShuffleVectorInst *Id12 = new ShuffleVectorInst(V0, ConstantVector::get(V: {CU, CU, CU, CU}), |
1269 | ConstantVector::get(V: {C0, CU, C2, C3, CU, CU, C6, C7})); |
1270 | EXPECT_FALSE(Id12->isIdentity()); |
1271 | EXPECT_FALSE(Id12->isIdentityWithPadding()); |
1272 | EXPECT_FALSE(Id12->isIdentityWithExtract()); |
1273 | EXPECT_FALSE(Id12->isConcat()); |
1274 | delete Id12; |
1275 | |
1276 | // Not possible to express shuffle mask for scalable vector for extract |
1277 | // subvector. |
1278 | Type *VScaleV4Int32Ty = ScalableVectorType::get(ElementType: Int32Ty, MinNumElts: 4); |
1279 | ShuffleVectorInst *Id13 = |
1280 | new ShuffleVectorInst(Constant::getAllOnesValue(Ty: VScaleV4Int32Ty), |
1281 | UndefValue::get(T: VScaleV4Int32Ty), |
1282 | Constant::getNullValue(Ty: VScaleV4Int32Ty)); |
1283 | int Index = 0; |
1284 | EXPECT_FALSE(Id13->isExtractSubvectorMask(Index)); |
1285 | EXPECT_FALSE(Id13->changesLength()); |
1286 | EXPECT_FALSE(Id13->increasesLength()); |
1287 | delete Id13; |
1288 | |
1289 | // Result has twice as many operands. |
1290 | Type *VScaleV2Int32Ty = ScalableVectorType::get(ElementType: Int32Ty, MinNumElts: 2); |
1291 | ShuffleVectorInst *Id14 = |
1292 | new ShuffleVectorInst(Constant::getAllOnesValue(Ty: VScaleV2Int32Ty), |
1293 | UndefValue::get(T: VScaleV2Int32Ty), |
1294 | Constant::getNullValue(Ty: VScaleV4Int32Ty)); |
1295 | EXPECT_TRUE(Id14->changesLength()); |
1296 | EXPECT_TRUE(Id14->increasesLength()); |
1297 | delete Id14; |
1298 | |
1299 | // Not possible to express these masks for scalable vectors, make sure we |
1300 | // don't crash. |
1301 | ShuffleVectorInst *Id15 = |
1302 | new ShuffleVectorInst(Constant::getAllOnesValue(Ty: VScaleV2Int32Ty), |
1303 | Constant::getNullValue(Ty: VScaleV2Int32Ty), |
1304 | Constant::getNullValue(Ty: VScaleV2Int32Ty)); |
1305 | EXPECT_FALSE(Id15->isIdentityWithPadding()); |
1306 | EXPECT_FALSE(Id15->isIdentityWithExtract()); |
1307 | EXPECT_FALSE(Id15->isConcat()); |
1308 | delete Id15; |
1309 | } |
1310 | |
1311 | TEST(InstructionsTest, ShuffleMaskIsReplicationMask) { |
1312 | for (int ReplicationFactor : seq_inclusive(Begin: 1, End: 8)) { |
1313 | for (int VF : seq_inclusive(Begin: 1, End: 8)) { |
1314 | const auto ReplicatedMask = createReplicatedMask(ReplicationFactor, VF); |
1315 | int GuessedReplicationFactor = -1, GuessedVF = -1; |
1316 | EXPECT_TRUE(ShuffleVectorInst::isReplicationMask( |
1317 | ReplicatedMask, GuessedReplicationFactor, GuessedVF)); |
1318 | EXPECT_EQ(GuessedReplicationFactor, ReplicationFactor); |
1319 | EXPECT_EQ(GuessedVF, VF); |
1320 | |
1321 | for (int OpVF : seq_inclusive(Begin: VF, End: 2 * VF + 1)) { |
1322 | LLVMContext Ctx; |
1323 | Type *OpVFTy = FixedVectorType::get(ElementType: IntegerType::getInt1Ty(C&: Ctx), NumElts: OpVF); |
1324 | Value *Op = ConstantVector::getNullValue(Ty: OpVFTy); |
1325 | ShuffleVectorInst *SVI = new ShuffleVectorInst(Op, Op, ReplicatedMask); |
1326 | EXPECT_EQ(SVI->isReplicationMask(GuessedReplicationFactor, GuessedVF), |
1327 | OpVF == VF); |
1328 | delete SVI; |
1329 | } |
1330 | } |
1331 | } |
1332 | } |
1333 | |
1334 | TEST(InstructionsTest, ShuffleMaskIsReplicationMask_undef) { |
1335 | for (int ReplicationFactor : seq_inclusive(Begin: 1, End: 4)) { |
1336 | for (int VF : seq_inclusive(Begin: 1, End: 4)) { |
1337 | const auto ReplicatedMask = createReplicatedMask(ReplicationFactor, VF); |
1338 | int GuessedReplicationFactor = -1, GuessedVF = -1; |
1339 | |
1340 | // If we change some mask elements to undef, we should still match. |
1341 | |
1342 | SmallVector<SmallVector<bool>> ElementChoices(ReplicatedMask.size(), |
1343 | {false, true}); |
1344 | |
1345 | CombinationGenerator<bool, decltype(ElementChoices)::value_type, |
1346 | /*variable_smallsize=*/4> |
1347 | G(ElementChoices); |
1348 | |
1349 | G.generate(Callback: [&](ArrayRef<bool> UndefOverrides) -> bool { |
1350 | SmallVector<int> AdjustedMask; |
1351 | AdjustedMask.reserve(N: ReplicatedMask.size()); |
1352 | for (auto I : zip(t: ReplicatedMask, u&: UndefOverrides)) |
1353 | AdjustedMask.emplace_back(Args: std::get<1>(t&: I) ? -1 : std::get<0>(t&: I)); |
1354 | assert(AdjustedMask.size() == ReplicatedMask.size() && |
1355 | "Size misprediction" ); |
1356 | |
1357 | EXPECT_TRUE(ShuffleVectorInst::isReplicationMask( |
1358 | AdjustedMask, GuessedReplicationFactor, GuessedVF)); |
1359 | // Do not check GuessedReplicationFactor and GuessedVF, |
1360 | // with enough undef's we may deduce a different tuple. |
1361 | |
1362 | return /*Abort=*/false; |
1363 | }); |
1364 | } |
1365 | } |
1366 | } |
1367 | |
1368 | TEST(InstructionsTest, ShuffleMaskIsReplicationMask_Exhaustive_Correctness) { |
1369 | for (int ShufMaskNumElts : seq_inclusive(Begin: 1, End: 6)) { |
1370 | SmallVector<int> PossibleShufMaskElts; |
1371 | PossibleShufMaskElts.reserve(N: ShufMaskNumElts + 2); |
1372 | for (int PossibleShufMaskElt : seq_inclusive(Begin: -1, End: ShufMaskNumElts)) |
1373 | PossibleShufMaskElts.emplace_back(Args&: PossibleShufMaskElt); |
1374 | assert(PossibleShufMaskElts.size() == ShufMaskNumElts + 2U && |
1375 | "Size misprediction" ); |
1376 | |
1377 | SmallVector<SmallVector<int>> ElementChoices(ShufMaskNumElts, |
1378 | PossibleShufMaskElts); |
1379 | |
1380 | CombinationGenerator<int, decltype(ElementChoices)::value_type, |
1381 | /*variable_smallsize=*/4> |
1382 | G(ElementChoices); |
1383 | |
1384 | G.generate(Callback: [&](ArrayRef<int> Mask) -> bool { |
1385 | int GuessedReplicationFactor = -1, GuessedVF = -1; |
1386 | bool Match = ShuffleVectorInst::isReplicationMask( |
1387 | Mask, ReplicationFactor&: GuessedReplicationFactor, VF&: GuessedVF); |
1388 | if (!Match) |
1389 | return /*Abort=*/false; |
1390 | |
1391 | const auto ActualMask = |
1392 | createReplicatedMask(ReplicationFactor: GuessedReplicationFactor, VF: GuessedVF); |
1393 | EXPECT_EQ(Mask.size(), ActualMask.size()); |
1394 | for (auto I : zip(t&: Mask, u: ActualMask)) { |
1395 | int Elt = std::get<0>(t&: I); |
1396 | int ActualElt = std::get<0>(t&: I); |
1397 | |
1398 | if (Elt != -1) { |
1399 | EXPECT_EQ(Elt, ActualElt); |
1400 | } |
1401 | } |
1402 | |
1403 | return /*Abort=*/false; |
1404 | }); |
1405 | } |
1406 | } |
1407 | |
1408 | TEST(InstructionsTest, GetSplat) { |
1409 | // Create the elements for various constant vectors. |
1410 | LLVMContext Ctx; |
1411 | Type *Int32Ty = Type::getInt32Ty(C&: Ctx); |
1412 | Constant *CU = UndefValue::get(T: Int32Ty); |
1413 | Constant *CP = PoisonValue::get(T: Int32Ty); |
1414 | Constant *C0 = ConstantInt::get(Ty: Int32Ty, V: 0); |
1415 | Constant *C1 = ConstantInt::get(Ty: Int32Ty, V: 1); |
1416 | |
1417 | Constant *Splat0 = ConstantVector::get(V: {C0, C0, C0, C0}); |
1418 | Constant *Splat1 = ConstantVector::get(V: {C1, C1, C1, C1 ,C1}); |
1419 | Constant *Splat0Undef = ConstantVector::get(V: {C0, CU, C0, CU}); |
1420 | Constant *Splat1Undef = ConstantVector::get(V: {CU, CU, C1, CU}); |
1421 | Constant *NotSplat = ConstantVector::get(V: {C1, C1, C0, C1 ,C1}); |
1422 | Constant *NotSplatUndef = ConstantVector::get(V: {CU, C1, CU, CU ,C0}); |
1423 | Constant *Splat0Poison = ConstantVector::get(V: {C0, CP, C0, CP}); |
1424 | Constant *Splat1Poison = ConstantVector::get(V: {CP, CP, C1, CP}); |
1425 | Constant *NotSplatPoison = ConstantVector::get(V: {CP, C1, CP, CP, C0}); |
1426 | |
1427 | // Default - undef/poison is not allowed. |
1428 | EXPECT_EQ(Splat0->getSplatValue(), C0); |
1429 | EXPECT_EQ(Splat1->getSplatValue(), C1); |
1430 | EXPECT_EQ(Splat0Undef->getSplatValue(), nullptr); |
1431 | EXPECT_EQ(Splat1Undef->getSplatValue(), nullptr); |
1432 | EXPECT_EQ(Splat0Poison->getSplatValue(), nullptr); |
1433 | EXPECT_EQ(Splat1Poison->getSplatValue(), nullptr); |
1434 | EXPECT_EQ(NotSplat->getSplatValue(), nullptr); |
1435 | EXPECT_EQ(NotSplatUndef->getSplatValue(), nullptr); |
1436 | EXPECT_EQ(NotSplatPoison->getSplatValue(), nullptr); |
1437 | |
1438 | // Disallow poison explicitly. |
1439 | EXPECT_EQ(Splat0->getSplatValue(false), C0); |
1440 | EXPECT_EQ(Splat1->getSplatValue(false), C1); |
1441 | EXPECT_EQ(Splat0Undef->getSplatValue(false), nullptr); |
1442 | EXPECT_EQ(Splat1Undef->getSplatValue(false), nullptr); |
1443 | EXPECT_EQ(Splat0Poison->getSplatValue(false), nullptr); |
1444 | EXPECT_EQ(Splat1Poison->getSplatValue(false), nullptr); |
1445 | EXPECT_EQ(NotSplat->getSplatValue(false), nullptr); |
1446 | EXPECT_EQ(NotSplatUndef->getSplatValue(false), nullptr); |
1447 | EXPECT_EQ(NotSplatPoison->getSplatValue(false), nullptr); |
1448 | |
1449 | // Allow poison but not undef. |
1450 | EXPECT_EQ(Splat0->getSplatValue(true), C0); |
1451 | EXPECT_EQ(Splat1->getSplatValue(true), C1); |
1452 | EXPECT_EQ(Splat0Undef->getSplatValue(true), nullptr); |
1453 | EXPECT_EQ(Splat1Undef->getSplatValue(true), nullptr); |
1454 | EXPECT_EQ(Splat0Poison->getSplatValue(true), C0); |
1455 | EXPECT_EQ(Splat1Poison->getSplatValue(true), C1); |
1456 | EXPECT_EQ(NotSplat->getSplatValue(true), nullptr); |
1457 | EXPECT_EQ(NotSplatUndef->getSplatValue(true), nullptr); |
1458 | EXPECT_EQ(NotSplatPoison->getSplatValue(true), nullptr); |
1459 | } |
1460 | |
1461 | TEST(InstructionsTest, SkipDebug) { |
1462 | LLVMContext C; |
1463 | std::unique_ptr<Module> M = parseIR(C, |
1464 | IR: R"( |
1465 | declare void @llvm.dbg.value(metadata, metadata, metadata) |
1466 | |
1467 | define void @f() { |
1468 | entry: |
1469 | call void @llvm.dbg.value(metadata i32 0, metadata !11, metadata !DIExpression()), !dbg !13 |
1470 | ret void |
1471 | } |
1472 | |
1473 | !llvm.dbg.cu = !{!0} |
1474 | !llvm.module.flags = !{!3, !4} |
1475 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) |
1476 | !1 = !DIFile(filename: "t2.c", directory: "foo") |
1477 | !2 = !{} |
1478 | !3 = !{i32 2, !"Dwarf Version", i32 4} |
1479 | !4 = !{i32 2, !"Debug Info Version", i32 3} |
1480 | !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) |
1481 | !9 = !DISubroutineType(types: !10) |
1482 | !10 = !{null} |
1483 | !11 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !12) |
1484 | !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) |
1485 | !13 = !DILocation(line: 2, column: 7, scope: !8) |
1486 | )" ); |
1487 | ASSERT_TRUE(M); |
1488 | Function *F = cast<Function>(Val: M->getNamedValue(Name: "f" )); |
1489 | BasicBlock &BB = F->front(); |
1490 | |
1491 | // The first non-debug instruction is the terminator. |
1492 | auto *Term = BB.getTerminator(); |
1493 | EXPECT_EQ(Term, BB.begin()->getNextNonDebugInstruction()); |
1494 | EXPECT_EQ(Term->getIterator(), skipDebugIntrinsics(BB.begin())); |
1495 | |
1496 | // After the terminator, there are no non-debug instructions. |
1497 | EXPECT_EQ(nullptr, Term->getNextNonDebugInstruction()); |
1498 | } |
1499 | |
1500 | TEST(InstructionsTest, PhiMightNotBeFPMathOperator) { |
1501 | LLVMContext Context; |
1502 | IRBuilder<> Builder(Context); |
1503 | MDBuilder MDHelper(Context); |
1504 | Instruction *I = Builder.CreatePHI(Ty: Builder.getInt32Ty(), NumReservedValues: 0); |
1505 | EXPECT_FALSE(isa<FPMathOperator>(I)); |
1506 | I->deleteValue(); |
1507 | Instruction *FP = Builder.CreatePHI(Ty: Builder.getDoubleTy(), NumReservedValues: 0); |
1508 | EXPECT_TRUE(isa<FPMathOperator>(FP)); |
1509 | FP->deleteValue(); |
1510 | } |
1511 | |
1512 | TEST(InstructionsTest, FPCallIsFPMathOperator) { |
1513 | LLVMContext C; |
1514 | |
1515 | Type *ITy = Type::getInt32Ty(C); |
1516 | FunctionType *IFnTy = FunctionType::get(Result: ITy, isVarArg: {}); |
1517 | PointerType *PtrTy = PointerType::getUnqual(C); |
1518 | Value *ICallee = Constant::getNullValue(Ty: PtrTy); |
1519 | std::unique_ptr<CallInst> ICall(CallInst::Create(Ty: IFnTy, Func: ICallee, Args: {}, NameStr: "" )); |
1520 | EXPECT_FALSE(isa<FPMathOperator>(ICall)); |
1521 | |
1522 | Type *VITy = FixedVectorType::get(ElementType: ITy, NumElts: 2); |
1523 | FunctionType *VIFnTy = FunctionType::get(Result: VITy, isVarArg: {}); |
1524 | Value *VICallee = Constant::getNullValue(Ty: PtrTy); |
1525 | std::unique_ptr<CallInst> VICall(CallInst::Create(Ty: VIFnTy, Func: VICallee, Args: {}, NameStr: "" )); |
1526 | EXPECT_FALSE(isa<FPMathOperator>(VICall)); |
1527 | |
1528 | Type *AITy = ArrayType::get(ElementType: ITy, NumElements: 2); |
1529 | FunctionType *AIFnTy = FunctionType::get(Result: AITy, isVarArg: {}); |
1530 | Value *AICallee = Constant::getNullValue(Ty: PtrTy); |
1531 | std::unique_ptr<CallInst> AICall(CallInst::Create(Ty: AIFnTy, Func: AICallee, Args: {}, NameStr: "" )); |
1532 | EXPECT_FALSE(isa<FPMathOperator>(AICall)); |
1533 | |
1534 | Type *FTy = Type::getFloatTy(C); |
1535 | FunctionType *FFnTy = FunctionType::get(Result: FTy, isVarArg: {}); |
1536 | Value *FCallee = Constant::getNullValue(Ty: PtrTy); |
1537 | std::unique_ptr<CallInst> FCall(CallInst::Create(Ty: FFnTy, Func: FCallee, Args: {}, NameStr: "" )); |
1538 | EXPECT_TRUE(isa<FPMathOperator>(FCall)); |
1539 | |
1540 | Type *VFTy = FixedVectorType::get(ElementType: FTy, NumElts: 2); |
1541 | FunctionType *VFFnTy = FunctionType::get(Result: VFTy, isVarArg: {}); |
1542 | Value *VFCallee = Constant::getNullValue(Ty: PtrTy); |
1543 | std::unique_ptr<CallInst> VFCall(CallInst::Create(Ty: VFFnTy, Func: VFCallee, Args: {}, NameStr: "" )); |
1544 | EXPECT_TRUE(isa<FPMathOperator>(VFCall)); |
1545 | |
1546 | Type *AFTy = ArrayType::get(ElementType: FTy, NumElements: 2); |
1547 | FunctionType *AFFnTy = FunctionType::get(Result: AFTy, isVarArg: {}); |
1548 | Value *AFCallee = Constant::getNullValue(Ty: PtrTy); |
1549 | std::unique_ptr<CallInst> AFCall(CallInst::Create(Ty: AFFnTy, Func: AFCallee, Args: {}, NameStr: "" )); |
1550 | EXPECT_TRUE(isa<FPMathOperator>(AFCall)); |
1551 | |
1552 | Type *AVFTy = ArrayType::get(ElementType: VFTy, NumElements: 2); |
1553 | FunctionType *AVFFnTy = FunctionType::get(Result: AVFTy, isVarArg: {}); |
1554 | Value *AVFCallee = Constant::getNullValue(Ty: PtrTy); |
1555 | std::unique_ptr<CallInst> AVFCall( |
1556 | CallInst::Create(Ty: AVFFnTy, Func: AVFCallee, Args: {}, NameStr: "" )); |
1557 | EXPECT_TRUE(isa<FPMathOperator>(AVFCall)); |
1558 | |
1559 | Type *AAVFTy = ArrayType::get(ElementType: AVFTy, NumElements: 2); |
1560 | FunctionType *AAVFFnTy = FunctionType::get(Result: AAVFTy, isVarArg: {}); |
1561 | Value *AAVFCallee = Constant::getNullValue(Ty: PtrTy); |
1562 | std::unique_ptr<CallInst> AAVFCall( |
1563 | CallInst::Create(Ty: AAVFFnTy, Func: AAVFCallee, Args: {}, NameStr: "" )); |
1564 | EXPECT_TRUE(isa<FPMathOperator>(AAVFCall)); |
1565 | } |
1566 | |
1567 | TEST(InstructionsTest, FNegInstruction) { |
1568 | LLVMContext Context; |
1569 | Type *FltTy = Type::getFloatTy(C&: Context); |
1570 | Constant *One = ConstantFP::get(Ty: FltTy, V: 1.0); |
1571 | BinaryOperator *FAdd = BinaryOperator::CreateFAdd(V1: One, V2: One); |
1572 | FAdd->setHasNoNaNs(true); |
1573 | UnaryOperator *FNeg = UnaryOperator::CreateFNegFMF(Op: One, FMFSource: FAdd); |
1574 | EXPECT_TRUE(FNeg->hasNoNaNs()); |
1575 | EXPECT_FALSE(FNeg->hasNoInfs()); |
1576 | EXPECT_FALSE(FNeg->hasNoSignedZeros()); |
1577 | EXPECT_FALSE(FNeg->hasAllowReciprocal()); |
1578 | EXPECT_FALSE(FNeg->hasAllowContract()); |
1579 | EXPECT_FALSE(FNeg->hasAllowReassoc()); |
1580 | EXPECT_FALSE(FNeg->hasApproxFunc()); |
1581 | FAdd->deleteValue(); |
1582 | FNeg->deleteValue(); |
1583 | } |
1584 | |
1585 | TEST(InstructionsTest, CallBrInstruction) { |
1586 | LLVMContext Context; |
1587 | std::unique_ptr<Module> M = parseIR(C&: Context, IR: R"( |
1588 | define void @foo() { |
1589 | entry: |
1590 | callbr void asm sideeffect "// XXX: ${0:l}", "!i"() |
1591 | to label %land.rhs.i [label %branch_test.exit] |
1592 | |
1593 | land.rhs.i: |
1594 | br label %branch_test.exit |
1595 | |
1596 | branch_test.exit: |
1597 | %0 = phi i1 [ true, %entry ], [ false, %land.rhs.i ] |
1598 | br i1 %0, label %if.end, label %if.then |
1599 | |
1600 | if.then: |
1601 | ret void |
1602 | |
1603 | if.end: |
1604 | ret void |
1605 | } |
1606 | )" ); |
1607 | Function *Foo = M->getFunction(Name: "foo" ); |
1608 | auto BBs = Foo->begin(); |
1609 | CallBrInst &CBI = cast<CallBrInst>(Val&: BBs->front()); |
1610 | ++BBs; |
1611 | ++BBs; |
1612 | BasicBlock &BranchTestExit = *BBs; |
1613 | ++BBs; |
1614 | BasicBlock &IfThen = *BBs; |
1615 | |
1616 | // Test that setting the first indirect destination of callbr updates the dest |
1617 | EXPECT_EQ(&BranchTestExit, CBI.getIndirectDest(0)); |
1618 | CBI.setIndirectDest(i: 0, B: &IfThen); |
1619 | EXPECT_EQ(&IfThen, CBI.getIndirectDest(0)); |
1620 | } |
1621 | |
1622 | TEST(InstructionsTest, UnaryOperator) { |
1623 | LLVMContext Context; |
1624 | IRBuilder<> Builder(Context); |
1625 | Instruction *I = Builder.CreatePHI(Ty: Builder.getDoubleTy(), NumReservedValues: 0); |
1626 | Value *F = Builder.CreateFNeg(V: I); |
1627 | |
1628 | EXPECT_TRUE(isa<Value>(F)); |
1629 | EXPECT_TRUE(isa<Instruction>(F)); |
1630 | EXPECT_TRUE(isa<UnaryInstruction>(F)); |
1631 | EXPECT_TRUE(isa<UnaryOperator>(F)); |
1632 | EXPECT_FALSE(isa<BinaryOperator>(F)); |
1633 | |
1634 | F->deleteValue(); |
1635 | I->deleteValue(); |
1636 | } |
1637 | |
1638 | TEST(InstructionsTest, DropLocation) { |
1639 | LLVMContext C; |
1640 | std::unique_ptr<Module> M = parseIR(C, |
1641 | IR: R"( |
1642 | declare void @callee() |
1643 | |
1644 | define void @no_parent_scope() { |
1645 | call void @callee() ; I1: Call with no location. |
1646 | call void @callee(), !dbg !11 ; I2: Call with location. |
1647 | ret void, !dbg !11 ; I3: Non-call with location. |
1648 | } |
1649 | |
1650 | define void @with_parent_scope() !dbg !8 { |
1651 | call void @callee() ; I1: Call with no location. |
1652 | call void @callee(), !dbg !11 ; I2: Call with location. |
1653 | ret void, !dbg !11 ; I3: Non-call with location. |
1654 | } |
1655 | |
1656 | !llvm.dbg.cu = !{!0} |
1657 | !llvm.module.flags = !{!3, !4} |
1658 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) |
1659 | !1 = !DIFile(filename: "t2.c", directory: "foo") |
1660 | !2 = !{} |
1661 | !3 = !{i32 2, !"Dwarf Version", i32 4} |
1662 | !4 = !{i32 2, !"Debug Info Version", i32 3} |
1663 | !8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) |
1664 | !9 = !DISubroutineType(types: !10) |
1665 | !10 = !{null} |
1666 | !11 = !DILocation(line: 2, column: 7, scope: !8, inlinedAt: !12) |
1667 | !12 = !DILocation(line: 3, column: 8, scope: !8) |
1668 | )" ); |
1669 | ASSERT_TRUE(M); |
1670 | |
1671 | { |
1672 | Function *NoParentScopeF = |
1673 | cast<Function>(Val: M->getNamedValue(Name: "no_parent_scope" )); |
1674 | BasicBlock &BB = NoParentScopeF->front(); |
1675 | |
1676 | auto *I1 = BB.getFirstNonPHI(); |
1677 | auto *I2 = I1->getNextNode(); |
1678 | auto *I3 = BB.getTerminator(); |
1679 | |
1680 | EXPECT_EQ(I1->getDebugLoc(), DebugLoc()); |
1681 | I1->dropLocation(); |
1682 | EXPECT_EQ(I1->getDebugLoc(), DebugLoc()); |
1683 | |
1684 | EXPECT_EQ(I2->getDebugLoc().getLine(), 2U); |
1685 | I2->dropLocation(); |
1686 | EXPECT_EQ(I1->getDebugLoc(), DebugLoc()); |
1687 | |
1688 | EXPECT_EQ(I3->getDebugLoc().getLine(), 2U); |
1689 | I3->dropLocation(); |
1690 | EXPECT_EQ(I3->getDebugLoc(), DebugLoc()); |
1691 | } |
1692 | |
1693 | { |
1694 | Function *WithParentScopeF = |
1695 | cast<Function>(Val: M->getNamedValue(Name: "with_parent_scope" )); |
1696 | BasicBlock &BB = WithParentScopeF->front(); |
1697 | |
1698 | auto *I2 = BB.getFirstNonPHI()->getNextNode(); |
1699 | |
1700 | MDNode *Scope = cast<MDNode>(Val: WithParentScopeF->getSubprogram()); |
1701 | EXPECT_EQ(I2->getDebugLoc().getLine(), 2U); |
1702 | I2->dropLocation(); |
1703 | EXPECT_EQ(I2->getDebugLoc().getLine(), 0U); |
1704 | EXPECT_EQ(I2->getDebugLoc().getScope(), Scope); |
1705 | EXPECT_EQ(I2->getDebugLoc().getInlinedAt(), nullptr); |
1706 | } |
1707 | } |
1708 | |
1709 | TEST(InstructionsTest, BranchWeightOverflow) { |
1710 | LLVMContext C; |
1711 | std::unique_ptr<Module> M = parseIR(C, |
1712 | IR: R"( |
1713 | declare void @callee() |
1714 | |
1715 | define void @caller() { |
1716 | call void @callee(), !prof !1 |
1717 | ret void |
1718 | } |
1719 | |
1720 | !1 = !{!"branch_weights", i32 20000} |
1721 | )" ); |
1722 | ASSERT_TRUE(M); |
1723 | CallInst *CI = |
1724 | cast<CallInst>(Val: &M->getFunction(Name: "caller" )->getEntryBlock().front()); |
1725 | uint64_t ProfWeight; |
1726 | CI->extractProfTotalWeight(TotalVal&: ProfWeight); |
1727 | ASSERT_EQ(ProfWeight, 20000U); |
1728 | CI->updateProfWeight(S: 10000000, T: 1); |
1729 | CI->extractProfTotalWeight(TotalVal&: ProfWeight); |
1730 | ASSERT_EQ(ProfWeight, UINT32_MAX); |
1731 | } |
1732 | |
1733 | TEST(InstructionsTest, AllocaInst) { |
1734 | LLVMContext Ctx; |
1735 | std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"( |
1736 | %T = type { i64, [3 x i32]} |
1737 | define void @f(i32 %n) { |
1738 | entry: |
1739 | %A = alloca i32, i32 1 |
1740 | %B = alloca i32, i32 4 |
1741 | %C = alloca i32, i32 %n |
1742 | %D = alloca <8 x double> |
1743 | %E = alloca <vscale x 8 x double> |
1744 | %F = alloca [2 x half] |
1745 | %G = alloca [2 x [3 x i128]] |
1746 | %H = alloca %T |
1747 | ret void |
1748 | } |
1749 | )" ); |
1750 | const DataLayout &DL = M->getDataLayout(); |
1751 | ASSERT_TRUE(M); |
1752 | Function *Fun = cast<Function>(Val: M->getNamedValue(Name: "f" )); |
1753 | BasicBlock &BB = Fun->front(); |
1754 | auto It = BB.begin(); |
1755 | AllocaInst &A = cast<AllocaInst>(Val&: *It++); |
1756 | AllocaInst &B = cast<AllocaInst>(Val&: *It++); |
1757 | AllocaInst &C = cast<AllocaInst>(Val&: *It++); |
1758 | AllocaInst &D = cast<AllocaInst>(Val&: *It++); |
1759 | AllocaInst &E = cast<AllocaInst>(Val&: *It++); |
1760 | AllocaInst &F = cast<AllocaInst>(Val&: *It++); |
1761 | AllocaInst &G = cast<AllocaInst>(Val&: *It++); |
1762 | AllocaInst &H = cast<AllocaInst>(Val&: *It++); |
1763 | EXPECT_EQ(A.getAllocationSizeInBits(DL), TypeSize::getFixed(32)); |
1764 | EXPECT_EQ(B.getAllocationSizeInBits(DL), TypeSize::getFixed(128)); |
1765 | EXPECT_FALSE(C.getAllocationSizeInBits(DL)); |
1766 | EXPECT_EQ(D.getAllocationSizeInBits(DL), TypeSize::getFixed(512)); |
1767 | EXPECT_EQ(E.getAllocationSizeInBits(DL), TypeSize::getScalable(512)); |
1768 | EXPECT_EQ(F.getAllocationSizeInBits(DL), TypeSize::getFixed(32)); |
1769 | EXPECT_EQ(G.getAllocationSizeInBits(DL), TypeSize::getFixed(768)); |
1770 | EXPECT_EQ(H.getAllocationSizeInBits(DL), TypeSize::getFixed(160)); |
1771 | } |
1772 | |
1773 | TEST(InstructionsTest, InsertAtBegin) { |
1774 | LLVMContext Ctx; |
1775 | std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"( |
1776 | define void @f(i32 %a, i32 %b) { |
1777 | entry: |
1778 | ret void |
1779 | } |
1780 | )" ); |
1781 | Function *F = &*M->begin(); |
1782 | Argument *ArgA = F->getArg(i: 0); |
1783 | Argument *ArgB = F->getArg(i: 1); |
1784 | BasicBlock *BB = &*F->begin(); |
1785 | Instruction *Ret = &*BB->begin(); |
1786 | Instruction *I = BinaryOperator::CreateAdd(V1: ArgA, V2: ArgB); |
1787 | auto It = I->insertInto(ParentBB: BB, It: BB->begin()); |
1788 | EXPECT_EQ(&*It, I); |
1789 | EXPECT_EQ(I->getNextNode(), Ret); |
1790 | } |
1791 | |
1792 | TEST(InstructionsTest, InsertAtEnd) { |
1793 | LLVMContext Ctx; |
1794 | std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"( |
1795 | define void @f(i32 %a, i32 %b) { |
1796 | entry: |
1797 | ret void |
1798 | } |
1799 | )" ); |
1800 | Function *F = &*M->begin(); |
1801 | Argument *ArgA = F->getArg(i: 0); |
1802 | Argument *ArgB = F->getArg(i: 1); |
1803 | BasicBlock *BB = &*F->begin(); |
1804 | Instruction *Ret = &*BB->begin(); |
1805 | Instruction *I = BinaryOperator::CreateAdd(V1: ArgA, V2: ArgB); |
1806 | auto It = I->insertInto(ParentBB: BB, It: BB->end()); |
1807 | EXPECT_EQ(&*It, I); |
1808 | EXPECT_EQ(Ret->getNextNode(), I); |
1809 | } |
1810 | |
1811 | } // end anonymous namespace |
1812 | } // end namespace llvm |
1813 | |