23 if (
From == To)
return Changed;
25 assert((!isa<Constant>(
this) || isa<GlobalValue>(
this)) &&
26 "Cannot call User::replaceUsesOfWith on a constant!");
36 if (
auto DVI = dyn_cast_or_null<DbgVariableIntrinsic>(
this)) {
38 DVI->replaceVariableLocationOp(
From, To);
53 static_assert(
alignof(
Use) >=
alignof(BasicBlock *),
54 "Alignment is insufficient for 'hung-off-uses' pieces");
60 Use *Begin =
static_cast<Use*
>(::operator
new(
size));
62 setOperandList(Begin);
63 for (; Begin !=
End; Begin++)
64 new (Begin)
Use(
this);
74 assert(NewNumUses > OldNumUses &&
"realloc must grow num uses");
81 std::copy(OldOps, OldOps + OldNumUses, NewOps);
85 auto *OldPtr =
reinterpret_cast<char *
>(OldOps + OldNumUses);
86 auto *NewPtr =
reinterpret_cast<char *
>(NewOps + NewNumUses);
87 std::copy(OldPtr, OldPtr + (OldNumUses *
sizeof(BasicBlock *)), NewPtr);
89 Use::zap(OldOps, OldOps + OldNumUses,
true);
95struct DescriptorInfo {
101 return {MutableARef.begin(), MutableARef.end()};
108 auto *DI =
reinterpret_cast<DescriptorInfo *
>(getIntrusiveOperands()) - 1;
109 assert(DI->SizeInBytes != 0 &&
"Should not have had a descriptor otherwise!");
111 return MutableArrayRef<uint8_t>(
112 reinterpret_cast<uint8_t *
>(DI) - DI->SizeInBytes, DI->SizeInBytes);
116 if (
auto *
II = dyn_cast<IntrinsicInst>(
this)) {
117 switch (
II->getIntrinsicID()) {
120 case Intrinsic::assume:
121 case Intrinsic::pseudoprobe:
122 case Intrinsic::experimental_noalias_scope_decl:
133void *User::allocateFixedOperandUser(
size_t Size,
unsigned Us,
134 unsigned DescBytes) {
137 static_assert(
sizeof(DescriptorInfo) %
sizeof(
void *) == 0,
"Required below");
139 unsigned DescBytesToAllocate =
140 DescBytes == 0 ? 0 : (DescBytes +
sizeof(DescriptorInfo));
141 assert(DescBytesToAllocate %
sizeof(
void *) == 0 &&
142 "We need this to satisfy alignment constraints for Uses");
145 ::operator
new(
Size +
sizeof(
Use) * Us + DescBytesToAllocate));
146 Use *Start =
reinterpret_cast<Use *
>(Storage + DescBytesToAllocate);
149 for (; Start !=
End; Start++)
150 new (Start)
Use(Obj);
152 if (DescBytes != 0) {
153 auto *DescInfo =
reinterpret_cast<DescriptorInfo *
>(Storage + DescBytes);
154 DescInfo->SizeInBytes = DescBytes;
160void *User::operator
new(
size_t Size, IntrusiveOperandsAllocMarker allocTrait) {
161 return allocateFixedOperandUser(
Size, allocTrait.NumOps, 0);
164void *User::operator
new(
size_t Size,
165 IntrusiveOperandsAndDescriptorAllocMarker allocTrait) {
166 return allocateFixedOperandUser(
Size, allocTrait.NumOps,
167 allocTrait.DescBytes);
170void *User::operator
new(
size_t Size, HungOffOperandsAllocMarker) {
172 void *Storage = ::operator
new(
Size +
sizeof(
Use *));
173 Use **HungOffOperandList =
static_cast<Use **
>(Storage);
174 User *Obj =
reinterpret_cast<User *
>(HungOffOperandList + 1);
175 *HungOffOperandList =
nullptr;
188 User *Obj =
static_cast<User *
>(Usr);
189 if (Obj->HasHungOffUses) {
190 assert(!Obj->HasDescriptor &&
"not supported!");
192 Use **HungOffOperandList =
static_cast<Use **
>(Usr) - 1;
194 Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands,
196 ::operator
delete(HungOffOperandList);
197 }
else if (Obj->HasDescriptor) {
198 Use *UseBegin =
static_cast<Use *
>(Usr) - Obj->NumUserOperands;
199 Use::zap(UseBegin, UseBegin + Obj->NumUserOperands,
false);
201 auto *DI =
reinterpret_cast<DescriptorInfo *
>(UseBegin) - 1;
202 uint8_t *Storage =
reinterpret_cast<uint8_t *
>(DI) - DI->SizeInBytes;
203 ::operator
delete(Storage);
205 Use *Storage =
static_cast<Use *
>(Usr) - Obj->NumUserOperands;
206 Use::zap(Storage, Storage + Obj->NumUserOperands,
208 ::operator
delete(Storage);
BlockVerifier::State From
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void zap(Use *Start, const Use *Stop, bool del=false)
Destroys Use operands when the number of operands of a User changes.
const Use * getOperandList() const
ArrayRef< const uint8_t > getDescriptor() const
Returns the descriptor co-allocated with this User instance.
bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
void allocHungoffUses(unsigned N, bool IsPhi=false)
Allocate the array of Uses, followed by a pointer (with bottom bit set) to the User.
User(Type *ty, unsigned vty, AllocInfo AllocInfo)
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
void growHungoffUses(unsigned N, bool IsPhi=false)
Grow the number of hung off uses.
@ BasicBlock
Various leaf nodes.
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.