diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index b68dcf9cc24..998e93a6a94 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -58,6 +58,11 @@ protected: /// \param IsPhi identifies callers which are phi nodes and which need /// N BasicBlock* allocated along with N Use *allocHungoffUses(unsigned N, bool IsPhi = false); + + /// \brief Grow the number of hung off uses. Note that allocHungoffUses + /// should be called if there are no uses. + void growHungoffUses(unsigned N, bool IsPhi = false); + public: ~User() override { // drop the hung off uses. diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 9c8f66c11de..5fb51156638 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -128,16 +128,8 @@ void PHINode::growOperands() { unsigned NumOps = e + e / 2; if (NumOps < 2) NumOps = 2; // 2 op PHI nodes are VERY common. - Use *OldOps = op_begin(); - BasicBlock **OldBlocks = block_begin(); - ReservedSpace = NumOps; - OperandList = allocHungoffUses(ReservedSpace); - - std::copy(OldOps, OldOps + e, op_begin()); - std::copy(OldBlocks, OldBlocks + e, block_begin()); - - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace, /* IsPhi */ true); } /// hasConstantValue - If the specified PHI node always merges together the same @@ -218,14 +210,7 @@ void LandingPadInst::growOperands(unsigned Size) { unsigned e = getNumOperands(); if (ReservedSpace >= e + Size) return; ReservedSpace = (e + Size / 2) * 2; - - Use *NewOps = allocHungoffUses(ReservedSpace); - Use *OldOps = OperandList; - for (unsigned i = 0; i != e; ++i) - NewOps[i] = OldOps[i]; - - OperandList = NewOps; - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace); } void LandingPadInst::addClause(Constant *Val) { @@ -3363,13 +3348,7 @@ void SwitchInst::growOperands() { unsigned NumOps = e*3; ReservedSpace = NumOps; - Use *NewOps = allocHungoffUses(NumOps); - Use *OldOps = OperandList; - for (unsigned i = 0; i != e; ++i) { - NewOps[i] = OldOps[i]; - } - OperandList = NewOps; - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace); } @@ -3406,12 +3385,7 @@ void IndirectBrInst::growOperands() { unsigned NumOps = e*2; ReservedSpace = NumOps; - Use *NewOps = allocHungoffUses(NumOps); - Use *OldOps = OperandList; - for (unsigned i = 0; i != e; ++i) - NewOps[i] = OldOps[i]; - OperandList = NewOps; - Use::zap(OldOps, OldOps + e, true); + growHungoffUses(ReservedSpace); } IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases, diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp index e5450946006..8035989f1dc 100644 --- a/lib/IR/User.cpp +++ b/lib/IR/User.cpp @@ -56,6 +56,33 @@ Use *User::allocHungoffUses(unsigned N, bool IsPhi) { return Uses; } +void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) { + assert(HasHungOffUses && "realloc must have hung off uses"); + + unsigned OldNumUses = getNumOperands(); + + // We don't support shrinking the number of uses. We wouldn't have enough + // space to copy the old uses in to the new space. + assert(NewNumUses > OldNumUses && "realloc must grow num uses"); + + Use *OldOps = OperandList; + allocHungoffUses(NewNumUses, IsPhi); + Use *NewOps = OperandList; + + // Now copy from the old operands list to the new one. + std::copy(OldOps, OldOps + OldNumUses, NewOps); + + // If this is a Phi, then we need to copy the BB pointers too. + if (IsPhi) { + auto *OldPtr = + reinterpret_cast(OldOps + OldNumUses) + sizeof(Use::UserRef); + auto *NewPtr = + reinterpret_cast(NewOps + NewNumUses) + sizeof(Use::UserRef); + std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr); + } + Use::zap(OldOps, OldOps + OldNumUses, true); +} + //===----------------------------------------------------------------------===// // User operator new Implementations //===----------------------------------------------------------------------===//