1; RUN: opt < %s -inline -S | FileCheck %s 2; RUN: opt < %s -passes='cgscc(inline,function(instcombine))' -S | FileCheck %s 3 4declare void @ext_method(i8*, i32) 5declare signext i16 @vararg_fn(...) #0 6declare "cc 9" void @vararg_fn_cc9(i8* %p, ...) 7 8define linkonce_odr void @thunk(i8* %this, ...) { 9 %this_adj = getelementptr i8, i8* %this, i32 4 10 musttail call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* nonnull %this_adj, ...) 11 ret void 12} 13 14define void @thunk_caller(i8* %p) { 15 call void (i8*, ...) @thunk(i8* %p, i32 42) 16 ret void 17} 18; CHECK-LABEL: define void @thunk_caller(i8* %p) 19; CHECK: call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* nonnull %this_adj.i, i32 42) 20 21define signext i16 @test_callee_2(...) { 22 %res = musttail call signext i16 (...) @vararg_fn(...) #0 23 ret i16 %res 24} 25 26define void @test_caller_2(i8* %p, i8* %q, i16 %r) { 27 call signext i16 (...) @test_callee_2(i8* %p, i8* byval(i8) %q, i16 signext %r) 28 ret void 29} 30; CHECK-LABEL: define void @test_caller_2 31; CHECK: call signext i16 (...) @vararg_fn(i8* %p, i8* byval(i8) %q, i16 signext %r) [[FN_ATTRS:#[0-9]+]] 32 33define void @test_callee_3(i8* %p, ...) { 34 call signext i16 (...) @vararg_fn() 35 ret void 36} 37 38define void @test_caller_3(i8* %p, i8* %q) { 39 call void (i8*, ...) @test_callee_3(i8* nonnull %p, i8* %q) 40 ret void 41} 42; CHECK-LABEL: define void @test_caller_3 43; CHECK: call signext i16 (...) @vararg_fn() 44 45define void @test_preserve_cc(i8* %p, ...) { 46 musttail call "cc 9" void (i8*, ...) @vararg_fn_cc9(i8* %p, ...) 47 ret void 48} 49 50define void @test_caller_preserve_cc(i8* %p, i8* %q) { 51 call void (i8*, ...) @test_preserve_cc(i8* %p, i8* %q) 52 ret void 53} 54; CHECK-LABEL: define void @test_caller_preserve_cc 55; CHECK: call "cc 9" void (i8*, ...) @vararg_fn_cc9(i8* %p, i8* %q) 56 57define internal i32 @varg_accessed(...) { 58entry: 59 %vargs = alloca i8*, align 8 60 %vargs.ptr = bitcast i8** %vargs to i8* 61 call void @llvm.va_start(i8* %vargs.ptr) 62 %va1 = va_arg i8** %vargs, i32 63 call void @llvm.va_end(i8* %vargs.ptr) 64 ret i32 %va1 65} 66 67define internal i32 @varg_accessed_alwaysinline(...) alwaysinline { 68entry: 69 %vargs = alloca i8*, align 8 70 %vargs.ptr = bitcast i8** %vargs to i8* 71 call void @llvm.va_start(i8* %vargs.ptr) 72 %va1 = va_arg i8** %vargs, i32 73 call void @llvm.va_end(i8* %vargs.ptr) 74 ret i32 %va1 75} 76 77define i32 @call_vargs() { 78 %res1 = call i32 (...) @varg_accessed(i32 10) 79 %res2 = call i32 (...) @varg_accessed_alwaysinline(i32 15) 80 %res = add i32 %res1, %res2 81 ret i32 %res 82} 83; CHECK-LABEL: @call_vargs 84; CHECK: %res1 = call i32 (...) @varg_accessed(i32 10) 85; CHECK-NEXT: %res2 = call i32 (...) @varg_accessed_alwaysinline(i32 15) 86 87define void @caller_with_vastart(i8* noalias nocapture readnone %args, ...) { 88entry: 89 %ap = alloca i8*, align 4 90 %ap.ptr = bitcast i8** %ap to i8* 91 %ap2 = alloca i8*, align 4 92 %ap2.ptr = bitcast i8** %ap to i8* 93 call void @llvm.va_start(i8* nonnull %ap.ptr) 94 call fastcc void @callee_with_vaend(i8* nonnull %ap.ptr) 95 call void @llvm.va_start(i8* nonnull %ap2.ptr) 96 call fastcc void @callee_with_vaend_alwaysinline(i8* nonnull %ap2.ptr) 97 ret void 98} 99 100define internal fastcc void @callee_with_vaend_alwaysinline(i8* %a) alwaysinline { 101entry: 102 tail call void @llvm.va_end(i8* %a) 103 ret void 104} 105 106define internal fastcc void @callee_with_vaend(i8* %a) { 107entry: 108 tail call void @llvm.va_end(i8* %a) 109 ret void 110} 111 112; CHECK-LABEL: @caller_with_vastart 113; CHECK-NOT: @callee_with_vaend 114; CHECK-NOT: @callee_with_vaend_alwaysinline 115 116declare void @llvm.va_start(i8*) 117declare void @llvm.va_end(i8*) 118 119; CHECK: attributes [[FN_ATTRS]] = { "foo"="bar" } 120attributes #0 = { "foo"="bar" } 121