/// \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.
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
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) {
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);
}
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,
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<char *>(OldOps + OldNumUses) + sizeof(Use::UserRef);
+ auto *NewPtr =
+ reinterpret_cast<char *>(NewOps + NewNumUses) + sizeof(Use::UserRef);
+ std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr);
+ }
+ Use::zap(OldOps, OldOps + OldNumUses, true);
+}
+
//===----------------------------------------------------------------------===//
// User operator new Implementations
//===----------------------------------------------------------------------===//