LLVM: lib/Analysis/TypeMetadataUtils.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
20
21using namespace llvm;
22
23
24static void
28 for (const Use &U : FPtr->uses()) {
30
31
32
33
34
35
37 continue;
39 continue;
40 if (isa(User)) {
42 DT);
43 } else if (auto *CI = dyn_cast(User)) {
45 } else if (auto *II = dyn_cast(User)) {
47 } else if (HasNonCallUses) {
48 *HasNonCallUses = true;
49 }
50 }
51}
52
53
57 for (const Use &U : VPtr->uses()) {
59 if (isa(User)) {
61 } else if (isa(User)) {
63 } else if (auto GEP = dyn_cast(User)) {
64
65 if (VPtr == GEP->getPointerOperand() && GEP->hasAllConstantIndices()) {
67 int64_t GEPOffset = M->getDataLayout().getIndexedOffsetInType(
68 GEP->getSourceElementType(), Indices);
70 CI, DT);
71 }
72 } else if (auto *Call = dyn_cast(User)) {
73 if (Call->getIntrinsicID() == llvm::Intrinsic::load_relative) {
74 if (auto *LoadOffset = dyn_cast(Call->getOperand(1))) {
76 Offset + LoadOffset->getSExtValue(), CI,
77 DT);
78 }
79 }
80 }
81 }
82}
83
90 Intrinsic::public_type_test);
91
92 const Module *M = CI->getParent()->getParent()->getParent();
93
94
95 for (const Use &CIU : CI->uses())
96 if (auto *Assume = dyn_cast(CIU.getUser()))
98
99
100
101 if (!Assumes.empty())
104}
105
112 Intrinsic::type_checked_load ||
114 Intrinsic::type_checked_load_relative);
115
118 HasNonCallUses = true;
119 return;
120 }
121
122 for (const Use &U : CI->uses()) {
123 auto CIU = U.getUser();
124 if (auto EVI = dyn_cast(CIU)) {
125 if (EVI->getNumIndices() == 1 && EVI->getIndices()[0] == 0) {
127 continue;
128 }
129 if (EVI->getNumIndices() == 1 && EVI->getIndices()[0] == 1) {
131 continue;
132 }
133 }
134 HasNonCallUses = true;
135 }
136
137 for (Value *LoadedPtr : LoadedPtrs)
139 Offset->getZExtValue(), CI, DT);
140}
141
144
145
146
147 if (auto *Equiv = dyn_cast(I))
148 I = Equiv->getGlobalValue();
149
150 if (I->getType()->isPointerTy()) {
152 return I;
153 return nullptr;
154 }
155
157
158 if (auto *C = dyn_cast(I)) {
159 const StructLayout *SL = DL.getStructLayout(C->getType());
161 return nullptr;
162
166 TopLevelGlobal);
167 }
168 if (auto *C = dyn_cast(I)) {
171
172 unsigned Op = Offset / ElemSize;
173 if (Op >= C->getNumOperands())
174 return nullptr;
175
177 Offset % ElemSize, M, TopLevelGlobal);
178 }
179
180
181 if (auto *CI = dyn_cast(I)) {
182 if (Offset == 0 && CI->isZero()) {
183 return I;
184 }
185 }
186 if (auto *C = dyn_cast(I)) {
187 switch (C->getOpcode()) {
188 case Instruction::Trunc:
189 case Instruction::PtrToInt:
191 TopLevelGlobal);
192 case Instruction::Sub: {
193 auto *Operand0 = cast(C->getOperand(0));
194 auto *Operand1 = cast(C->getOperand(1));
195
196 auto StripGEP = [](Constant *C) {
197 auto *CE = dyn_cast(C);
198 if (!CE)
199 return C;
200 if (CE->getOpcode() != Instruction::GetElementPtr)
201 return C;
202 return CE->getOperand(0);
203 };
204 auto *Operand1TargetGlobal = StripGEP(getPointerAtOffset(Operand1, 0, M));
205
206
207
208 if (Operand1TargetGlobal != TopLevelGlobal)
209 return nullptr;
210
212 }
213 default:
214 return nullptr;
215 }
216 }
217 return nullptr;
218}
219
220std::pair<Function *, Constant *>
224 if ()
225 return std::pair<Function *, Constant *>(nullptr, nullptr);
226
227 auto C = Ptr->stripPointerCasts();
228
229 auto Fn = dyn_cast(C);
231 if (!Fn && A)
232 Fn = dyn_cast(A->getAliasee());
233
234 if (!Fn)
235 return std::pair<Function *, Constant *>(nullptr, nullptr);
236
237 return std::pair<Function *, Constant *>(Fn, C);
238}
239
241 auto *PtrExpr = dyn_cast(U);
242 if (!PtrExpr || PtrExpr->getOpcode() != Instruction::PtrToInt)
243 return;
244
245 for (auto *PtrToIntUser : PtrExpr->users()) {
246 auto *SubExpr = dyn_cast(PtrToIntUser);
247 if (!SubExpr || SubExpr->getOpcode() != Instruction::Sub)
248 return;
249
250 SubExpr->replaceNonMetadataUsesWith(
251 ConstantInt::get(SubExpr->getType(), 0));
252 }
253}
254
256 for (auto *U : C->users()) {
257 if (auto *Equiv = dyn_cast(U))
259 else
261 }
262}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class to represent array types.
Type * getElementType() const
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
const Function * getFunction() const
Return the function this instruction belongs to.
A Module instance is used to store all the information related to an LLVM module.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getSizeInBytes() const
unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
TypeSize getElementOffset(unsigned Idx) const
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
const ParentTy * getParent() const
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void findDevirtualizableCallsForTypeCheckedLoad(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< Instruction * > &LoadedPtrs, SmallVectorImpl< Instruction * > &Preds, bool &HasNonCallUses, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.checked.load, find all devirtualizable call sites based on t...
void replaceRelativePointerUsersWithZero(Constant *C)
Finds the same "relative pointer" pattern as described above, where the target is C,...
void findDevirtualizableCallsForTypeTest(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< CallInst * > &Assumes, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.test, find all devirtualizable call sites based on the call ...
Constant * getPointerAtOffset(Constant *I, uint64_t Offset, Module &M, Constant *TopLevelGlobal=nullptr)
Processes a Constant recursively looking into elements of arrays, structs and expressions to find a t...
std::pair< Function *, Constant * > getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset, Module &M)
Given a vtable and a specified offset, returns the function and the trivial pointer at the specified ...