brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.7 KiB · 2073e0d Raw
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