1 //===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===// 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 // This file defines various helper methods and classes used by 10 // LLVMContextImpl for creating and managing constants. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H 15 #define LLVM_LIB_IR_CONSTANTSCONTEXT_H 16 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/DenseMapInfo.h" 19 #include "llvm/ADT/DenseSet.h" 20 #include "llvm/ADT/Hashing.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/IR/Constant.h" 24 #include "llvm/IR/Constants.h" 25 #include "llvm/IR/DerivedTypes.h" 26 #include "llvm/IR/GlobalVariable.h" 27 #include "llvm/IR/InlineAsm.h" 28 #include "llvm/IR/Instruction.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/IR/OperandTraits.h" 31 #include "llvm/Support/Casting.h" 32 #include "llvm/Support/Debug.h" 33 #include "llvm/Support/ErrorHandling.h" 34 #include "llvm/Support/raw_ostream.h" 35 #include <cassert> 36 #include <cstddef> 37 #include <cstdint> 38 #include <utility> 39 40 #define DEBUG_TYPE "ir" 41 42 namespace llvm { 43 44 /// CastConstantExpr - This class is private to Constants.cpp, and is used 45 /// behind the scenes to implement cast constant exprs. 46 class CastConstantExpr final : public ConstantExpr { 47 public: CastConstantExpr(unsigned Opcode,Constant * C,Type * Ty)48 CastConstantExpr(unsigned Opcode, Constant *C, Type *Ty) 49 : ConstantExpr(Ty, Opcode, &Op<0>(), 1) { 50 Op<0>() = C; 51 } 52 53 // allocate space for exactly one operand new(size_t S)54 void *operator new(size_t S) { return User::operator new(S, 1); } delete(void * Ptr)55 void operator delete(void *Ptr) { User::operator delete(Ptr); } 56 57 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 58 classof(const ConstantExpr * CE)59 static bool classof(const ConstantExpr *CE) { 60 return Instruction::isCast(CE->getOpcode()); 61 } classof(const Value * V)62 static bool classof(const Value *V) { 63 return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); 64 } 65 }; 66 67 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used 68 /// behind the scenes to implement binary constant exprs. 69 class BinaryConstantExpr final : public ConstantExpr { 70 public: BinaryConstantExpr(unsigned Opcode,Constant * C1,Constant * C2,unsigned Flags)71 BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2, 72 unsigned Flags) 73 : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) { 74 Op<0>() = C1; 75 Op<1>() = C2; 76 SubclassOptionalData = Flags; 77 } 78 79 // allocate space for exactly two operands new(size_t S)80 void *operator new(size_t S) { return User::operator new(S, 2); } delete(void * Ptr)81 void operator delete(void *Ptr) { User::operator delete(Ptr); } 82 83 /// Transparently provide more efficient getOperand methods. 84 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 85 classof(const ConstantExpr * CE)86 static bool classof(const ConstantExpr *CE) { 87 return Instruction::isBinaryOp(CE->getOpcode()); 88 } classof(const Value * V)89 static bool classof(const Value *V) { 90 return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); 91 } 92 }; 93 94 /// ExtractElementConstantExpr - This class is private to 95 /// Constants.cpp, and is used behind the scenes to implement 96 /// extractelement constant exprs. 97 class ExtractElementConstantExpr final : public ConstantExpr { 98 public: ExtractElementConstantExpr(Constant * C1,Constant * C2)99 ExtractElementConstantExpr(Constant *C1, Constant *C2) 100 : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(), 101 Instruction::ExtractElement, &Op<0>(), 2) { 102 Op<0>() = C1; 103 Op<1>() = C2; 104 } 105 106 // allocate space for exactly two operands new(size_t S)107 void *operator new(size_t S) { return User::operator new(S, 2); } delete(void * Ptr)108 void operator delete(void *Ptr) { User::operator delete(Ptr); } 109 110 /// Transparently provide more efficient getOperand methods. 111 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 112 classof(const ConstantExpr * CE)113 static bool classof(const ConstantExpr *CE) { 114 return CE->getOpcode() == Instruction::ExtractElement; 115 } classof(const Value * V)116 static bool classof(const Value *V) { 117 return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); 118 } 119 }; 120 121 /// InsertElementConstantExpr - This class is private to 122 /// Constants.cpp, and is used behind the scenes to implement 123 /// insertelement constant exprs. 124 class InsertElementConstantExpr final : public ConstantExpr { 125 public: InsertElementConstantExpr(Constant * C1,Constant * C2,Constant * C3)126 InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3) 127 : ConstantExpr(C1->getType(), Instruction::InsertElement, 128 &Op<0>(), 3) { 129 Op<0>() = C1; 130 Op<1>() = C2; 131 Op<2>() = C3; 132 } 133 134 // allocate space for exactly three operands new(size_t S)135 void *operator new(size_t S) { return User::operator new(S, 3); } delete(void * Ptr)136 void operator delete(void *Ptr) { User::operator delete(Ptr); } 137 138 /// Transparently provide more efficient getOperand methods. 139 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 140 classof(const ConstantExpr * CE)141 static bool classof(const ConstantExpr *CE) { 142 return CE->getOpcode() == Instruction::InsertElement; 143 } classof(const Value * V)144 static bool classof(const Value *V) { 145 return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); 146 } 147 }; 148 149 /// ShuffleVectorConstantExpr - This class is private to 150 /// Constants.cpp, and is used behind the scenes to implement 151 /// shufflevector constant exprs. 152 class ShuffleVectorConstantExpr final : public ConstantExpr { 153 public: ShuffleVectorConstantExpr(Constant * C1,Constant * C2,ArrayRef<int> Mask)154 ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask) 155 : ConstantExpr(VectorType::get( 156 cast<VectorType>(C1->getType())->getElementType(), 157 Mask.size(), isa<ScalableVectorType>(C1->getType())), 158 Instruction::ShuffleVector, &Op<0>(), 2) { 159 assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) && 160 "Invalid shuffle vector instruction operands!"); 161 Op<0>() = C1; 162 Op<1>() = C2; 163 ShuffleMask.assign(Mask.begin(), Mask.end()); 164 ShuffleMaskForBitcode = 165 ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, getType()); 166 } 167 168 SmallVector<int, 4> ShuffleMask; 169 Constant *ShuffleMaskForBitcode; 170 new(size_t S)171 void *operator new(size_t S) { return User::operator new(S, 2); } delete(void * Ptr)172 void operator delete(void *Ptr) { return User::operator delete(Ptr); } 173 174 /// Transparently provide more efficient getOperand methods. 175 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 176 classof(const ConstantExpr * CE)177 static bool classof(const ConstantExpr *CE) { 178 return CE->getOpcode() == Instruction::ShuffleVector; 179 } classof(const Value * V)180 static bool classof(const Value *V) { 181 return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); 182 } 183 }; 184 185 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is 186 /// used behind the scenes to implement getelementptr constant exprs. 187 class GetElementPtrConstantExpr : public ConstantExpr { 188 Type *SrcElementTy; 189 Type *ResElementTy; 190 std::optional<ConstantRange> InRange; 191 192 GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C, 193 ArrayRef<Constant *> IdxList, Type *DestTy, 194 std::optional<ConstantRange> InRange); 195 196 public: 197 static GetElementPtrConstantExpr * Create(Type * SrcElementTy,Constant * C,ArrayRef<Constant * > IdxList,Type * DestTy,unsigned Flags,std::optional<ConstantRange> InRange)198 Create(Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, 199 Type *DestTy, unsigned Flags, std::optional<ConstantRange> InRange) { 200 GetElementPtrConstantExpr *Result = new (IdxList.size() + 1) 201 GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy, 202 std::move(InRange)); 203 Result->SubclassOptionalData = Flags; 204 return Result; 205 } 206 207 Type *getSourceElementType() const; 208 Type *getResultElementType() const; 209 std::optional<ConstantRange> getInRange() const; 210 211 /// Transparently provide more efficient getOperand methods. 212 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 213 classof(const ConstantExpr * CE)214 static bool classof(const ConstantExpr *CE) { 215 return CE->getOpcode() == Instruction::GetElementPtr; 216 } classof(const Value * V)217 static bool classof(const Value *V) { 218 return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); 219 } 220 }; 221 222 template <> 223 struct OperandTraits<CastConstantExpr> 224 : public FixedNumOperandTraits<CastConstantExpr, 1> {}; 225 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr, Value) 226 227 template <> 228 struct OperandTraits<BinaryConstantExpr> 229 : public FixedNumOperandTraits<BinaryConstantExpr, 2> {}; 230 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value) 231 232 template <> 233 struct OperandTraits<ExtractElementConstantExpr> 234 : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {}; 235 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value) 236 237 template <> 238 struct OperandTraits<InsertElementConstantExpr> 239 : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {}; 240 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value) 241 242 template <> 243 struct OperandTraits<ShuffleVectorConstantExpr> 244 : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {}; 245 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value) 246 247 template <> 248 struct OperandTraits<GetElementPtrConstantExpr> 249 : public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {}; 250 251 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value) 252 253 template <class ConstantClass> struct ConstantAggrKeyType; 254 struct InlineAsmKeyType; 255 struct ConstantExprKeyType; 256 struct ConstantPtrAuthKeyType; 257 258 template <class ConstantClass> struct ConstantInfo; 259 template <> struct ConstantInfo<ConstantExpr> { 260 using ValType = ConstantExprKeyType; 261 using TypeClass = Type; 262 }; 263 template <> struct ConstantInfo<InlineAsm> { 264 using ValType = InlineAsmKeyType; 265 using TypeClass = PointerType; 266 }; 267 template <> struct ConstantInfo<ConstantArray> { 268 using ValType = ConstantAggrKeyType<ConstantArray>; 269 using TypeClass = ArrayType; 270 }; 271 template <> struct ConstantInfo<ConstantStruct> { 272 using ValType = ConstantAggrKeyType<ConstantStruct>; 273 using TypeClass = StructType; 274 }; 275 template <> struct ConstantInfo<ConstantVector> { 276 using ValType = ConstantAggrKeyType<ConstantVector>; 277 using TypeClass = VectorType; 278 }; 279 template <> struct ConstantInfo<ConstantPtrAuth> { 280 using ValType = ConstantPtrAuthKeyType; 281 using TypeClass = Type; 282 }; 283 284 template <class ConstantClass> struct ConstantAggrKeyType { 285 ArrayRef<Constant *> Operands; 286 287 ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {} 288 289 ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *) 290 : Operands(Operands) {} 291 292 ConstantAggrKeyType(const ConstantClass *C, 293 SmallVectorImpl<Constant *> &Storage) { 294 assert(Storage.empty() && "Expected empty storage"); 295 for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) 296 Storage.push_back(C->getOperand(I)); 297 Operands = Storage; 298 } 299 300 bool operator==(const ConstantAggrKeyType &X) const { 301 return Operands == X.Operands; 302 } 303 304 bool operator==(const ConstantClass *C) const { 305 if (Operands.size() != C->getNumOperands()) 306 return false; 307 for (unsigned I = 0, E = Operands.size(); I != E; ++I) 308 if (Operands[I] != C->getOperand(I)) 309 return false; 310 return true; 311 } 312 313 unsigned getHash() const { 314 return hash_combine_range(Operands.begin(), Operands.end()); 315 } 316 317 using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass; 318 319 ConstantClass *create(TypeClass *Ty) const { 320 return new (Operands.size()) ConstantClass(Ty, Operands); 321 } 322 }; 323 324 struct InlineAsmKeyType { 325 StringRef AsmString; 326 StringRef Constraints; 327 FunctionType *FTy; 328 bool HasSideEffects; 329 bool IsAlignStack; 330 InlineAsm::AsmDialect AsmDialect; 331 bool CanThrow; 332 333 InlineAsmKeyType(StringRef AsmString, StringRef Constraints, 334 FunctionType *FTy, bool HasSideEffects, bool IsAlignStack, 335 InlineAsm::AsmDialect AsmDialect, bool canThrow) 336 : AsmString(AsmString), Constraints(Constraints), FTy(FTy), 337 HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack), 338 AsmDialect(AsmDialect), CanThrow(canThrow) {} 339 340 InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &) 341 : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()), 342 FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()), 343 IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()), 344 CanThrow(Asm->canThrow()) {} 345 346 bool operator==(const InlineAsmKeyType &X) const { 347 return HasSideEffects == X.HasSideEffects && 348 IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect && 349 AsmString == X.AsmString && Constraints == X.Constraints && 350 FTy == X.FTy && CanThrow == X.CanThrow; 351 } 352 353 bool operator==(const InlineAsm *Asm) const { 354 return HasSideEffects == Asm->hasSideEffects() && 355 IsAlignStack == Asm->isAlignStack() && 356 AsmDialect == Asm->getDialect() && 357 AsmString == Asm->getAsmString() && 358 Constraints == Asm->getConstraintString() && 359 FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow(); 360 } 361 362 unsigned getHash() const { 363 return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack, 364 AsmDialect, FTy, CanThrow); 365 } 366 367 using TypeClass = ConstantInfo<InlineAsm>::TypeClass; 368 369 InlineAsm *create(TypeClass *Ty) const { 370 assert(PointerType::getUnqual(FTy) == Ty); 371 return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints), 372 HasSideEffects, IsAlignStack, AsmDialect, CanThrow); 373 } 374 }; 375 376 struct ConstantExprKeyType { 377 private: 378 uint8_t Opcode; 379 uint8_t SubclassOptionalData; 380 ArrayRef<Constant *> Ops; 381 ArrayRef<int> ShuffleMask; 382 Type *ExplicitTy; 383 std::optional<ConstantRange> InRange; 384 385 static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) { 386 if (CE->getOpcode() == Instruction::ShuffleVector) 387 return CE->getShuffleMask(); 388 return std::nullopt; 389 } 390 391 static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) { 392 if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE)) 393 return GEPCE->getSourceElementType(); 394 return nullptr; 395 } 396 397 static std::optional<ConstantRange> 398 getInRangeIfValid(const ConstantExpr *CE) { 399 if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE)) 400 return GEPCE->getInRange(); 401 return std::nullopt; 402 } 403 404 public: 405 ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops, 406 unsigned short SubclassOptionalData = 0, 407 ArrayRef<int> ShuffleMask = std::nullopt, 408 Type *ExplicitTy = nullptr, 409 std::optional<ConstantRange> InRange = std::nullopt) 410 : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), Ops(Ops), 411 ShuffleMask(ShuffleMask), ExplicitTy(ExplicitTy), 412 InRange(std::move(InRange)) {} 413 414 ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE) 415 : Opcode(CE->getOpcode()), 416 SubclassOptionalData(CE->getRawSubclassOptionalData()), Ops(Operands), 417 ShuffleMask(getShuffleMaskIfValid(CE)), 418 ExplicitTy(getSourceElementTypeIfValid(CE)), 419 InRange(getInRangeIfValid(CE)) {} 420 421 ConstantExprKeyType(const ConstantExpr *CE, 422 SmallVectorImpl<Constant *> &Storage) 423 : Opcode(CE->getOpcode()), 424 SubclassOptionalData(CE->getRawSubclassOptionalData()), 425 ShuffleMask(getShuffleMaskIfValid(CE)), 426 ExplicitTy(getSourceElementTypeIfValid(CE)), 427 InRange(getInRangeIfValid(CE)) { 428 assert(Storage.empty() && "Expected empty storage"); 429 for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I) 430 Storage.push_back(CE->getOperand(I)); 431 Ops = Storage; 432 } 433 434 static bool rangesEqual(const std::optional<ConstantRange> &A, 435 const std::optional<ConstantRange> &B) { 436 if (!A.has_value() || !B.has_value()) 437 return A.has_value() == B.has_value(); 438 return A->getBitWidth() == B->getBitWidth() && A == B; 439 } 440 441 bool operator==(const ConstantExprKeyType &X) const { 442 return Opcode == X.Opcode && 443 SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops && 444 ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy && 445 rangesEqual(InRange, X.InRange); 446 } 447 448 bool operator==(const ConstantExpr *CE) const { 449 if (Opcode != CE->getOpcode()) 450 return false; 451 if (SubclassOptionalData != CE->getRawSubclassOptionalData()) 452 return false; 453 if (Ops.size() != CE->getNumOperands()) 454 return false; 455 for (unsigned I = 0, E = Ops.size(); I != E; ++I) 456 if (Ops[I] != CE->getOperand(I)) 457 return false; 458 if (ShuffleMask != getShuffleMaskIfValid(CE)) 459 return false; 460 if (ExplicitTy != getSourceElementTypeIfValid(CE)) 461 return false; 462 if (!rangesEqual(InRange, getInRangeIfValid(CE))) 463 return false; 464 return true; 465 } 466 467 unsigned getHash() const { 468 return hash_combine( 469 Opcode, SubclassOptionalData, 470 hash_combine_range(Ops.begin(), Ops.end()), 471 hash_combine_range(ShuffleMask.begin(), ShuffleMask.end()), ExplicitTy); 472 } 473 474 using TypeClass = ConstantInfo<ConstantExpr>::TypeClass; 475 476 ConstantExpr *create(TypeClass *Ty) const { 477 switch (Opcode) { 478 default: 479 if (Instruction::isCast(Opcode)) 480 return new CastConstantExpr(Opcode, Ops[0], Ty); 481 if ((Opcode >= Instruction::BinaryOpsBegin && 482 Opcode < Instruction::BinaryOpsEnd)) 483 return new BinaryConstantExpr(Opcode, Ops[0], Ops[1], 484 SubclassOptionalData); 485 llvm_unreachable("Invalid ConstantExpr!"); 486 case Instruction::ExtractElement: 487 return new ExtractElementConstantExpr(Ops[0], Ops[1]); 488 case Instruction::InsertElement: 489 return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]); 490 case Instruction::ShuffleVector: 491 return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask); 492 case Instruction::GetElementPtr: 493 return GetElementPtrConstantExpr::Create( 494 ExplicitTy, Ops[0], Ops.slice(1), Ty, SubclassOptionalData, InRange); 495 } 496 } 497 }; 498 499 struct ConstantPtrAuthKeyType { 500 ArrayRef<Constant *> Operands; 501 502 ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {} 503 504 ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands, const ConstantPtrAuth *) 505 : Operands(Operands) {} 506 507 ConstantPtrAuthKeyType(const ConstantPtrAuth *C, 508 SmallVectorImpl<Constant *> &Storage) { 509 assert(Storage.empty() && "Expected empty storage"); 510 for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) 511 Storage.push_back(cast<Constant>(C->getOperand(I))); 512 Operands = Storage; 513 } 514 515 bool operator==(const ConstantPtrAuthKeyType &X) const { 516 return Operands == X.Operands; 517 } 518 519 bool operator==(const ConstantPtrAuth *C) const { 520 if (Operands.size() != C->getNumOperands()) 521 return false; 522 for (unsigned I = 0, E = Operands.size(); I != E; ++I) 523 if (Operands[I] != C->getOperand(I)) 524 return false; 525 return true; 526 } 527 528 unsigned getHash() const { 529 return hash_combine_range(Operands.begin(), Operands.end()); 530 } 531 532 using TypeClass = typename ConstantInfo<ConstantPtrAuth>::TypeClass; 533 534 ConstantPtrAuth *create(TypeClass *Ty) const { 535 return new ConstantPtrAuth(Operands[0], cast<ConstantInt>(Operands[1]), 536 cast<ConstantInt>(Operands[2]), Operands[3]); 537 } 538 }; 539 540 // Free memory for a given constant. Assumes the constant has already been 541 // removed from all relevant maps. 542 void deleteConstant(Constant *C); 543 544 template <class ConstantClass> class ConstantUniqueMap { 545 public: 546 using ValType = typename ConstantInfo<ConstantClass>::ValType; 547 using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass; 548 using LookupKey = std::pair<TypeClass *, ValType>; 549 550 /// Key and hash together, so that we compute the hash only once and reuse it. 551 using LookupKeyHashed = std::pair<unsigned, LookupKey>; 552 553 private: 554 struct MapInfo { 555 using ConstantClassInfo = DenseMapInfo<ConstantClass *>; 556 557 static inline ConstantClass *getEmptyKey() { 558 return ConstantClassInfo::getEmptyKey(); 559 } 560 561 static inline ConstantClass *getTombstoneKey() { 562 return ConstantClassInfo::getTombstoneKey(); 563 } 564 565 static unsigned getHashValue(const ConstantClass *CP) { 566 SmallVector<Constant *, 32> Storage; 567 return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage))); 568 } 569 570 static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) { 571 return LHS == RHS; 572 } 573 574 static unsigned getHashValue(const LookupKey &Val) { 575 return hash_combine(Val.first, Val.second.getHash()); 576 } 577 578 static unsigned getHashValue(const LookupKeyHashed &Val) { 579 return Val.first; 580 } 581 582 static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) { 583 if (RHS == getEmptyKey() || RHS == getTombstoneKey()) 584 return false; 585 if (LHS.first != RHS->getType()) 586 return false; 587 return LHS.second == RHS; 588 } 589 590 static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) { 591 return isEqual(LHS.second, RHS); 592 } 593 }; 594 595 public: 596 using MapTy = DenseSet<ConstantClass *, MapInfo>; 597 598 private: 599 MapTy Map; 600 601 public: 602 typename MapTy::iterator begin() { return Map.begin(); } 603 typename MapTy::iterator end() { return Map.end(); } 604 605 void freeConstants() { 606 for (auto &I : Map) 607 deleteConstant(I); 608 } 609 610 private: 611 ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) { 612 ConstantClass *Result = V.create(Ty); 613 614 assert(Result->getType() == Ty && "Type specified is not correct!"); 615 Map.insert_as(Result, HashKey); 616 617 return Result; 618 } 619 620 public: 621 /// Return the specified constant from the map, creating it if necessary. 622 ConstantClass *getOrCreate(TypeClass *Ty, ValType V) { 623 LookupKey Key(Ty, V); 624 /// Hash once, and reuse it for the lookup and the insertion if needed. 625 LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key); 626 627 ConstantClass *Result = nullptr; 628 629 auto I = Map.find_as(Lookup); 630 if (I == Map.end()) 631 Result = create(Ty, V, Lookup); 632 else 633 Result = *I; 634 assert(Result && "Unexpected nullptr"); 635 636 return Result; 637 } 638 639 /// Remove this constant from the map 640 void remove(ConstantClass *CP) { 641 typename MapTy::iterator I = Map.find(CP); 642 assert(I != Map.end() && "Constant not found in constant table!"); 643 assert(*I == CP && "Didn't find correct element?"); 644 Map.erase(I); 645 } 646 647 ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands, 648 ConstantClass *CP, Value *From, 649 Constant *To, unsigned NumUpdated = 0, 650 unsigned OperandNo = ~0u) { 651 LookupKey Key(CP->getType(), ValType(Operands, CP)); 652 /// Hash once, and reuse it for the lookup and the insertion if needed. 653 LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key); 654 655 auto ItMap = Map.find_as(Lookup); 656 if (ItMap != Map.end()) 657 return *ItMap; 658 659 // Update to the new value. Optimize for the case when we have a single 660 // operand that we're changing, but handle bulk updates efficiently. 661 remove(CP); 662 if (NumUpdated == 1) { 663 assert(OperandNo < CP->getNumOperands() && "Invalid index"); 664 assert(CP->getOperand(OperandNo) != To && "I didn't contain From!"); 665 CP->setOperand(OperandNo, To); 666 } else { 667 for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I) 668 if (CP->getOperand(I) == From) 669 CP->setOperand(I, To); 670 } 671 Map.insert_as(CP, Lookup); 672 return nullptr; 673 } 674 675 void dump() const { 676 LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); 677 } 678 }; 679 680 template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() { 681 for (auto &I : Map) 682 delete I; 683 } 684 685 } // end namespace llvm 686 687 #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H 688