26 if (isa<StoreInst>(
I))
29 if (
auto *II = dyn_cast<IntrinsicInst>(
I)) {
30 switch (II->getIntrinsicID()) {
31 case Intrinsic::memcpy_inline:
33 case Intrinsic::memmove:
34 case Intrinsic::memset:
35 case Intrinsic::memcpy_element_unordered_atomic:
36 case Intrinsic::memmove_element_unordered_atomic:
37 case Intrinsic::memset_element_unordered_atomic:
44 if (
auto *CI = dyn_cast<CallInst>(
I)) {
45 auto *CF = CI->getCalledFunction();
58 case LibFunc_memcpy_chk:
59 case LibFunc_mempcpy_chk:
60 case LibFunc_memset_chk:
61 case LibFunc_memmove_chk:
83 if (
auto *
SI = dyn_cast<StoreInst>(
I)) {
91 if (
auto *II = dyn_cast<IntrinsicInst>(
I)) {
92 visitIntrinsicCall(*II);
100 if (
auto *CI = dyn_cast<CallInst>(
I)) {
109 return (
Type +
".").str();
115 return "MemoryOpStore";
117 return "MemoryOpUnknown";
118 case RK_IntrinsicCall:
119 return "MemoryOpIntrinsicCall";
121 return "MemoryOpCall";
129 if (Inline && *Inline)
130 R <<
" Inlined: " <<
NV(
"StoreInlined",
true) <<
".";
132 R <<
" Volatile: " <<
NV(
"StoreVolatile",
true) <<
".";
134 R <<
" Atomic: " <<
NV(
"StoreAtomic",
true) <<
".";
137 if ((Inline && !*Inline) || !Volatile || !Atomic)
139 if (Inline && !*Inline)
140 R <<
" Inlined: " <<
NV(
"StoreInlined",
false) <<
".";
142 R <<
" Volatile: " <<
NV(
"StoreVolatile",
false) <<
".";
144 R <<
" Atomic: " <<
NV(
"StoreAtomic",
false) <<
".";
148 if (!SizeInBits || *SizeInBits % 8 != 0)
150 return *SizeInBits / 8;
153 template<
typename ...Ts>
154 std::unique_ptr<DiagnosticInfoIROptimization>
155 MemoryOpRemark::makeRemark(Ts...
Args) {
156 switch (diagnosticKind()) {
158 return std::make_unique<OptimizationRemarkAnalysis>(
Args...);
160 return std::make_unique<OptimizationRemarkMissed>(
Args...);
166 void MemoryOpRemark::visitStore(
const StoreInst &
SI) {
168 bool Atomic =
SI.isAtomic();
169 int64_t
Size =
DL.getTypeStoreSize(
SI.getOperand(0)->getType());
171 auto R = makeRemark(RemarkPass.data(), remarkName(RK_Store), &
SI);
172 *
R << explainSource(
"Store") <<
"\nStore size: " <<
NV(
"StoreSize", Size)
174 visitPtr(
SI.getOperand(1),
false, *R);
179 void MemoryOpRemark::visitUnknown(
const Instruction &
I) {
180 auto R = makeRemark(RemarkPass.data(), remarkName(RK_Unknown), &
I);
181 *
R << explainSource(
"Initialization");
185 void MemoryOpRemark::visitIntrinsicCall(
const IntrinsicInst &II) {
190 case Intrinsic::memcpy_inline:
197 case Intrinsic::memmove:
200 case Intrinsic::memset:
203 case Intrinsic::memcpy_element_unordered_atomic:
207 case Intrinsic::memmove_element_unordered_atomic:
211 case Intrinsic::memset_element_unordered_atomic:
216 return visitUnknown(II);
219 auto R = makeRemark(RemarkPass.data(), remarkName(RK_IntrinsicCall), &II);
220 visitCallee(CallTo.
str(),
true, *R);
223 auto *CIVolatile = dyn_cast<ConstantInt>(II.
getOperand(3));
225 bool Volatile = !Atomic && CIVolatile && CIVolatile->getZExtValue();
227 case Intrinsic::memcpy_inline:
229 case Intrinsic::memmove:
230 case Intrinsic::memcpy_element_unordered_atomic:
234 case Intrinsic::memset:
235 case Intrinsic::memset_element_unordered_atomic:
243 void MemoryOpRemark::visitCall(
const CallInst &CI) {
246 return visitUnknown(CI);
249 bool KnownLibCall = TLI.getLibFunc(*
F, LF) && TLI.has(LF);
250 auto R = makeRemark(RemarkPass.data(), remarkName(RK_Call), &CI);
251 visitCallee(
F, KnownLibCall, *R);
252 visitKnownLibCall(CI, LF, *R);
256 template <
typename FTy>
257 void MemoryOpRemark::visitCallee(FTy
F,
bool KnownLibCall,
261 R <<
NV(
"UnknownLibCall",
"unknown") <<
" function ";
262 R <<
NV(
"Callee",
F) << explainSource(
"");
270 case LibFunc_memset_chk:
279 case LibFunc_memcpy_chk:
280 case LibFunc_mempcpy_chk:
281 case LibFunc_memmove_chk:
283 case LibFunc_mempcpy:
284 case LibFunc_memmove:
294 if (
auto *Len = dyn_cast<ConstantInt>(V)) {
296 R <<
" Memory operation size: " <<
NV(
"StoreSize", Size) <<
" bytes.";
306 void MemoryOpRemark::visitVariable(
const Value *V,
308 if (
auto *GV = dyn_cast<GlobalVariable>(V)) {
309 auto *Ty = GV->getValueType();
318 bool FoundDI =
false;
325 VariableInfo Var{DILV->getName(), DISize};
326 if (!Var.isEmpty()) {
337 const auto *AI = dyn_cast<AllocaInst>(V);
355 for (
const Value *V : Objects)
356 visitVariable(V, VIs);
367 R << (IsRead ?
"\n Read Variables: " :
"\n Written Variables: ");
368 for (
unsigned i = 0;
i < VIs.size(); ++
i) {
369 const VariableInfo &
VI = VIs[
i];
370 assert(!
VI.isEmpty() &&
"No extra content to display.");
374 R <<
NV(IsRead ?
"RVarName" :
"WVarName", *
VI.Name);
376 R <<
NV(IsRead ?
"RVarName" :
"WVarName",
"<unknown>");
378 R <<
" (" <<
NV(IsRead ?
"RVarSize" :
"WVarSize", *
VI.Size) <<
" bytes)";
384 if (!
I->hasMetadata(LLVMContext::MD_annotation))
386 return any_of(
I->getMetadata(LLVMContext::MD_annotation)->operands(),
388 return cast<MDString>(Op.get())->getString() ==
"auto-init";
393 return (
Type +
" inserted by -ftrivial-auto-var-init.").str();
399 return "AutoInitStore";
401 return "AutoInitUnknownInstruction";
402 case RK_IntrinsicCall:
403 return "AutoInitIntrinsicCall";
405 return "AutoInitCall";