[llvm] [CodeGen][WinEH] Update saved esp for inlined inallocas (PR #116585)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 19 03:54:44 PST 2024
================
@@ -774,3 +778,27 @@ void WinEHStatePass::insertStateNumberStore(Instruction *IP, int State) {
RegNode, StateFieldIndex);
Builder.CreateStore(Builder.getInt32(State), StateField);
}
+
+void WinEHStatePass::updateEspForInAllocas(Function &F) {
+ for (BasicBlock &BB : F) {
+ for (Instruction &I : BB) {
+ if (auto *Alloca = dyn_cast<AllocaInst>(&I)) {
+ if (!Alloca->isUsedWithInAlloca())
----------------
MuellerMP wrote:
updated
First of all thanks for the review.
Also added another test case for dynamic allocas.
I was unsure if this was actually a case we have to handle because my test cases never seemd to generate one.
But I see now that you can just use the c alloca api directly to generate one.
Regarding the inalloca case:
Statement expressions are not the only way to introduce this hazard - inlining does as well as I have demonstrated in the C++ code of issue #116583.
There I overrun the inalloca stack object within the called function itself.
This is actually something I find more often in my test code base then "alloca" calls.
Lifetime annoations and stacksave/restore intrinsics will get properly inlined into a caller if they exist.
My initial thought was to then maybe allow WinEH to process the lifetimes of these dynamically allocated stack objects.
The problem that I encountered with this approach is the following:
```llvm
; Function Attrs: mustprogress sspstrong
define internal fastcc noundef i32 @"??$invoke at AAV<lambda_0>@?0??..."(ptr noundef nonnull align 4 dereferenceable(48) %_Obj, ptr noundef nonnull align 4 dereferenceable(8) %_Arg1, ptr noundef nonnull align 4 dereferenceable(4) %_Args21, ptr noundef nonnull align 4 dereferenceable(28) %_Args2) unnamed_addr #3 !dbg !7302 {
entry:
tail call void @llvm.dbg.value(metadata ptr %_Args2, metadata !7306, metadata !DIExpression()), !dbg !7315
tail call void @llvm.dbg.value(metadata ptr %_Args21, metadata !7307, metadata !DIExpression()), !dbg !7315
tail call void @llvm.dbg.value(metadata ptr %_Arg1, metadata !7308, metadata !DIExpression()), !dbg !7315
tail call void @llvm.dbg.value(metadata ptr %_Obj, metadata !7309, metadata !DIExpression()), !dbg !7315
%argmem = alloca inalloca <{ %"class.std::shared_ptr.16", ptr, ptr }>, align 4
%call = call x86_thiscallcc noundef ptr @"??0?$shared_ptr at ..."(ptr noundef nonnull align 4 dereferenceable(8) %argmem, ptr noundef nonnull align 4 dereferenceable(8) %_Arg1) #18, !dbg !7316
%0 = getelementptr inbounds <{ %"class.std::shared_ptr.16", ptr, ptr }>, ptr %argmem, i32 0, i32 1, !dbg !7316
store ptr %_Args21, ptr %0, align 4, !dbg !7316
%1 = getelementptr inbounds <{ %"class.std::shared_ptr.16", ptr, ptr }>, ptr %argmem, i32 0, i32 2, !dbg !7316
store ptr %_Args2, ptr %1, align 4, !dbg !7316
%call3 = call fastcc noundef i32 @"??R<lambda_0>@?0??.."(ptr noundef nonnull %_Obj, ptr nonnull %argmem), !dbg !7316, !range !7232
ret i32 %call3, !dbg !7316
}
```
Here we have a std::invoke instantiation (truncated for readability) which does execute the call operator of the lambda.
We do not have lifetimes for the argmem and also the call operator has its inalloca attribute stripped.
I see the case for not emitting lifetime annotations here in the frontend due to this being a single block func.
But what is more problematic in my opinion is that GlobalOpt does strip the inalloca attribute of argmem inside the CallBase but doesnt strip the attribute for the alloca.
If we now inline the call operator func and want to generate lifetimes for the inalloca alloca we would have to walk all instructions to check if the caller has an inalloca alloca.
We can't determine it from the CallBase since the Inliner runs after GlobalOpt.
So TL;DR is:
I guess the lifetime management of inalloca allocas is also suboptimal and could be improved.
https://github.com/llvm/llvm-project/pull/116585
More information about the llvm-commits
mailing list