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