/// 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.
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
; 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 different 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(
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)
; 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" }
; 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@YAPEAX_K@Z"(i64) local_unnamed_addr