1//===- llvm/unittest/IR/IRBuilderTest.cpp - IRBuilder 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/Analysis/InstSimplifyFolder.h"
10#include "llvm/IR/IRBuilder.h"
11#include "llvm/IR/BasicBlock.h"
12#include "llvm/IR/DIBuilder.h"
13#include "llvm/IR/DataLayout.h"
14#include "llvm/IR/Function.h"
15#include "llvm/IR/IntrinsicInst.h"
16#include "llvm/IR/IntrinsicsAArch64.h"
17#include "llvm/IR/LLVMContext.h"
18#include "llvm/IR/MDBuilder.h"
19#include "llvm/IR/Module.h"
20#include "llvm/IR/NoFolder.h"
21#include "llvm/IR/Verifier.h"
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
24
25#include <type_traits>
26
27using namespace llvm;
28using ::testing::UnorderedElementsAre;
29
30namespace {
31
32class IRBuilderTest : public testing::Test {
33protected:
34 void SetUp() override {
35 M.reset(p: new Module("MyModule", Ctx));
36 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C&: Ctx),
37 /*isVarArg=*/false);
38 F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "", M: M.get());
39 BB = BasicBlock::Create(Context&: Ctx, Name: "", Parent: F);
40 GV = new GlobalVariable(*M, Type::getFloatTy(C&: Ctx), true,
41 GlobalValue::ExternalLinkage, nullptr);
42 }
43
44 void TearDown() override {
45 BB = nullptr;
46 M.reset();
47 }
48
49 LLVMContext Ctx;
50 std::unique_ptr<Module> M;
51 Function *F;
52 BasicBlock *BB;
53 GlobalVariable *GV;
54};
55
56TEST_F(IRBuilderTest, Intrinsics) {
57 IRBuilder<> Builder(BB);
58 Value *V;
59 Instruction *I;
60 Value *Result;
61 IntrinsicInst *II;
62
63 V = Builder.CreateLoad(Ty: GV->getValueType(), Ptr: GV);
64 I = cast<Instruction>(Val: Builder.CreateFAdd(L: V, R: V));
65 I->setHasNoInfs(true);
66 I->setHasNoNaNs(false);
67
68 Result = Builder.CreateMinNum(LHS: V, RHS: V);
69 II = cast<IntrinsicInst>(Val: Result);
70 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::minnum);
71
72 Result = Builder.CreateMaxNum(LHS: V, RHS: V);
73 II = cast<IntrinsicInst>(Val: Result);
74 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::maxnum);
75
76 Result = Builder.CreateMinimum(LHS: V, RHS: V);
77 II = cast<IntrinsicInst>(Val: Result);
78 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::minimum);
79
80 Result = Builder.CreateMaximum(LHS: V, RHS: V);
81 II = cast<IntrinsicInst>(Val: Result);
82 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::maximum);
83
84 Result = Builder.CreateIntrinsic(Intrinsic::readcyclecounter, {}, {});
85 II = cast<IntrinsicInst>(Val: Result);
86 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::readcyclecounter);
87
88 Result = Builder.CreateUnaryIntrinsic(Intrinsic::ID: fabs, V);
89 II = cast<IntrinsicInst>(Val: Result);
90 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs);
91 EXPECT_FALSE(II->hasNoInfs());
92 EXPECT_FALSE(II->hasNoNaNs());
93
94 Result = Builder.CreateUnaryIntrinsic(Intrinsic::ID: fabs, V, FMFSource: I);
95 II = cast<IntrinsicInst>(Val: Result);
96 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs);
97 EXPECT_TRUE(II->hasNoInfs());
98 EXPECT_FALSE(II->hasNoNaNs());
99
100 Result = Builder.CreateBinaryIntrinsic(Intrinsic::ID: pow, LHS: V, RHS: V);
101 II = cast<IntrinsicInst>(Val: Result);
102 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow);
103 EXPECT_FALSE(II->hasNoInfs());
104 EXPECT_FALSE(II->hasNoNaNs());
105
106 Result = Builder.CreateBinaryIntrinsic(Intrinsic::ID: pow, LHS: V, RHS: V, FMFSource: I);
107 II = cast<IntrinsicInst>(Val: Result);
108 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow);
109 EXPECT_TRUE(II->hasNoInfs());
110 EXPECT_FALSE(II->hasNoNaNs());
111
112 Result = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V});
113 II = cast<IntrinsicInst>(Val: Result);
114 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
115 EXPECT_FALSE(II->hasNoInfs());
116 EXPECT_FALSE(II->hasNoNaNs());
117
118 Result =
119 Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
120 II = cast<IntrinsicInst>(Val: Result);
121 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
122 EXPECT_TRUE(II->hasNoInfs());
123 EXPECT_FALSE(II->hasNoNaNs());
124
125 Result =
126 Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I);
127 II = cast<IntrinsicInst>(Val: Result);
128 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma);
129 EXPECT_TRUE(II->hasNoInfs());
130 EXPECT_FALSE(II->hasNoNaNs());
131
132 Result = Builder.CreateUnaryIntrinsic(Intrinsic::ID: roundeven, V);
133 II = cast<IntrinsicInst>(Val: Result);
134 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::roundeven);
135 EXPECT_FALSE(II->hasNoInfs());
136 EXPECT_FALSE(II->hasNoNaNs());
137
138 Result = Builder.CreateIntrinsic(
139 Intrinsic::set_rounding, {},
140 {Builder.getInt32(C: static_cast<uint32_t>(RoundingMode::TowardZero))});
141 II = cast<IntrinsicInst>(Val: Result);
142 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::set_rounding);
143}
144
145TEST_F(IRBuilderTest, IntrinsicMangling) {
146 IRBuilder<> Builder(BB);
147 Type *VoidTy = Builder.getVoidTy();
148 Type *Int64Ty = Builder.getInt64Ty();
149 Value *Int64Val = Builder.getInt64(C: 0);
150 Value *DoubleVal = PoisonValue::get(T: Builder.getDoubleTy());
151 CallInst *Call;
152
153 // Mangled return type, no arguments.
154 Call = Builder.CreateIntrinsic(Int64Ty, Intrinsic::coro_size, {});
155 EXPECT_EQ(Call->getCalledFunction()->getName(), "llvm.coro.size.i64");
156
157 // Void return type, mangled argument type.
158 Call =
159 Builder.CreateIntrinsic(VoidTy, Intrinsic::set_loop_iterations, Int64Val);
160 EXPECT_EQ(Call->getCalledFunction()->getName(),
161 "llvm.set.loop.iterations.i64");
162
163 // Mangled return type and argument type.
164 Call = Builder.CreateIntrinsic(Int64Ty, Intrinsic::lround, DoubleVal);
165 EXPECT_EQ(Call->getCalledFunction()->getName(), "llvm.lround.i64.f64");
166}
167
168TEST_F(IRBuilderTest, IntrinsicsWithScalableVectors) {
169 IRBuilder<> Builder(BB);
170 CallInst *Call;
171 FunctionType *FTy;
172
173 // Test scalable flag isn't dropped for intrinsic that is explicitly defined
174 // with scalable vectors, e.g. LLVMType<nxv4i32>.
175 Type *SrcVecTy = VectorType::get(ElementType: Builder.getHalfTy(), NumElements: 8, Scalable: true);
176 Type *DstVecTy = VectorType::get(ElementType: Builder.getInt32Ty(), NumElements: 4, Scalable: true);
177 Type *PredTy = VectorType::get(ElementType: Builder.getInt1Ty(), NumElements: 4, Scalable: true);
178
179 SmallVector<Value*, 3> ArgTys;
180 ArgTys.push_back(Elt: UndefValue::get(T: DstVecTy));
181 ArgTys.push_back(Elt: UndefValue::get(T: PredTy));
182 ArgTys.push_back(Elt: UndefValue::get(T: SrcVecTy));
183
184 Call = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_fcvtzs_i32f16, {},
185 ArgTys, nullptr, "aarch64.sve.fcvtzs.i32f16");
186 FTy = Call->getFunctionType();
187 EXPECT_EQ(FTy->getReturnType(), DstVecTy);
188 for (unsigned i = 0; i != ArgTys.size(); ++i)
189 EXPECT_EQ(FTy->getParamType(i), ArgTys[i]->getType());
190
191 // Test scalable flag isn't dropped for intrinsic defined with
192 // LLVMScalarOrSameVectorWidth.
193
194 Type *VecTy = VectorType::get(ElementType: Builder.getInt32Ty(), NumElements: 4, Scalable: true);
195 Type *PtrToVecTy = Builder.getPtrTy();
196 PredTy = VectorType::get(ElementType: Builder.getInt1Ty(), NumElements: 4, Scalable: true);
197
198 ArgTys.clear();
199 ArgTys.push_back(Elt: UndefValue::get(T: PtrToVecTy));
200 ArgTys.push_back(Elt: UndefValue::get(T: Builder.getInt32Ty()));
201 ArgTys.push_back(Elt: UndefValue::get(T: PredTy));
202 ArgTys.push_back(Elt: UndefValue::get(T: VecTy));
203
204 Call = Builder.CreateIntrinsic(Intrinsic::masked_load,
205 {VecTy, PtrToVecTy}, ArgTys,
206 nullptr, "masked.load");
207 FTy = Call->getFunctionType();
208 EXPECT_EQ(FTy->getReturnType(), VecTy);
209 for (unsigned i = 0; i != ArgTys.size(); ++i)
210 EXPECT_EQ(FTy->getParamType(i), ArgTys[i]->getType());
211}
212
213TEST_F(IRBuilderTest, CreateVScale) {
214 IRBuilder<> Builder(BB);
215
216 Constant *Zero = Builder.getInt32(C: 0);
217 Value *VScale = Builder.CreateVScale(Scaling: Zero);
218 EXPECT_TRUE(isa<ConstantInt>(VScale) && cast<ConstantInt>(VScale)->isZero());
219}
220
221TEST_F(IRBuilderTest, CreateStepVector) {
222 IRBuilder<> Builder(BB);
223
224 // Fixed width vectors
225 Type *DstVecTy = VectorType::get(ElementType: Builder.getInt32Ty(), NumElements: 4, Scalable: false);
226 Value *StepVec = Builder.CreateStepVector(DstType: DstVecTy);
227 EXPECT_TRUE(isa<Constant>(StepVec));
228 EXPECT_EQ(StepVec->getType(), DstVecTy);
229
230 const auto *VectorValue = cast<Constant>(Val: StepVec);
231 for (unsigned i = 0; i < 4; i++) {
232 EXPECT_TRUE(isa<ConstantInt>(VectorValue->getAggregateElement(i)));
233 ConstantInt *El = cast<ConstantInt>(Val: VectorValue->getAggregateElement(Elt: i));
234 EXPECT_EQ(El->getValue(), i);
235 }
236
237 // Scalable vectors
238 DstVecTy = VectorType::get(ElementType: Builder.getInt32Ty(), NumElements: 4, Scalable: true);
239 StepVec = Builder.CreateStepVector(DstType: DstVecTy);
240 EXPECT_TRUE(isa<CallInst>(StepVec));
241 CallInst *Call = cast<CallInst>(Val: StepVec);
242 FunctionType *FTy = Call->getFunctionType();
243 EXPECT_EQ(FTy->getReturnType(), DstVecTy);
244 EXPECT_EQ(Call->getIntrinsicID(), Intrinsic::experimental_stepvector);
245}
246
247TEST_F(IRBuilderTest, CreateStepVectorI3) {
248 IRBuilder<> Builder(BB);
249
250 // Scalable vectors
251 Type *DstVecTy = VectorType::get(ElementType: IntegerType::get(C&: Ctx, NumBits: 3), NumElements: 2, Scalable: true);
252 Type *VecI8Ty = VectorType::get(ElementType: Builder.getInt8Ty(), NumElements: 2, Scalable: true);
253 Value *StepVec = Builder.CreateStepVector(DstType: DstVecTy);
254 EXPECT_TRUE(isa<TruncInst>(StepVec));
255 TruncInst *Trunc = cast<TruncInst>(Val: StepVec);
256 EXPECT_EQ(Trunc->getDestTy(), DstVecTy);
257 EXPECT_EQ(Trunc->getSrcTy(), VecI8Ty);
258 EXPECT_TRUE(isa<CallInst>(Trunc->getOperand(0)));
259
260 CallInst *Call = cast<CallInst>(Val: Trunc->getOperand(i_nocapture: 0));
261 FunctionType *FTy = Call->getFunctionType();
262 EXPECT_EQ(FTy->getReturnType(), VecI8Ty);
263 EXPECT_EQ(Call->getIntrinsicID(), Intrinsic::experimental_stepvector);
264}
265
266TEST_F(IRBuilderTest, ConstrainedFP) {
267 IRBuilder<> Builder(BB);
268 Value *V;
269 Value *VDouble;
270 Value *VInt;
271 CallInst *Call;
272 IntrinsicInst *II;
273 GlobalVariable *GVDouble = new GlobalVariable(*M, Type::getDoubleTy(C&: Ctx),
274 true, GlobalValue::ExternalLinkage, nullptr);
275
276 V = Builder.CreateLoad(Ty: GV->getValueType(), Ptr: GV);
277 VDouble = Builder.CreateLoad(Ty: GVDouble->getValueType(), Ptr: GVDouble);
278
279 // See if we get constrained intrinsics instead of non-constrained
280 // instructions.
281 Builder.setIsFPConstrained(true);
282 auto Parent = BB->getParent();
283 Parent->addFnAttr(Attribute::StrictFP);
284
285 V = Builder.CreateFAdd(L: V, R: V);
286 ASSERT_TRUE(isa<IntrinsicInst>(V));
287 II = cast<IntrinsicInst>(Val: V);
288 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
289
290 V = Builder.CreateFSub(L: V, R: V);
291 ASSERT_TRUE(isa<IntrinsicInst>(V));
292 II = cast<IntrinsicInst>(Val: V);
293 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fsub);
294
295 V = Builder.CreateFMul(L: V, R: V);
296 ASSERT_TRUE(isa<IntrinsicInst>(V));
297 II = cast<IntrinsicInst>(Val: V);
298 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fmul);
299
300 V = Builder.CreateFDiv(L: V, R: V);
301 ASSERT_TRUE(isa<IntrinsicInst>(V));
302 II = cast<IntrinsicInst>(Val: V);
303 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fdiv);
304
305 V = Builder.CreateFRem(L: V, R: V);
306 ASSERT_TRUE(isa<IntrinsicInst>(V));
307 II = cast<IntrinsicInst>(Val: V);
308 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
309
310 VInt = Builder.CreateFPToUI(V: VDouble, DestTy: Builder.getInt32Ty());
311 ASSERT_TRUE(isa<IntrinsicInst>(VInt));
312 II = cast<IntrinsicInst>(Val: VInt);
313 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fptoui);
314
315 VInt = Builder.CreateFPToSI(V: VDouble, DestTy: Builder.getInt32Ty());
316 ASSERT_TRUE(isa<IntrinsicInst>(VInt));
317 II = cast<IntrinsicInst>(Val: VInt);
318 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fptosi);
319
320 VDouble = Builder.CreateUIToFP(V: VInt, DestTy: Builder.getDoubleTy());
321 ASSERT_TRUE(isa<IntrinsicInst>(VDouble));
322 II = cast<IntrinsicInst>(Val: VDouble);
323 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_uitofp);
324
325 VDouble = Builder.CreateSIToFP(V: VInt, DestTy: Builder.getDoubleTy());
326 ASSERT_TRUE(isa<IntrinsicInst>(VDouble));
327 II = cast<IntrinsicInst>(Val: VDouble);
328 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_sitofp);
329
330 V = Builder.CreateFPTrunc(V: VDouble, DestTy: Type::getFloatTy(C&: Ctx));
331 ASSERT_TRUE(isa<IntrinsicInst>(V));
332 II = cast<IntrinsicInst>(Val: V);
333 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fptrunc);
334
335 VDouble = Builder.CreateFPExt(V, DestTy: Type::getDoubleTy(C&: Ctx));
336 ASSERT_TRUE(isa<IntrinsicInst>(VDouble));
337 II = cast<IntrinsicInst>(Val: VDouble);
338 EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fpext);
339
340 // Verify attributes on the call are created automatically.
341 AttributeSet CallAttrs = II->getAttributes().getFnAttrs();
342 EXPECT_EQ(CallAttrs.hasAttribute(Attribute::StrictFP), true);
343
344 // Verify attributes on the containing function are created when requested.
345 Builder.setConstrainedFPFunctionAttr();
346 AttributeList Attrs = BB->getParent()->getAttributes();
347 AttributeSet FnAttrs = Attrs.getFnAttrs();
348 EXPECT_EQ(FnAttrs.hasAttribute(Attribute::StrictFP), true);
349
350 // Verify the codepaths for setting and overriding the default metadata.
351 V = Builder.CreateFAdd(L: V, R: V);
352 ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
353 auto *CII = cast<ConstrainedFPIntrinsic>(Val: V);
354 EXPECT_EQ(fp::ebStrict, CII->getExceptionBehavior());
355 EXPECT_EQ(RoundingMode::Dynamic, CII->getRoundingMode());
356
357 Builder.setDefaultConstrainedExcept(fp::ebIgnore);
358 Builder.setDefaultConstrainedRounding(RoundingMode::TowardPositive);
359 V = Builder.CreateFAdd(L: V, R: V);
360 CII = cast<ConstrainedFPIntrinsic>(Val: V);
361 EXPECT_EQ(fp::ebIgnore, CII->getExceptionBehavior());
362 EXPECT_EQ(CII->getRoundingMode(), RoundingMode::TowardPositive);
363
364 Builder.setDefaultConstrainedExcept(fp::ebIgnore);
365 Builder.setDefaultConstrainedRounding(RoundingMode::NearestTiesToEven);
366 V = Builder.CreateFAdd(L: V, R: V);
367 CII = cast<ConstrainedFPIntrinsic>(Val: V);
368 EXPECT_EQ(fp::ebIgnore, CII->getExceptionBehavior());
369 EXPECT_EQ(RoundingMode::NearestTiesToEven, CII->getRoundingMode());
370
371 Builder.setDefaultConstrainedExcept(fp::ebMayTrap);
372 Builder.setDefaultConstrainedRounding(RoundingMode::TowardNegative);
373 V = Builder.CreateFAdd(L: V, R: V);
374 CII = cast<ConstrainedFPIntrinsic>(Val: V);
375 EXPECT_EQ(fp::ebMayTrap, CII->getExceptionBehavior());
376 EXPECT_EQ(RoundingMode::TowardNegative, CII->getRoundingMode());
377
378 Builder.setDefaultConstrainedExcept(fp::ebStrict);
379 Builder.setDefaultConstrainedRounding(RoundingMode::TowardZero);
380 V = Builder.CreateFAdd(L: V, R: V);
381 CII = cast<ConstrainedFPIntrinsic>(Val: V);
382 EXPECT_EQ(fp::ebStrict, CII->getExceptionBehavior());
383 EXPECT_EQ(RoundingMode::TowardZero, CII->getRoundingMode());
384
385 Builder.setDefaultConstrainedExcept(fp::ebIgnore);
386 Builder.setDefaultConstrainedRounding(RoundingMode::Dynamic);
387 V = Builder.CreateFAdd(L: V, R: V);
388 CII = cast<ConstrainedFPIntrinsic>(Val: V);
389 EXPECT_EQ(fp::ebIgnore, CII->getExceptionBehavior());
390 EXPECT_EQ(RoundingMode::Dynamic, CII->getRoundingMode());
391
392 // Now override the defaults.
393 Call = Builder.CreateConstrainedFPBinOp(
394 Intrinsic::ID: experimental_constrained_fadd, L: V, R: V, FMFSource: nullptr, Name: "", FPMathTag: nullptr,
395 Rounding: RoundingMode::TowardNegative, Except: fp::ebMayTrap);
396 CII = cast<ConstrainedFPIntrinsic>(Val: Call);
397 EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
398 EXPECT_EQ(fp::ebMayTrap, CII->getExceptionBehavior());
399 EXPECT_EQ(RoundingMode::TowardNegative, CII->getRoundingMode());
400
401 Builder.CreateRetVoid();
402 EXPECT_FALSE(verifyModule(*M));
403}
404
405TEST_F(IRBuilderTest, ConstrainedFPIntrinsics) {
406 IRBuilder<> Builder(BB);
407 Value *V;
408 Value *VDouble;
409 ConstrainedFPIntrinsic *CII;
410 GlobalVariable *GVDouble = new GlobalVariable(
411 *M, Type::getDoubleTy(C&: Ctx), true, GlobalValue::ExternalLinkage, nullptr);
412 VDouble = Builder.CreateLoad(Ty: GVDouble->getValueType(), Ptr: GVDouble);
413
414 Builder.setDefaultConstrainedExcept(fp::ebStrict);
415 Builder.setDefaultConstrainedRounding(RoundingMode::TowardZero);
416 Function *Fn = Intrinsic::getDeclaration(M: M.get(),
417 Intrinsic::id: experimental_constrained_roundeven, Tys: { Type::getDoubleTy(C&: Ctx) });
418 V = Builder.CreateConstrainedFPCall(Callee: Fn, Args: { VDouble });
419 CII = cast<ConstrainedFPIntrinsic>(Val: V);
420 EXPECT_EQ(Intrinsic::experimental_constrained_roundeven, CII->getIntrinsicID());
421 EXPECT_EQ(fp::ebStrict, CII->getExceptionBehavior());
422}
423
424TEST_F(IRBuilderTest, ConstrainedFPFunctionCall) {
425 IRBuilder<> Builder(BB);
426
427 // Create an empty constrained FP function.
428 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C&: Ctx),
429 /*isVarArg=*/false);
430 Function *Callee =
431 Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "", M: M.get());
432 BasicBlock *CalleeBB = BasicBlock::Create(Context&: Ctx, Name: "", Parent: Callee);
433 IRBuilder<> CalleeBuilder(CalleeBB);
434 CalleeBuilder.setIsFPConstrained(true);
435 CalleeBuilder.setConstrainedFPFunctionAttr();
436 CalleeBuilder.CreateRetVoid();
437
438 // Now call the empty constrained FP function.
439 Builder.setIsFPConstrained(true);
440 Builder.setConstrainedFPFunctionAttr();
441 CallInst *FCall = Builder.CreateCall(Callee, Args: std::nullopt);
442
443 // Check the attributes to verify the strictfp attribute is on the call.
444 EXPECT_TRUE(
445 FCall->getAttributes().getFnAttrs().hasAttribute(Attribute::StrictFP));
446
447 Builder.CreateRetVoid();
448 EXPECT_FALSE(verifyModule(*M));
449}
450
451TEST_F(IRBuilderTest, Lifetime) {
452 IRBuilder<> Builder(BB);
453 AllocaInst *Var1 = Builder.CreateAlloca(Ty: Builder.getInt8Ty());
454 AllocaInst *Var2 = Builder.CreateAlloca(Ty: Builder.getInt32Ty());
455 AllocaInst *Var3 = Builder.CreateAlloca(Ty: Builder.getInt8Ty(),
456 ArraySize: Builder.getInt32(C: 123));
457
458 CallInst *Start1 = Builder.CreateLifetimeStart(Ptr: Var1);
459 CallInst *Start2 = Builder.CreateLifetimeStart(Ptr: Var2);
460 CallInst *Start3 = Builder.CreateLifetimeStart(Ptr: Var3, Size: Builder.getInt64(C: 100));
461
462 EXPECT_EQ(Start1->getArgOperand(0), Builder.getInt64(-1));
463 EXPECT_EQ(Start2->getArgOperand(0), Builder.getInt64(-1));
464 EXPECT_EQ(Start3->getArgOperand(0), Builder.getInt64(100));
465
466 EXPECT_EQ(Start1->getArgOperand(1), Var1);
467 EXPECT_EQ(Start2->getArgOperand(1)->stripPointerCasts(), Var2);
468 EXPECT_EQ(Start3->getArgOperand(1), Var3);
469
470 Value *End1 = Builder.CreateLifetimeEnd(Ptr: Var1);
471 Builder.CreateLifetimeEnd(Ptr: Var2);
472 Builder.CreateLifetimeEnd(Ptr: Var3);
473
474 IntrinsicInst *II_Start1 = dyn_cast<IntrinsicInst>(Val: Start1);
475 IntrinsicInst *II_End1 = dyn_cast<IntrinsicInst>(Val: End1);
476 ASSERT_TRUE(II_Start1 != nullptr);
477 EXPECT_EQ(II_Start1->getIntrinsicID(), Intrinsic::lifetime_start);
478 ASSERT_TRUE(II_End1 != nullptr);
479 EXPECT_EQ(II_End1->getIntrinsicID(), Intrinsic::lifetime_end);
480}
481
482TEST_F(IRBuilderTest, CreateCondBr) {
483 IRBuilder<> Builder(BB);
484 BasicBlock *TBB = BasicBlock::Create(Context&: Ctx, Name: "", Parent: F);
485 BasicBlock *FBB = BasicBlock::Create(Context&: Ctx, Name: "", Parent: F);
486
487 BranchInst *BI = Builder.CreateCondBr(Cond: Builder.getTrue(), True: TBB, False: FBB);
488 Instruction *TI = BB->getTerminator();
489 EXPECT_EQ(BI, TI);
490 EXPECT_EQ(2u, TI->getNumSuccessors());
491 EXPECT_EQ(TBB, TI->getSuccessor(0));
492 EXPECT_EQ(FBB, TI->getSuccessor(1));
493
494 BI->eraseFromParent();
495 MDNode *Weights = MDBuilder(Ctx).createBranchWeights(TrueWeight: 42, FalseWeight: 13);
496 BI = Builder.CreateCondBr(Cond: Builder.getTrue(), True: TBB, False: FBB, BranchWeights: Weights);
497 TI = BB->getTerminator();
498 EXPECT_EQ(BI, TI);
499 EXPECT_EQ(2u, TI->getNumSuccessors());
500 EXPECT_EQ(TBB, TI->getSuccessor(0));
501 EXPECT_EQ(FBB, TI->getSuccessor(1));
502 EXPECT_EQ(Weights, TI->getMetadata(LLVMContext::MD_prof));
503}
504
505TEST_F(IRBuilderTest, LandingPadName) {
506 IRBuilder<> Builder(BB);
507 LandingPadInst *LP = Builder.CreateLandingPad(Ty: Builder.getInt32Ty(), NumClauses: 0, Name: "LP");
508 EXPECT_EQ(LP->getName(), "LP");
509}
510
511TEST_F(IRBuilderTest, DataLayout) {
512 std::unique_ptr<Module> M(new Module("test", Ctx));
513 M->setDataLayout("e-n32");
514 EXPECT_TRUE(M->getDataLayout().isLegalInteger(32));
515 M->setDataLayout("e");
516 EXPECT_FALSE(M->getDataLayout().isLegalInteger(32));
517}
518
519TEST_F(IRBuilderTest, GetIntTy) {
520 IRBuilder<> Builder(BB);
521 IntegerType *Ty1 = Builder.getInt1Ty();
522 EXPECT_EQ(Ty1, IntegerType::get(Ctx, 1));
523
524 DataLayout* DL = new DataLayout(M.get());
525 IntegerType *IntPtrTy = Builder.getIntPtrTy(DL: *DL);
526 unsigned IntPtrBitSize = DL->getPointerSizeInBits(AS: 0);
527 EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
528 delete DL;
529}
530
531TEST_F(IRBuilderTest, UnaryOperators) {
532 IRBuilder<NoFolder> Builder(BB);
533 Value *V = Builder.CreateLoad(Ty: GV->getValueType(), Ptr: GV);
534
535 // Test CreateUnOp(X)
536 Value *U = Builder.CreateUnOp(Opc: Instruction::FNeg, V);
537 ASSERT_TRUE(isa<Instruction>(U));
538 ASSERT_TRUE(isa<FPMathOperator>(U));
539 ASSERT_TRUE(isa<UnaryOperator>(U));
540 ASSERT_FALSE(isa<BinaryOperator>(U));
541
542 // Test CreateFNegFMF(X)
543 Instruction *I = cast<Instruction>(Val: U);
544 I->setHasNoSignedZeros(true);
545 I->setHasNoNaNs(true);
546 Value *VFMF = Builder.CreateFNegFMF(V, FMFSource: I);
547 Instruction *IFMF = cast<Instruction>(Val: VFMF);
548 EXPECT_TRUE(IFMF->hasNoSignedZeros());
549 EXPECT_TRUE(IFMF->hasNoNaNs());
550 EXPECT_FALSE(IFMF->hasAllowReassoc());
551}
552
553TEST_F(IRBuilderTest, FastMathFlags) {
554 IRBuilder<> Builder(BB);
555 Value *F, *FC;
556 Instruction *FDiv, *FAdd, *FCmp, *FCall, *FNeg, *FSub, *FMul, *FRem;
557
558 F = Builder.CreateLoad(Ty: GV->getValueType(), Ptr: GV);
559 F = Builder.CreateFAdd(L: F, R: F);
560
561 EXPECT_FALSE(Builder.getFastMathFlags().any());
562 ASSERT_TRUE(isa<Instruction>(F));
563 FAdd = cast<Instruction>(Val: F);
564 EXPECT_FALSE(FAdd->hasNoNaNs());
565
566 FastMathFlags FMF;
567 Builder.setFastMathFlags(FMF);
568
569 // By default, no flags are set.
570 F = Builder.CreateFAdd(L: F, R: F);
571 EXPECT_FALSE(Builder.getFastMathFlags().any());
572 ASSERT_TRUE(isa<Instruction>(F));
573 FAdd = cast<Instruction>(Val: F);
574 EXPECT_FALSE(FAdd->hasNoNaNs());
575 EXPECT_FALSE(FAdd->hasNoInfs());
576 EXPECT_FALSE(FAdd->hasNoSignedZeros());
577 EXPECT_FALSE(FAdd->hasAllowReciprocal());
578 EXPECT_FALSE(FAdd->hasAllowContract());
579 EXPECT_FALSE(FAdd->hasAllowReassoc());
580 EXPECT_FALSE(FAdd->hasApproxFunc());
581
582 // Set all flags in the instruction.
583 FAdd->setFast(true);
584 EXPECT_TRUE(FAdd->hasNoNaNs());
585 EXPECT_TRUE(FAdd->hasNoInfs());
586 EXPECT_TRUE(FAdd->hasNoSignedZeros());
587 EXPECT_TRUE(FAdd->hasAllowReciprocal());
588 EXPECT_TRUE(FAdd->hasAllowContract());
589 EXPECT_TRUE(FAdd->hasAllowReassoc());
590 EXPECT_TRUE(FAdd->hasApproxFunc());
591
592 // All flags are set in the builder.
593 FMF.setFast();
594 Builder.setFastMathFlags(FMF);
595
596 F = Builder.CreateFAdd(L: F, R: F);
597 EXPECT_TRUE(Builder.getFastMathFlags().any());
598 EXPECT_TRUE(Builder.getFastMathFlags().all());
599 ASSERT_TRUE(isa<Instruction>(F));
600 FAdd = cast<Instruction>(Val: F);
601 EXPECT_TRUE(FAdd->hasNoNaNs());
602 EXPECT_TRUE(FAdd->isFast());
603
604 // Now, try it with CreateBinOp
605 F = Builder.CreateBinOp(Opc: Instruction::FAdd, LHS: F, RHS: F);
606 EXPECT_TRUE(Builder.getFastMathFlags().any());
607 ASSERT_TRUE(isa<Instruction>(F));
608 FAdd = cast<Instruction>(Val: F);
609 EXPECT_TRUE(FAdd->hasNoNaNs());
610 EXPECT_TRUE(FAdd->isFast());
611
612 F = Builder.CreateFDiv(L: F, R: F);
613 EXPECT_TRUE(Builder.getFastMathFlags().all());
614 ASSERT_TRUE(isa<Instruction>(F));
615 FDiv = cast<Instruction>(Val: F);
616 EXPECT_TRUE(FDiv->hasAllowReciprocal());
617
618 // Clear all FMF in the builder.
619 Builder.clearFastMathFlags();
620
621 F = Builder.CreateFDiv(L: F, R: F);
622 ASSERT_TRUE(isa<Instruction>(F));
623 FDiv = cast<Instruction>(Val: F);
624 EXPECT_FALSE(FDiv->hasAllowReciprocal());
625
626 // Try individual flags.
627 FMF.clear();
628 FMF.setAllowReciprocal();
629 Builder.setFastMathFlags(FMF);
630
631 F = Builder.CreateFDiv(L: F, R: F);
632 EXPECT_TRUE(Builder.getFastMathFlags().any());
633 EXPECT_TRUE(Builder.getFastMathFlags().AllowReciprocal);
634 ASSERT_TRUE(isa<Instruction>(F));
635 FDiv = cast<Instruction>(Val: F);
636 EXPECT_TRUE(FDiv->hasAllowReciprocal());
637
638 Builder.clearFastMathFlags();
639
640 FC = Builder.CreateFCmpOEQ(LHS: F, RHS: F);
641 ASSERT_TRUE(isa<Instruction>(FC));
642 FCmp = cast<Instruction>(Val: FC);
643 EXPECT_FALSE(FCmp->hasAllowReciprocal());
644
645 FMF.clear();
646 FMF.setAllowReciprocal();
647 Builder.setFastMathFlags(FMF);
648
649 FC = Builder.CreateFCmpOEQ(LHS: F, RHS: F);
650 EXPECT_TRUE(Builder.getFastMathFlags().any());
651 EXPECT_TRUE(Builder.getFastMathFlags().AllowReciprocal);
652 ASSERT_TRUE(isa<Instruction>(FC));
653 FCmp = cast<Instruction>(Val: FC);
654 EXPECT_TRUE(FCmp->hasAllowReciprocal());
655
656 Builder.clearFastMathFlags();
657
658 // Test FP-contract
659 FC = Builder.CreateFAdd(L: F, R: F);
660 ASSERT_TRUE(isa<Instruction>(FC));
661 FAdd = cast<Instruction>(Val: FC);
662 EXPECT_FALSE(FAdd->hasAllowContract());
663
664 FMF.clear();
665 FMF.setAllowContract(true);
666 Builder.setFastMathFlags(FMF);
667
668 FC = Builder.CreateFAdd(L: F, R: F);
669 EXPECT_TRUE(Builder.getFastMathFlags().any());
670 EXPECT_TRUE(Builder.getFastMathFlags().AllowContract);
671 ASSERT_TRUE(isa<Instruction>(FC));
672 FAdd = cast<Instruction>(Val: FC);
673 EXPECT_TRUE(FAdd->hasAllowContract());
674
675 FMF.setApproxFunc();
676 Builder.clearFastMathFlags();
677 Builder.setFastMathFlags(FMF);
678 // Now 'aml' and 'contract' are set.
679 F = Builder.CreateFMul(L: F, R: F);
680 FAdd = cast<Instruction>(Val: F);
681 EXPECT_TRUE(FAdd->hasApproxFunc());
682 EXPECT_TRUE(FAdd->hasAllowContract());
683 EXPECT_FALSE(FAdd->hasAllowReassoc());
684
685 FMF.setAllowReassoc();
686 Builder.clearFastMathFlags();
687 Builder.setFastMathFlags(FMF);
688 // Now 'aml' and 'contract' and 'reassoc' are set.
689 F = Builder.CreateFMul(L: F, R: F);
690 FAdd = cast<Instruction>(Val: F);
691 EXPECT_TRUE(FAdd->hasApproxFunc());
692 EXPECT_TRUE(FAdd->hasAllowContract());
693 EXPECT_TRUE(FAdd->hasAllowReassoc());
694
695 // Test a call with FMF.
696 auto CalleeTy = FunctionType::get(Result: Type::getFloatTy(C&: Ctx),
697 /*isVarArg=*/false);
698 auto Callee =
699 Function::Create(Ty: CalleeTy, Linkage: Function::ExternalLinkage, N: "", M: M.get());
700
701 FCall = Builder.CreateCall(Callee, Args: std::nullopt);
702 EXPECT_FALSE(FCall->hasNoNaNs());
703
704 Function *V =
705 Function::Create(Ty: CalleeTy, Linkage: Function::ExternalLinkage, N: "", M: M.get());
706 FCall = Builder.CreateCall(Callee: V, Args: std::nullopt);
707 EXPECT_FALSE(FCall->hasNoNaNs());
708
709 FMF.clear();
710 FMF.setNoNaNs();
711 Builder.setFastMathFlags(FMF);
712
713 FCall = Builder.CreateCall(Callee, Args: std::nullopt);
714 EXPECT_TRUE(Builder.getFastMathFlags().any());
715 EXPECT_TRUE(Builder.getFastMathFlags().NoNaNs);
716 EXPECT_TRUE(FCall->hasNoNaNs());
717
718 FCall = Builder.CreateCall(Callee: V, Args: std::nullopt);
719 EXPECT_TRUE(Builder.getFastMathFlags().any());
720 EXPECT_TRUE(Builder.getFastMathFlags().NoNaNs);
721 EXPECT_TRUE(FCall->hasNoNaNs());
722
723 Builder.clearFastMathFlags();
724
725 // To test a copy, make sure that a '0' and a '1' change state.
726 F = Builder.CreateFDiv(L: F, R: F);
727 ASSERT_TRUE(isa<Instruction>(F));
728 FDiv = cast<Instruction>(Val: F);
729 EXPECT_FALSE(FDiv->getFastMathFlags().any());
730 FDiv->setHasAllowReciprocal(true);
731 FAdd->setHasAllowReciprocal(false);
732 FAdd->setHasNoNaNs(true);
733 FDiv->copyFastMathFlags(I: FAdd);
734 EXPECT_TRUE(FDiv->hasNoNaNs());
735 EXPECT_FALSE(FDiv->hasAllowReciprocal());
736
737 // Test that CreateF*FMF functions copy flags from the source instruction
738 // instead of using the builder default.
739 Instruction *const FMFSource = FAdd;
740 EXPECT_FALSE(Builder.getFastMathFlags().noNaNs());
741 EXPECT_TRUE(FMFSource->hasNoNaNs());
742
743 F = Builder.CreateFNegFMF(V: F, FMFSource);
744 ASSERT_TRUE(isa<Instruction>(F));
745 FNeg = cast<Instruction>(Val: F);
746 EXPECT_TRUE(FNeg->hasNoNaNs());
747 F = Builder.CreateFAddFMF(L: F, R: F, FMFSource);
748 ASSERT_TRUE(isa<Instruction>(F));
749 FAdd = cast<Instruction>(Val: F);
750 EXPECT_TRUE(FAdd->hasNoNaNs());
751 F = Builder.CreateFSubFMF(L: F, R: F, FMFSource);
752 ASSERT_TRUE(isa<Instruction>(F));
753 FSub = cast<Instruction>(Val: F);
754 EXPECT_TRUE(FSub->hasNoNaNs());
755 F = Builder.CreateFMulFMF(L: F, R: F, FMFSource);
756 ASSERT_TRUE(isa<Instruction>(F));
757 FMul = cast<Instruction>(Val: F);
758 EXPECT_TRUE(FMul->hasNoNaNs());
759 F = Builder.CreateFDivFMF(L: F, R: F, FMFSource);
760 ASSERT_TRUE(isa<Instruction>(F));
761 FDiv = cast<Instruction>(Val: F);
762 EXPECT_TRUE(FDiv->hasNoNaNs());
763 F = Builder.CreateFRemFMF(L: F, R: F, FMFSource);
764 ASSERT_TRUE(isa<Instruction>(F));
765 FRem = cast<Instruction>(Val: F);
766 EXPECT_TRUE(FRem->hasNoNaNs());
767}
768
769TEST_F(IRBuilderTest, WrapFlags) {
770 IRBuilder<NoFolder> Builder(BB);
771
772 // Test instructions.
773 GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true,
774 GlobalValue::ExternalLinkage, nullptr);
775 Value *V = Builder.CreateLoad(Ty: G->getValueType(), Ptr: G);
776 EXPECT_TRUE(
777 cast<BinaryOperator>(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap());
778 EXPECT_TRUE(
779 cast<BinaryOperator>(Builder.CreateNSWMul(V, V))->hasNoSignedWrap());
780 EXPECT_TRUE(
781 cast<BinaryOperator>(Builder.CreateNSWSub(V, V))->hasNoSignedWrap());
782 EXPECT_TRUE(cast<BinaryOperator>(
783 Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true))
784 ->hasNoSignedWrap());
785
786 EXPECT_TRUE(
787 cast<BinaryOperator>(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap());
788 EXPECT_TRUE(
789 cast<BinaryOperator>(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap());
790 EXPECT_TRUE(
791 cast<BinaryOperator>(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap());
792 EXPECT_TRUE(cast<BinaryOperator>(
793 Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false))
794 ->hasNoUnsignedWrap());
795
796 // Test operators created with constants.
797 Constant *C = Builder.getInt32(C: 42);
798 EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWAdd(C, C))
799 ->hasNoSignedWrap());
800 EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWSub(C, C))
801 ->hasNoSignedWrap());
802 EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWMul(C, C))
803 ->hasNoSignedWrap());
804 EXPECT_TRUE(cast<OverflowingBinaryOperator>(
805 Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true))
806 ->hasNoSignedWrap());
807
808 EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWAdd(C, C))
809 ->hasNoUnsignedWrap());
810 EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWSub(C, C))
811 ->hasNoUnsignedWrap());
812 EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWMul(C, C))
813 ->hasNoUnsignedWrap());
814 EXPECT_TRUE(cast<OverflowingBinaryOperator>(
815 Builder.CreateShl(C, C, "", /* NUW */ true, /* NSW */ false))
816 ->hasNoUnsignedWrap());
817}
818
819TEST_F(IRBuilderTest, RAIIHelpersTest) {
820 IRBuilder<> Builder(BB);
821 EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
822 MDBuilder MDB(M->getContext());
823
824 MDNode *FPMathA = MDB.createFPMath(Accuracy: 0.01f);
825 MDNode *FPMathB = MDB.createFPMath(Accuracy: 0.1f);
826
827 Builder.setDefaultFPMathTag(FPMathA);
828
829 {
830 IRBuilder<>::FastMathFlagGuard Guard(Builder);
831 FastMathFlags FMF;
832 FMF.setAllowReciprocal();
833 Builder.setFastMathFlags(FMF);
834 Builder.setDefaultFPMathTag(FPMathB);
835 EXPECT_TRUE(Builder.getFastMathFlags().allowReciprocal());
836 EXPECT_EQ(FPMathB, Builder.getDefaultFPMathTag());
837 }
838
839 EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
840 EXPECT_EQ(FPMathA, Builder.getDefaultFPMathTag());
841
842 Value *F = Builder.CreateLoad(Ty: GV->getValueType(), Ptr: GV);
843
844 {
845 IRBuilder<>::InsertPointGuard Guard(Builder);
846 Builder.SetInsertPoint(cast<Instruction>(Val: F));
847 EXPECT_EQ(F, &*Builder.GetInsertPoint());
848 }
849
850 EXPECT_EQ(BB->end(), Builder.GetInsertPoint());
851 EXPECT_EQ(BB, Builder.GetInsertBlock());
852}
853
854TEST_F(IRBuilderTest, createFunction) {
855 IRBuilder<> Builder(BB);
856 DIBuilder DIB(*M);
857 auto File = DIB.createFile(Filename: "error.swift", Directory: "/");
858 auto CU =
859 DIB.createCompileUnit(Lang: dwarf::DW_LANG_Swift, File, Producer: "swiftc", isOptimized: true, Flags: "", RV: 0);
860 auto Type = DIB.createSubroutineType(ParameterTypes: DIB.getOrCreateTypeArray(Elements: std::nullopt));
861 auto NoErr = DIB.createFunction(
862 Scope: CU, Name: "noerr", LinkageName: "", File, LineNo: 1, Ty: Type, ScopeLine: 1, Flags: DINode::FlagZero,
863 SPFlags: DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
864 EXPECT_TRUE(!NoErr->getThrownTypes());
865 auto Int = DIB.createBasicType(Name: "Int", SizeInBits: 64, Encoding: dwarf::DW_ATE_signed);
866 auto Error = DIB.getOrCreateArray(Elements: {Int});
867 auto Err = DIB.createFunction(
868 Scope: CU, Name: "err", LinkageName: "", File, LineNo: 1, Ty: Type, ScopeLine: 1, Flags: DINode::FlagZero,
869 SPFlags: DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized, TParams: nullptr,
870 Decl: nullptr, ThrownTypes: Error.get());
871 EXPECT_TRUE(Err->getThrownTypes().get() == Error.get());
872 DIB.finalize();
873}
874
875TEST_F(IRBuilderTest, DIBuilder) {
876 auto GetLastDbgRecord = [](const Instruction *I) -> DbgRecord * {
877 if (I->getDbgRecordRange().empty())
878 return nullptr;
879 return &*std::prev(x: I->getDbgRecordRange().end());
880 };
881
882 auto ExpectOrder = [&](DbgInstPtr First, BasicBlock::iterator Second) {
883 if (M->IsNewDbgInfoFormat) {
884 EXPECT_TRUE(First.is<DbgRecord *>());
885 EXPECT_FALSE(Second->getDbgRecordRange().empty());
886 EXPECT_EQ(GetLastDbgRecord(&*Second), First.get<DbgRecord *>());
887 } else {
888 EXPECT_TRUE(First.is<Instruction *>());
889 EXPECT_EQ(&*std::prev(Second), First.get<Instruction *>());
890 }
891 };
892
893 auto RunTest = [&]() {
894 IRBuilder<> Builder(BB);
895 DIBuilder DIB(*M);
896 auto File = DIB.createFile(Filename: "F.CBL", Directory: "/");
897 auto CU = DIB.createCompileUnit(Lang: dwarf::DW_LANG_Cobol74,
898 File: DIB.createFile(Filename: "F.CBL", Directory: "/"),
899 Producer: "llvm-cobol74", isOptimized: true, Flags: "", RV: 0);
900 auto Type =
901 DIB.createSubroutineType(ParameterTypes: DIB.getOrCreateTypeArray(Elements: std::nullopt));
902 auto SP = DIB.createFunction(
903 Scope: CU, Name: "foo", LinkageName: "", File, LineNo: 1, Ty: Type, ScopeLine: 1, Flags: DINode::FlagZero,
904 SPFlags: DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
905 F->setSubprogram(SP);
906 AllocaInst *I = Builder.CreateAlloca(Ty: Builder.getInt8Ty());
907 auto BarSP = DIB.createFunction(
908 Scope: CU, Name: "bar", LinkageName: "", File, LineNo: 1, Ty: Type, ScopeLine: 1, Flags: DINode::FlagZero,
909 SPFlags: DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
910 auto BarScope = DIB.createLexicalBlockFile(Scope: BarSP, File, Discriminator: 0);
911 I->setDebugLoc(DILocation::get(Context&: Ctx, Line: 2, Column: 0, Scope: BarScope));
912
913 // Create another instruction so that there's one before the alloca we're
914 // inserting debug intrinsics before, to make end-checking easier.
915 I = Builder.CreateAlloca(Ty: Builder.getInt1Ty());
916
917 // Label metadata and records
918 // --------------------------
919 DILocation *LabelLoc = DILocation::get(Context&: Ctx, Line: 1, Column: 0, Scope: BarScope);
920 DILabel *AlwaysPreserveLabel = DIB.createLabel(
921 Scope: BarScope, Name: "meles_meles", File, LineNo: 1, /*AlwaysPreserve*/ true);
922 DILabel *Label =
923 DIB.createLabel(Scope: BarScope, Name: "badger", File, LineNo: 1, /*AlwaysPreserve*/ false);
924
925 { /* dbg.label | DbgLabelRecord */
926 // Insert before I and check order.
927 ExpectOrder(DIB.insertLabel(LabelInfo: Label, DL: LabelLoc, InsertBefore: I), I->getIterator());
928
929 // We should be able to insert at the end of the block, even if there's
930 // no terminator yet. Note that in RemoveDIs mode this record won't get
931 // inserted into the block untill another instruction is added.
932 DbgInstPtr LabelRecord = DIB.insertLabel(LabelInfo: Label, DL: LabelLoc, InsertAtEnd: BB);
933 // Specifically do not insert a terminator, to check this works. `I`
934 // should have absorbed the DbgLabelRecord in the new debug info mode.
935 I = Builder.CreateAlloca(Ty: Builder.getInt32Ty());
936 ExpectOrder(LabelRecord, I->getIterator());
937 }
938
939 // Variable metadata and records
940 // -----------------------------
941 DILocation *VarLoc = DILocation::get(Context&: Ctx, Line: 2, Column: 0, Scope: BarScope);
942 auto *IntType = DIB.createBasicType(Name: "int", SizeInBits: 32, Encoding: dwarf::DW_ATE_signed);
943 DILocalVariable *VarX =
944 DIB.createAutoVariable(Scope: BarSP, Name: "X", File, LineNo: 2, Ty: IntType, AlwaysPreserve: true);
945 DILocalVariable *VarY =
946 DIB.createAutoVariable(Scope: BarSP, Name: "Y", File, LineNo: 2, Ty: IntType, AlwaysPreserve: true);
947 { /* dbg.value | DbgVariableRecord::Value */
948 ExpectOrder(DIB.insertDbgValueIntrinsic(Val: I, VarInfo: VarX, Expr: DIB.createExpression(),
949 DL: VarLoc, InsertBefore: I),
950 I->getIterator());
951 // Check inserting at end of the block works as with labels.
952 DbgInstPtr VarXValue = DIB.insertDbgValueIntrinsic(
953 Val: I, VarInfo: VarX, Expr: DIB.createExpression(), DL: VarLoc, InsertAtEnd: BB);
954 I = Builder.CreateAlloca(Ty: Builder.getInt32Ty());
955 ExpectOrder(VarXValue, I->getIterator());
956 EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr);
957 }
958 { /* dbg.declare | DbgVariableRecord::Declare */
959 ExpectOrder(DIB.insertDeclare(Storage: I, VarInfo: VarY, Expr: DIB.createExpression(), DL: VarLoc, InsertBefore: I),
960 I->getIterator());
961 // Check inserting at end of the block works as with labels.
962 DbgInstPtr VarYDeclare =
963 DIB.insertDeclare(Storage: I, VarInfo: VarY, Expr: DIB.createExpression(), DL: VarLoc, InsertAtEnd: BB);
964 I = Builder.CreateAlloca(Ty: Builder.getInt32Ty());
965 ExpectOrder(VarYDeclare, I->getIterator());
966 EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr);
967 }
968 { /* dbg.assign | DbgVariableRecord::Assign */
969 I = Builder.CreateAlloca(Ty: Builder.getInt32Ty());
970 I->setMetadata(KindID: LLVMContext::MD_DIAssignID, Node: DIAssignID::getDistinct(Context&: Ctx));
971 // DbgAssign interface is slightly different - it always inserts after the
972 // linked instr. Check we can do this with no instruction to insert
973 // before.
974 DbgInstPtr VarXAssign =
975 DIB.insertDbgAssign(LinkedInstr: I, Val: I, SrcVar: VarX, ValExpr: DIB.createExpression(), Addr: I,
976 AddrExpr: DIB.createExpression(), DL: VarLoc);
977 I = Builder.CreateAlloca(Ty: Builder.getInt32Ty());
978 ExpectOrder(VarXAssign, I->getIterator());
979 EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr);
980 }
981
982 Builder.CreateRet(V: nullptr);
983 DIB.finalize();
984 // Check the labels are not/are added to Bar's retainedNodes array
985 // (AlwaysPreserve).
986 EXPECT_EQ(find(BarSP->getRetainedNodes(), Label),
987 BarSP->getRetainedNodes().end());
988 EXPECT_NE(find(BarSP->getRetainedNodes(), AlwaysPreserveLabel),
989 BarSP->getRetainedNodes().end());
990 EXPECT_NE(find(BarSP->getRetainedNodes(), VarX),
991 BarSP->getRetainedNodes().end());
992 EXPECT_NE(find(BarSP->getRetainedNodes(), VarY),
993 BarSP->getRetainedNodes().end());
994 EXPECT_TRUE(verifyModule(*M));
995 };
996
997 // Test in old-debug mode.
998 EXPECT_FALSE(M->IsNewDbgInfoFormat);
999 RunTest();
1000
1001 // Test in new-debug mode.
1002 // Reset the test then call convertToNewDbgValues to flip the flag
1003 // on the test's Module, Function and BasicBlock.
1004 TearDown();
1005 SetUp();
1006 M->convertToNewDbgValues();
1007 EXPECT_TRUE(M->IsNewDbgInfoFormat);
1008 RunTest();
1009}
1010
1011TEST_F(IRBuilderTest, createArtificialSubprogram) {
1012 IRBuilder<> Builder(BB);
1013 DIBuilder DIB(*M);
1014 auto File = DIB.createFile(Filename: "main.c", Directory: "/");
1015 auto CU = DIB.createCompileUnit(Lang: dwarf::DW_LANG_C, File, Producer: "clang",
1016 /*isOptimized=*/true, /*Flags=*/"",
1017 /*Runtime Version=*/RV: 0);
1018 auto Type = DIB.createSubroutineType(ParameterTypes: DIB.getOrCreateTypeArray(Elements: std::nullopt));
1019 auto SP = DIB.createFunction(
1020 Scope: CU, Name: "foo", /*LinkageName=*/"", File,
1021 /*LineNo=*/1, Ty: Type, /*ScopeLine=*/2, Flags: DINode::FlagZero,
1022 SPFlags: DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1023 EXPECT_TRUE(SP->isDistinct());
1024
1025 F->setSubprogram(SP);
1026 AllocaInst *I = Builder.CreateAlloca(Ty: Builder.getInt8Ty());
1027 ReturnInst *R = Builder.CreateRetVoid();
1028 I->setDebugLoc(DILocation::get(Context&: Ctx, Line: 3, Column: 2, Scope: SP));
1029 R->setDebugLoc(DILocation::get(Context&: Ctx, Line: 4, Column: 2, Scope: SP));
1030 DIB.finalize();
1031 EXPECT_FALSE(verifyModule(*M));
1032
1033 Function *G = Function::Create(Ty: F->getFunctionType(),
1034 Linkage: Function::ExternalLinkage, N: "", M: M.get());
1035 BasicBlock *GBB = BasicBlock::Create(Context&: Ctx, Name: "", Parent: G);
1036 Builder.SetInsertPoint(GBB);
1037 I->removeFromParent();
1038 Builder.Insert(I);
1039 Builder.CreateRetVoid();
1040 EXPECT_FALSE(verifyModule(*M));
1041
1042 DISubprogram *GSP = DIBuilder::createArtificialSubprogram(SP: F->getSubprogram());
1043 EXPECT_EQ(SP->getFile(), GSP->getFile());
1044 EXPECT_EQ(SP->getType(), GSP->getType());
1045 EXPECT_EQ(SP->getLine(), GSP->getLine());
1046 EXPECT_EQ(SP->getScopeLine(), GSP->getScopeLine());
1047 EXPECT_TRUE(GSP->isDistinct());
1048
1049 G->setSubprogram(GSP);
1050 EXPECT_TRUE(verifyModule(*M));
1051
1052 auto *InlinedAtNode =
1053 DILocation::getDistinct(Context&: Ctx, Line: GSP->getScopeLine(), Column: 0, Scope: GSP);
1054 DebugLoc DL = I->getDebugLoc();
1055 DenseMap<const MDNode *, MDNode *> IANodes;
1056 auto IA = DebugLoc::appendInlinedAt(DL, InlinedAt: InlinedAtNode, Ctx, Cache&: IANodes);
1057 auto NewDL =
1058 DILocation::get(Context&: Ctx, Line: DL.getLine(), Column: DL.getCol(), Scope: DL.getScope(), InlinedAt: IA);
1059 I->setDebugLoc(NewDL);
1060 EXPECT_FALSE(verifyModule(*M));
1061
1062 EXPECT_EQ("foo", SP->getName());
1063 EXPECT_EQ("foo", GSP->getName());
1064 EXPECT_FALSE(SP->isArtificial());
1065 EXPECT_TRUE(GSP->isArtificial());
1066}
1067
1068// Check that we can add debug info to an existing DICompileUnit.
1069TEST_F(IRBuilderTest, appendDebugInfo) {
1070 IRBuilder<> Builder(BB);
1071 Builder.CreateRetVoid();
1072 EXPECT_FALSE(verifyModule(*M));
1073
1074 auto GetNames = [](DICompileUnit *CU) {
1075 SmallVector<StringRef> Names;
1076 for (auto *ET : CU->getEnumTypes())
1077 Names.push_back(Elt: ET->getName());
1078 for (auto *RT : CU->getRetainedTypes())
1079 Names.push_back(Elt: RT->getName());
1080 for (auto *GV : CU->getGlobalVariables())
1081 Names.push_back(Elt: GV->getVariable()->getName());
1082 for (auto *IE : CU->getImportedEntities())
1083 Names.push_back(Elt: IE->getName());
1084 for (auto *Node : CU->getMacros())
1085 if (auto *MN = dyn_cast_or_null<DIMacro>(Val: Node))
1086 Names.push_back(Elt: MN->getName());
1087 return Names;
1088 };
1089
1090 DICompileUnit *CU;
1091 {
1092 DIBuilder DIB(*M);
1093 auto *File = DIB.createFile(Filename: "main.c", Directory: "/");
1094 CU = DIB.createCompileUnit(Lang: dwarf::DW_LANG_C, File, Producer: "clang",
1095 /*isOptimized=*/true, /*Flags=*/"",
1096 /*Runtime Version=*/RV: 0);
1097 auto *ByteTy = DIB.createBasicType(Name: "byte0", SizeInBits: 8, Encoding: dwarf::DW_ATE_signed);
1098 DIB.createEnumerationType(Scope: CU, Name: "ET0", File, /*LineNo=*/LineNumber: 0, /*SizeInBits=*/8,
1099 /*AlignInBits=*/8, /*Elements=*/{}, UnderlyingType: ByteTy);
1100 DIB.retainType(T: ByteTy);
1101 DIB.createGlobalVariableExpression(Context: CU, Name: "GV0", /*LinkageName=*/"", File,
1102 /*LineNo=*/1, Ty: ByteTy,
1103 /*IsLocalToUnit=*/true);
1104 DIB.createImportedDeclaration(Context: CU, Decl: nullptr, File, /*LineNo=*/Line: 2, Name: "IM0");
1105 DIB.createMacro(Parent: nullptr, /*LineNo=*/Line: 0, MacroType: dwarf::DW_MACINFO_define, Name: "M0");
1106 DIB.finalize();
1107 }
1108 EXPECT_FALSE(verifyModule(*M));
1109 EXPECT_THAT(GetNames(CU),
1110 UnorderedElementsAre("ET0", "byte0", "GV0", "IM0", "M0"));
1111
1112 {
1113 DIBuilder DIB(*M, true, CU);
1114 auto *File = CU->getFile();
1115 auto *ByteTy = DIB.createBasicType(Name: "byte1", SizeInBits: 8, Encoding: dwarf::DW_ATE_signed);
1116 DIB.createEnumerationType(Scope: CU, Name: "ET1", File, /*LineNo=*/LineNumber: 0,
1117 /*SizeInBits=*/8, /*AlignInBits=*/8,
1118 /*Elements=*/{}, UnderlyingType: ByteTy);
1119 DIB.retainType(T: ByteTy);
1120 DIB.createGlobalVariableExpression(Context: CU, Name: "GV1", /*LinkageName=*/"", File,
1121 /*LineNo=*/1, Ty: ByteTy,
1122 /*IsLocalToUnit=*/true);
1123 DIB.createImportedDeclaration(Context: CU, Decl: nullptr, File, /*LineNo=*/Line: 2, Name: "IM1");
1124 DIB.createMacro(Parent: nullptr, /*LineNo=*/Line: 0, MacroType: dwarf::DW_MACINFO_define, Name: "M1");
1125 DIB.finalize();
1126 }
1127 EXPECT_FALSE(verifyModule(*M));
1128 EXPECT_THAT(GetNames(CU),
1129 UnorderedElementsAre("ET0", "byte0", "GV0", "IM0", "M0", "ET1",
1130 "byte1", "GV1", "IM1", "M1"));
1131}
1132
1133TEST_F(IRBuilderTest, InsertExtractElement) {
1134 IRBuilder<> Builder(BB);
1135
1136 auto VecTy = FixedVectorType::get(ElementType: Builder.getInt64Ty(), NumElts: 4);
1137 auto Elt1 = Builder.getInt64(C: -1);
1138 auto Elt2 = Builder.getInt64(C: -2);
1139 Value *Vec = Builder.CreateInsertElement(VecTy, NewElt: Elt1, Idx: Builder.getInt8(C: 1));
1140 Vec = Builder.CreateInsertElement(Vec, NewElt: Elt2, Idx: 2);
1141 auto X1 = Builder.CreateExtractElement(Vec, Idx: 1);
1142 auto X2 = Builder.CreateExtractElement(Vec, Idx: Builder.getInt32(C: 2));
1143 EXPECT_EQ(Elt1, X1);
1144 EXPECT_EQ(Elt2, X2);
1145}
1146
1147TEST_F(IRBuilderTest, CreateGlobalStringPtr) {
1148 IRBuilder<> Builder(BB);
1149
1150 auto String1a = Builder.CreateGlobalStringPtr(Str: "TestString", Name: "String1a");
1151 auto String1b = Builder.CreateGlobalStringPtr(Str: "TestString", Name: "String1b", AddressSpace: 0);
1152 auto String2 = Builder.CreateGlobalStringPtr(Str: "TestString", Name: "String2", AddressSpace: 1);
1153 auto String3 = Builder.CreateGlobalString(Str: "TestString", Name: "String3", AddressSpace: 2);
1154
1155 EXPECT_TRUE(String1a->getType()->getPointerAddressSpace() == 0);
1156 EXPECT_TRUE(String1b->getType()->getPointerAddressSpace() == 0);
1157 EXPECT_TRUE(String2->getType()->getPointerAddressSpace() == 1);
1158 EXPECT_TRUE(String3->getType()->getPointerAddressSpace() == 2);
1159}
1160
1161TEST_F(IRBuilderTest, DebugLoc) {
1162 auto CalleeTy = FunctionType::get(Result: Type::getVoidTy(C&: Ctx),
1163 /*isVarArg=*/false);
1164 auto Callee =
1165 Function::Create(Ty: CalleeTy, Linkage: Function::ExternalLinkage, N: "", M: M.get());
1166
1167 DIBuilder DIB(*M);
1168 auto File = DIB.createFile(Filename: "tmp.cpp", Directory: "/");
1169 auto CU = DIB.createCompileUnit(Lang: dwarf::DW_LANG_C_plus_plus_11,
1170 File: DIB.createFile(Filename: "tmp.cpp", Directory: "/"), Producer: "", isOptimized: true, Flags: "",
1171 RV: 0);
1172 auto SPType =
1173 DIB.createSubroutineType(ParameterTypes: DIB.getOrCreateTypeArray(Elements: std::nullopt));
1174 auto SP =
1175 DIB.createFunction(Scope: CU, Name: "foo", LinkageName: "foo", File, LineNo: 1, Ty: SPType, ScopeLine: 1, Flags: DINode::FlagZero,
1176 SPFlags: DISubprogram::SPFlagDefinition);
1177 DebugLoc DL1 = DILocation::get(Context&: Ctx, Line: 2, Column: 0, Scope: SP);
1178 DebugLoc DL2 = DILocation::get(Context&: Ctx, Line: 3, Column: 0, Scope: SP);
1179
1180 auto BB2 = BasicBlock::Create(Context&: Ctx, Name: "bb2", Parent: F);
1181 auto Br = BranchInst::Create(IfTrue: BB2, InsertAtEnd: BB);
1182 Br->setDebugLoc(DL1);
1183
1184 IRBuilder<> Builder(Ctx);
1185 Builder.SetInsertPoint(Br);
1186 EXPECT_EQ(DL1, Builder.getCurrentDebugLocation());
1187 auto Call1 = Builder.CreateCall(Callee, Args: std::nullopt);
1188 EXPECT_EQ(DL1, Call1->getDebugLoc());
1189
1190 Call1->setDebugLoc(DL2);
1191 Builder.SetInsertPoint(TheBB: Call1->getParent(), IP: Call1->getIterator());
1192 EXPECT_EQ(DL2, Builder.getCurrentDebugLocation());
1193 auto Call2 = Builder.CreateCall(Callee, Args: std::nullopt);
1194 EXPECT_EQ(DL2, Call2->getDebugLoc());
1195
1196 DIB.finalize();
1197}
1198
1199TEST_F(IRBuilderTest, DIImportedEntity) {
1200 IRBuilder<> Builder(BB);
1201 DIBuilder DIB(*M);
1202 auto F = DIB.createFile(Filename: "F.CBL", Directory: "/");
1203 auto CU = DIB.createCompileUnit(Lang: dwarf::DW_LANG_Cobol74,
1204 File: F, Producer: "llvm-cobol74",
1205 isOptimized: true, Flags: "", RV: 0);
1206 MDTuple *Elements = MDTuple::getDistinct(Context&: Ctx, MDs: std::nullopt);
1207
1208 DIB.createImportedDeclaration(Context: CU, Decl: nullptr, File: F, Line: 1);
1209 DIB.createImportedDeclaration(Context: CU, Decl: nullptr, File: F, Line: 1);
1210 DIB.createImportedModule(Context: CU, NS: (DIImportedEntity *)nullptr, File: F, Line: 2);
1211 DIB.createImportedModule(Context: CU, NS: (DIImportedEntity *)nullptr, File: F, Line: 2);
1212 DIB.createImportedModule(Context: CU, NS: (DIImportedEntity *)nullptr, File: F, Line: 2, Elements);
1213 DIB.createImportedModule(Context: CU, NS: (DIImportedEntity *)nullptr, File: F, Line: 2, Elements);
1214 DIB.finalize();
1215 EXPECT_TRUE(verifyModule(*M));
1216 EXPECT_TRUE(CU->getImportedEntities().size() == 3);
1217}
1218
1219// 0: #define M0 V0 <-- command line definition
1220// 0: main.c <-- main file
1221// 3: #define M1 V1 <-- M1 definition in main.c
1222// 5: #include "file.h" <-- inclusion of file.h from main.c
1223// 1: #define M2 <-- M2 definition in file.h with no value
1224// 7: #undef M1 V1 <-- M1 un-definition in main.c
1225TEST_F(IRBuilderTest, DIBuilderMacro) {
1226 IRBuilder<> Builder(BB);
1227 DIBuilder DIB(*M);
1228 auto File1 = DIB.createFile(Filename: "main.c", Directory: "/");
1229 auto File2 = DIB.createFile(Filename: "file.h", Directory: "/");
1230 auto CU = DIB.createCompileUnit(
1231 Lang: dwarf::DW_LANG_C, File: DIB.createFile(Filename: "main.c", Directory: "/"), Producer: "llvm-c", isOptimized: true, Flags: "", RV: 0);
1232 auto MDef0 =
1233 DIB.createMacro(Parent: nullptr, Line: 0, MacroType: dwarf::DW_MACINFO_define, Name: "M0", Value: "V0");
1234 auto TMF1 = DIB.createTempMacroFile(Parent: nullptr, Line: 0, File: File1);
1235 auto MDef1 = DIB.createMacro(Parent: TMF1, Line: 3, MacroType: dwarf::DW_MACINFO_define, Name: "M1", Value: "V1");
1236 auto TMF2 = DIB.createTempMacroFile(Parent: TMF1, Line: 5, File: File2);
1237 auto MDef2 = DIB.createMacro(Parent: TMF2, Line: 1, MacroType: dwarf::DW_MACINFO_define, Name: "M2");
1238 auto MUndef1 = DIB.createMacro(Parent: TMF1, Line: 7, MacroType: dwarf::DW_MACINFO_undef, Name: "M1");
1239
1240 EXPECT_EQ(dwarf::DW_MACINFO_define, MDef1->getMacinfoType());
1241 EXPECT_EQ(3u, MDef1->getLine());
1242 EXPECT_EQ("M1", MDef1->getName());
1243 EXPECT_EQ("V1", MDef1->getValue());
1244
1245 EXPECT_EQ(dwarf::DW_MACINFO_undef, MUndef1->getMacinfoType());
1246 EXPECT_EQ(7u, MUndef1->getLine());
1247 EXPECT_EQ("M1", MUndef1->getName());
1248 EXPECT_EQ("", MUndef1->getValue());
1249
1250 EXPECT_EQ(dwarf::DW_MACINFO_start_file, TMF2->getMacinfoType());
1251 EXPECT_EQ(5u, TMF2->getLine());
1252 EXPECT_EQ(File2, TMF2->getFile());
1253
1254 DIB.finalize();
1255
1256 SmallVector<Metadata *, 4> Elements;
1257 Elements.push_back(Elt: MDef2);
1258 auto MF2 = DIMacroFile::get(Context&: Ctx, MIType: dwarf::DW_MACINFO_start_file, Line: 5, File: File2,
1259 Elements: DIB.getOrCreateMacroArray(Elements));
1260
1261 Elements.clear();
1262 Elements.push_back(Elt: MDef1);
1263 Elements.push_back(Elt: MF2);
1264 Elements.push_back(Elt: MUndef1);
1265 auto MF1 = DIMacroFile::get(Context&: Ctx, MIType: dwarf::DW_MACINFO_start_file, Line: 0, File: File1,
1266 Elements: DIB.getOrCreateMacroArray(Elements));
1267
1268 Elements.clear();
1269 Elements.push_back(Elt: MDef0);
1270 Elements.push_back(Elt: MF1);
1271 auto MN0 = MDTuple::get(Context&: Ctx, MDs: Elements);
1272 EXPECT_EQ(MN0, CU->getRawMacros());
1273
1274 Elements.clear();
1275 Elements.push_back(Elt: MDef1);
1276 Elements.push_back(Elt: MF2);
1277 Elements.push_back(Elt: MUndef1);
1278 auto MN1 = MDTuple::get(Context&: Ctx, MDs: Elements);
1279 EXPECT_EQ(MN1, MF1->getRawElements());
1280
1281 Elements.clear();
1282 Elements.push_back(Elt: MDef2);
1283 auto MN2 = MDTuple::get(Context&: Ctx, MDs: Elements);
1284 EXPECT_EQ(MN2, MF2->getRawElements());
1285 EXPECT_TRUE(verifyModule(*M));
1286}
1287
1288TEST_F(IRBuilderTest, NoFolderNames) {
1289 IRBuilder<NoFolder> Builder(BB);
1290 auto *Add =
1291 Builder.CreateAdd(LHS: Builder.getInt32(C: 1), RHS: Builder.getInt32(C: 2), Name: "add");
1292 EXPECT_EQ(Add->getName(), "add");
1293}
1294
1295TEST_F(IRBuilderTest, CTAD) {
1296 struct TestInserter : public IRBuilderDefaultInserter {
1297 TestInserter() = default;
1298 };
1299 InstSimplifyFolder Folder(M->getDataLayout());
1300
1301 IRBuilder Builder1(Ctx, Folder, TestInserter());
1302 static_assert(std::is_same_v<decltype(Builder1),
1303 IRBuilder<InstSimplifyFolder, TestInserter>>);
1304 IRBuilder Builder2(Ctx);
1305 static_assert(std::is_same_v<decltype(Builder2), IRBuilder<>>);
1306 IRBuilder Builder3(BB, Folder);
1307 static_assert(
1308 std::is_same_v<decltype(Builder3), IRBuilder<InstSimplifyFolder>>);
1309 IRBuilder Builder4(BB);
1310 static_assert(std::is_same_v<decltype(Builder4), IRBuilder<>>);
1311 // The block BB is empty, so don't test this one.
1312 // IRBuilder Builder5(BB->getTerminator());
1313 // static_assert(std::is_same_v<decltype(Builder5), IRBuilder<>>);
1314 IRBuilder Builder6(BB, BB->end(), Folder);
1315 static_assert(
1316 std::is_same_v<decltype(Builder6), IRBuilder<InstSimplifyFolder>>);
1317 IRBuilder Builder7(BB, BB->end());
1318 static_assert(std::is_same_v<decltype(Builder7), IRBuilder<>>);
1319}
1320}
1321

source code of llvm/unittests/IR/IRBuilderTest.cpp