1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs 2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,coro-cleanup' -S | FileCheck %s 3target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-apple-macosx10.12.0" 5 6define {ptr, ptr} @f(ptr %buffer, ptr %ptr) presplitcoroutine { 7entry: 8 %temp = alloca i32, align 4 9 %id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype, ptr @allocate, ptr @deallocate) 10 %hdl = call ptr @llvm.coro.begin(token %id, ptr null) 11 %oldvalue = load i32, ptr %ptr 12 store i32 %oldvalue, ptr %temp 13 %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp) 14 br i1 %unwind, label %cleanup, label %cont 15 16cont: 17 %newvalue = load i32, ptr %temp 18 store i32 %newvalue, ptr %ptr 19 br label %cleanup 20 21cleanup: 22 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 23 unreachable 24} 25 26 27define {ptr, ptr} @g(ptr %buffer, ptr %ptr, i8 %val) presplitcoroutine { 28entry: 29 %temp = alloca i32, align 4 30 %id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype2, ptr @allocate, ptr @deallocate) 31 %hdl = call ptr @llvm.coro.begin(token %id, ptr null) 32 %oldvalue = load i32, ptr %ptr 33 store i32 %oldvalue, ptr %temp 34 %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp) 35 br i1 %unwind, label %cleanup, label %cont 36 37cont: 38 %newvalue = load i32, ptr %temp 39 store i32 %newvalue, ptr %ptr 40 br label %cleanup 41 42cleanup: 43 %tok = call token (...) @llvm.coro.end.results(i8 %val) 44 call i1 @llvm.coro.end(ptr %hdl, i1 0, token %tok) 45 unreachable 46} 47 48 49define {ptr, ptr} @h(ptr %buffer, ptr %ptr) presplitcoroutine { 50entry: 51 %temp = alloca i32, align 4 52 %id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype3, ptr @allocate, ptr @deallocate) 53 %hdl = call ptr @llvm.coro.begin(token %id, ptr null) 54 %oldvalue = load i32, ptr %ptr 55 store i32 %oldvalue, ptr %temp 56 %unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp) 57 br i1 %unwind, label %cleanup, label %cont 58 59cont: 60 %newvalue = load i32, ptr %temp 61 store i32 %newvalue, ptr %ptr 62 br label %cleanup 63 64cleanup: 65 %tok = call token (...) @llvm.coro.end.results(ptr null, i32 123, ptr @deallocate) 66 call i1 @llvm.coro.end(ptr %hdl, i1 0, token %tok) 67 unreachable 68} 69 70 71declare token @llvm.coro.id.retcon.once(i32, i32, ptr, ptr, ptr, ptr) 72declare ptr @llvm.coro.begin(token, ptr) 73declare i1 @llvm.coro.suspend.retcon.i1(...) 74declare i1 @llvm.coro.end(ptr, i1, token) 75declare token @llvm.coro.end.results(...) 76 77declare void @prototype(ptr, i1 zeroext) 78declare i8 @prototype2(ptr, i1 zeroext) 79declare {ptr, i32, ptr} @prototype3(ptr, i1 zeroext) 80 81declare noalias ptr @allocate(i32 %size) 82declare fastcc void @deallocate(ptr %ptr) 83 84declare void @print(i32) 85; CHECK-LABEL: @f( 86; CHECK-NEXT: entry: 87; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16) 88; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8 89; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1 90; CHECK-NEXT: store ptr [[PTR:%.*]], ptr [[TMP0]], align 8 91; CHECK-NEXT: [[OLDVALUE:%.*]] = load i32, ptr [[PTR]], align 4 92; CHECK-NEXT: store i32 [[OLDVALUE]], ptr [[TEMP]], align 4 93; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, ptr } { ptr @f.resume.0, ptr poison }, ptr [[TEMP]], 1 94; CHECK-NEXT: ret { ptr, ptr } [[TMP1]] 95; 96; 97; CHECK-LABEL: @f.resume.0( 98; CHECK-NEXT: entryresume.0: 99; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8 100; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1 101; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[COROEND:%.*]], label [[CONT:%.*]] 102; CHECK: cont: 103; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[TMP2]], align 8 104; CHECK-NEXT: [[NEWVALUE:%.*]] = load i32, ptr [[TEMP]], align 4 105; CHECK-NEXT: store i32 [[NEWVALUE]], ptr [[PTR_RELOAD]], align 4 106; CHECK-NEXT: br label [[COROEND]] 107; CHECK: CoroEnd: 108; CHECK-NEXT: call fastcc void @deallocate(ptr [[TMP2]]) 109; CHECK-NEXT: ret void 110; 111; 112; CHECK-LABEL: @g( 113; CHECK-NEXT: entry: 114; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16) 115; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8 116; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1 117; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[TMP0]], i32 0, i32 2 118; CHECK-NEXT: store i8 [[VAL:%.*]], ptr [[VAL_SPILL_ADDR]], align 1 119; CHECK-NEXT: store ptr [[PTR:%.*]], ptr [[TMP0]], align 8 120; CHECK-NEXT: [[OLDVALUE:%.*]] = load i32, ptr [[PTR]], align 4 121; CHECK-NEXT: store i32 [[OLDVALUE]], ptr [[TEMP]], align 4 122; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, ptr } { ptr @g.resume.0, ptr poison }, ptr [[TEMP]], 1 123; CHECK-NEXT: ret { ptr, ptr } [[TMP1]] 124; 125; 126; CHECK-LABEL: @g.resume.0( 127; CHECK-NEXT: entryresume.0: 128; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8 129; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1 130; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[CLEANUP:%.*]], label [[CONT:%.*]] 131; CHECK: cont: 132; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[TMP2]], align 8 133; CHECK-NEXT: [[NEWVALUE:%.*]] = load i32, ptr [[TEMP]], align 4 134; CHECK-NEXT: store i32 [[NEWVALUE]], ptr [[PTR_RELOAD]], align 4 135; CHECK-NEXT: br label [[CLEANUP]] 136; CHECK: cleanup: 137; CHECK-NEXT: [[VAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[TMP2]], i32 0, i32 2 138; CHECK-NEXT: [[VAL_RELOAD:%.*]] = load i8, ptr [[VAL_RELOAD_ADDR]], align 1 139; CHECK-NEXT: call fastcc void @deallocate(ptr [[TMP2]]) 140; CHECK-NEXT: ret i8 [[VAL_RELOAD]] 141; 142; 143; CHECK-LABEL: @h( 144; CHECK-NEXT: entry: 145; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16) 146; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8 147; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[H_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1 148; CHECK-NEXT: store ptr [[PTR:%.*]], ptr [[TMP0]], align 8 149; CHECK-NEXT: [[OLDVALUE:%.*]] = load i32, ptr [[PTR]], align 4 150; CHECK-NEXT: store i32 [[OLDVALUE]], ptr [[TEMP]], align 4 151; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, ptr } { ptr @h.resume.0, ptr poison }, ptr [[TEMP]], 1 152; CHECK-NEXT: ret { ptr, ptr } [[TMP1]] 153; 154; 155; CHECK-LABEL: @h.resume.0( 156; CHECK-NEXT: entryresume.0: 157; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8 158; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[H_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1 159; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[COROEND:%.*]], label [[CONT:%.*]] 160; CHECK: cont: 161; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[TMP2]], align 8 162; CHECK-NEXT: [[NEWVALUE:%.*]] = load i32, ptr [[TEMP]], align 4 163; CHECK-NEXT: store i32 [[NEWVALUE]], ptr [[PTR_RELOAD]], align 4 164; CHECK-NEXT: br label [[COROEND]] 165; CHECK: CoroEnd: 166; CHECK-NEXT: call fastcc void @deallocate(ptr [[TMP2]]) 167; CHECK-NEXT: ret { ptr, i32, ptr } { ptr null, i32 123, ptr @deallocate } 168; 169