28 if (isa<StoreInst>(
I))
31 if (
auto *
II = dyn_cast<IntrinsicInst>(
I)) {
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:
46 if (
auto *CI = dyn_cast<CallInst>(
I)) {
47 auto *CF = CI->getCalledFunction();
60 case LibFunc_memcpy_chk:
61 case LibFunc_mempcpy_chk:
62 case LibFunc_memset_chk:
63 case LibFunc_memmove_chk:
85 if (
auto *SI = dyn_cast<StoreInst>(
I)) {
93 if (
auto *
II = dyn_cast<IntrinsicInst>(
I)) {
94 visitIntrinsicCall(*
II);
102 if (
auto *CI = dyn_cast<CallInst>(
I)) {
111 return (
Type +
".").str();
117 return "MemoryOpStore";
119 return "MemoryOpUnknown";
121 return "MemoryOpIntrinsicCall";
123 return "MemoryOpCall";
131 if (Inline && *Inline)
132 R <<
" Inlined: " <<
NV(
"StoreInlined",
true) <<
".";
134 R <<
" Volatile: " <<
NV(
"StoreVolatile",
true) <<
".";
136 R <<
" Atomic: " <<
NV(
"StoreAtomic",
true) <<
".";
139 if ((Inline && !*Inline) || !Volatile || !Atomic)
141 if (Inline && !*Inline)
142 R <<
" Inlined: " <<
NV(
"StoreInlined",
false) <<
".";
144 R <<
" Volatile: " <<
NV(
"StoreVolatile",
false) <<
".";
146 R <<
" Atomic: " <<
NV(
"StoreAtomic",
false) <<
".";
149static std::optional<uint64_t>
151 if (!SizeInBits || *SizeInBits % 8 != 0)
153 return *SizeInBits / 8;
156template<
typename ...Ts>
157std::unique_ptr<DiagnosticInfoIROptimization>
158MemoryOpRemark::makeRemark(Ts... Args) {
161 return std::make_unique<OptimizationRemarkAnalysis>(
Args...);
163 return std::make_unique<OptimizationRemarkMissed>(
Args...);
169void MemoryOpRemark::visitStore(
const StoreInst &SI) {
171 bool Atomic =
SI.isAtomic();
177 visitPtr(
SI.getOperand(1),
false, *R);
182void MemoryOpRemark::visitUnknown(
const Instruction &
I) {
192 switch (
II.getIntrinsicID()) {
193 case Intrinsic::memcpy_inline:
197 case Intrinsic::memcpy:
200 case Intrinsic::memmove:
203 case Intrinsic::memset:
206 case Intrinsic::memcpy_element_unordered_atomic:
210 case Intrinsic::memmove_element_unordered_atomic:
214 case Intrinsic::memset_element_unordered_atomic:
219 return visitUnknown(
II);
223 visitCallee(CallTo.
str(),
true, *R);
224 visitSizeOperand(
II.getOperand(2), *R);
226 auto *CIVolatile = dyn_cast<ConstantInt>(
II.getOperand(3));
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);
237 case Intrinsic::memset:
238 case Intrinsic::memset_element_unordered_atomic:
239 visitPtr(
II.getOperand(0),
false, *R);
246void MemoryOpRemark::visitCall(
const CallInst &CI) {
249 return visitUnknown(CI);
254 visitCallee(
F, KnownLibCall, *R);
255 visitKnownLibCall(CI, LF, *R);
259template <
typename FTy>
260void MemoryOpRemark::visitCallee(FTy
F,
bool KnownLibCall,
264 R <<
NV(
"UnknownLibCall",
"unknown") <<
" function ";
273 case LibFunc_memset_chk:
282 case LibFunc_memcpy_chk:
283 case LibFunc_mempcpy_chk:
284 case LibFunc_memmove_chk:
286 case LibFunc_mempcpy:
287 case LibFunc_memmove:
297 if (
auto *Len = dyn_cast<ConstantInt>(V)) {
299 R <<
" Memory operation size: " <<
NV(
"StoreSize",
Size) <<
" bytes.";
309void MemoryOpRemark::visitVariable(
const Value *V,
311 if (
auto *GV = dyn_cast<GlobalVariable>(V)) {
312 auto *Ty = GV->getValueType();
316 Result.push_back(std::move(Var));
321 bool FoundDI =
false;
324 auto FindDI = [&](
const auto *DVI) {
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));
342 const auto *AI = dyn_cast<AllocaInst>(V);
347 std::optional<TypeSize> TySize = AI->getAllocationSize(
DL);
348 std::optional<uint64_t>
Size =
349 TySize ? std::optional(TySize->getFixedValue()) :
std::nullopt;
352 Result.push_back(std::move(Var));
360 for (
const Value *V : Objects)
361 visitVariable(V, VIs);
372 R << (IsRead ?
"\n Read Variables: " :
"\n Written Variables: ");
373 for (
unsigned i = 0; i < VIs.
size(); ++i) {
374 const VariableInfo &
VI = VIs[i];
375 assert(!
VI.isEmpty() &&
"No extra content to display.");
379 R <<
NV(IsRead ?
"RVarName" :
"WVarName", *
VI.Name);
381 R <<
NV(IsRead ?
"RVarName" :
"WVarName",
"<unknown>");
383 R <<
" (" <<
NV(IsRead ?
"RVarSize" :
"WVarSize", *
VI.Size) <<
" bytes)";
389 if (!
I->hasMetadata(LLVMContext::MD_annotation))
391 return any_of(
I->getMetadata(LLVMContext::MD_annotation)->operands(),
393 return isa<MDString>(Op.get()) &&
394 cast<MDString>(Op.get())->getString() ==
"auto-init";
399 return (
Type +
" inserted by -ftrivial-auto-var-init.").str();
405 return "AutoInitStore";
407 return "AutoInitUnknownInstruction";
409 return "AutoInitIntrinsicCall";
411 return "AutoInitCall";
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
This class represents an Operation in the Expression.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
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.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
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)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
The instances of the Type class are immutable: once they are created, they are never changed.
Value * getOperand(unsigned i) const
LLVM Value Representation.
constexpr ScalarTy getFixedValue() const
#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::setExtraArgs setExtraArgs
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
TinyPtrVector< DbgDeclareInst * > findDbgDeclares(Value *V)
Finds dbg.declare intrinsics declaring local variables as living in the memory that 'V' points to.
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.
TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
As above, for DVRDeclares.
Implement std::hash so that hash_code can be used in STL containers.