27 if (isa<StoreInst>(
I))
30 if (
auto *II = dyn_cast<IntrinsicInst>(
I)) {
31 switch (II->getIntrinsicID()) {
32 case Intrinsic::memcpy_inline:
33 case Intrinsic::memcpy:
34 case Intrinsic::memmove:
35 case Intrinsic::memset:
36 case Intrinsic::memcpy_element_unordered_atomic:
37 case Intrinsic::memmove_element_unordered_atomic:
38 case Intrinsic::memset_element_unordered_atomic:
45 if (
auto *CI = dyn_cast<CallInst>(
I)) {
46 auto *CF = CI->getCalledFunction();
59 case LibFunc_memcpy_chk:
60 case LibFunc_mempcpy_chk:
61 case LibFunc_memset_chk:
62 case LibFunc_memmove_chk:
84 if (
auto *
SI = dyn_cast<StoreInst>(
I)) {
92 if (
auto *II = dyn_cast<IntrinsicInst>(
I)) {
93 visitIntrinsicCall(*II);
101 if (
auto *CI = dyn_cast<CallInst>(
I)) {
110 return (
Type +
".").str();
116 return "MemoryOpStore";
118 return "MemoryOpUnknown";
120 return "MemoryOpIntrinsicCall";
122 return "MemoryOpCall";
130 if (Inline && *Inline)
131 R <<
" Inlined: " <<
NV(
"StoreInlined",
true) <<
".";
133 R <<
" Volatile: " <<
NV(
"StoreVolatile",
true) <<
".";
135 R <<
" Atomic: " <<
NV(
"StoreAtomic",
true) <<
".";
138 if ((Inline && !*Inline) || !Volatile || !Atomic)
140 if (Inline && !*Inline)
141 R <<
" Inlined: " <<
NV(
"StoreInlined",
false) <<
".";
143 R <<
" Volatile: " <<
NV(
"StoreVolatile",
false) <<
".";
145 R <<
" Atomic: " <<
NV(
"StoreAtomic",
false) <<
".";
148static std::optional<uint64_t>
150 if (!SizeInBits || *SizeInBits % 8 != 0)
152 return *SizeInBits / 8;
155template<
typename ...Ts>
156std::unique_ptr<DiagnosticInfoIROptimization>
157MemoryOpRemark::makeRemark(Ts... Args) {
160 return std::make_unique<OptimizationRemarkAnalysis>(
Args...);
162 return std::make_unique<OptimizationRemarkMissed>(
Args...);
168void MemoryOpRemark::visitStore(
const StoreInst &SI) {
170 bool Atomic =
SI.isAtomic();
176 visitPtr(
SI.getOperand(1),
false, *R);
181void MemoryOpRemark::visitUnknown(
const Instruction &
I) {
187void MemoryOpRemark::visitIntrinsicCall(
const IntrinsicInst &II) {
192 case Intrinsic::memcpy_inline:
196 case Intrinsic::memcpy:
199 case Intrinsic::memmove:
202 case Intrinsic::memset:
205 case Intrinsic::memcpy_element_unordered_atomic:
209 case Intrinsic::memmove_element_unordered_atomic:
213 case Intrinsic::memset_element_unordered_atomic:
218 return visitUnknown(II);
222 visitCallee(CallTo.
str(),
true, *R);
225 auto *CIVolatile = dyn_cast<ConstantInt>(II.
getOperand(3));
227 bool Volatile = !Atomic && CIVolatile && CIVolatile->getZExtValue();
229 case Intrinsic::memcpy_inline:
230 case Intrinsic::memcpy:
231 case Intrinsic::memmove:
232 case Intrinsic::memcpy_element_unordered_atomic:
236 case Intrinsic::memset:
237 case Intrinsic::memset_element_unordered_atomic:
245void MemoryOpRemark::visitCall(
const CallInst &CI) {
248 return visitUnknown(CI);
253 visitCallee(
F, KnownLibCall, *R);
254 visitKnownLibCall(CI, LF, *R);
258template <
typename FTy>
259void MemoryOpRemark::visitCallee(FTy
F,
bool KnownLibCall,
263 R <<
NV(
"UnknownLibCall",
"unknown") <<
" function ";
272 case LibFunc_memset_chk:
281 case LibFunc_memcpy_chk:
282 case LibFunc_mempcpy_chk:
283 case LibFunc_memmove_chk:
285 case LibFunc_mempcpy:
286 case LibFunc_memmove:
296 if (
auto *Len = dyn_cast<ConstantInt>(V)) {
298 R <<
" Memory operation size: " <<
NV(
"StoreSize",
Size) <<
" bytes.";
308void MemoryOpRemark::visitVariable(
const Value *V,
310 if (
auto *GV = dyn_cast<GlobalVariable>(V)) {
311 auto *Ty = GV->getValueType();
315 Result.push_back(std::move(Var));
320 bool FoundDI =
false;
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));
339 const auto *AI = dyn_cast<AllocaInst>(V);
344 std::optional<TypeSize> TySize = AI->getAllocationSize(
DL);
345 std::optional<uint64_t>
Size =
346 TySize ? std::optional(TySize->getFixedValue()) :
std::nullopt;
349 Result.push_back(std::move(Var));
357 for (
const Value *V : Objects)
358 visitVariable(V, VIs);
369 R << (IsRead ?
"\n Read Variables: " :
"\n Written Variables: ");
370 for (
unsigned i = 0; i < VIs.
size(); ++i) {
371 const VariableInfo &
VI = VIs[i];
372 assert(!
VI.isEmpty() &&
"No extra content to display.");
376 R <<
NV(IsRead ?
"RVarName" :
"WVarName", *
VI.Name);
378 R <<
NV(IsRead ?
"RVarName" :
"WVarName",
"<unknown>");
380 R <<
" (" <<
NV(IsRead ?
"RVarSize" :
"WVarSize", *
VI.Size) <<
" bytes)";
386 if (!
I->hasMetadata(LLVMContext::MD_annotation))
388 return any_of(
I->getMetadata(LLVMContext::MD_annotation)->operands(),
390 return cast<MDString>(Op.get())->getString() ==
"auto-init";
395 return (
Type +
" inserted by -ftrivial-auto-var-init.").str();
401 return "AutoInitStore";
403 return "AutoInitUnknownInstruction";
405 return "AutoInitIntrinsicCall";
407 return "AutoInitCall";
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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.
This is the common base class for debug info intrinsics for variables.
Common features for diagnostics dealing with optimization remarks that are used by IR passes.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
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.
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.
TinyPtrVector< DbgDeclareInst * > FindDbgDeclareUses(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.