Skip to content

[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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 8 additions & 11 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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");
Expand Down
47 changes: 16 additions & 31 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand All @@ -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.
Expand All @@ -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);
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down
8 changes: 2 additions & 6 deletions clang/lib/CodeGen/CGCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}

Expand Down
33 changes: 14 additions & 19 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand Down
20 changes: 6 additions & 14 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,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;

Expand Down Expand Up @@ -622,11 +620,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) {
Expand Down Expand Up @@ -5766,13 +5761,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;
}
Expand Down
10 changes: 3 additions & 7 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,24 +300,20 @@ 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() ==
llvm::Intrinsic::lifetime_start &&
"Last insertion wasn't a lifetime.start?");

CGF.pushFullExprCleanup<CodeGenFunction::CallLifetimeEnd>(
NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr);
NormalEHLifetimeMarker, RetAddr);
LifetimeEndBlock = CGF.EHStack.stable_begin();
}
}
Expand All @@ -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());
}
}

Expand Down
Loading