X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FIR%2FFunction.cpp;h=cfdfc40cd8aa71d156ec10d68549d7c217a38199;hp=5e4d2d2054eb54ef46bab7d45697d02b9984314a;hb=3569d3c5ebfff8b9b20c47e7eb1ddf508e6e9bbf;hpb=8855924964c05ae46fe93905a974d4b4577e7461 diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 5e4d2d2054e..cfdfc40cd8a 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -279,9 +279,6 @@ Function::~Function() { // Remove the function from the on-the-side GC table. clearGC(); - - // FIXME: needed by operator delete - setFunctionNumOperands(1); } void Function::BuildLazyArguments() const { @@ -328,14 +325,15 @@ void Function::dropAllReferences() { while (!BasicBlocks.empty()) BasicBlocks.begin()->eraseFromParent(); - // Prefix and prologue data are stored in a side table. - setPrefixData(nullptr); - setPrologueData(nullptr); + // Drop uses of any optional data (real or placeholder). + if (getNumOperands()) { + User::dropAllReferences(); + setNumHungOffUseOperands(0); + setValueSubclassData(getSubclassDataFromValue() & ~0xe); + } // Metadata is stored in a side-table. clearMetadata(); - - setPersonalityFn(nullptr); } void Function::addAttribute(unsigned i, Attribute::AttrKind attr) { @@ -368,47 +366,21 @@ void Function::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { setAttributes(PAL); } -// Maintain the GC name for each function in an on-the-side table. This saves -// allocating an additional word in Function for programs which do not use GC -// (i.e., most programs) at the cost of increased overhead for clients which do -// use GC. -static DenseMap *GCNames; -static StringPool *GCNamePool; -static ManagedStatic > GCLock; - -bool Function::hasGC() const { - sys::SmartScopedReader Reader(*GCLock); - return GCNames && GCNames->count(this); -} - -const char *Function::getGC() const { +const std::string &Function::getGC() const { assert(hasGC() && "Function has no collector"); - sys::SmartScopedReader Reader(*GCLock); - return *(*GCNames)[this]; + return getContext().getGC(*this); } -void Function::setGC(const char *Str) { - sys::SmartScopedWriter Writer(*GCLock); - if (!GCNamePool) - GCNamePool = new StringPool(); - if (!GCNames) - GCNames = new DenseMap(); - (*GCNames)[this] = GCNamePool->intern(Str); +void Function::setGC(const std::string Str) { + setValueSubclassDataBit(14, !Str.empty()); + getContext().setGC(*this, std::move(Str)); } void Function::clearGC() { - sys::SmartScopedWriter Writer(*GCLock); - if (GCNames) { - GCNames->erase(this); - if (GCNames->empty()) { - delete GCNames; - GCNames = nullptr; - if (GCNamePool->empty()) { - delete GCNamePool; - GCNamePool = nullptr; - } - } - } + if (!hasGC()) + return; + getContext().deleteGC(*this); + setValueSubclassDataBit(14, false); } /// Copy all additional attributes (those not needed to create a Function) from @@ -425,18 +397,12 @@ void Function::copyAttributesFrom(const GlobalValue *Src) { setGC(SrcF->getGC()); else clearGC(); + if (SrcF->hasPersonalityFn()) + setPersonalityFn(SrcF->getPersonalityFn()); if (SrcF->hasPrefixData()) setPrefixData(SrcF->getPrefixData()); - else - setPrefixData(nullptr); if (SrcF->hasPrologueData()) setPrologueData(SrcF->getPrologueData()); - else - setPrologueData(nullptr); - if (SrcF->hasPersonalityFn()) - setPersonalityFn(SrcF->getPersonalityFn()); - else - setPersonalityFn(nullptr); } /// \brief This does the actual lookup of an intrinsic ID which @@ -944,61 +910,68 @@ bool Function::callsFunctionThatReturnsTwice() const { return false; } -static Constant * -getFunctionData(const Function *F, - const LLVMContextImpl::FunctionDataMapTy &Map) { - const auto &Entry = Map.find(F); - assert(Entry != Map.end()); - return cast(Entry->second->getReturnValue()); -} - -/// setFunctionData - Set "Map[F] = Data". Return an updated SubclassData value -/// in which Bit is low iff Data is null. -static unsigned setFunctionData(Function *F, - LLVMContextImpl::FunctionDataMapTy &Map, - Constant *Data, unsigned SCData, unsigned Bit) { - ReturnInst *&Holder = Map[F]; - if (Data) { - if (Holder) - Holder->setOperand(0, Data); - else - Holder = ReturnInst::Create(F->getContext(), Data); - return SCData | (1 << Bit); - } else { - delete Holder; - Map.erase(F); - return SCData & ~(1 << Bit); - } +Constant *Function::getPersonalityFn() const { + assert(hasPersonalityFn() && getNumOperands()); + return cast(Op<0>()); +} + +void Function::setPersonalityFn(Constant *Fn) { + setHungoffOperand<0>(Fn); + setValueSubclassDataBit(3, Fn != nullptr); } Constant *Function::getPrefixData() const { - assert(hasPrefixData()); - return getFunctionData(this, getContext().pImpl->PrefixDataMap); + assert(hasPrefixData() && getNumOperands()); + return cast(Op<1>()); } void Function::setPrefixData(Constant *PrefixData) { - if (!PrefixData && !hasPrefixData()) - return; - - unsigned SCData = getSubclassDataFromValue(); - SCData = setFunctionData(this, getContext().pImpl->PrefixDataMap, PrefixData, - SCData, /*Bit=*/1); - setValueSubclassData(SCData); + setHungoffOperand<1>(PrefixData); + setValueSubclassDataBit(1, PrefixData != nullptr); } Constant *Function::getPrologueData() const { - assert(hasPrologueData()); - return getFunctionData(this, getContext().pImpl->PrologueDataMap); + assert(hasPrologueData() && getNumOperands()); + return cast(Op<2>()); } void Function::setPrologueData(Constant *PrologueData) { - if (!PrologueData && !hasPrologueData()) + setHungoffOperand<2>(PrologueData); + setValueSubclassDataBit(2, PrologueData != nullptr); +} + +void Function::allocHungoffUselist() { + // If we've already allocated a uselist, stop here. + if (getNumOperands()) return; - unsigned SCData = getSubclassDataFromValue(); - SCData = setFunctionData(this, getContext().pImpl->PrologueDataMap, - PrologueData, SCData, /*Bit=*/2); - setValueSubclassData(SCData); + allocHungoffUses(3, /*IsPhi=*/ false); + setNumHungOffUseOperands(3); + + // Initialize the uselist with placeholder operands to allow traversal. + auto *CPN = ConstantPointerNull::get(Type::getInt1PtrTy(getContext(), 0)); + Op<0>().set(CPN); + Op<1>().set(CPN); + Op<2>().set(CPN); +} + +template +void Function::setHungoffOperand(Constant *C) { + if (C) { + allocHungoffUselist(); + Op().set(C); + } else if (getNumOperands()) { + Op().set( + ConstantPointerNull::get(Type::getInt1PtrTy(getContext(), 0))); + } +} + +void Function::setValueSubclassDataBit(unsigned Bit, bool On) { + assert(Bit < 16 && "SubclassData contains only 16 bits"); + if (On) + setValueSubclassData(getSubclassDataFromValue() | (1 << Bit)); + else + setValueSubclassData(getSubclassDataFromValue() & ~(1 << Bit)); } void Function::setEntryCount(uint64_t Count) { @@ -1016,22 +989,3 @@ Optional Function::getEntryCount() const { } return None; } - -void Function::setPersonalityFn(Constant *C) { - if (!C) { - if (hasPersonalityFn()) { - // Note, the num operands is used to compute the offset of the operand, so - // the order here matters. Clearing the operand then clearing the num - // operands ensures we have the correct offset to the operand. - Op<0>().set(nullptr); - setFunctionNumOperands(0); - } - } else { - // Note, the num operands is used to compute the offset of the operand, so - // the order here matters. We need to set num operands to 1 first so that - // we get the correct offset to the first operand when we set it. - if (!hasPersonalityFn()) - setFunctionNumOperands(1); - Op<0>().set(C); - } -}