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