[llvm] 86fd4d4 - [Coroutines] Fix another crash related to CallGraph update (#116756)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 21 06:07:22 PST 2024


Author: Yuxuan Chen
Date: 2024-11-21T15:07:17+01:00
New Revision: 86fd4d4b5b95d58844e521cf7319965eea7d8d0b

URL: https://github.com/llvm/llvm-project/commit/86fd4d4b5b95d58844e521cf7319965eea7d8d0b
DIFF: https://github.com/llvm/llvm-project/commit/86fd4d4b5b95d58844e521cf7319965eea7d8d0b.diff

LOG: [Coroutines] Fix another crash related to CallGraph update (#116756)

The previous fix
https://github.com/llvm/llvm-project/commit/c6414970d76ad79168fe7ec3c4400c5a5ca89d2d
failed to consider the fact that the call graph update doesn't make any
sense if the caller node hasn't been populated in the LazyCallGraph yet.
This patch changes to skip this CG update step when that happens.

Added: 
    llvm/test/Transforms/Coroutines/gh114487-crash-in-cgscc-2.ll

Modified: 
    llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
index 7dbf501b817010..9115946d205a48 100644
--- a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
@@ -146,7 +146,10 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
       bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe);
       if (IsCallerPresplitCoroutine && HasAttr) {
         auto *CallerN = CG.lookup(*Caller);
-        auto *CallerC = CG.lookupSCC(*CallerN);
+        auto *CallerC = CallerN ? CG.lookupSCC(*CallerN) : nullptr;
+        // If CallerC is nullptr, it means LazyCallGraph hasn't visited Caller
+        // yet. Skip the call graph update.
+        auto ShouldUpdateCallGraph = !!CallerC;
         processCall(CB, Caller, NewCallee, FrameSize, FrameAlign);
 
         ORE.emit([&]() {
@@ -158,8 +161,9 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
 
         FAM.invalidate(*Caller, PreservedAnalyses::none());
         Changed = true;
-        updateCGAndAnalysisManagerForCGSCCPass(CG, *CallerC, *CallerN, AM, UR,
-                                               FAM);
+        if (ShouldUpdateCallGraph)
+          updateCGAndAnalysisManagerForCGSCCPass(CG, *CallerC, *CallerN, AM, UR,
+                                                 FAM);
 
       } else {
         ORE.emit([&]() {

diff  --git a/llvm/test/Transforms/Coroutines/gh114487-crash-in-cgscc-2.ll b/llvm/test/Transforms/Coroutines/gh114487-crash-in-cgscc-2.ll
new file mode 100644
index 00000000000000..690e01121315c0
--- /dev/null
+++ b/llvm/test/Transforms/Coroutines/gh114487-crash-in-cgscc-2.ll
@@ -0,0 +1,158 @@
+; RUN: opt -passes="cgscc(coro-annotation-elide)" -S < %s | FileCheck %s
+
+%foo.Frame = type { ptr, ptr, i1 }
+
+ at foo.resumers = private constant [3 x ptr] [ptr @foo.resume, ptr @foo.destroy, ptr @foo.cleanup]
+ at foo.resumers.1 = private constant [4 x ptr] [ptr @foo.resume, ptr @foo.destroy, ptr @foo.cleanup, ptr @foo.noalloc]
+
+; CHECK-LABEL: define void @foo
+define void @foo(ptr %agg.result, ptr %this) personality ptr null {
+entry:
+  %0 = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @foo, ptr @foo.resumers.1)
+  %1 = call noalias nonnull ptr @llvm.coro.begin(token %0, ptr null)
+  %resume.addr = getelementptr inbounds nuw %foo.Frame, ptr %1, i32 0, i32 0
+  store ptr @foo.resume, ptr %resume.addr, align 8
+  %destroy.addr = getelementptr inbounds nuw %foo.Frame, ptr %1, i32 0, i32 1
+  store ptr @foo.destroy, ptr %destroy.addr, align 8
+  br label %AllocaSpillBB
+
+AllocaSpillBB:                                    ; preds = %entry
+  br label %PostSpill
+
+PostSpill:                                        ; preds = %AllocaSpillBB
+  br label %CoroSave
+
+CoroSave:                                         ; preds = %PostSpill
+  %index.addr1 = getelementptr inbounds nuw %foo.Frame, ptr %1, i32 0, i32 2
+  store i1 false, ptr %index.addr1, align 1
+  br label %CoroSuspend
+
+CoroSuspend:                                      ; preds = %CoroSave
+  br label %resume.0.landing
+
+resume.0.landing:                                 ; preds = %CoroSuspend
+  br label %AfterCoroSuspend
+
+AfterCoroSuspend:                                 ; preds = %resume.0.landing
+  ret void
+}
+
+; CHECK-LABEL: define internal void @bar
+; Function Attrs: presplitcoroutine
+define internal void @bar() #0 personality ptr null {
+entry:
+  ; CHECK: %[[CALLEE_FRAME:.+]] = alloca [24 x i8], align 8
+  %0 = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @bar, ptr null)
+  %1 = call i1 @llvm.coro.alloc(token %0)
+  call void @foo(ptr null, ptr null) #4
+  ; CHECK: %[[FOO_ID:.+]] = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @foo, ptr @foo.resumers)
+  ; CHECK-NEXT: store ptr @foo.resume, ptr %[[CALLEE_FRAME]], align 8
+  ; CHECK-NEXT: %[[DESTROY_ADDR:.+]] = getelementptr inbounds nuw %foo.Frame, ptr %[[CALLEE_FRAME]], i32 0, i32 1
+  ; CHECK-NEXT: store ptr @foo.destroy, ptr %[[DESTROY_ADDR]], align 8
+  ; CHECK-NEXT: %[[INDEX_ADDR:.+]] = getelementptr inbounds nuw %foo.Frame, ptr %[[CALLEE_FRAME]], i32 0, i32 2
+  ; CHECK-NEXT: store i1 false, ptr %[[INDEX_ADDR]], align 1
+  ; CHECK: ret void
+  ret void
+}
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: read)
+declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
+
+; Function Attrs: nounwind
+declare i1 @llvm.coro.alloc(token) #2
+
+; Function Attrs: nounwind
+declare ptr @llvm.coro.begin(token, ptr writeonly) #2
+
+; Function Attrs: nomerge nounwind
+declare token @llvm.coro.save(ptr) #3
+
+; Function Attrs: nounwind
+declare i8 @llvm.coro.suspend(token, i1) #2
+
+define internal fastcc void @foo.resume(ptr noundef nonnull align 8 dereferenceable(24) %0) personality ptr null {
+entry.resume:
+  br label %resume.entry
+
+resume.0:                                         ; preds = %resume.entry
+  br label %resume.0.landing
+
+resume.0.landing:                                 ; preds = %resume.0
+  br label %AfterCoroSuspend
+
+AfterCoroSuspend:                                 ; preds = %resume.0.landing
+  unreachable
+
+resume.entry:                                     ; preds = %entry.resume
+  br label %resume.0
+}
+
+define internal fastcc void @foo.destroy(ptr noundef nonnull align 8 dereferenceable(24) %0) personality ptr null {
+entry.destroy:
+  br label %resume.entry
+
+resume.0:                                         ; preds = %resume.entry
+  br label %resume.0.landing
+
+resume.0.landing:                                 ; preds = %resume.0
+  br label %AfterCoroSuspend
+
+AfterCoroSuspend:                                 ; preds = %resume.0.landing
+  unreachable
+
+resume.entry:                                     ; preds = %entry.destroy
+  br label %resume.0
+}
+
+define internal fastcc void @foo.cleanup(ptr noundef nonnull align 8 dereferenceable(24) %0) personality ptr null {
+entry.cleanup:
+  br label %resume.entry
+
+resume.0:                                         ; preds = %resume.entry
+  br label %resume.0.landing
+
+resume.0.landing:                                 ; preds = %resume.0
+  br label %AfterCoroSuspend
+
+AfterCoroSuspend:                                 ; preds = %resume.0.landing
+  unreachable
+
+resume.entry:                                     ; preds = %entry.cleanup
+  br label %resume.0
+}
+
+define internal void @foo.noalloc(ptr %0, ptr %1, ptr noundef nonnull align 8 dereferenceable(24) %2) personality ptr null {
+entry:
+  %3 = call token @llvm.coro.id(i32 0, ptr null, ptr nonnull @foo, ptr @foo.resumers)
+  %resume.addr = getelementptr inbounds nuw %foo.Frame, ptr %2, i32 0, i32 0
+  store ptr @foo.resume, ptr %resume.addr, align 8
+  %destroy.addr = getelementptr inbounds nuw %foo.Frame, ptr %2, i32 0, i32 1
+  store ptr @foo.destroy, ptr %destroy.addr, align 8
+  br label %AllocaSpillBB
+
+AllocaSpillBB:                                    ; preds = %entry
+  br label %PostSpill
+
+PostSpill:                                        ; preds = %AllocaSpillBB
+  br label %CoroSave
+
+CoroSave:                                         ; preds = %PostSpill
+  %index.addr1 = getelementptr inbounds nuw %foo.Frame, ptr %2, i32 0, i32 2
+  store i1 false, ptr %index.addr1, align 1
+  br label %CoroSuspend
+
+CoroSuspend:                                      ; preds = %CoroSave
+  br label %resume.0.landing
+
+resume.0.landing:                                 ; preds = %CoroSuspend
+  br label %AfterCoroSuspend
+
+AfterCoroSuspend:                                 ; preds = %resume.0.landing
+  ret void
+}
+
+attributes #0 = { presplitcoroutine }
+attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: read) }
+attributes #2 = { nounwind }
+attributes #3 = { nomerge nounwind }
+attributes #4 = { coro_elide_safe }


        


More information about the llvm-commits mailing list