19
19
20
20
#define DEBUG_TYPE " sil-opt-remark-gen"
21
21
22
- #include " swift/Basic/Defer.h"
23
22
#include " swift/AST/SemanticAttrs.h"
23
+ #include " swift/Basic/Defer.h"
24
+ #include " swift/SIL/DebugUtils.h"
25
+ #include " swift/SIL/DynamicCasts.h"
24
26
#include " swift/SIL/MemAccessUtils.h"
25
27
#include " swift/SIL/OptimizationRemark.h"
26
28
#include " swift/SIL/Projection.h"
@@ -244,19 +246,20 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
244
246
// Then see if we have a debug_value that is associated with a non-inlined
245
247
// debug scope. Such an instruction is an instruction that is from the
246
248
// current function.
247
- auto *dvi = dyn_cast<DebugValueInst> (use->getUser ());
248
- if (!dvi )
249
+ auto debugInst = DebugVarCarryingInst (use->getUser ());
250
+ if (!debugInst )
249
251
return false ;
250
252
251
- if (!hasNonInlinedDebugScope (dvi))
253
+ LLVM_DEBUG (llvm::dbgs () << " Found DebugInst: " << **debugInst);
254
+ if (!hasNonInlinedDebugScope (*debugInst))
252
255
return false ;
253
256
254
257
// See if we have already inferred this debug_value as a potential source
255
258
// for this instruction. In such a case, just return.
256
- if (!visitedDebugValueInsts.insert (dvi ).second )
259
+ if (!visitedDebugValueInsts.insert (*debugInst ).second )
257
260
return false ;
258
261
259
- if (auto *decl = dvi-> getDecl ()) {
262
+ if (auto *decl = debugInst. getDecl ()) {
260
263
std::string msg;
261
264
{
262
265
llvm::raw_string_ostream stream (msg);
@@ -279,7 +282,7 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
279
282
if (!DecllessDebugValueUseSILDebugInfo)
280
283
return false ;
281
284
282
- auto varInfo = dvi-> getVarInfo ();
285
+ auto varInfo = debugInst. getVarInfo ();
283
286
if (!varInfo)
284
287
return false ;
285
288
@@ -293,8 +296,8 @@ bool ValueUseToDeclInferrer::findDecls(Operand *use, SILValue value) {
293
296
object.printNote (stream, name,
294
297
use->get () == value /* print projection path*/ );
295
298
}
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 ()));
298
301
return true ;
299
302
}
300
303
@@ -315,7 +318,10 @@ bool ValueToDeclInferrer::infer(
315
318
// the bottom of the while loop where we always return true (since we did not
316
319
// hit a could not compute case). Reassign value and continue to go to the
317
320
// next step.
321
+ LLVM_DEBUG (llvm::dbgs () << " Searching for decls!\n " );
318
322
while (true ) {
323
+ LLVM_DEBUG (llvm::dbgs () << " Visiting: " << *value);
324
+
319
325
// First check for "identified values" like arguments and global_addr.
320
326
if (auto *arg = dyn_cast<SILArgument>(value))
321
327
if (auto *decl = arg->getDecl ()) {
@@ -368,6 +374,10 @@ bool ValueToDeclInferrer::infer(
368
374
}
369
375
}
370
376
377
+ // We prefer decls not from uses since these are inherently noisier. Still,
378
+ // it is better than nothing.
379
+ bool foundDeclFromUse = false ;
380
+
371
381
if (auto *asi = dyn_cast<AllocStackInst>(value)) {
372
382
if (auto *decl = asi->getDecl ()) {
373
383
std::string msg;
@@ -379,6 +389,23 @@ bool ValueToDeclInferrer::infer(
379
389
Argument ({keyKind, " InferredValue" }, std::move (msg), decl));
380
390
return true ;
381
391
}
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
+ }
382
409
}
383
410
384
411
// Then visit our users (ignoring rc identical transformations) and see if
@@ -388,7 +415,6 @@ bool ValueToDeclInferrer::infer(
388
415
// The reason why we do this is that sometimes we reform a struct from its
389
416
// constituant parts and then construct the debug_value from that. For
390
417
// instance, if we FSOed.
391
- bool foundDeclFromUse = false ;
392
418
rcfi.visitRCUses (value, [&](Operand *use) {
393
419
foundDeclFromUse |= valueUseInferrer.findDecls (use, value);
394
420
});
@@ -460,10 +486,58 @@ struct OptRemarkGeneratorInstructionVisitor
460
486
void visitSILInstruction (SILInstruction *) {}
461
487
void visitBeginAccessInst (BeginAccessInst *bai);
462
488
void visitEndAccessInst (EndAccessInst *eai);
489
+ void visitCheckedCastAddrBranchInst (CheckedCastAddrBranchInst *ccabi);
490
+ void visitUnconditionalCheckedCastAddrInst (
491
+ UnconditionalCheckedCastAddrInst *uccai);
463
492
};
464
493
465
494
} // anonymous namespace
466
495
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
+
467
541
void OptRemarkGeneratorInstructionVisitor::visitBeginAccessInst (
468
542
BeginAccessInst *bai) {
469
543
ORE.emit ([&]() {
0 commit comments