LLVM: lib/Transforms/Utils/MemoryOpRemark.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
20#include
21
22using namespace llvm;
24
26
29 return true;
30
32 switch (II->getIntrinsicID()) {
33 case Intrinsic::memcpy_inline:
34 case Intrinsic::memcpy:
35 case Intrinsic::memmove:
36 case Intrinsic::memset:
37 case Intrinsic::memcpy_element_unordered_atomic:
38 case Intrinsic::memmove_element_unordered_atomic:
39 case Intrinsic::memset_element_unordered_atomic:
40 return true;
41 default:
42 return false;
43 }
44 }
45
47 auto *CF = CI->getCalledFunction();
48 if (!CF)
49 return false;
50
51 if (!CF->hasName())
52 return false;
53
54 LibFunc LF;
55 bool KnownLibCall = TLI.getLibFunc(*CF, LF) && TLI.has(LF);
56 if (!KnownLibCall)
57 return false;
58
59 switch (LF) {
60 case LibFunc_memcpy_chk:
61 case LibFunc_mempcpy_chk:
62 case LibFunc_memset_chk:
63 case LibFunc_memmove_chk:
64 case LibFunc_memcpy:
65 case LibFunc_mempcpy:
66 case LibFunc_memset:
67 case LibFunc_memmove:
68 case LibFunc_bzero:
69 case LibFunc_bcopy:
70 return true;
71 default:
72 return false;
73 }
74 }
75
76 return false;
77}
78
80
81
82
83
84
86 visitStore(*SI);
87 return;
88 }
89
90
91
92
94 visitIntrinsicCall(*II);
95 return;
96 }
97
98
99
100
101
103 visitCall(*CI);
104 return;
105 }
106
107 visitUnknown(*I);
108}
109
111 return (Type + ".").str();
112}
113
115 switch (RK) {
117 return "MemoryOpStore";
119 return "MemoryOpUnknown";
121 return "MemoryOpIntrinsicCall";
123 return "MemoryOpCall";
124 }
126}
127
129 bool Atomic,
131 if (Inline && *Inline)
132 R << " Inlined: " << NV("StoreInlined", true) << ".";
133 if (Volatile)
134 R << " Volatile: " << NV("StoreVolatile", true) << ".";
135 if (Atomic)
136 R << " Atomic: " << NV("StoreAtomic", true) << ".";
137
138
139 if ((Inline && !*Inline) || !Volatile || !Atomic)
141 if (Inline && !*Inline)
142 R << " Inlined: " << NV("StoreInlined", false) << ".";
143 if (!Volatile)
144 R << " Volatile: " << NV("StoreVolatile", false) << ".";
145 if (!Atomic)
146 R << " Atomic: " << NV("StoreAtomic", false) << ".";
147}
148
149static std::optional<uint64_t>
151 if (!SizeInBits || *SizeInBits % 8 != 0)
152 return std::nullopt;
153 return *SizeInBits / 8;
154}
155
156template<typename ...Ts>
157std::unique_ptr
158MemoryOpRemark::makeRemark(Ts... Args) {
161 return std::make_unique(Args...);
163 return std::make_unique(Args...);
164 default:
166 }
167}
168
169void MemoryOpRemark::visitStore(const StoreInst &SI) {
171 bool Atomic = SI.isAtomic();
172 int64_t Size = DL.getTypeStoreSize(SI.getOperand(0)->getType());
173
176 << " bytes.";
177 visitPtr(SI.getOperand(1), false, *R);
179 ORE.emit(*R);
180}
181
182void MemoryOpRemark::visitUnknown(const Instruction &I) {
185 ORE.emit(*R);
186}
187
188void MemoryOpRemark::visitIntrinsicCall(const IntrinsicInst &II) {
189 SmallString<32> CallTo;
190 bool Atomic = false;
192 switch (II.getIntrinsicID()) {
193 case Intrinsic::memcpy_inline:
194 CallTo = "memcpy";
196 break;
197 case Intrinsic::memcpy:
198 CallTo = "memcpy";
199 break;
200 case Intrinsic::memmove:
201 CallTo = "memmove";
202 break;
203 case Intrinsic::memset:
204 CallTo = "memset";
205 break;
206 case Intrinsic::memcpy_element_unordered_atomic:
207 CallTo = "memcpy";
208 Atomic = true;
209 break;
210 case Intrinsic::memmove_element_unordered_atomic:
211 CallTo = "memmove";
212 Atomic = true;
213 break;
214 case Intrinsic::memset_element_unordered_atomic:
215 CallTo = "memset";
216 Atomic = true;
217 break;
218 default:
219 return visitUnknown(II);
220 }
221
223 visitCallee(CallTo.str(), true, *R);
224 visitSizeOperand(II.getOperand(2), *R);
225
227
228 bool Volatile = !Atomic && CIVolatile && CIVolatile->getZExtValue();
229 switch (II.getIntrinsicID()) {
230 case Intrinsic::memcpy_inline:
231 case Intrinsic::memcpy:
232 case Intrinsic::memmove:
233 case Intrinsic::memcpy_element_unordered_atomic:
234 visitPtr(II.getOperand(1), true, *R);
235 visitPtr(II.getOperand(0), false, *R);
236 break;
237 case Intrinsic::memset:
238 case Intrinsic::memset_element_unordered_atomic:
239 visitPtr(II.getOperand(0), false, *R);
240 break;
241 }
243 ORE.emit(*R);
244}
245
246void MemoryOpRemark::visitCall(const CallInst &CI) {
248 if ()
249 return visitUnknown(CI);
250
251 LibFunc LF;
252 bool KnownLibCall = TLI.getLibFunc(*F, LF) && TLI.has(LF);
254 visitCallee(F, KnownLibCall, *R);
255 visitKnownLibCall(CI, LF, *R);
256 ORE.emit(*R);
257}
258
259template
260void MemoryOpRemark::visitCallee(FTy F, bool KnownLibCall,
262 R << "Call to ";
263 if (!KnownLibCall)
264 R << NV("UnknownLibCall", "unknown") << " function ";
266}
267
268void MemoryOpRemark::visitKnownLibCall(const CallInst &CI, LibFunc LF,
270 switch (LF) {
271 default:
272 return;
273 case LibFunc_memset_chk:
274 case LibFunc_memset:
275 visitSizeOperand(CI.getOperand(2), R);
276 visitPtr(CI.getOperand(0), false, R);
277 break;
278 case LibFunc_bzero:
279 visitSizeOperand(CI.getOperand(1), R);
280 visitPtr(CI.getOperand(0), false, R);
281 break;
282 case LibFunc_memcpy_chk:
283 case LibFunc_mempcpy_chk:
284 case LibFunc_memmove_chk:
285 case LibFunc_memcpy:
286 case LibFunc_mempcpy:
287 case LibFunc_memmove:
288 case LibFunc_bcopy:
289 visitSizeOperand(CI.getOperand(2), R);
290 visitPtr(CI.getOperand(1), true, R);
291 visitPtr(CI.getOperand(0), false, R);
292 break;
293 }
294}
295
298 uint64_t Size = Len->getZExtValue();
299 R << " Memory operation size: " << NV("StoreSize", Size) << " bytes.";
300 }
301}
302
304 if (V->hasName())
305 return V->getName();
306 return std::nullopt;
307}
308
309void MemoryOpRemark::visitVariable(const Value *V,
312 auto *Ty = GV->getValueType();
313 uint64_t Size = DL.getTypeSizeInBits(Ty).getFixedValue();
315 if (!Var.isEmpty())
316 Result.push_back(std::move(Var));
317 return;
318 }
319
320
321 bool FoundDI = false;
322
323
324 auto FindDI = [&](const DbgVariableRecord *DVI) {
325 if (DILocalVariable *DILV = DVI->getVariable()) {
326 std::optional<uint64_t> DISize = getSizeInBytes(DILV->getSizeInBits());
327 VariableInfo Var{DILV->getName(), DISize};
328 if (!Var.isEmpty()) {
329 Result.push_back(std::move(Var));
330 FoundDI = true;
331 }
332 }
333 };
335
336 if (FoundDI) {
338 return;
339 }
340
342 if (!AI)
343 return;
344
345
346 std::optional TySize = AI->getAllocationSize(DL);
347 std::optional<uint64_t> Size =
348 TySize ? std::optional(TySize->getFixedValue()) : std::nullopt;
350 if (!Var.isEmpty())
351 Result.push_back(std::move(Var));
352}
353
355
356 SmallVector<Value *, 2> Objects;
359 for (const Value *V : Objects)
360 visitVariable(V, VIs);
361
362 if (VIs.empty()) {
363 bool CanBeNull;
364 bool CanBeFreed;
367 return;
369 }
370
371 R << (IsRead ? "\n Read Variables: " : "\n Written Variables: ");
372 for (unsigned i = 0; i < VIs.size(); ++i) {
373 const VariableInfo &VI = VIs[i];
374 assert(.isEmpty() && "No extra content to display.");
375 if (i != 0)
376 R << ", ";
377 if (VI.Name)
378 R << NV(IsRead ? "RVarName" : "WVarName", *VI.Name);
379 else
380 R << NV(IsRead ? "RVarName" : "WVarName", "");
381 if (VI.Size)
382 R << " (" << NV(IsRead ? "RVarSize" : "WVarSize", *VI.Size) << " bytes)";
383 }
384 R << ".";
385}
386
388 if (->hasMetadata(LLVMContext::MD_annotation))
389 return false;
390 return any_of(I->getMetadata(LLVMContext::MD_annotation)->operands(),
392 return isa(Op.get()) &&
393 cast(Op.get())->getString() == "auto-init";
394 });
395}
396
398 return (Type + " inserted by -ftrivial-auto-var-init.").str();
399}
400
402 switch (RK) {
404 return "AutoInitStore";
406 return "AutoInitUnknownInstruction";
408 return "AutoInitIntrinsicCall";
410 return "AutoInitCall";
411 }
413}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t IntrinsicInst * II
This file defines the SmallString class.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
This class represents a function call, abstracting a target machine's calling convention.
Common features for diagnostics dealing with optimization remarks that are used by IR passes.
A wrapper class for inspecting calls to intrinsic functions.
Tracking metadata reference owned by Metadata.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
Value * getOperand(unsigned i) const
LLVM Value Representation.
LLVM_ABI uint64_t getPointerDereferenceableBytes(const DataLayout &DL, bool &CanBeNull, bool &CanBeFreed) const
Returns the number of bytes known to be dereferenceable for the pointer value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
DiagnosticInfoOptimizationBase::Argument NV
DiagnosticInfoOptimizationBase::setExtraArgs setExtraArgs
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI bool getUnderlyingObjectsForCodeGen(const Value *V, SmallVectorImpl< Value * > &Objects)
This is a wrapper around getUnderlyingObjects and adds support for basic ptrtoint+arithmetic+inttoptr...
@ DK_OptimizationRemarkAnalysis
@ DK_OptimizationRemarkMissed
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.