-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[IR] Remove size argument from lifetime intrinsics #150248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions c,cl,h,cpp -- clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CGCall.h clang/lib/CodeGen/CGDecl.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprAgg.cpp clang/lib/CodeGen/CodeGenFunction.h clang/test/C/C11/n1285_1.c clang/test/CodeGen/AArch64/ABI-align-packed.c clang/test/CodeGen/AArch64/byval-temp.c clang/test/CodeGen/AArch64/pure-scalable-args.c clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.cpp clang/test/CodeGen/RISCV/riscv-v-lifetime.cpp clang/test/CodeGen/aggregate-assign-call.c clang/test/CodeGen/attr-counted-by.c clang/test/CodeGen/cleanup-destslot-simple.c clang/test/CodeGen/dominating-store-to-return.c clang/test/CodeGen/lifetime-sanitizer.c clang/test/CodeGen/lifetime.c clang/test/CodeGen/lifetime2.c clang/test/CodeGen/lifetime3.cpp clang/test/CodeGen/math-libcalls-tbaa.c clang/test/CodeGen/nofpclass.c clang/test/CodeGen/temporary-lifetime-exceptions.cpp clang/test/CodeGen/temporary-lifetime.cpp clang/test/CodeGen/union-tbaa1.c clang/test/CodeGenCXX/amdgcn_declspec_get.cpp clang/test/CodeGenCXX/attr-likelihood-iteration-stmt.cpp clang/test/CodeGenCXX/destructors.cpp clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp clang/test/CodeGenCXX/stack-reuse-exceptions.cpp clang/test/CodeGenCXX/stack-reuse-miscompile.cpp clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl clang/test/CodeGenOpenCL/amdgpu-printf.cl clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl clang/test/CodeGenOpenCL/implicit-addrspacecast-function-parameter.cl clang/test/OpenMP/bug54082.c clang/test/OpenMP/bug56913.c clang/test/OpenMP/nvptx_target_parallel_reduction_codegen_tbaa_PR46146.cpp flang/include/flang/Optimizer/Builder/FIRBuilder.h flang/lib/Optimizer/Builder/FIRBuilder.cpp flang/lib/Optimizer/Transforms/StackArrays.cpp llvm/include/llvm/Analysis/StackLifetime.h llvm/include/llvm/CodeGen/SelectionDAG.h llvm/include/llvm/CodeGen/SelectionDAGNodes.h llvm/include/llvm/IR/IRBuilder.h llvm/lib/Analysis/MemoryDependenceAnalysis.cpp llvm/lib/Analysis/MemoryLocation.cpp llvm/lib/Analysis/StackLifetime.cpp llvm/lib/CodeGen/AtomicExpandPass.cpp llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp llvm/lib/IR/AutoUpgrade.cpp llvm/lib/IR/IRBuilder.cpp llvm/lib/IR/Verifier.cpp llvm/lib/Target/AArch64/AArch64StackTagging.cpp llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp llvm/lib/Transforms/Coroutines/CoroFrame.cpp llvm/lib/Transforms/IPO/ExpandVariadics.cpp llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp llvm/lib/Transforms/Scalar/NewGVN.cpp llvm/lib/Transforms/Scalar/SROA.cpp llvm/lib/Transforms/Utils/CodeExtractor.cpp llvm/lib/Transforms/Utils/InlineFunction.cpp llvm/lib/Transforms/Utils/Local.cpp llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp llvm/unittests/Analysis/MemorySSATest.cpp llvm/unittests/IR/IRBuilderTest.cpp mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp View the diff from clang-format here.diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 900da7645..03305de3a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -941,11 +941,8 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
OS << " [TF=" << TF << ']';
} else if (const AddrSpaceCastSDNode *ASC =
dyn_cast<AddrSpaceCastSDNode>(this)) {
- OS << '['
- << ASC->getSrcAddressSpace()
- << " -> "
- << ASC->getDestAddressSpace()
- << ']';
+ OS << '[' << ASC->getSrcAddressSpace() << " -> "
+ << ASC->getDestAddressSpace() << ']';
} else if (const auto *AA = dyn_cast<AssertAlignSDNode>(this)) {
OS << '<' << AA->getAlign().value() << '>';
}
|
a56aec7
to
ef647f8
Compare
@llvm/pr-subscribers-backend-systemz @llvm/pr-subscribers-backend-amdgpu Author: Nikita Popov (nikic) ChangesNow that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this). Patch is 1.54 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150248.diff 479 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f784fc8e798f..1254b0f38966a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5981,8 +5981,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// Create a temporary array to hold the sizes of local pointer arguments
// for the block. \p First is the position of the first size argument.
- auto CreateArrayForSizeVar = [=](unsigned First)
- -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
+ auto CreateArrayForSizeVar =
+ [=](unsigned First) -> std::pair<llvm::Value *, llvm::Value *> {
llvm::APInt ArraySize(32, NumArgs - First);
QualType SizeArrayTy = getContext().getConstantArrayType(
getContext().getSizeType(), ArraySize, nullptr,
@@ -5995,9 +5995,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// actually the Alloca ascasted to the default AS, hence the
// stripPointerCasts()
llvm::Value *Alloca = TmpPtr->stripPointerCasts();
- llvm::Value *TmpSize = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca);
llvm::Value *ElemPtr;
+ EmitLifetimeStart(Alloca);
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
@@ -6014,7 +6013,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}
// Return the Alloca itself rather than a potential ascast as this is only
// used by the paired EmitLifetimeEnd.
- return {ElemPtr, TmpSize, Alloca};
+ return {ElemPtr, Alloca};
};
// Could have events and/or varargs.
@@ -6026,7 +6025,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *Kernel =
Builder.CreatePointerCast(Info.KernelHandle, GenericVoidPtrTy);
auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(4);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(4);
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
@@ -6041,8 +6040,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
// Any calls now have event arguments passed.
@@ -6107,15 +6105,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_varargs";
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(7);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(7);
Args.push_back(ElemPtr);
ArgTys.push_back(ElemPtr->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
llvm_unreachable("Unexpected enqueue_kernel signature");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d9bd443455e0f..6e0c2c11a9f3b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4319,10 +4319,7 @@ static void emitWriteback(CodeGenFunction &CGF,
if (writeback.WritebackExpr) {
CGF.EmitIgnoredExpr(writeback.WritebackExpr);
-
- if (writeback.LifetimeSz)
- CGF.EmitLifetimeEnd(writeback.LifetimeSz,
- writeback.Temporary.getBasePointer());
+ CGF.EmitLifetimeEnd(writeback.Temporary.getBasePointer());
return;
}
@@ -5282,7 +5279,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- llvm::Value *UnusedReturnSizePtr = nullptr;
+ bool NeedSRetLifetimeEnd = false;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
// For virtual function pointer thunks and musttail calls, we must always
// forward an incoming SRet pointer to the callee, because a local alloca
@@ -5296,11 +5293,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SRetPtr = ReturnValue.getAddress();
} else {
SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp");
- if (HaveInsertPoint() && ReturnValue.isUnused()) {
- llvm::TypeSize size =
- CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getBasePointer());
- }
+ if (HaveInsertPoint() && ReturnValue.isUnused())
+ NeedSRetLifetimeEnd = EmitLifetimeStart(SRetPtr.getBasePointer());
}
if (IRFunctionArgs.hasSRetArg()) {
// A mismatch between the allocated return value's AS and the target's
@@ -5484,15 +5478,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Val = Builder.CreateFreeze(Val);
IRCallArgs[FirstIRArg] = Val;
- // Emit lifetime markers for the temporary alloca.
- llvm::TypeSize ByvalTempElementSize =
- CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
- llvm::Value *LifetimeSize =
- EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
-
- // Add cleanup code to emit the end lifetime marker after the call.
- if (LifetimeSize) // In case we disabled lifetime markers.
- CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
+ // Emit lifetime markers for the temporary alloca and add cleanup code to
+ // emit the end lifetime marker after the call.
+ if (EmitLifetimeStart(AI.getPointer()))
+ CallLifetimeEndAfterCall.emplace_back(AI);
// Generate the copy.
I->copyInto(*this, AI);
@@ -5653,9 +5642,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
auto unpaddedCoercionType = ArgInfo.getUnpaddedCoerceAndExpandType();
auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType);
- llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
RawAddress AllocaAddr = RawAddress::invalid();
+ bool NeedLifetimeEnd = false;
if (I->isAggregate()) {
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
: I->getKnownRValue().getAggregateAddress();
@@ -5665,7 +5654,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
- auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType);
// Materialize to a temporary.
@@ -5674,7 +5662,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
layout->getAlignment(), scalarAlign)),
"tmp",
/*ArraySize=*/nullptr, &AllocaAddr);
- tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
+ NeedLifetimeEnd = EmitLifetimeStart(AllocaAddr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -5699,10 +5687,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
assert(IRArgPos == FirstIRArg + NumIRArgs);
- if (tempSize) {
- EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
- }
-
+ if (NeedLifetimeEnd)
+ EmitLifetimeEnd(AllocaAddr.getPointer());
break;
}
@@ -5871,9 +5857,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// can't depend on being inside of an ExprWithCleanups, so we need to manually
// pop this cleanup later on. Being eager about this is OK, since this
// temporary is 'invisible' outside of the callee.
- if (UnusedReturnSizePtr)
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
- UnusedReturnSizePtr);
+ if (NeedSRetLifetimeEnd)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr);
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
@@ -6007,7 +5992,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CI->doesNotReturn()) {
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
@@ -6122,7 +6107,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
return ret;
}
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 0b4e3f9cb0365..3157b7f16f294 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -289,9 +289,6 @@ class CallArgList : public SmallVector<CallArg, 8> {
/// An Expression (optional) that performs the writeback with any required
/// casting.
const Expr *WritebackExpr;
-
- // Size for optional lifetime end on the temporary.
- llvm::Value *LifetimeSz;
};
struct CallArgCleanup {
@@ -321,9 +318,8 @@ class CallArgList : public SmallVector<CallArg, 8> {
}
void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,
- const Expr *writebackExpr = nullptr,
- llvm::Value *lifetimeSz = nullptr) {
- Writeback writeback = {srcLV, temporary, toUse, writebackExpr, lifetimeSz};
+ const Expr *writebackExpr = nullptr) {
+ Writeback writeback = {srcLV, temporary, toUse, writebackExpr};
Writebacks.push_back(writeback);
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..d224b09522d86 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1347,30 +1347,27 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
}
/// Emit a lifetime.begin marker if some criteria are satisfied.
-/// \return a pointer to the temporary size Value if a marker was emitted, null
-/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
- llvm::Value *Addr) {
+/// \return whether the marker was emitted.
+bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
if (!ShouldEmitLifetimeMarkers)
- return nullptr;
+ return false;
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::Value *SizeV = llvm::ConstantInt::get(
- Int64Ty, Size.isScalable() ? -1 : Size.getFixedValue());
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {Addr});
C->setDoesNotThrow();
- return SizeV;
+ return true;
}
-void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Addr) {
+ if (!ShouldEmitLifetimeMarkers)
+ return;
+
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Addr});
C->setDoesNotThrow();
}
@@ -1628,9 +1625,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// is rare.
if (!Bypasses.IsBypassed(&D) &&
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
- llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
- emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(Size, AllocaAddr.getPointer());
+ emission.UseLifetimeMarkers =
+ EmitLifetimeStart(AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1723,9 +1719,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
- EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
- emission.getOriginalAllocatedAddress(),
- emission.getSizeForLifetimeMarkers());
+ EHStack.pushCleanup<CallLifetimeEnd>(
+ NormalEHLifetimeMarker, emission.getOriginalAllocatedAddress());
// Analogous to lifetime markers, we use a 'cleanup' to emit fake.use
// calls for local variables. We are exempting volatile variables and
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 85c768807572f..576307d707b69 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -577,11 +577,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
+ if (EmitLifetimeStart(Alloca.getPointer())) {
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
+ Alloca);
}
break;
@@ -612,11 +610,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
Block, llvm::BasicBlock::iterator(Block->back())));
}
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ if (EmitLifetimeStart(Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca);
}
if (OldConditional) {
@@ -5743,13 +5738,10 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
llvm::Value *Addr = TempLV.getAddress().getBasePointer();
llvm::Type *ElTy = ConvertTypeForMem(TempLV.getType());
- llvm::TypeSize Sz = CGM.getDataLayout().getTypeAllocSize(ElTy);
-
- llvm::Value *LifetimeSize = EmitLifetimeStart(Sz, Addr);
+ EmitLifetimeStart(Addr);
Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
- Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast(),
- LifetimeSize);
+ Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
Args.add(RValue::get(TmpAddr, *this), Ty);
return TempLV;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index cad6731173700..e2f11b86b2053 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -300,16 +300,12 @@ void AggExprEmitter::withReturnValueSlot(
Address RetAddr = Address::invalid();
EHScopeStack::stable_iterator LifetimeEndBlock;
- llvm::Value *LifetimeSizePtr = nullptr;
llvm::IntrinsicInst *LifetimeStartInst = nullptr;
if (!UseTemp) {
RetAddr = Dest.getAddress();
} else {
RetAddr = CGF.CreateMemTempWithoutCast(RetTy, "tmp");
- llvm::TypeSize Size =
- CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
- LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getBasePointer());
- if (LifetimeSizePtr) {
+ if (CGF.EmitLifetimeStart(RetAddr.getBasePointer())) {
LifetimeStartInst =
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
assert(LifetimeStartInst->getIntrinsicID() ==
@@ -317,7 +313,7 @@ void AggExprEmitter::withReturnValueSlot(
"Last insertion wasn't a lifetime.start?");
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
- NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
+ NormalEHLifetimeMarker, RetAddr);
LifetimeEndBlock = CGF.EHStack.stable_begin();
}
}
@@ -338,7 +334,7 @@ void AggExprEmitter::withReturnValueSlot(
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
// eagerly.
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
- CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getBasePointer());
+ CGF.EmitLifetimeEnd(RetAddr.getBasePointer());
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6c32c98cec011..272587f7fa4b5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -701,14 +701,12 @@ class CodeGenFunction : public CodeGenTypeCache {
bool isRedundantBeforeReturn() override { return true; }
llvm::Value *Addr;
- llvm::Value *Size;
public:
- CallLifetimeEnd(RawAddress addr, llvm::Value *size)
- : Addr(addr.getPointer()), Size(size) {}
+ CallLifetimeEnd(RawAddress addr) : Addr(addr.getPointer()) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitLifetimeEnd(Size, Addr);
+ CGF.EmitLifetimeEnd(Addr);
}
};
@@ -3233,8 +3231,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitSehTryScopeBegin();
void EmitSehTryScopeEnd();
- llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
- void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+ bool EmitLifetimeStart(llvm::Value *Addr);
+ void EmitLifetimeEnd(llvm::Value *Addr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -3417,8 +3415,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// initializer.
bool IsConstantAggregate;
- /// Non-null if we should use lifetime annotations.
- llvm::Value *SizeForLifetimeMarkers;
+ /// True if lifetime markers should be used.
+ bool UseLifetimeMarkers;
/// Address with original alloca instruction. Invalid if the variable was
/// emitted as a global constant.
@@ -3432,20 +3430,14 @@ class CodeGenFunction : public CodeGenTypeCache {
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsEscapingByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {}
+ UseLifetimeMarkers(false), AllocaAddr(RawAddress::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool useLifetimeMarkers() const {
- return SizeForLifetimeMarkers != nullptr;
- }
- llvm::Value *getSizeForLifetimeMarkers() const {
- assert(useLifetimeMarkers());
- return SizeForLifetimeMarkers;
- }
+ bool useLifetimeMarkers() const { return UseLifetimeMarkers; }
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself. It is casted to default
diff --git a/clang/test/C/C11/n1285_1.c b/clang/test/C/C11/n1285_1.c
index 50100042e82fd..25b68e3145b04 100644
--- a/clang/test/C/C11/n1285_1.c
+++ b/clang/test/C/C11/n1285_1.c
@@ -26,16 +26,16 @@ struct X f(void);
...
[truncated]
|
@llvm/pr-subscribers-backend-webassembly Author: Nikita Popov (nikic) ChangesNow that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this). Patch is 1.54 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150248.diff 479 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f784fc8e798f..1254b0f38966a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5981,8 +5981,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// Create a temporary array to hold the sizes of local pointer arguments
// for the block. \p First is the position of the first size argument.
- auto CreateArrayForSizeVar = [=](unsigned First)
- -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
+ auto CreateArrayForSizeVar =
+ [=](unsigned First) -> std::pair<llvm::Value *, llvm::Value *> {
llvm::APInt ArraySize(32, NumArgs - First);
QualType SizeArrayTy = getContext().getConstantArrayType(
getContext().getSizeType(), ArraySize, nullptr,
@@ -5995,9 +5995,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// actually the Alloca ascasted to the default AS, hence the
// stripPointerCasts()
llvm::Value *Alloca = TmpPtr->stripPointerCasts();
- llvm::Value *TmpSize = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca);
llvm::Value *ElemPtr;
+ EmitLifetimeStart(Alloca);
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
@@ -6014,7 +6013,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}
// Return the Alloca itself rather than a potential ascast as this is only
// used by the paired EmitLifetimeEnd.
- return {ElemPtr, TmpSize, Alloca};
+ return {ElemPtr, Alloca};
};
// Could have events and/or varargs.
@@ -6026,7 +6025,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *Kernel =
Builder.CreatePointerCast(Info.KernelHandle, GenericVoidPtrTy);
auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(4);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(4);
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
@@ -6041,8 +6040,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
// Any calls now have event arguments passed.
@@ -6107,15 +6105,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_varargs";
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(7);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(7);
Args.push_back(ElemPtr);
ArgTys.push_back(ElemPtr->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
llvm_unreachable("Unexpected enqueue_kernel signature");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d9bd443455e0f..6e0c2c11a9f3b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4319,10 +4319,7 @@ static void emitWriteback(CodeGenFunction &CGF,
if (writeback.WritebackExpr) {
CGF.EmitIgnoredExpr(writeback.WritebackExpr);
-
- if (writeback.LifetimeSz)
- CGF.EmitLifetimeEnd(writeback.LifetimeSz,
- writeback.Temporary.getBasePointer());
+ CGF.EmitLifetimeEnd(writeback.Temporary.getBasePointer());
return;
}
@@ -5282,7 +5279,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- llvm::Value *UnusedReturnSizePtr = nullptr;
+ bool NeedSRetLifetimeEnd = false;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
// For virtual function pointer thunks and musttail calls, we must always
// forward an incoming SRet pointer to the callee, because a local alloca
@@ -5296,11 +5293,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SRetPtr = ReturnValue.getAddress();
} else {
SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp");
- if (HaveInsertPoint() && ReturnValue.isUnused()) {
- llvm::TypeSize size =
- CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getBasePointer());
- }
+ if (HaveInsertPoint() && ReturnValue.isUnused())
+ NeedSRetLifetimeEnd = EmitLifetimeStart(SRetPtr.getBasePointer());
}
if (IRFunctionArgs.hasSRetArg()) {
// A mismatch between the allocated return value's AS and the target's
@@ -5484,15 +5478,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Val = Builder.CreateFreeze(Val);
IRCallArgs[FirstIRArg] = Val;
- // Emit lifetime markers for the temporary alloca.
- llvm::TypeSize ByvalTempElementSize =
- CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
- llvm::Value *LifetimeSize =
- EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
-
- // Add cleanup code to emit the end lifetime marker after the call.
- if (LifetimeSize) // In case we disabled lifetime markers.
- CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
+ // Emit lifetime markers for the temporary alloca and add cleanup code to
+ // emit the end lifetime marker after the call.
+ if (EmitLifetimeStart(AI.getPointer()))
+ CallLifetimeEndAfterCall.emplace_back(AI);
// Generate the copy.
I->copyInto(*this, AI);
@@ -5653,9 +5642,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
auto unpaddedCoercionType = ArgInfo.getUnpaddedCoerceAndExpandType();
auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType);
- llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
RawAddress AllocaAddr = RawAddress::invalid();
+ bool NeedLifetimeEnd = false;
if (I->isAggregate()) {
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
: I->getKnownRValue().getAggregateAddress();
@@ -5665,7 +5654,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
- auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType);
// Materialize to a temporary.
@@ -5674,7 +5662,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
layout->getAlignment(), scalarAlign)),
"tmp",
/*ArraySize=*/nullptr, &AllocaAddr);
- tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
+ NeedLifetimeEnd = EmitLifetimeStart(AllocaAddr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -5699,10 +5687,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
assert(IRArgPos == FirstIRArg + NumIRArgs);
- if (tempSize) {
- EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
- }
-
+ if (NeedLifetimeEnd)
+ EmitLifetimeEnd(AllocaAddr.getPointer());
break;
}
@@ -5871,9 +5857,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// can't depend on being inside of an ExprWithCleanups, so we need to manually
// pop this cleanup later on. Being eager about this is OK, since this
// temporary is 'invisible' outside of the callee.
- if (UnusedReturnSizePtr)
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
- UnusedReturnSizePtr);
+ if (NeedSRetLifetimeEnd)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr);
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
@@ -6007,7 +5992,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CI->doesNotReturn()) {
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
@@ -6122,7 +6107,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
return ret;
}
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 0b4e3f9cb0365..3157b7f16f294 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -289,9 +289,6 @@ class CallArgList : public SmallVector<CallArg, 8> {
/// An Expression (optional) that performs the writeback with any required
/// casting.
const Expr *WritebackExpr;
-
- // Size for optional lifetime end on the temporary.
- llvm::Value *LifetimeSz;
};
struct CallArgCleanup {
@@ -321,9 +318,8 @@ class CallArgList : public SmallVector<CallArg, 8> {
}
void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,
- const Expr *writebackExpr = nullptr,
- llvm::Value *lifetimeSz = nullptr) {
- Writeback writeback = {srcLV, temporary, toUse, writebackExpr, lifetimeSz};
+ const Expr *writebackExpr = nullptr) {
+ Writeback writeback = {srcLV, temporary, toUse, writebackExpr};
Writebacks.push_back(writeback);
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..d224b09522d86 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1347,30 +1347,27 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
}
/// Emit a lifetime.begin marker if some criteria are satisfied.
-/// \return a pointer to the temporary size Value if a marker was emitted, null
-/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
- llvm::Value *Addr) {
+/// \return whether the marker was emitted.
+bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
if (!ShouldEmitLifetimeMarkers)
- return nullptr;
+ return false;
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::Value *SizeV = llvm::ConstantInt::get(
- Int64Ty, Size.isScalable() ? -1 : Size.getFixedValue());
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {Addr});
C->setDoesNotThrow();
- return SizeV;
+ return true;
}
-void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Addr) {
+ if (!ShouldEmitLifetimeMarkers)
+ return;
+
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Addr});
C->setDoesNotThrow();
}
@@ -1628,9 +1625,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// is rare.
if (!Bypasses.IsBypassed(&D) &&
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
- llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
- emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(Size, AllocaAddr.getPointer());
+ emission.UseLifetimeMarkers =
+ EmitLifetimeStart(AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1723,9 +1719,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
- EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
- emission.getOriginalAllocatedAddress(),
- emission.getSizeForLifetimeMarkers());
+ EHStack.pushCleanup<CallLifetimeEnd>(
+ NormalEHLifetimeMarker, emission.getOriginalAllocatedAddress());
// Analogous to lifetime markers, we use a 'cleanup' to emit fake.use
// calls for local variables. We are exempting volatile variables and
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 85c768807572f..576307d707b69 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -577,11 +577,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
+ if (EmitLifetimeStart(Alloca.getPointer())) {
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
+ Alloca);
}
break;
@@ -612,11 +610,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
Block, llvm::BasicBlock::iterator(Block->back())));
}
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ if (EmitLifetimeStart(Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca);
}
if (OldConditional) {
@@ -5743,13 +5738,10 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
llvm::Value *Addr = TempLV.getAddress().getBasePointer();
llvm::Type *ElTy = ConvertTypeForMem(TempLV.getType());
- llvm::TypeSize Sz = CGM.getDataLayout().getTypeAllocSize(ElTy);
-
- llvm::Value *LifetimeSize = EmitLifetimeStart(Sz, Addr);
+ EmitLifetimeStart(Addr);
Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
- Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast(),
- LifetimeSize);
+ Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
Args.add(RValue::get(TmpAddr, *this), Ty);
return TempLV;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index cad6731173700..e2f11b86b2053 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -300,16 +300,12 @@ void AggExprEmitter::withReturnValueSlot(
Address RetAddr = Address::invalid();
EHScopeStack::stable_iterator LifetimeEndBlock;
- llvm::Value *LifetimeSizePtr = nullptr;
llvm::IntrinsicInst *LifetimeStartInst = nullptr;
if (!UseTemp) {
RetAddr = Dest.getAddress();
} else {
RetAddr = CGF.CreateMemTempWithoutCast(RetTy, "tmp");
- llvm::TypeSize Size =
- CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
- LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getBasePointer());
- if (LifetimeSizePtr) {
+ if (CGF.EmitLifetimeStart(RetAddr.getBasePointer())) {
LifetimeStartInst =
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
assert(LifetimeStartInst->getIntrinsicID() ==
@@ -317,7 +313,7 @@ void AggExprEmitter::withReturnValueSlot(
"Last insertion wasn't a lifetime.start?");
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
- NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
+ NormalEHLifetimeMarker, RetAddr);
LifetimeEndBlock = CGF.EHStack.stable_begin();
}
}
@@ -338,7 +334,7 @@ void AggExprEmitter::withReturnValueSlot(
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
// eagerly.
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
- CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getBasePointer());
+ CGF.EmitLifetimeEnd(RetAddr.getBasePointer());
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6c32c98cec011..272587f7fa4b5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -701,14 +701,12 @@ class CodeGenFunction : public CodeGenTypeCache {
bool isRedundantBeforeReturn() override { return true; }
llvm::Value *Addr;
- llvm::Value *Size;
public:
- CallLifetimeEnd(RawAddress addr, llvm::Value *size)
- : Addr(addr.getPointer()), Size(size) {}
+ CallLifetimeEnd(RawAddress addr) : Addr(addr.getPointer()) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitLifetimeEnd(Size, Addr);
+ CGF.EmitLifetimeEnd(Addr);
}
};
@@ -3233,8 +3231,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitSehTryScopeBegin();
void EmitSehTryScopeEnd();
- llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
- void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+ bool EmitLifetimeStart(llvm::Value *Addr);
+ void EmitLifetimeEnd(llvm::Value *Addr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -3417,8 +3415,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// initializer.
bool IsConstantAggregate;
- /// Non-null if we should use lifetime annotations.
- llvm::Value *SizeForLifetimeMarkers;
+ /// True if lifetime markers should be used.
+ bool UseLifetimeMarkers;
/// Address with original alloca instruction. Invalid if the variable was
/// emitted as a global constant.
@@ -3432,20 +3430,14 @@ class CodeGenFunction : public CodeGenTypeCache {
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsEscapingByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {}
+ UseLifetimeMarkers(false), AllocaAddr(RawAddress::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool useLifetimeMarkers() const {
- return SizeForLifetimeMarkers != nullptr;
- }
- llvm::Value *getSizeForLifetimeMarkers() const {
- assert(useLifetimeMarkers());
- return SizeForLifetimeMarkers;
- }
+ bool useLifetimeMarkers() const { return UseLifetimeMarkers; }
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself. It is casted to default
diff --git a/clang/test/C/C11/n1285_1.c b/clang/test/C/C11/n1285_1.c
index 50100042e82fd..25b68e3145b04 100644
--- a/clang/test/C/C11/n1285_1.c
+++ b/clang/test/C/C11/n1285_1.c
@@ -26,16 +26,16 @@ struct X f(void);
...
[truncated]
|
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Nikita Popov (nikic) ChangesNow that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this). Patch is 1.54 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150248.diff 479 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f784fc8e798f..1254b0f38966a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5981,8 +5981,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// Create a temporary array to hold the sizes of local pointer arguments
// for the block. \p First is the position of the first size argument.
- auto CreateArrayForSizeVar = [=](unsigned First)
- -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
+ auto CreateArrayForSizeVar =
+ [=](unsigned First) -> std::pair<llvm::Value *, llvm::Value *> {
llvm::APInt ArraySize(32, NumArgs - First);
QualType SizeArrayTy = getContext().getConstantArrayType(
getContext().getSizeType(), ArraySize, nullptr,
@@ -5995,9 +5995,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// actually the Alloca ascasted to the default AS, hence the
// stripPointerCasts()
llvm::Value *Alloca = TmpPtr->stripPointerCasts();
- llvm::Value *TmpSize = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca);
llvm::Value *ElemPtr;
+ EmitLifetimeStart(Alloca);
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
@@ -6014,7 +6013,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}
// Return the Alloca itself rather than a potential ascast as this is only
// used by the paired EmitLifetimeEnd.
- return {ElemPtr, TmpSize, Alloca};
+ return {ElemPtr, Alloca};
};
// Could have events and/or varargs.
@@ -6026,7 +6025,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *Kernel =
Builder.CreatePointerCast(Info.KernelHandle, GenericVoidPtrTy);
auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(4);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(4);
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
@@ -6041,8 +6040,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
// Any calls now have event arguments passed.
@@ -6107,15 +6105,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_varargs";
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(7);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(7);
Args.push_back(ElemPtr);
ArgTys.push_back(ElemPtr->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
llvm_unreachable("Unexpected enqueue_kernel signature");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d9bd443455e0f..6e0c2c11a9f3b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4319,10 +4319,7 @@ static void emitWriteback(CodeGenFunction &CGF,
if (writeback.WritebackExpr) {
CGF.EmitIgnoredExpr(writeback.WritebackExpr);
-
- if (writeback.LifetimeSz)
- CGF.EmitLifetimeEnd(writeback.LifetimeSz,
- writeback.Temporary.getBasePointer());
+ CGF.EmitLifetimeEnd(writeback.Temporary.getBasePointer());
return;
}
@@ -5282,7 +5279,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- llvm::Value *UnusedReturnSizePtr = nullptr;
+ bool NeedSRetLifetimeEnd = false;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
// For virtual function pointer thunks and musttail calls, we must always
// forward an incoming SRet pointer to the callee, because a local alloca
@@ -5296,11 +5293,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SRetPtr = ReturnValue.getAddress();
} else {
SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp");
- if (HaveInsertPoint() && ReturnValue.isUnused()) {
- llvm::TypeSize size =
- CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getBasePointer());
- }
+ if (HaveInsertPoint() && ReturnValue.isUnused())
+ NeedSRetLifetimeEnd = EmitLifetimeStart(SRetPtr.getBasePointer());
}
if (IRFunctionArgs.hasSRetArg()) {
// A mismatch between the allocated return value's AS and the target's
@@ -5484,15 +5478,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Val = Builder.CreateFreeze(Val);
IRCallArgs[FirstIRArg] = Val;
- // Emit lifetime markers for the temporary alloca.
- llvm::TypeSize ByvalTempElementSize =
- CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
- llvm::Value *LifetimeSize =
- EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
-
- // Add cleanup code to emit the end lifetime marker after the call.
- if (LifetimeSize) // In case we disabled lifetime markers.
- CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
+ // Emit lifetime markers for the temporary alloca and add cleanup code to
+ // emit the end lifetime marker after the call.
+ if (EmitLifetimeStart(AI.getPointer()))
+ CallLifetimeEndAfterCall.emplace_back(AI);
// Generate the copy.
I->copyInto(*this, AI);
@@ -5653,9 +5642,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
auto unpaddedCoercionType = ArgInfo.getUnpaddedCoerceAndExpandType();
auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType);
- llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
RawAddress AllocaAddr = RawAddress::invalid();
+ bool NeedLifetimeEnd = false;
if (I->isAggregate()) {
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
: I->getKnownRValue().getAggregateAddress();
@@ -5665,7 +5654,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
- auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType);
// Materialize to a temporary.
@@ -5674,7 +5662,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
layout->getAlignment(), scalarAlign)),
"tmp",
/*ArraySize=*/nullptr, &AllocaAddr);
- tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
+ NeedLifetimeEnd = EmitLifetimeStart(AllocaAddr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -5699,10 +5687,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
assert(IRArgPos == FirstIRArg + NumIRArgs);
- if (tempSize) {
- EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
- }
-
+ if (NeedLifetimeEnd)
+ EmitLifetimeEnd(AllocaAddr.getPointer());
break;
}
@@ -5871,9 +5857,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// can't depend on being inside of an ExprWithCleanups, so we need to manually
// pop this cleanup later on. Being eager about this is OK, since this
// temporary is 'invisible' outside of the callee.
- if (UnusedReturnSizePtr)
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
- UnusedReturnSizePtr);
+ if (NeedSRetLifetimeEnd)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr);
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
@@ -6007,7 +5992,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CI->doesNotReturn()) {
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
@@ -6122,7 +6107,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
return ret;
}
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 0b4e3f9cb0365..3157b7f16f294 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -289,9 +289,6 @@ class CallArgList : public SmallVector<CallArg, 8> {
/// An Expression (optional) that performs the writeback with any required
/// casting.
const Expr *WritebackExpr;
-
- // Size for optional lifetime end on the temporary.
- llvm::Value *LifetimeSz;
};
struct CallArgCleanup {
@@ -321,9 +318,8 @@ class CallArgList : public SmallVector<CallArg, 8> {
}
void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,
- const Expr *writebackExpr = nullptr,
- llvm::Value *lifetimeSz = nullptr) {
- Writeback writeback = {srcLV, temporary, toUse, writebackExpr, lifetimeSz};
+ const Expr *writebackExpr = nullptr) {
+ Writeback writeback = {srcLV, temporary, toUse, writebackExpr};
Writebacks.push_back(writeback);
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..d224b09522d86 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1347,30 +1347,27 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
}
/// Emit a lifetime.begin marker if some criteria are satisfied.
-/// \return a pointer to the temporary size Value if a marker was emitted, null
-/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
- llvm::Value *Addr) {
+/// \return whether the marker was emitted.
+bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
if (!ShouldEmitLifetimeMarkers)
- return nullptr;
+ return false;
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::Value *SizeV = llvm::ConstantInt::get(
- Int64Ty, Size.isScalable() ? -1 : Size.getFixedValue());
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {Addr});
C->setDoesNotThrow();
- return SizeV;
+ return true;
}
-void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Addr) {
+ if (!ShouldEmitLifetimeMarkers)
+ return;
+
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Addr});
C->setDoesNotThrow();
}
@@ -1628,9 +1625,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// is rare.
if (!Bypasses.IsBypassed(&D) &&
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
- llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
- emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(Size, AllocaAddr.getPointer());
+ emission.UseLifetimeMarkers =
+ EmitLifetimeStart(AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1723,9 +1719,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
- EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
- emission.getOriginalAllocatedAddress(),
- emission.getSizeForLifetimeMarkers());
+ EHStack.pushCleanup<CallLifetimeEnd>(
+ NormalEHLifetimeMarker, emission.getOriginalAllocatedAddress());
// Analogous to lifetime markers, we use a 'cleanup' to emit fake.use
// calls for local variables. We are exempting volatile variables and
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 85c768807572f..576307d707b69 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -577,11 +577,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
+ if (EmitLifetimeStart(Alloca.getPointer())) {
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
+ Alloca);
}
break;
@@ -612,11 +610,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
Block, llvm::BasicBlock::iterator(Block->back())));
}
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ if (EmitLifetimeStart(Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca);
}
if (OldConditional) {
@@ -5743,13 +5738,10 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
llvm::Value *Addr = TempLV.getAddress().getBasePointer();
llvm::Type *ElTy = ConvertTypeForMem(TempLV.getType());
- llvm::TypeSize Sz = CGM.getDataLayout().getTypeAllocSize(ElTy);
-
- llvm::Value *LifetimeSize = EmitLifetimeStart(Sz, Addr);
+ EmitLifetimeStart(Addr);
Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
- Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast(),
- LifetimeSize);
+ Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
Args.add(RValue::get(TmpAddr, *this), Ty);
return TempLV;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index cad6731173700..e2f11b86b2053 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -300,16 +300,12 @@ void AggExprEmitter::withReturnValueSlot(
Address RetAddr = Address::invalid();
EHScopeStack::stable_iterator LifetimeEndBlock;
- llvm::Value *LifetimeSizePtr = nullptr;
llvm::IntrinsicInst *LifetimeStartInst = nullptr;
if (!UseTemp) {
RetAddr = Dest.getAddress();
} else {
RetAddr = CGF.CreateMemTempWithoutCast(RetTy, "tmp");
- llvm::TypeSize Size =
- CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
- LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getBasePointer());
- if (LifetimeSizePtr) {
+ if (CGF.EmitLifetimeStart(RetAddr.getBasePointer())) {
LifetimeStartInst =
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
assert(LifetimeStartInst->getIntrinsicID() ==
@@ -317,7 +313,7 @@ void AggExprEmitter::withReturnValueSlot(
"Last insertion wasn't a lifetime.start?");
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
- NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
+ NormalEHLifetimeMarker, RetAddr);
LifetimeEndBlock = CGF.EHStack.stable_begin();
}
}
@@ -338,7 +334,7 @@ void AggExprEmitter::withReturnValueSlot(
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
// eagerly.
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
- CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getBasePointer());
+ CGF.EmitLifetimeEnd(RetAddr.getBasePointer());
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6c32c98cec011..272587f7fa4b5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -701,14 +701,12 @@ class CodeGenFunction : public CodeGenTypeCache {
bool isRedundantBeforeReturn() override { return true; }
llvm::Value *Addr;
- llvm::Value *Size;
public:
- CallLifetimeEnd(RawAddress addr, llvm::Value *size)
- : Addr(addr.getPointer()), Size(size) {}
+ CallLifetimeEnd(RawAddress addr) : Addr(addr.getPointer()) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitLifetimeEnd(Size, Addr);
+ CGF.EmitLifetimeEnd(Addr);
}
};
@@ -3233,8 +3231,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitSehTryScopeBegin();
void EmitSehTryScopeEnd();
- llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
- void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+ bool EmitLifetimeStart(llvm::Value *Addr);
+ void EmitLifetimeEnd(llvm::Value *Addr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -3417,8 +3415,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// initializer.
bool IsConstantAggregate;
- /// Non-null if we should use lifetime annotations.
- llvm::Value *SizeForLifetimeMarkers;
+ /// True if lifetime markers should be used.
+ bool UseLifetimeMarkers;
/// Address with original alloca instruction. Invalid if the variable was
/// emitted as a global constant.
@@ -3432,20 +3430,14 @@ class CodeGenFunction : public CodeGenTypeCache {
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsEscapingByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {}
+ UseLifetimeMarkers(false), AllocaAddr(RawAddress::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool useLifetimeMarkers() const {
- return SizeForLifetimeMarkers != nullptr;
- }
- llvm::Value *getSizeForLifetimeMarkers() const {
- assert(useLifetimeMarkers());
- return SizeForLifetimeMarkers;
- }
+ bool useLifetimeMarkers() const { return UseLifetimeMarkers; }
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself. It is casted to default
diff --git a/clang/test/C/C11/n1285_1.c b/clang/test/C/C11/n1285_1.c
index 50100042e82fd..25b68e3145b04 100644
--- a/clang/test/C/C11/n1285_1.c
+++ b/clang/test/C/C11/n1285_1.c
@@ -26,16 +26,16 @@ struct X f(void);
...
[truncated]
|
@llvm/pr-subscribers-backend-aarch64 Author: Nikita Popov (nikic) ChangesNow that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this). Patch is 1.54 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150248.diff 479 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f784fc8e798f..1254b0f38966a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5981,8 +5981,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// Create a temporary array to hold the sizes of local pointer arguments
// for the block. \p First is the position of the first size argument.
- auto CreateArrayForSizeVar = [=](unsigned First)
- -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
+ auto CreateArrayForSizeVar =
+ [=](unsigned First) -> std::pair<llvm::Value *, llvm::Value *> {
llvm::APInt ArraySize(32, NumArgs - First);
QualType SizeArrayTy = getContext().getConstantArrayType(
getContext().getSizeType(), ArraySize, nullptr,
@@ -5995,9 +5995,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// actually the Alloca ascasted to the default AS, hence the
// stripPointerCasts()
llvm::Value *Alloca = TmpPtr->stripPointerCasts();
- llvm::Value *TmpSize = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca);
llvm::Value *ElemPtr;
+ EmitLifetimeStart(Alloca);
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
@@ -6014,7 +6013,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}
// Return the Alloca itself rather than a potential ascast as this is only
// used by the paired EmitLifetimeEnd.
- return {ElemPtr, TmpSize, Alloca};
+ return {ElemPtr, Alloca};
};
// Could have events and/or varargs.
@@ -6026,7 +6025,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *Kernel =
Builder.CreatePointerCast(Info.KernelHandle, GenericVoidPtrTy);
auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(4);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(4);
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
@@ -6041,8 +6040,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
// Any calls now have event arguments passed.
@@ -6107,15 +6105,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_varargs";
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(7);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(7);
Args.push_back(ElemPtr);
ArgTys.push_back(ElemPtr->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
llvm_unreachable("Unexpected enqueue_kernel signature");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d9bd443455e0f..6e0c2c11a9f3b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4319,10 +4319,7 @@ static void emitWriteback(CodeGenFunction &CGF,
if (writeback.WritebackExpr) {
CGF.EmitIgnoredExpr(writeback.WritebackExpr);
-
- if (writeback.LifetimeSz)
- CGF.EmitLifetimeEnd(writeback.LifetimeSz,
- writeback.Temporary.getBasePointer());
+ CGF.EmitLifetimeEnd(writeback.Temporary.getBasePointer());
return;
}
@@ -5282,7 +5279,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- llvm::Value *UnusedReturnSizePtr = nullptr;
+ bool NeedSRetLifetimeEnd = false;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
// For virtual function pointer thunks and musttail calls, we must always
// forward an incoming SRet pointer to the callee, because a local alloca
@@ -5296,11 +5293,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SRetPtr = ReturnValue.getAddress();
} else {
SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp");
- if (HaveInsertPoint() && ReturnValue.isUnused()) {
- llvm::TypeSize size =
- CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getBasePointer());
- }
+ if (HaveInsertPoint() && ReturnValue.isUnused())
+ NeedSRetLifetimeEnd = EmitLifetimeStart(SRetPtr.getBasePointer());
}
if (IRFunctionArgs.hasSRetArg()) {
// A mismatch between the allocated return value's AS and the target's
@@ -5484,15 +5478,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Val = Builder.CreateFreeze(Val);
IRCallArgs[FirstIRArg] = Val;
- // Emit lifetime markers for the temporary alloca.
- llvm::TypeSize ByvalTempElementSize =
- CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
- llvm::Value *LifetimeSize =
- EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
-
- // Add cleanup code to emit the end lifetime marker after the call.
- if (LifetimeSize) // In case we disabled lifetime markers.
- CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
+ // Emit lifetime markers for the temporary alloca and add cleanup code to
+ // emit the end lifetime marker after the call.
+ if (EmitLifetimeStart(AI.getPointer()))
+ CallLifetimeEndAfterCall.emplace_back(AI);
// Generate the copy.
I->copyInto(*this, AI);
@@ -5653,9 +5642,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
auto unpaddedCoercionType = ArgInfo.getUnpaddedCoerceAndExpandType();
auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType);
- llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
RawAddress AllocaAddr = RawAddress::invalid();
+ bool NeedLifetimeEnd = false;
if (I->isAggregate()) {
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
: I->getKnownRValue().getAggregateAddress();
@@ -5665,7 +5654,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
- auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType);
// Materialize to a temporary.
@@ -5674,7 +5662,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
layout->getAlignment(), scalarAlign)),
"tmp",
/*ArraySize=*/nullptr, &AllocaAddr);
- tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
+ NeedLifetimeEnd = EmitLifetimeStart(AllocaAddr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -5699,10 +5687,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
assert(IRArgPos == FirstIRArg + NumIRArgs);
- if (tempSize) {
- EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
- }
-
+ if (NeedLifetimeEnd)
+ EmitLifetimeEnd(AllocaAddr.getPointer());
break;
}
@@ -5871,9 +5857,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// can't depend on being inside of an ExprWithCleanups, so we need to manually
// pop this cleanup later on. Being eager about this is OK, since this
// temporary is 'invisible' outside of the callee.
- if (UnusedReturnSizePtr)
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
- UnusedReturnSizePtr);
+ if (NeedSRetLifetimeEnd)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr);
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
@@ -6007,7 +5992,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CI->doesNotReturn()) {
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
@@ -6122,7 +6107,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
return ret;
}
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 0b4e3f9cb0365..3157b7f16f294 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -289,9 +289,6 @@ class CallArgList : public SmallVector<CallArg, 8> {
/// An Expression (optional) that performs the writeback with any required
/// casting.
const Expr *WritebackExpr;
-
- // Size for optional lifetime end on the temporary.
- llvm::Value *LifetimeSz;
};
struct CallArgCleanup {
@@ -321,9 +318,8 @@ class CallArgList : public SmallVector<CallArg, 8> {
}
void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,
- const Expr *writebackExpr = nullptr,
- llvm::Value *lifetimeSz = nullptr) {
- Writeback writeback = {srcLV, temporary, toUse, writebackExpr, lifetimeSz};
+ const Expr *writebackExpr = nullptr) {
+ Writeback writeback = {srcLV, temporary, toUse, writebackExpr};
Writebacks.push_back(writeback);
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..d224b09522d86 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1347,30 +1347,27 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
}
/// Emit a lifetime.begin marker if some criteria are satisfied.
-/// \return a pointer to the temporary size Value if a marker was emitted, null
-/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
- llvm::Value *Addr) {
+/// \return whether the marker was emitted.
+bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
if (!ShouldEmitLifetimeMarkers)
- return nullptr;
+ return false;
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::Value *SizeV = llvm::ConstantInt::get(
- Int64Ty, Size.isScalable() ? -1 : Size.getFixedValue());
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {Addr});
C->setDoesNotThrow();
- return SizeV;
+ return true;
}
-void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Addr) {
+ if (!ShouldEmitLifetimeMarkers)
+ return;
+
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Addr});
C->setDoesNotThrow();
}
@@ -1628,9 +1625,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// is rare.
if (!Bypasses.IsBypassed(&D) &&
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
- llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
- emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(Size, AllocaAddr.getPointer());
+ emission.UseLifetimeMarkers =
+ EmitLifetimeStart(AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1723,9 +1719,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
- EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
- emission.getOriginalAllocatedAddress(),
- emission.getSizeForLifetimeMarkers());
+ EHStack.pushCleanup<CallLifetimeEnd>(
+ NormalEHLifetimeMarker, emission.getOriginalAllocatedAddress());
// Analogous to lifetime markers, we use a 'cleanup' to emit fake.use
// calls for local variables. We are exempting volatile variables and
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 85c768807572f..576307d707b69 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -577,11 +577,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
+ if (EmitLifetimeStart(Alloca.getPointer())) {
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
+ Alloca);
}
break;
@@ -612,11 +610,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
Block, llvm::BasicBlock::iterator(Block->back())));
}
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ if (EmitLifetimeStart(Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca);
}
if (OldConditional) {
@@ -5743,13 +5738,10 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
llvm::Value *Addr = TempLV.getAddress().getBasePointer();
llvm::Type *ElTy = ConvertTypeForMem(TempLV.getType());
- llvm::TypeSize Sz = CGM.getDataLayout().getTypeAllocSize(ElTy);
-
- llvm::Value *LifetimeSize = EmitLifetimeStart(Sz, Addr);
+ EmitLifetimeStart(Addr);
Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
- Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast(),
- LifetimeSize);
+ Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
Args.add(RValue::get(TmpAddr, *this), Ty);
return TempLV;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index cad6731173700..e2f11b86b2053 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -300,16 +300,12 @@ void AggExprEmitter::withReturnValueSlot(
Address RetAddr = Address::invalid();
EHScopeStack::stable_iterator LifetimeEndBlock;
- llvm::Value *LifetimeSizePtr = nullptr;
llvm::IntrinsicInst *LifetimeStartInst = nullptr;
if (!UseTemp) {
RetAddr = Dest.getAddress();
} else {
RetAddr = CGF.CreateMemTempWithoutCast(RetTy, "tmp");
- llvm::TypeSize Size =
- CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
- LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getBasePointer());
- if (LifetimeSizePtr) {
+ if (CGF.EmitLifetimeStart(RetAddr.getBasePointer())) {
LifetimeStartInst =
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
assert(LifetimeStartInst->getIntrinsicID() ==
@@ -317,7 +313,7 @@ void AggExprEmitter::withReturnValueSlot(
"Last insertion wasn't a lifetime.start?");
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
- NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
+ NormalEHLifetimeMarker, RetAddr);
LifetimeEndBlock = CGF.EHStack.stable_begin();
}
}
@@ -338,7 +334,7 @@ void AggExprEmitter::withReturnValueSlot(
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
// eagerly.
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
- CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getBasePointer());
+ CGF.EmitLifetimeEnd(RetAddr.getBasePointer());
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6c32c98cec011..272587f7fa4b5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -701,14 +701,12 @@ class CodeGenFunction : public CodeGenTypeCache {
bool isRedundantBeforeReturn() override { return true; }
llvm::Value *Addr;
- llvm::Value *Size;
public:
- CallLifetimeEnd(RawAddress addr, llvm::Value *size)
- : Addr(addr.getPointer()), Size(size) {}
+ CallLifetimeEnd(RawAddress addr) : Addr(addr.getPointer()) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitLifetimeEnd(Size, Addr);
+ CGF.EmitLifetimeEnd(Addr);
}
};
@@ -3233,8 +3231,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitSehTryScopeBegin();
void EmitSehTryScopeEnd();
- llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
- void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+ bool EmitLifetimeStart(llvm::Value *Addr);
+ void EmitLifetimeEnd(llvm::Value *Addr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -3417,8 +3415,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// initializer.
bool IsConstantAggregate;
- /// Non-null if we should use lifetime annotations.
- llvm::Value *SizeForLifetimeMarkers;
+ /// True if lifetime markers should be used.
+ bool UseLifetimeMarkers;
/// Address with original alloca instruction. Invalid if the variable was
/// emitted as a global constant.
@@ -3432,20 +3430,14 @@ class CodeGenFunction : public CodeGenTypeCache {
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsEscapingByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {}
+ UseLifetimeMarkers(false), AllocaAddr(RawAddress::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool useLifetimeMarkers() const {
- return SizeForLifetimeMarkers != nullptr;
- }
- llvm::Value *getSizeForLifetimeMarkers() const {
- assert(useLifetimeMarkers());
- return SizeForLifetimeMarkers;
- }
+ bool useLifetimeMarkers() const { return UseLifetimeMarkers; }
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself. It is casted to default
diff --git a/clang/test/C/C11/n1285_1.c b/clang/test/C/C11/n1285_1.c
index 50100042e82fd..25b68e3145b04 100644
--- a/clang/test/C/C11/n1285_1.c
+++ b/clang/test/C/C11/n1285_1.c
@@ -26,16 +26,16 @@ struct X f(void);
...
[truncated]
|
@llvm/pr-subscribers-coroutines Author: Nikita Popov (nikic) ChangesNow that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this). Patch is 1.54 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150248.diff 479 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3f784fc8e798f..1254b0f38966a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5981,8 +5981,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// Create a temporary array to hold the sizes of local pointer arguments
// for the block. \p First is the position of the first size argument.
- auto CreateArrayForSizeVar = [=](unsigned First)
- -> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
+ auto CreateArrayForSizeVar =
+ [=](unsigned First) -> std::pair<llvm::Value *, llvm::Value *> {
llvm::APInt ArraySize(32, NumArgs - First);
QualType SizeArrayTy = getContext().getConstantArrayType(
getContext().getSizeType(), ArraySize, nullptr,
@@ -5995,9 +5995,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// actually the Alloca ascasted to the default AS, hence the
// stripPointerCasts()
llvm::Value *Alloca = TmpPtr->stripPointerCasts();
- llvm::Value *TmpSize = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca);
llvm::Value *ElemPtr;
+ EmitLifetimeStart(Alloca);
// Each of the following arguments specifies the size of the corresponding
// argument passed to the enqueued block.
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
@@ -6014,7 +6013,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}
// Return the Alloca itself rather than a potential ascast as this is only
// used by the paired EmitLifetimeEnd.
- return {ElemPtr, TmpSize, Alloca};
+ return {ElemPtr, Alloca};
};
// Could have events and/or varargs.
@@ -6026,7 +6025,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Value *Kernel =
Builder.CreatePointerCast(Info.KernelHandle, GenericVoidPtrTy);
auto *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy);
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(4);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(4);
// Create a vector of the arguments, as well as a constant value to
// express to the runtime the number of variadic arguments.
@@ -6041,8 +6040,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
// Any calls now have event arguments passed.
@@ -6107,15 +6105,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_varargs";
- auto [ElemPtr, TmpSize, TmpPtr] = CreateArrayForSizeVar(7);
+ auto [ElemPtr, TmpPtr] = CreateArrayForSizeVar(7);
Args.push_back(ElemPtr);
ArgTys.push_back(ElemPtr->getType());
llvm::FunctionType *FTy = llvm::FunctionType::get(Int32Ty, ArgTys, false);
auto Call = RValue::get(
EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), Args));
- if (TmpSize)
- EmitLifetimeEnd(TmpSize, TmpPtr);
+ EmitLifetimeEnd(TmpPtr);
return Call;
}
llvm_unreachable("Unexpected enqueue_kernel signature");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d9bd443455e0f..6e0c2c11a9f3b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4319,10 +4319,7 @@ static void emitWriteback(CodeGenFunction &CGF,
if (writeback.WritebackExpr) {
CGF.EmitIgnoredExpr(writeback.WritebackExpr);
-
- if (writeback.LifetimeSz)
- CGF.EmitLifetimeEnd(writeback.LifetimeSz,
- writeback.Temporary.getBasePointer());
+ CGF.EmitLifetimeEnd(writeback.Temporary.getBasePointer());
return;
}
@@ -5282,7 +5279,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
- llvm::Value *UnusedReturnSizePtr = nullptr;
+ bool NeedSRetLifetimeEnd = false;
if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
// For virtual function pointer thunks and musttail calls, we must always
// forward an incoming SRet pointer to the callee, because a local alloca
@@ -5296,11 +5293,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
SRetPtr = ReturnValue.getAddress();
} else {
SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp");
- if (HaveInsertPoint() && ReturnValue.isUnused()) {
- llvm::TypeSize size =
- CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getBasePointer());
- }
+ if (HaveInsertPoint() && ReturnValue.isUnused())
+ NeedSRetLifetimeEnd = EmitLifetimeStart(SRetPtr.getBasePointer());
}
if (IRFunctionArgs.hasSRetArg()) {
// A mismatch between the allocated return value's AS and the target's
@@ -5484,15 +5478,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Val = Builder.CreateFreeze(Val);
IRCallArgs[FirstIRArg] = Val;
- // Emit lifetime markers for the temporary alloca.
- llvm::TypeSize ByvalTempElementSize =
- CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
- llvm::Value *LifetimeSize =
- EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
-
- // Add cleanup code to emit the end lifetime marker after the call.
- if (LifetimeSize) // In case we disabled lifetime markers.
- CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
+ // Emit lifetime markers for the temporary alloca and add cleanup code to
+ // emit the end lifetime marker after the call.
+ if (EmitLifetimeStart(AI.getPointer()))
+ CallLifetimeEndAfterCall.emplace_back(AI);
// Generate the copy.
I->copyInto(*this, AI);
@@ -5653,9 +5642,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
auto unpaddedCoercionType = ArgInfo.getUnpaddedCoerceAndExpandType();
auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType);
- llvm::Value *tempSize = nullptr;
Address addr = Address::invalid();
RawAddress AllocaAddr = RawAddress::invalid();
+ bool NeedLifetimeEnd = false;
if (I->isAggregate()) {
addr = I->hasLValue() ? I->getKnownLValue().getAddress()
: I->getKnownRValue().getAggregateAddress();
@@ -5665,7 +5654,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(RV.isScalar()); // complex should always just be direct
llvm::Type *scalarType = RV.getScalarVal()->getType();
- auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType);
// Materialize to a temporary.
@@ -5674,7 +5662,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
layout->getAlignment(), scalarAlign)),
"tmp",
/*ArraySize=*/nullptr, &AllocaAddr);
- tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
+ NeedLifetimeEnd = EmitLifetimeStart(AllocaAddr.getPointer());
Builder.CreateStore(RV.getScalarVal(), addr);
}
@@ -5699,10 +5687,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
assert(IRArgPos == FirstIRArg + NumIRArgs);
- if (tempSize) {
- EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
- }
-
+ if (NeedLifetimeEnd)
+ EmitLifetimeEnd(AllocaAddr.getPointer());
break;
}
@@ -5871,9 +5857,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// can't depend on being inside of an ExprWithCleanups, so we need to manually
// pop this cleanup later on. Being eager about this is OK, since this
// temporary is 'invisible' outside of the callee.
- if (UnusedReturnSizePtr)
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr,
- UnusedReturnSizePtr);
+ if (NeedSRetLifetimeEnd)
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetPtr);
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
@@ -6007,7 +5992,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CI->doesNotReturn()) {
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
// Strip away the noreturn attribute to better diagnose unreachable UB.
@@ -6122,7 +6107,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
- if (UnusedReturnSizePtr)
+ if (NeedSRetLifetimeEnd)
PopCleanupBlock();
return ret;
}
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 0b4e3f9cb0365..3157b7f16f294 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -289,9 +289,6 @@ class CallArgList : public SmallVector<CallArg, 8> {
/// An Expression (optional) that performs the writeback with any required
/// casting.
const Expr *WritebackExpr;
-
- // Size for optional lifetime end on the temporary.
- llvm::Value *LifetimeSz;
};
struct CallArgCleanup {
@@ -321,9 +318,8 @@ class CallArgList : public SmallVector<CallArg, 8> {
}
void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse,
- const Expr *writebackExpr = nullptr,
- llvm::Value *lifetimeSz = nullptr) {
- Writeback writeback = {srcLV, temporary, toUse, writebackExpr, lifetimeSz};
+ const Expr *writebackExpr = nullptr) {
+ Writeback writeback = {srcLV, temporary, toUse, writebackExpr};
Writebacks.push_back(writeback);
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 04f13c7d7a6a3..d224b09522d86 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1347,30 +1347,27 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
}
/// Emit a lifetime.begin marker if some criteria are satisfied.
-/// \return a pointer to the temporary size Value if a marker was emitted, null
-/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
- llvm::Value *Addr) {
+/// \return whether the marker was emitted.
+bool CodeGenFunction::EmitLifetimeStart(llvm::Value *Addr) {
if (!ShouldEmitLifetimeMarkers)
- return nullptr;
+ return false;
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::Value *SizeV = llvm::ConstantInt::get(
- Int64Ty, Size.isScalable() ? -1 : Size.getFixedValue());
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {Addr});
C->setDoesNotThrow();
- return SizeV;
+ return true;
}
-void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
+void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Addr) {
+ if (!ShouldEmitLifetimeMarkers)
+ return;
+
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::CallInst *C =
- Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
+ llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Addr});
C->setDoesNotThrow();
}
@@ -1628,9 +1625,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// is rare.
if (!Bypasses.IsBypassed(&D) &&
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
- llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
- emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(Size, AllocaAddr.getPointer());
+ emission.UseLifetimeMarkers =
+ EmitLifetimeStart(AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1723,9 +1719,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// Make sure we call @llvm.lifetime.end.
if (emission.useLifetimeMarkers())
- EHStack.pushCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker,
- emission.getOriginalAllocatedAddress(),
- emission.getSizeForLifetimeMarkers());
+ EHStack.pushCleanup<CallLifetimeEnd>(
+ NormalEHLifetimeMarker, emission.getOriginalAllocatedAddress());
// Analogous to lifetime markers, we use a 'cleanup' to emit fake.use
// calls for local variables. We are exempting volatile variables and
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 85c768807572f..576307d707b69 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -577,11 +577,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
+ if (EmitLifetimeStart(Alloca.getPointer())) {
pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
+ Alloca);
}
break;
@@ -612,11 +610,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
Block, llvm::BasicBlock::iterator(Block->back())));
}
- if (auto *Size = EmitLifetimeStart(
- CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
- Alloca.getPointer())) {
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ if (EmitLifetimeStart(Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca);
}
if (OldConditional) {
@@ -5743,13 +5738,10 @@ LValue CodeGenFunction::EmitHLSLOutArgExpr(const HLSLOutArgExpr *E,
llvm::Value *Addr = TempLV.getAddress().getBasePointer();
llvm::Type *ElTy = ConvertTypeForMem(TempLV.getType());
- llvm::TypeSize Sz = CGM.getDataLayout().getTypeAllocSize(ElTy);
-
- llvm::Value *LifetimeSize = EmitLifetimeStart(Sz, Addr);
+ EmitLifetimeStart(Addr);
Address TmpAddr(Addr, ElTy, TempLV.getAlignment());
- Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast(),
- LifetimeSize);
+ Args.addWriteback(BaseLV, TmpAddr, nullptr, E->getWritebackCast());
Args.add(RValue::get(TmpAddr, *this), Ty);
return TempLV;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index cad6731173700..e2f11b86b2053 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -300,16 +300,12 @@ void AggExprEmitter::withReturnValueSlot(
Address RetAddr = Address::invalid();
EHScopeStack::stable_iterator LifetimeEndBlock;
- llvm::Value *LifetimeSizePtr = nullptr;
llvm::IntrinsicInst *LifetimeStartInst = nullptr;
if (!UseTemp) {
RetAddr = Dest.getAddress();
} else {
RetAddr = CGF.CreateMemTempWithoutCast(RetTy, "tmp");
- llvm::TypeSize Size =
- CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
- LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getBasePointer());
- if (LifetimeSizePtr) {
+ if (CGF.EmitLifetimeStart(RetAddr.getBasePointer())) {
LifetimeStartInst =
cast<llvm::IntrinsicInst>(std::prev(Builder.GetInsertPoint()));
assert(LifetimeStartInst->getIntrinsicID() ==
@@ -317,7 +313,7 @@ void AggExprEmitter::withReturnValueSlot(
"Last insertion wasn't a lifetime.start?");
CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
- NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
+ NormalEHLifetimeMarker, RetAddr);
LifetimeEndBlock = CGF.EHStack.stable_begin();
}
}
@@ -338,7 +334,7 @@ void AggExprEmitter::withReturnValueSlot(
// Since we're not guaranteed to be in an ExprWithCleanups, clean up
// eagerly.
CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst);
- CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getBasePointer());
+ CGF.EmitLifetimeEnd(RetAddr.getBasePointer());
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6c32c98cec011..272587f7fa4b5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -701,14 +701,12 @@ class CodeGenFunction : public CodeGenTypeCache {
bool isRedundantBeforeReturn() override { return true; }
llvm::Value *Addr;
- llvm::Value *Size;
public:
- CallLifetimeEnd(RawAddress addr, llvm::Value *size)
- : Addr(addr.getPointer()), Size(size) {}
+ CallLifetimeEnd(RawAddress addr) : Addr(addr.getPointer()) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitLifetimeEnd(Size, Addr);
+ CGF.EmitLifetimeEnd(Addr);
}
};
@@ -3233,8 +3231,8 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitSehTryScopeBegin();
void EmitSehTryScopeEnd();
- llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
- void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
+ bool EmitLifetimeStart(llvm::Value *Addr);
+ void EmitLifetimeEnd(llvm::Value *Addr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
@@ -3417,8 +3415,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// initializer.
bool IsConstantAggregate;
- /// Non-null if we should use lifetime annotations.
- llvm::Value *SizeForLifetimeMarkers;
+ /// True if lifetime markers should be used.
+ bool UseLifetimeMarkers;
/// Address with original alloca instruction. Invalid if the variable was
/// emitted as a global constant.
@@ -3432,20 +3430,14 @@ class CodeGenFunction : public CodeGenTypeCache {
AutoVarEmission(const VarDecl &variable)
: Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsEscapingByRef(false), IsConstantAggregate(false),
- SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {}
+ UseLifetimeMarkers(false), AllocaAddr(RawAddress::invalid()) {}
bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
- bool useLifetimeMarkers() const {
- return SizeForLifetimeMarkers != nullptr;
- }
- llvm::Value *getSizeForLifetimeMarkers() const {
- assert(useLifetimeMarkers());
- return SizeForLifetimeMarkers;
- }
+ bool useLifetimeMarkers() const { return UseLifetimeMarkers; }
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself. It is casted to default
diff --git a/clang/test/C/C11/n1285_1.c b/clang/test/C/C11/n1285_1.c
index 50100042e82fd..25b68e3145b04 100644
--- a/clang/test/C/C11/n1285_1.c
+++ b/clang/test/C/C11/n1285_1.c
@@ -26,16 +26,16 @@ struct X f(void);
...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some downstream projects should be informed:
rustc: https://github.com/rust-lang/rust/blob/a955f1cd09a027363729ceed919952d09f76f28e/compiler/rustc_codegen_llvm/src/builder.rs#L1656-L1668
julia: https://github.com/JuliaLang/julia/blob/16a2bf0a3b106b03dda23b8c9478aab90ffda5e1/src/llvm-alloc-opt.cpp#L439-L443
Do we need to note the breaking change?
Probably should release note, yes. Also, can we try to land some of the changes separately? I mean, some things can't land separately, or it would be a pain in the neck to land them separately because of test changes, but we can at least merge the SelectionDAG bits and the analysis changes first, so the remaining bits are easier to review. |
I've added a release note.
I guess I could split this up into two changes:
Then the first one should have most of the interesting bits, and the second one be mostly mechanical... |
@@ -1462,6 +1462,7 @@ void HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo, | |||
Value *AICast = IRB.CreatePointerCast(AI, PtrTy); | |||
|
|||
auto HandleLifetime = [&](IntrinsicInst *II) { | |||
// FIXME: Remove this code entirely. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just submitted #150510, so we can just remove the whole thing now.
Split out from llvm#150248: Specify that the argument of lifetime.start/lifetime.end is ignored and will be removed in the future. Remove lifetime size handling from SDAG. The size was previously discarded during isel, so was always ignored for stack coloring. Where necessary, obtain the size of the full frame index.
Split out from llvm#150248: Specify that the argument of lifetime.start/lifetime.end is ignored and will be removed in the future. Remove lifetime size handling from SDAG. The size was previously discarded during isel, so was always ignored for stack coloring. Where necessary, obtain the size of the full frame index.
Split out from #150248: Specify that the argument of lifetime.start/lifetime.end is ignored and will be removed in the future. Remove lifetime size handling from SDAG. The size was previously discarded during isel, so was always ignored for stack coloring anyway. Where necessary, obtain the size of the full frame index.
Now that llvm#149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (many key places, including stack coloring, did not actually respect this).
Split out from llvm/llvm-project#150248: Specify that the argument of lifetime.start/lifetime.end is ignored and will be removed in the future. Remove lifetime size handling from SDAG. The size was previously discarded during isel, so was always ignored for stack coloring anyway. Where necessary, obtain the size of the full frame index.
Now that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca.
This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this).