28
28
#include " llvm/ADT/TinyPtrVector.h"
29
29
#include " llvm/Support/SaveAndRestore.h"
30
30
#include " llvm/Support/Debug.h"
31
+ #include " llvm/Transforms/Utils/Local.h"
31
32
#include " clang/AST/ASTContext.h"
32
33
#include " clang/Basic/TargetInfo.h"
33
34
#include " swift/Basic/ExternalUnion.h"
@@ -646,6 +647,41 @@ class IRGenSILFunction :
646
647
return Name;
647
648
}
648
649
650
+ // / Try to emit an inline assembly gadget which extends the lifetime of
651
+ // / \p Var. Returns whether or not this was successful.
652
+ bool emitLifetimeExtendingUse (llvm::Value *Var) {
653
+ llvm::Type *ArgTys;
654
+ auto *Ty = Var->getType ();
655
+ // Vectors, Pointers and Floats are expected to fit into a register.
656
+ if (Ty->isPointerTy () || Ty->isFloatingPointTy () || Ty->isVectorTy ())
657
+ ArgTys = {Ty};
658
+ else {
659
+ // If this is not a scalar or vector type, we can't handle it.
660
+ if (isa<llvm::CompositeType>(Ty))
661
+ return false ;
662
+ // The storage is guaranteed to be no larger than the register width.
663
+ // Extend the storage so it would fit into a register.
664
+ llvm::Type *IntTy;
665
+ switch (IGM.getClangASTContext ().getTargetInfo ().getRegisterWidth ()) {
666
+ case 64 :
667
+ IntTy = IGM.Int64Ty ;
668
+ break ;
669
+ case 32 :
670
+ IntTy = IGM.Int32Ty ;
671
+ break ;
672
+ default :
673
+ llvm_unreachable (" unsupported register width" );
674
+ }
675
+ ArgTys = {IntTy};
676
+ Var = Builder.CreateZExtOrBitCast (Var, IntTy);
677
+ }
678
+ // Emit an empty inline assembler expression depending on the register.
679
+ auto *AsmFnTy = llvm::FunctionType::get (IGM.VoidTy , ArgTys, false );
680
+ auto *InlineAsm = llvm::InlineAsm::get (AsmFnTy, " " , " r" , true );
681
+ Builder.CreateAsmCall (InlineAsm, Var);
682
+ return true ;
683
+ }
684
+
649
685
// / At -Onone, forcibly keep all LLVM values that are tracked by
650
686
// / debug variables alive by inserting an empty inline assembler
651
687
// / expression depending on the value in the blocks dominated by the
@@ -654,53 +690,31 @@ class IRGenSILFunction :
654
690
if (IGM.IRGen .Opts .shouldOptimize ())
655
691
return ;
656
692
for (auto &Variable : ValueDomPoints) {
657
- auto VarDominancePoint = Variable.second ;
658
- llvm::Value *Storage = Variable.first ;
693
+ llvm::Instruction *Var = Variable.first ;
694
+ DominancePoint VarDominancePoint = Variable.second ;
659
695
if (getActiveDominancePoint () == VarDominancePoint ||
660
696
isActiveDominancePointDominatedBy (VarDominancePoint)) {
661
- llvm::Type *ArgTys;
662
- auto *Ty = Storage->getType ();
663
- // Vectors, Pointers and Floats are expected to fit into a register.
664
- if (Ty->isPointerTy () || Ty->isFloatingPointTy () || Ty->isVectorTy ())
665
- ArgTys = { Ty };
666
- else {
667
- // If this is not a scalar or vector type, we can't handle it.
668
- if (isa<llvm::CompositeType>(Ty))
669
- continue ;
670
- // The storage is guaranteed to be no larger than the register width.
671
- // Extend the storage so it would fit into a register.
672
- llvm::Type *IntTy;
673
- switch (IGM.getClangASTContext ().getTargetInfo ().getRegisterWidth ()) {
674
- case 64 : IntTy = IGM.Int64Ty ; break ;
675
- case 32 : IntTy = IGM.Int32Ty ; break ;
676
- default : llvm_unreachable (" unsupported register width" );
677
- }
678
- ArgTys = { IntTy };
679
- Storage = Builder.CreateZExtOrBitCast (Storage, IntTy);
680
- }
681
- // Emit an empty inline assembler expression depending on the register.
682
- auto *AsmFnTy = llvm::FunctionType::get (IGM.VoidTy , ArgTys, false );
683
- auto *InlineAsm = llvm::InlineAsm::get (AsmFnTy, " " , " r" , true );
684
- Builder.CreateAsmCall (InlineAsm, Storage);
685
- // Propagate the dbg.value intrinsics into the later basic blocks. Note
697
+ bool ExtendedLifetime = emitLifetimeExtendingUse (Var);
698
+ if (!ExtendedLifetime)
699
+ continue ;
700
+
701
+ // Propagate dbg.values for Var into the current basic block. Note
686
702
// that this shouldn't be necessary. LiveDebugValues should be doing
687
703
// this but can't in general because it currently only tracks register
688
704
// locations.
689
- llvm::Instruction *Value = Variable.first ;
690
- auto It = llvm::BasicBlock::iterator (Value);
691
- auto *BB = Value->getParent ();
692
- auto *CurBB = Builder.GetInsertBlock ();
693
- if (BB != CurBB)
694
- for (auto I = std::next (It), E = BB->end (); I != E; ++I) {
695
- auto *DVI = dyn_cast<llvm::DbgValueInst>(I);
696
- if (DVI && DVI->getValue () == Value)
697
- IGM.DebugInfo ->getBuilder ().insertDbgValueIntrinsic (
698
- DVI->getValue (), DVI->getVariable (), DVI->getExpression (),
699
- DVI->getDebugLoc (), &*CurBB->getFirstInsertionPt ());
700
- else
701
- // Found all dbg.value intrinsics describing this location.
702
- break ;
703
- }
705
+ llvm::BasicBlock *BB = Var->getParent ();
706
+ llvm::BasicBlock *CurBB = Builder.GetInsertBlock ();
707
+ if (BB == CurBB)
708
+ // The current basic block must be a successor of the dbg.value().
709
+ continue ;
710
+
711
+ llvm::SmallVector<llvm::DbgValueInst *, 4 > DbgValues;
712
+ llvm::findDbgValues (DbgValues, Var);
713
+ for (auto *DVI : DbgValues)
714
+ if (DVI->getParent () == BB)
715
+ IGM.DebugInfo ->getBuilder ().insertDbgValueIntrinsic (
716
+ DVI->getValue (), DVI->getVariable (), DVI->getExpression (),
717
+ DVI->getDebugLoc (), &*CurBB->getFirstInsertionPt ());
704
718
}
705
719
}
706
720
}
@@ -754,10 +768,18 @@ class IRGenSILFunction :
754
768
if (ArgNo == 0 )
755
769
// Otherwise only if debug value range extension is not feasible.
756
770
if (!needsShadowCopy (Storage)) {
757
- // Mark for debug value range extension unless this is a constant.
758
- if (auto *Value = dyn_cast<llvm::Instruction>(Storage))
759
- if (ValueVariables.insert (Value).second )
760
- ValueDomPoints.push_back ({Value, getActiveDominancePoint ()});
771
+ // Mark for debug value range extension unless this is a constant, or
772
+ // unless it's not possible to emit lifetime-extending uses for this.
773
+ if (auto *Value = dyn_cast<llvm::Instruction>(Storage)) {
774
+ // Emit a use at the start of the storage lifetime to force early
775
+ // materialization. This makes variables available for inspection as
776
+ // soon as they are defined.
777
+ bool ExtendedLifetime = emitLifetimeExtendingUse (Value);
778
+ if (ExtendedLifetime)
779
+ if (ValueVariables.insert (Value).second )
780
+ ValueDomPoints.push_back ({Value, getActiveDominancePoint ()});
781
+ }
782
+
761
783
return Storage;
762
784
}
763
785
return emitShadowCopy (Storage, Scope, Name, ArgNo, Align);
0 commit comments