@@ -1352,6 +1352,14 @@ void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
13521352 C->setDoesNotThrow ();
13531353}
13541354
1355+ void CodeGenFunction::EmitFakeUse (Address Addr) {
1356+ auto NL = ApplyDebugLocation::CreateEmpty (*this );
1357+ llvm::Value *V = Builder.CreateLoad (Addr, " fake.use" );
1358+ llvm::CallInst *C = Builder.CreateCall (CGM.getLLVMFakeUseFn (), {V});
1359+ C->setDoesNotThrow ();
1360+ C->setTailCallKind (llvm::CallInst::TCK_NoTail);
1361+ }
1362+
13551363void CodeGenFunction::EmitAndRegisterVariableArrayDimensions (
13561364 CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo) {
13571365 // For each dimension stores its QualType and corresponding
@@ -1411,6 +1419,39 @@ void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
14111419 }
14121420}
14131421
1422+ // / Return the maximum size of an aggregate for which we generate a fake use
1423+ // / intrinsic when -fextend-lifetimes is in effect.
1424+ static uint64_t maxFakeUseAggregateSize (const ASTContext &C) {
1425+ return 4 * C.getTypeSize (C.UnsignedIntTy );
1426+ }
1427+
1428+ // Helper function to determine whether a variable's or parameter's lifetime
1429+ // should be extended.
1430+ static bool extendLifetime (const ASTContext &Context, const Decl *FuncDecl,
1431+ const VarDecl &D,
1432+ ImplicitParamDecl *CXXABIThisDecl) {
1433+ // When we're not inside a valid function it is unlikely that any
1434+ // lifetime extension is useful.
1435+ if (!FuncDecl)
1436+ return false ;
1437+ if (FuncDecl->isImplicit ())
1438+ return false ;
1439+ // Do not extend compiler-created variables except for the this pointer.
1440+ if (D.isImplicit () && &D != CXXABIThisDecl)
1441+ return false ;
1442+ QualType Ty = D.getType ();
1443+ // No need to extend volatiles, they have a memory location.
1444+ if (Ty.isVolatileQualified ())
1445+ return false ;
1446+ // Don't extend variables that exceed a certain size.
1447+ if (Context.getTypeSize (Ty) > maxFakeUseAggregateSize (Context))
1448+ return false ;
1449+ // Do not extend variables in nodebug functions.
1450+ if (FuncDecl->hasAttr <NoDebugAttr>())
1451+ return false ;
1452+ return true ;
1453+ }
1454+
14141455// / EmitAutoVarAlloca - Emit the alloca and debug information for a
14151456// / local variable. Does not emit initialization or destruction.
14161457CodeGenFunction::AutoVarEmission
@@ -1663,6 +1704,17 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
16631704 emission.getOriginalAllocatedAddress (),
16641705 emission.getSizeForLifetimeMarkers ());
16651706
1707+ // Analogous to lifetime markers, we use a 'cleanup' to emit fake.use
1708+ // calls for local variables. We are exempting volatile variables and
1709+ // non-scalars larger than 4 times the size of an unsigned int (32 bytes).
1710+ // Larger non-scalars are often allocated in memory and may create unnecessary
1711+ // overhead.
1712+ if (CGM.getCodeGenOpts ().ExtendLifetimes ) {
1713+ if (extendLifetime (getContext (), CurCodeDecl, D, CXXABIThisDecl))
1714+ EHStack.pushCleanup <FakeUse>(NormalFakeUse,
1715+ emission.getAllocatedAddress ());
1716+ }
1717+
16661718 return emission;
16671719}
16681720
@@ -2524,6 +2576,14 @@ llvm::Function *CodeGenModule::getLLVMLifetimeEndFn() {
25242576 return LifetimeEndFn;
25252577}
25262578
2579+ // / Lazily declare the @llvm.fake.use intrinsic.
2580+ llvm::Function *CodeGenModule::getLLVMFakeUseFn () {
2581+ if (!FakeUseFn)
2582+ FakeUseFn = llvm::Intrinsic::getDeclaration (&getModule (),
2583+ llvm::Intrinsic::fake_use);
2584+ return FakeUseFn;
2585+ }
2586+
25272587namespace {
25282588 // / A cleanup to perform a release of an object at the end of a
25292589 // / function. This is used to balance out the incoming +1 of a
@@ -2717,6 +2777,15 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
27172777
27182778 setAddrOfLocalVar (&D, DeclPtr);
27192779
2780+ // Push a FakeUse 'cleanup' object onto the EHStack for the parameter,
2781+ // which may be the 'this' pointer. This causes the emission of a fake.use
2782+ // call with the parameter as argument at the end of the function.
2783+ if (CGM.getCodeGenOpts ().ExtendLifetimes ||
2784+ (CGM.getCodeGenOpts ().ExtendThisPtr && &D == CXXABIThisDecl)) {
2785+ if (extendLifetime (getContext (), CurCodeDecl, D, CXXABIThisDecl))
2786+ EHStack.pushCleanup <FakeUse>(NormalFakeUse, DeclPtr);
2787+ }
2788+
27202789 // Emit debug info for param declarations in non-thunk functions.
27212790 if (CGDebugInfo *DI = getDebugInfo ()) {
27222791 if (CGM.getCodeGenOpts ().hasReducedDebugInfo () && !CurFuncIsThunk &&
0 commit comments