30 "Cannot call User::replaceUsesOfWith on a constant!");
32 for (
unsigned i = 0,
E = getNumOperands(); i !=
E; ++i)
33 if (getOperand(i) == From) {
42 DVI->replaceVariableLocationOp(From, To);
55 assert(HasHungOffUses &&
"alloc must have hung off uses");
57 static_assert(
alignof(
Use) >=
alignof(Value *),
58 "Alignment is insufficient for 'hung-off-uses' pieces");
63 size +=
N *
sizeof(Value *);
64 Use *Begin =
static_cast<Use*
>(::operator
new(
size));
66 setOperandList(Begin);
67 for (; Begin != End; Begin++)
68 new (Begin)
Use(
this);
72 assert(HasHungOffUses &&
"realloc must have hung off uses");
74 unsigned OldNumUses = getNumOperands();
78 assert(NewNumUses > OldNumUses &&
"realloc must grow num uses");
80 Use *OldOps = getOperandList();
81 allocHungoffUses(NewNumUses, WithExtraValues);
82 Use *NewOps = getOperandList();
85 std::copy(OldOps, OldOps + OldNumUses, NewOps);
89 if (WithExtraValues) {
90 auto *OldPtr =
reinterpret_cast<char *
>(OldOps + OldNumUses);
91 auto *NewPtr =
reinterpret_cast<char *
>(NewOps + NewNumUses);
92 std::copy(OldPtr, OldPtr + (OldNumUses *
sizeof(Value *)), NewPtr);
94 Use::zap(OldOps, OldOps + OldNumUses,
true);
104 auto MutableARef =
const_cast<User *
>(
this)->getDescriptor();
105 return {MutableARef.begin(), MutableARef.end()};
109 assert(HasDescriptor &&
"Don't call otherwise!");
110 assert(!HasHungOffUses &&
"Invariant!");
112 auto *DI =
reinterpret_cast<DescriptorInfo *
>(getIntrusiveOperands()) - 1;
113 assert(DI->SizeInBytes != 0 &&
"Should not have had a descriptor otherwise!");
116 reinterpret_cast<uint8_t *
>(DI) - DI->SizeInBytes, DI->SizeInBytes);
121 switch (
II->getIntrinsicID()) {
124 case Intrinsic::assume:
125 case Intrinsic::pseudoprobe:
126 case Intrinsic::experimental_noalias_scope_decl:
137void *User::allocateFixedOperandUser(
size_t Size,
unsigned Us,
138 unsigned DescBytes) {
139 assert(Us < (1u << NumUserOperandsBits) &&
"Too many operands");
141 static_assert(
sizeof(
DescriptorInfo) %
sizeof(
void *) == 0,
"Required below");
143 unsigned DescBytesToAllocate =
145 assert(DescBytesToAllocate %
sizeof(
void *) == 0 &&
146 "We need this to satisfy alignment constraints for Uses");
148 size_t LeadingSize = DescBytesToAllocate +
sizeof(
Use) * Us;
153 LeadingSize = std::max(LeadingSize,
sizeof(
void *));
156 User *
Obj =
reinterpret_cast<User *
>(Storage + LeadingSize);
157 Use *Operands =
reinterpret_cast<Use *
>(
Obj) - Us;
158 Obj->NumUserOperands = Us;
159 Obj->HasHungOffUses =
false;
160 Obj->HasDescriptor = DescBytes != 0;
161 for (
unsigned I = 0;
I < Us; ++
I)
162 new (&Operands[
I])
Use(Obj);
164 if (DescBytes != 0) {
165 auto *DescInfo =
reinterpret_cast<DescriptorInfo *
>(Operands) - 1;
172void *User::operator
new(
size_t Size, IntrusiveOperandsAllocMarker allocTrait) {
173 return allocateFixedOperandUser(
Size, allocTrait.NumOps, 0);
176void *User::operator
new(
size_t Size,
177 IntrusiveOperandsAndDescriptorAllocMarker allocTrait) {
178 return allocateFixedOperandUser(
Size, allocTrait.NumOps,
179 allocTrait.DescBytes);
182void *User::operator
new(
size_t Size, HungOffOperandsAllocMarker) {
184 void *Storage = ::operator
new(
Size +
sizeof(
Use *));
185 Use **HungOffOperandList =
static_cast<Use **
>(Storage);
186 User *
Obj =
reinterpret_cast<User *
>(HungOffOperandList + 1);
187 Obj->NumUserOperands = 0;
188 Obj->HasHungOffUses =
true;
189 Obj->HasDescriptor =
false;
190 *HungOffOperandList =
nullptr;
201 void *AllocStart =
nullptr;
202 if (HasHungOffUses) {
203 assert(!HasDescriptor &&
"not supported!");
205 Use **HungOffOperandList =
reinterpret_cast<Use **
>(
this) - 1;
207 Use::zap(*HungOffOperandList, *HungOffOperandList + NumUserOperands,
209 AllocStart = HungOffOperandList;
210 }
else if (HasDescriptor) {
211 Use *UseBegin =
reinterpret_cast<Use *
>(
this) - NumUserOperands;
212 Use::zap(UseBegin, UseBegin + NumUserOperands,
false);
215 AllocStart =
reinterpret_cast<uint8_t *
>(DI) - DI->SizeInBytes;
216 }
else if (NumUserOperands > 0) {
217 Use *Storage =
reinterpret_cast<Use *
>(
this) - NumUserOperands;
218 Use::zap(Storage, Storage + NumUserOperands,
220 AllocStart = Storage;
223 AllocStart = (
void **)(
this) - 1;
233 ((
void **)
this)[-1] = AllocStart;
236void User::operator
delete(
void *Usr) { ::operator
delete(((
void **)Usr)[-1]); }
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
uint64_t IntrinsicInst * II
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
A Use represents the edge between a Value definition and its users.
static LLVM_ABI void zap(Use *Start, const Use *Stop, bool del=false)
Destroys Use operands when the number of operands of a User changes.
LLVM_ABI void allocHungoffUses(unsigned N, bool WithExtraValues=false)
Allocate the array of Uses, followed by a pointer (with bottom bit set) to the User.
LLVM_ABI ArrayRef< const uint8_t > getDescriptor() const
Returns the descriptor co-allocated with this User instance.
LLVM_ABI bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
LLVM_ABI void growHungoffUses(unsigned N, bool WithExtraValues=false)
Grow the number of hung off uses.
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.