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