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