| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- ; RUN: opt < %s -inline -S | FileCheck %s
- ; We have to apply the less restrictive TailCallKind of the call site being
- ; inlined and any call sites cloned into the caller.
- ; No tail marker after inlining, since test_capture_c captures an alloca.
- ; CHECK: define void @test_capture_a(
- ; CHECK-NOT: tail
- ; CHECK: call void @test_capture_c(
- declare void @test_capture_c(i32*)
- define internal void @test_capture_b(i32* %P) {
- tail call void @test_capture_c(i32* %P)
- ret void
- }
- define void @test_capture_a() {
- %A = alloca i32 ; captured by test_capture_b
- call void @test_capture_b(i32* %A)
- ret void
- }
- ; No musttail marker after inlining, since the prototypes don't match.
- ; CHECK: define void @test_proto_mismatch_a(
- ; CHECK-NOT: musttail
- ; CHECK: call void @test_proto_mismatch_c(
- declare void @test_proto_mismatch_c(i32*)
- define internal void @test_proto_mismatch_b(i32* %p) {
- musttail call void @test_proto_mismatch_c(i32* %p)
- ret void
- }
- define void @test_proto_mismatch_a() {
- call void @test_proto_mismatch_b(i32* null)
- ret void
- }
- ; After inlining through a musttail call site, we need to keep musttail markers
- ; to prevent unbounded stack growth.
- ; CHECK: define void @test_musttail_basic_a(
- ; CHECK: musttail call void @test_musttail_basic_c(
- declare void @test_musttail_basic_c(i32* %p)
- define internal void @test_musttail_basic_b(i32* %p) {
- musttail call void @test_musttail_basic_c(i32* %p)
- ret void
- }
- define void @test_musttail_basic_a(i32* %p) {
- musttail call void @test_musttail_basic_b(i32* %p)
- ret void
- }
- ; Don't insert lifetime end markers here, the lifetime is trivially over due
- ; the return.
- ; CHECK: define void @test_byval_a(
- ; CHECK: musttail call void @test_byval_c(
- ; CHECK-NEXT: ret void
- declare void @test_byval_c(i32* byval %p)
- define internal void @test_byval_b(i32* byval %p) {
- musttail call void @test_byval_c(i32* byval %p)
- ret void
- }
- define void @test_byval_a(i32* byval %p) {
- musttail call void @test_byval_b(i32* byval %p)
- ret void
- }
- ; Don't insert a stack restore, we're about to return.
- ; CHECK: define void @test_dynalloca_a(
- ; CHECK: call i8* @llvm.stacksave(
- ; CHECK: alloca i8, i32 %n
- ; CHECK: musttail call void @test_dynalloca_c(
- ; CHECK-NEXT: ret void
- declare void @escape(i8* %buf)
- declare void @test_dynalloca_c(i32* byval %p, i32 %n)
- define internal void @test_dynalloca_b(i32* byval %p, i32 %n) alwaysinline {
- %buf = alloca i8, i32 %n ; dynamic alloca
- call void @escape(i8* %buf) ; escape it
- musttail call void @test_dynalloca_c(i32* byval %p, i32 %n)
- ret void
- }
- define void @test_dynalloca_a(i32* byval %p, i32 %n) {
- musttail call void @test_dynalloca_b(i32* byval %p, i32 %n)
- ret void
- }
- ; We can't merge the returns.
- ; CHECK: define void @test_multiret_a(
- ; CHECK: musttail call void @test_multiret_c(
- ; CHECK-NEXT: ret void
- ; CHECK: musttail call void @test_multiret_d(
- ; CHECK-NEXT: ret void
- declare void @test_multiret_c(i1 zeroext %b)
- declare void @test_multiret_d(i1 zeroext %b)
- define internal void @test_multiret_b(i1 zeroext %b) {
- br i1 %b, label %c, label %d
- c:
- musttail call void @test_multiret_c(i1 zeroext %b)
- ret void
- d:
- musttail call void @test_multiret_d(i1 zeroext %b)
- ret void
- }
- define void @test_multiret_a(i1 zeroext %b) {
- musttail call void @test_multiret_b(i1 zeroext %b)
- ret void
- }
- ; We have to avoid bitcast chains.
- ; CHECK: define i32* @test_retptr_a(
- ; CHECK: musttail call i8* @test_retptr_c(
- ; CHECK-NEXT: bitcast i8* {{.*}} to i32*
- ; CHECK-NEXT: ret i32*
- declare i8* @test_retptr_c()
- define internal i16* @test_retptr_b() {
- %rv = musttail call i8* @test_retptr_c()
- %v = bitcast i8* %rv to i16*
- ret i16* %v
- }
- define i32* @test_retptr_a() {
- %rv = musttail call i16* @test_retptr_b()
- %v = bitcast i16* %rv to i32*
- ret i32* %v
- }
- ; Combine the last two cases: multiple returns with pointer bitcasts.
- ; CHECK: define i32* @test_multiptrret_a(
- ; CHECK: musttail call i8* @test_multiptrret_c(
- ; CHECK-NEXT: bitcast i8* {{.*}} to i32*
- ; CHECK-NEXT: ret i32*
- ; CHECK: musttail call i8* @test_multiptrret_d(
- ; CHECK-NEXT: bitcast i8* {{.*}} to i32*
- ; CHECK-NEXT: ret i32*
- declare i8* @test_multiptrret_c(i1 zeroext %b)
- declare i8* @test_multiptrret_d(i1 zeroext %b)
- define internal i16* @test_multiptrret_b(i1 zeroext %b) {
- br i1 %b, label %c, label %d
- c:
- %c_rv = musttail call i8* @test_multiptrret_c(i1 zeroext %b)
- %c_v = bitcast i8* %c_rv to i16*
- ret i16* %c_v
- d:
- %d_rv = musttail call i8* @test_multiptrret_d(i1 zeroext %b)
- %d_v = bitcast i8* %d_rv to i16*
- ret i16* %d_v
- }
- define i32* @test_multiptrret_a(i1 zeroext %b) {
- %rv = musttail call i16* @test_multiptrret_b(i1 zeroext %b)
- %v = bitcast i16* %rv to i32*
- ret i32* %v
- }
- ; Inline a musttail call site which contains a normal return and a musttail call.
- ; CHECK: define i32 @test_mixedret_a(
- ; CHECK: br i1 %b
- ; CHECK: musttail call i32 @test_mixedret_c(
- ; CHECK-NEXT: ret i32
- ; CHECK: call i32 @test_mixedret_d(i1 zeroext %b)
- ; CHECK: add i32 1,
- ; CHECK-NOT: br
- ; CHECK: ret i32
- declare i32 @test_mixedret_c(i1 zeroext %b)
- declare i32 @test_mixedret_d(i1 zeroext %b)
- define internal i32 @test_mixedret_b(i1 zeroext %b) {
- br i1 %b, label %c, label %d
- c:
- %c_rv = musttail call i32 @test_mixedret_c(i1 zeroext %b)
- ret i32 %c_rv
- d:
- %d_rv = call i32 @test_mixedret_d(i1 zeroext %b)
- %d_rv1 = add i32 1, %d_rv
- ret i32 %d_rv1
- }
- define i32 @test_mixedret_a(i1 zeroext %b) {
- %rv = musttail call i32 @test_mixedret_b(i1 zeroext %b)
- ret i32 %rv
- }
|