mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	This reverts commit r220811 and r220839. It made an incorrect change to musttail handling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221226 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			183 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
; 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
 | 
						|
}
 |