1919
2020#define DEBUG_TYPE " sil-opt-remark-gen"
2121
22- #include " swift/Basic/Defer.h"
2322#include " swift/AST/SemanticAttrs.h"
23+ #include " swift/Basic/Defer.h"
24+ #include " swift/SIL/DebugUtils.h"
25+ #include " swift/SIL/DynamicCasts.h"
2426#include " swift/SIL/MemAccessUtils.h"
2527#include " swift/SIL/OptimizationRemark.h"
2628#include " swift/SIL/Projection.h"
@@ -244,19 +246,20 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
244246 // Then see if we have a debug_value that is associated with a non-inlined
245247 // debug scope. Such an instruction is an instruction that is from the
246248 // current function.
247- auto *dvi = dyn_cast<DebugValueInst> (use->getUser ());
248- if (!dvi )
249+ auto debugInst = DebugVarCarryingInst (use->getUser ());
250+ if (!debugInst )
249251 return false ;
250252
251- if (!hasNonInlinedDebugScope (dvi))
253+ LLVM_DEBUG (llvm::dbgs () << " Found DebugInst: " << **debugInst);
254+ if (!hasNonInlinedDebugScope (*debugInst))
252255 return false ;
253256
254257 // See if we have already inferred this debug_value as a potential source
255258 // for this instruction. In such a case, just return.
256- if (!visitedDebugValueInsts.insert (dvi ).second )
259+ if (!visitedDebugValueInsts.insert (*debugInst ).second )
257260 return false ;
258261
259- if (auto *decl = dvi-> getDecl ()) {
262+ if (auto *decl = debugInst. getDecl ()) {
260263 std::string msg;
261264 {
262265 llvm::raw_string_ostream stream (msg);
@@ -279,7 +282,7 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
279282 if (!DecllessDebugValueUseSILDebugInfo)
280283 return false ;
281284
282- auto varInfo = dvi-> getVarInfo ();
285+ auto varInfo = debugInst. getVarInfo ();
283286 if (!varInfo)
284287 return false ;
285288
@@ -293,8 +296,8 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
293296 object.printNote (stream, name,
294297 use->get () == value /* print projection path*/ );
295298 }
296- resultingInferredDecls.push_back (
297- Argument ( {keyKind, " InferredValue" }, std::move (msg), dvi ->getLoc ()));
299+ resultingInferredDecls.push_back (Argument (
300+ {keyKind, " InferredValue" }, std::move (msg), debugInst ->getLoc ()));
298301 return true ;
299302}
300303
@@ -315,7 +318,10 @@ bool ValueToDeclInferrer::infer(
315318 // the bottom of the while loop where we always return true (since we did not
316319 // hit a could not compute case). Reassign value and continue to go to the
317320 // next step.
321+ LLVM_DEBUG (llvm::dbgs () << " Searching for decls!\n " );
318322 while (true ) {
323+ LLVM_DEBUG (llvm::dbgs () << " Visiting: " << *value);
324+
319325 // First check for "identified values" like arguments and global_addr.
320326 if (auto *arg = dyn_cast<SILArgument>(value))
321327 if (auto *decl = arg->getDecl ()) {
@@ -368,6 +374,10 @@ bool ValueToDeclInferrer::infer(
368374 }
369375 }
370376
377+ // We prefer decls not from uses since these are inherently noisier. Still,
378+ // it is better than nothing.
379+ bool foundDeclFromUse = false ;
380+
371381 if (auto *asi = dyn_cast<AllocStackInst>(value)) {
372382 if (auto *decl = asi->getDecl ()) {
373383 std::string msg;
@@ -379,6 +389,23 @@ bool ValueToDeclInferrer::infer(
379389 Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
380390 return true ;
381391 }
392+
393+ // See if we have a single init alloc_stack and can infer a
394+ // debug_value/debug_value_addr from that.
395+ LLVM_DEBUG (llvm::dbgs () << " Checking for single init use!\n " );
396+ if (auto *initUse = getSingleInitAllocStackUse (asi)) {
397+ LLVM_DEBUG (llvm::dbgs () << " Found one: " << *initUse->getUser ());
398+ if (auto *si = dyn_cast<StoreInst>(initUse->getUser ())) {
399+ for (auto *use : si->getSrc ()->getUses ()) {
400+ foundDeclFromUse |= valueUseInferrer.findDecls (use, value);
401+ }
402+ }
403+ if (auto *cai = dyn_cast<CopyAddrInst>(initUse->getUser ())) {
404+ for (auto *use : cai->getSrc ()->getUses ()) {
405+ foundDeclFromUse |= valueUseInferrer.findDecls (use, value);
406+ }
407+ }
408+ }
382409 }
383410
384411 // Then visit our users (ignoring rc identical transformations) and see if
@@ -388,7 +415,6 @@ bool ValueToDeclInferrer::infer(
388415 // The reason why we do this is that sometimes we reform a struct from its
389416 // constituant parts and then construct the debug_value from that. For
390417 // instance, if we FSOed.
391- bool foundDeclFromUse = false ;
392418 rcfi.visitRCUses (value, [&](Operand *use) {
393419 foundDeclFromUse |= valueUseInferrer.findDecls (use, value);
394420 });
@@ -460,10 +486,58 @@ struct OptRemarkGeneratorInstructionVisitor
460486 void visitSILInstruction (SILInstruction *) {}
461487 void visitBeginAccessInst (BeginAccessInst *bai);
462488 void visitEndAccessInst (EndAccessInst *eai);
489+ void visitCheckedCastAddrBranchInst (CheckedCastAddrBranchInst *ccabi);
490+ void visitUnconditionalCheckedCastAddrInst (
491+ UnconditionalCheckedCastAddrInst *uccai);
463492};
464493
465494} // anonymous namespace
466495
496+ void OptRemarkGeneratorInstructionVisitor::
497+ visitUnconditionalCheckedCastAddrInst (
498+ UnconditionalCheckedCastAddrInst *uccai) {
499+ ORE.emit ([&]() {
500+ using namespace OptRemark ;
501+ SmallVector<Argument, 8 > inferredArgs;
502+ bool foundArgs = valueToDeclInferrer.infer (
503+ ArgumentKeyKind::Note, uccai->getSrc (), inferredArgs,
504+ true /* allow single ref elt peek*/ );
505+ (void )foundArgs;
506+
507+ // Use the actual source loc of the
508+ auto remark = RemarkMissed (" memory" , *uccai)
509+ << " unconditional runtime cast of value with type '"
510+ << NV (" ValueType" , uccai->getSrc ()->getType ()) << " ' to '"
511+ << NV (" CastType" , uccai->getDest ()->getType ()) << " '" ;
512+ for (auto arg : inferredArgs) {
513+ remark << arg;
514+ }
515+ return remark;
516+ });
517+ }
518+
519+ void OptRemarkGeneratorInstructionVisitor::visitCheckedCastAddrBranchInst (
520+ CheckedCastAddrBranchInst *ccabi) {
521+ ORE.emit ([&]() {
522+ using namespace OptRemark ;
523+ SmallVector<Argument, 8 > inferredArgs;
524+ bool foundArgs = valueToDeclInferrer.infer (
525+ ArgumentKeyKind::Note, ccabi->getSrc (), inferredArgs,
526+ true /* allow single ref elt peek*/ );
527+ (void )foundArgs;
528+
529+ // Use the actual source loc of the
530+ auto remark = RemarkMissed (" memory" , *ccabi)
531+ << " conditional runtime cast of value with type '"
532+ << NV (" ValueType" , ccabi->getSrc ()->getType ()) << " ' to '"
533+ << NV (" CastType" , ccabi->getDest ()->getType ()) << " '" ;
534+ for (auto arg : inferredArgs) {
535+ remark << arg;
536+ }
537+ return remark;
538+ });
539+ }
540+
467541void OptRemarkGeneratorInstructionVisitor::visitBeginAccessInst (
468542 BeginAccessInst *bai) {
469543 ORE.emit ([&]() {
0 commit comments