1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature 2; RUN: opt < %s -passes=globalopt -S | FileCheck %s 3 4declare token @llvm.call.preallocated.setup(i32) 5declare ptr @llvm.call.preallocated.arg(token, i32) 6declare i32 @__CxxFrameHandler3(...) 7 8; Don't touch functions with any musttail calls 9define internal i32 @preallocated_musttail(ptr preallocated(i32) %p) { 10; CHECK-LABEL: define {{[^@]+}}@preallocated_musttail 11; CHECK-SAME: (ptr preallocated(i32) [[P:%.*]]) unnamed_addr { 12; CHECK-NEXT: [[RV:%.*]] = load i32, ptr [[P]], align 4 13; CHECK-NEXT: ret i32 [[RV]] 14; 15 %rv = load i32, ptr %p 16 ret i32 %rv 17} 18 19define i32 @call_preallocated_musttail(ptr preallocated(i32) %a) { 20; CHECK-LABEL: define {{[^@]+}}@call_preallocated_musttail 21; CHECK-SAME: (ptr preallocated(i32) [[A:%.*]]) local_unnamed_addr { 22; CHECK-NEXT: [[R:%.*]] = musttail call i32 @preallocated_musttail(ptr preallocated(i32) [[A]]) 23; CHECK-NEXT: ret i32 [[R]] 24; 25 %r = musttail call i32 @preallocated_musttail(ptr preallocated(i32) %a) 26 ret i32 %r 27} 28 29define i32 @call_preallocated_musttail_without_musttail() { 30; CHECK-LABEL: define {{[^@]+}}@call_preallocated_musttail_without_musttail() local_unnamed_addr { 31; CHECK-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1) 32; CHECK-NEXT: [[N:%.*]] = call ptr @llvm.call.preallocated.arg(token [[C]], i32 0) #[[ATTR1:[0-9]+]] 33; CHECK-NEXT: [[R:%.*]] = call i32 @preallocated_musttail(ptr preallocated(i32) [[N]]) [ "preallocated"(token [[C]]) ] 34; CHECK-NEXT: ret i32 [[R]] 35; 36 %c = call token @llvm.call.preallocated.setup(i32 1) 37 %N = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32) 38 %r = call i32 @preallocated_musttail(ptr preallocated(i32) %N) ["preallocated"(token %c)] 39 ret i32 %r 40} 41 42; Check that only one alloca per preallocated arg 43define internal i32 @preallocated(ptr preallocated(i32) %a) { 44; CHECK-LABEL: define {{[^@]+}}@preallocated 45; CHECK-SAME: (ptr [[A:%.*]]) unnamed_addr { 46; CHECK-NEXT: [[RV:%.*]] = load i32, ptr [[A]], align 4 47; CHECK-NEXT: ret i32 [[RV]] 48; 49 %rv = load i32, ptr %a 50 ret i32 %rv 51} 52 53declare void @foo(ptr) 54 55define i32 @call_preallocated_multiple_args() { 56; CHECK-LABEL: define {{[^@]+}}@call_preallocated_multiple_args() local_unnamed_addr { 57; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.stacksave.p0() 58; CHECK-NEXT: [[PAARG:%.*]] = alloca i32, align 4 59; CHECK-NEXT: call void @foo(ptr [[PAARG]]) 60; CHECK-NEXT: call void @foo(ptr [[PAARG]]) 61; CHECK-NEXT: call void @foo(ptr [[PAARG]]) 62; CHECK-NEXT: [[R:%.*]] = call fastcc i32 @preallocated(ptr [[PAARG]]) 63; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP1]]) 64; CHECK-NEXT: ret i32 [[R]] 65; 66 %c = call token @llvm.call.preallocated.setup(i32 1) 67 %a1 = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32) 68 call void @foo(ptr %a1) 69 %a2 = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32) 70 call void @foo(ptr %a2) 71 %a3 = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32) 72 call void @foo(ptr %a3) 73 %r = call i32 @preallocated(ptr preallocated(i32) %a3) ["preallocated"(token %c)] 74 ret i32 %r 75} 76 77; Don't touch functions with any invokes 78define internal i32 @preallocated_invoke(ptr preallocated(i32) %p) { 79; CHECK-LABEL: define {{[^@]+}}@preallocated_invoke 80; CHECK-SAME: (ptr preallocated(i32) [[P:%.*]]) unnamed_addr { 81; CHECK-NEXT: [[RV:%.*]] = load i32, ptr [[P]], align 4 82; CHECK-NEXT: ret i32 [[RV]] 83; 84 %rv = load i32, ptr %p 85 ret i32 %rv 86} 87 88define i32 @call_preallocated_invoke() personality ptr @__CxxFrameHandler3 { 89; CHECK-LABEL: define {{[^@]+}}@call_preallocated_invoke() local_unnamed_addr personality ptr @__CxxFrameHandler3 { 90; CHECK-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1) 91; CHECK-NEXT: [[A:%.*]] = call ptr @llvm.call.preallocated.arg(token [[C]], i32 0) #[[ATTR1]] 92; CHECK-NEXT: [[R:%.*]] = invoke i32 @preallocated_invoke(ptr preallocated(i32) [[A]]) [ "preallocated"(token [[C]]) ] 93; CHECK-NEXT: to label [[CONTA:%.*]] unwind label [[CONTB:%.*]] 94; CHECK: conta: 95; CHECK-NEXT: ret i32 [[R]] 96; CHECK: contb: 97; CHECK-NEXT: [[S:%.*]] = catchswitch within none [label %catch] unwind to caller 98; CHECK: catch: 99; CHECK-NEXT: [[P:%.*]] = catchpad within [[S]] [] 100; CHECK-NEXT: catchret from [[P]] to label [[CONT:%.*]] 101; CHECK: cont: 102; CHECK-NEXT: ret i32 42 103; 104 %c = call token @llvm.call.preallocated.setup(i32 1) 105 %a = call ptr @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32) 106 %r = invoke i32 @preallocated_invoke(ptr preallocated(i32) %a) ["preallocated"(token %c)] 107 to label %conta unwind label %contb 108conta: 109 ret i32 %r 110contb: 111 %s = catchswitch within none [label %catch] unwind to caller 112catch: 113 %p = catchpad within %s [] 114 catchret from %p to label %cont 115cont: 116 ret i32 42 117} 118