[llvm] af838c1 - [Coroutines] Don't run optimizations for optnone functions

Chuanqi Xu via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 13 23:22:20 PST 2023


Author: Chuanqi Xu
Date: 2023-02-14T15:21:48+08:00
New Revision: af838c1b1c20c7b3b970e81039a1992857fe76bb

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

LOG: [Coroutines] Don't run optimizations for optnone functions

Currently we will run two optimization (rematerialization and sink
lifetime markers) unconditionally even if the coroutine is marked as
optnone (O0). This looks not good. This patch disables these 2
optimizations for optnone functions. An internal change shows the change
improve the compilation time for 3% in the debug build.

Added: 
    

Modified: 
    llvm/lib/Transforms/Coroutines/CoroFrame.cpp
    llvm/test/Transforms/Coroutines/coro-materialize.ll
    llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 9f9b45c9e9e48..5988ca27d84de 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -2688,6 +2688,9 @@ static void sinkSpillUsesAfterCoroBegin(Function &F,
 /// hence minimizing the amount of data we end up putting on the frame.
 static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape,
                                      SuspendCrossingInfo &Checker) {
+  if (F.hasOptNone())
+    return;
+
   DominatorTree DT(F);
 
   // Collect all possible basic blocks which may dominate all uses of allocas.
@@ -2892,6 +2895,9 @@ void coro::salvageDebugInfo(
 static void doRematerializations(
     Function &F, SuspendCrossingInfo &Checker,
     const std::function<bool(Instruction &)> &MaterializableCallback) {
+  if (F.hasOptNone())
+    return;
+
   SpillInfo Spills;
 
   // See if there are materializable instructions across suspend points

diff  --git a/llvm/test/Transforms/Coroutines/coro-materialize.ll b/llvm/test/Transforms/Coroutines/coro-materialize.ll
index b45df16eb8c4b..7385337ab5750 100644
--- a/llvm/test/Transforms/Coroutines/coro-materialize.ll
+++ b/llvm/test/Transforms/Coroutines/coro-materialize.ll
@@ -3,11 +3,13 @@
 
 ; See that we only spilled one value for f
 ; CHECK: %f.Frame = type { ptr, ptr, i32, i1 }
+; CHECK: %f_optnone.Frame = type { ptr, ptr, i32, i32, i1 }
 ; Check other variants where 
diff erent levels of materialization are achieved
 ; CHECK: %f_multiple_remat.Frame = type { ptr, ptr, i32, i1 }
 ; CHECK: %f_common_def.Frame = type { ptr, ptr, i32, i1 }
 ; CHECK: %f_common_def_multi_result.Frame = type { ptr, ptr, i32, i1 }
 ; CHECK-LABEL: @f(
+; CHECK-LABEL: @f_optnone
 ; CHECK-LABEL: @f_multiple_remat(
 ; CHECK-LABEL: @f_common_def(
 ; CHECK-LABEL: @f_common_def_multi_result(
@@ -43,6 +45,38 @@ suspend:
   ret ptr %hdl
 }
 
+; Checks that we won't transform functions with optnone.
+define ptr @f_optnone(i32 %n) presplitcoroutine optnone noinline {
+entry:
+  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
+  %size = call i32 @llvm.coro.size.i32()
+  %alloc = call ptr @malloc(i32 %size)
+  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
+
+  %inc1 = add i32 %n, 1
+  %sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
+  switch i8 %sp1, label %suspend [i8 0, label %resume1
+                                  i8 1, label %cleanup]
+resume1:
+  %inc2 = add i32 %inc1, 1
+  %sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
+  switch i8 %sp1, label %suspend [i8 0, label %resume2
+                                  i8 1, label %cleanup]
+
+resume2:
+  call void @print(i32 %inc1)
+  call void @print(i32 %inc2)
+  br label %cleanup
+
+cleanup:
+  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
+  call void @free(ptr %mem)
+  br label %suspend
+suspend:
+  call i1 @llvm.coro.end(ptr %hdl, i1 0)
+  ret ptr %hdl
+}
+
 define ptr @f_multiple_remat(i32 %n) presplitcoroutine {
 entry:
   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)

diff  --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
index f399429d9cd16..d7978c98153e6 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
@@ -2,6 +2,9 @@
 ; sink them to the places after the suspend block.
 ; RUN: opt -opaque-pointers=0 < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
 
+; CHECK: %a.Frame = type { void (%a.Frame*)*, void (%a.Frame*)*, %"struct.lean_future<int>::Awaiter", i1 }
+; CHECK: %a_optnone.Frame = type { void (%a_optnone.Frame*)*, void (%a_optnone.Frame*)*, %"struct.lean_future<int>::Awaiter", i8*, i32*, i32, i1 }
+
 %"struct.std::coroutine_handle" = type { i8* }
 %"struct.std::coroutine_handle.0" = type { %"struct.std::coroutine_handle" }
 %"struct.lean_future<int>::Awaiter" = type { i32, %"struct.std::coroutine_handle.0" }
@@ -53,6 +56,37 @@ exit:
 ; CHECK-NEXT:    call void @print(i32 %val)
 ; CHECK-NEXT:    ret void
 
+define void @a_optnone() presplitcoroutine optnone noinline {
+entry:
+  %ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
+  %testval = alloca i32
+  %cast = bitcast i32* %testval to i8*
+  ; lifetime of %testval starts here, but not used until await.ready.
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* %cast)
+  %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
+  %alloc = call i8* @malloc(i64 16) #3
+  %vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
+
+  %save = call token @llvm.coro.save(i8* null)
+  %Result.i19 = getelementptr inbounds %"struct.lean_future<int>::Awaiter", %"struct.lean_future<int>::Awaiter"* %ref.tmp7, i64 0, i32 0
+  %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
+  switch i8 %suspend, label %exit [
+    i8 0, label %await.ready
+    i8 1, label %exit
+  ]
+await.ready:
+  %StrayCoroSave = call token @llvm.coro.save(i8* null)
+  %val = load i32, i32* %Result.i19
+  %test = load i32, i32* %testval
+  call void @print(i32 %test)
+  call void @llvm.lifetime.end.p0i8(i64 4, i8*  %cast)
+  call void @print(i32 %val)
+  br label %exit
+exit:
+  call i1 @llvm.coro.end(i8* null, i1 false)
+  ret void
+}
+
 declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*)
 declare i1 @llvm.coro.alloc(token) #3
 declare noalias nonnull i8* @"\01??2 at YAPEAX_K@Z"(i64) local_unnamed_addr


        


More information about the llvm-commits mailing list