https://github.com/NewSigma created 
https://github.com/llvm/llvm-project/pull/219870

Consider the following code:

``` LLVM
%hdl1 = call ptr @llvm.coro.begin(token %coro.outer, ptr %mem1)
store ptr %hdl1, ptr %alloca, align 8
call i1 @llvm.coro.alloc(token %coro.inner)
call ptr @llvm.coro.begin(token %coro.inner, ptr %mem2)
%hdl1.ld = load ptr, ptr %alloca, align 8
%resumer = call ptr @llvm.coro.subfn.addr(ptr %hdl1.ld, i8 0)
invoke void %resumer(ptr %hdl1.ld)
```

The pattern occurs inside nested coroutines. Adding `memory(none)` attributes 
allows GVN to replace the store-load with direct references to `coro.begin`, 
thus enabling further optimizations. We can simplify #57852 into single `ret 0` 
after this change.

>From 46accf7215b3b11dbe613ff461a0013f2e2794be Mon Sep 17 00:00:00 2001
From: NewSigma <[email protected]>
Date: Sun, 23 Aug 2026 17:00:42 +0800
Subject: [PATCH] [Coro][IR] Model memory effects of coro.alloc and coro.begin
 more precisely

---
 .../coro-unhandled-exception.cpp                 |  4 ++--
 llvm/include/llvm/IR/Intrinsics.td               |  6 +++---
 .../Transforms/Coroutines/coro-byval-param.ll    | 16 +++++++++-------
 .../Transforms/Coroutines/coro-split-alloc.ll    |  3 +--
 4 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp 
b/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp
index 97ef983b7523a..ace0bbca62dbb 100644
--- a/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp
+++ b/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp
@@ -55,12 +55,12 @@ coro_t f() {
 // CHECK-LPAD:   invoke void @_Z9may_throwv()
 // CHECK-LPAD:       to label %[[CONT:.+]] unwind label %[[CLEANUP:.+]]
 // CHECK-LPAD: [[CLEANUP]]:
-// CHECK-LPAD:   call void @_ZN7CleanupD1Ev(ptr {{[^,]*}} %x) #2
+// CHECK-LPAD:   call void @_ZN7CleanupD1Ev(ptr {{[^,]*}} %x) #[[ATTR:[0-9]+]]
 // CHECK-LPAD:   br label %[[CATCH:.+]]
 
 // CHECK-LPAD: [[CATCH]]:
 // CHECK-LPAD:    call ptr @__cxa_begin_catch
-// CHECK-LPAD:    call void 
@_ZN6coro_t12promise_type19unhandled_exceptionEv(ptr {{[^,]*}} %__promise) #2
+// CHECK-LPAD:    call void 
@_ZN6coro_t12promise_type19unhandled_exceptionEv(ptr {{[^,]*}} %__promise) 
#[[ATTR]]
 // CHECK-LPAD:    invoke void @__cxa_end_catch()
 // CHECK-LPAD-NEXT:  to label %[[CATCHRETDEST:.+]] unwind label
 // CHECK-LPAD: [[CATCHRETDEST]]:
diff --git a/llvm/include/llvm/IR/Intrinsics.td 
b/llvm/include/llvm/IR/Intrinsics.td
index 1d960dc011a5a..0efe844900fd8 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1986,7 +1986,7 @@ def int_coro_id_retcon_once : Intrinsic<[llvm_token_ty],
     [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty,
      llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty],
     []>;
-def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>;
+def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], [IntrNoMem]>;
 def int_coro_id_async : Intrinsic<[llvm_token_ty],
   [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty],
   []>;
@@ -2007,10 +2007,10 @@ def int_coro_suspend_async
 def int_coro_prepare_async : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty],
                                        [IntrNoMem]>;
 def int_coro_begin : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
-                               [WriteOnly<ArgIndex<1>>]>;
+                               [IntrArgMemOnly, WriteOnly<ArgIndex<1>>]>;
 def int_coro_begin_custom_abi : Intrinsic<[llvm_ptr_ty],
                                   [llvm_token_ty, llvm_ptr_ty, llvm_i32_ty],
-                                  [WriteOnly<ArgIndex<1>>]>;
+                                  [IntrArgMemOnly, WriteOnly<ArgIndex<1>>]>;
 def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
                               [IntrReadMem, IntrArgMemOnly,
                                ReadOnly<ArgIndex<1>>,
diff --git a/llvm/test/Transforms/Coroutines/coro-byval-param.ll 
b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
index 44204de99ea66..9e4f383653435 100644
--- a/llvm/test/Transforms/Coroutines/coro-byval-param.ll
+++ b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
@@ -21,7 +21,7 @@ define ptr @foo(ptr nocapture readonly byval(%struct.A) align 
8 %a1) #0 !prof !0
 ; CHECK-NEXT:    [[TMP1:%.*]] = call i1 @llvm.coro.alloc(token [[TMP0]])
 ; CHECK-NEXT:    br i1 [[TMP1]], label %[[CORO_ALLOC:.*]], label 
%[[CORO_INIT:.*]]
 ; CHECK:       [[CORO_ALLOC]]:
-; CHECK-NEXT:    [[CALL:%.*]] = call noalias nonnull ptr @_Znwm(i64 48) 
#[[ATTR10:[0-9]+]]
+; CHECK-NEXT:    [[CALL:%.*]] = call noalias nonnull ptr @_Znwm(i64 48) 
#[[ATTR11:[0-9]+]]
 ; CHECK-NEXT:    br label %[[CORO_INIT]]
 ; CHECK:       [[CORO_INIT]]:
 ; CHECK-NEXT:    [[TMP2:%.*]] = phi ptr [ [[CALL]], %[[CORO_ALLOC]] ], [ null, 
%[[ENTRY]] ]
@@ -37,7 +37,7 @@ define ptr @foo(ptr nocapture readonly byval(%struct.A) align 
8 %a1) #0 !prof !0
 ; CHECK-NEXT:    call void @initial_suspend(ptr nonnull dereferenceable(1) 
[[__PROMISE_RELOAD_ADDR]])
 ; CHECK-NEXT:    [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr 
[[TMP3]], i64 17
 ; CHECK-NEXT:    store i1 false, ptr [[INDEX_ADDR5]], align 1
-; CHECK-NEXT:    call fastcc void 
@_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr
 [[TMP3]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    call fastcc void 
@_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr
 [[TMP3]]) #[[ATTR8:[0-9]+]]
 ; CHECK-NEXT:    ret ptr [[CALL2]]
 ;
 entry:
@@ -159,16 +159,18 @@ attributes #10 = { noduplicate }
 ;.
 ; CHECK: attributes #[[ATTR0]] = { mustprogress noinline ssp uwtable 
"frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="penryn" 
"target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
 "tune-cpu"="generic" }
 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind 
willreturn memory(argmem: read) }
-; CHECK: attributes #[[ATTR2]] = { nounwind }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind memory(none) }
 ; CHECK: attributes #[[ATTR3:[0-9]+]] = { nobuiltin nofree allocsize(0) 
"frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="penryn" 
"target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
 "tune-cpu"="generic" }
-; CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind memory(none) }
+; CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind memory(argmem: readwrite) }
 ; CHECK: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nosync nounwind 
willreturn memory(argmem: readwrite) }
 ; CHECK: attributes #[[ATTR6:[0-9]+]] = { mustprogress noinline nounwind ssp 
willreturn uwtable "frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="penryn" 
"target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
 "tune-cpu"="generic" }
 ; CHECK: attributes #[[ATTR7:[0-9]+]] = { nomerge nounwind }
-; CHECK: attributes #[[ATTR8:[0-9]+]] = { nobuiltin nounwind 
"frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="penryn" 
"target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
 "tune-cpu"="generic" }
-; CHECK: attributes #[[ATTR9:[0-9]+]] = { nounwind memory(argmem: read) }
-; CHECK: attributes #[[ATTR10]] = { allocsize(0) }
+; CHECK: attributes #[[ATTR8]] = { nounwind }
+; CHECK: attributes #[[ATTR9:[0-9]+]] = { nobuiltin nounwind 
"frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="penryn" 
"target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
 "tune-cpu"="generic" }
+; CHECK: attributes #[[ATTR10:[0-9]+]] = { nounwind memory(argmem: read) }
+; CHECK: attributes #[[ATTR11]] = { allocsize(0) }
 ;.
 ; CHECK: [[PROF0]] = !{!"function_entry_count", i64 1000}
 ; CHECK: [[PROF1]] = !{!"unknown", !"coro-split"}
+; CHECK: [[META2:![0-9]+]] = !{!"function_entry_count", i64 1333}
 ;.
diff --git a/llvm/test/Transforms/Coroutines/coro-split-alloc.ll 
b/llvm/test/Transforms/Coroutines/coro-split-alloc.ll
index db97cafeebbbb..3c3a2796d93ff 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-alloc.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-alloc.ll
@@ -42,8 +42,7 @@ suspend:
 ; CHECK: %incremented = add i32 %argument, 1
 ; CHECK-NEXT: store i32 %incremented, ptr %argument.addr
 ; CHECK-LABEL: dyn.alloc:
-; CHECK: %allocator_argument = load i32, ptr %argument.addr
-; CHECK: %alloc = call ptr @custom_alloctor(i32 24, i32 %allocator_argument)
+; CHECK: %alloc = call ptr @custom_alloctor(i32 24, i32 %incremented)
 ; CHECK-LABEL: begin:
 ; CHECK: %print_argument = load i32, ptr %argument.addr
 ; CHECK: call void @print(i32 %print_argument)

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to