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