| ; RUN: opt -instcombine -S < %s | FileCheck %s | 
 |  | 
 | declare void @llvm.init.trampoline(i8*, i8*, i8*) | 
 | declare i8* @llvm.adjust.trampoline(i8*) | 
 | declare i32 @f(i8 * nest, i32) | 
 |  | 
 | ; Most common case | 
 | define i32 @test0(i32 %n) { | 
 |   %alloca = alloca [10 x i8], align 16 | 
 |   %gep = getelementptr [10 x i8]* %alloca, i32 0, i32 0 | 
 |   call void @llvm.init.trampoline(i8* %gep, i8* bitcast (i32 (i8*, i32)* @f to i8*), | 
 |                                   i8* null) | 
 |   %tramp = call i8* @llvm.adjust.trampoline(i8* %gep) | 
 |   %function = bitcast i8* %tramp to i32(i32)* | 
 |   %ret = call i32 %function(i32 %n) | 
 |   ret i32 %ret | 
 |  | 
 | ; CHECK: define i32 @test0(i32 %n) { | 
 | ; CHECK: %ret = call i32 @f(i8* nest null, i32 %n) | 
 | } | 
 |  | 
 | define i32 @test1(i32 %n, i8* %trampmem) { | 
 |   call void @llvm.init.trampoline(i8* %trampmem, | 
 |                                   i8* bitcast (i32 (i8*, i32)* @f to i8*), | 
 |                                   i8* null) | 
 |   %tramp = call i8* @llvm.adjust.trampoline(i8* %trampmem) | 
 |   %function = bitcast i8* %tramp to i32(i32)* | 
 |   %ret = call i32 %function(i32 %n) | 
 |   ret i32 %ret | 
 | ; CHECK: define i32 @test1(i32 %n, i8* %trampmem) { | 
 | ; CHECK: %ret = call i32 @f(i8* nest null, i32 %n) | 
 | } | 
 |  | 
 | define i32 @test2(i32 %n, i8* %trampmem) { | 
 |   %tramp = call i8* @llvm.adjust.trampoline(i8* %trampmem) | 
 |   %functiona = bitcast i8* %tramp to i32(i32)* | 
 |   %ret = call i32 %functiona(i32 %n) | 
 |   ret i32 %ret | 
 | ; CHECK: define i32 @test2(i32 %n, i8* %trampmem) { | 
 | ; CHECK: %ret = call i32 %functiona(i32 %n) | 
 | } | 
 |  | 
 | define i32 @test3(i32 %n, i8* %trampmem) { | 
 |   call void @llvm.init.trampoline(i8* %trampmem, | 
 |                                   i8* bitcast (i32 (i8*, i32)* @f to i8*), | 
 |                                   i8* null) | 
 |  | 
 | ; CHECK: define i32 @test3(i32 %n, i8* %trampmem) { | 
 | ; CHECK: %ret0 = call i32 @f(i8* nest null, i32 %n) | 
 |   %tramp0 = call i8* @llvm.adjust.trampoline(i8* %trampmem) | 
 |   %function0 = bitcast i8* %tramp0 to i32(i32)* | 
 |   %ret0 = call i32 %function0(i32 %n) | 
 |  | 
 |   ;; Not optimized since previous call could be writing. | 
 |   %tramp1 = call i8* @llvm.adjust.trampoline(i8* %trampmem) | 
 |   %function1 = bitcast i8* %tramp1 to i32(i32)* | 
 |   %ret1 = call i32 %function1(i32 %n) | 
 | ; CHECK: %ret1 = call i32 %function1(i32 %n) | 
 |  | 
 |   ret i32 %ret1 | 
 | } | 
 |  | 
 | define i32 @test4(i32 %n) { | 
 |   %alloca = alloca [10 x i8], align 16 | 
 |   %gep = getelementptr [10 x i8]* %alloca, i32 0, i32 0 | 
 |   call void @llvm.init.trampoline(i8* %gep, i8* bitcast (i32 (i8*, i32)* @f to i8*), | 
 |                                   i8* null) | 
 |  | 
 |   %tramp0 = call i8* @llvm.adjust.trampoline(i8* %gep) | 
 |   %function0 = bitcast i8* %tramp0 to i32(i32)* | 
 |   %ret0 = call i32 %function0(i32 %n) | 
 |  | 
 |   %tramp1 = call i8* @llvm.adjust.trampoline(i8* %gep) | 
 |   %function1 = bitcast i8* %tramp0 to i32(i32)* | 
 |   %ret1 = call i32 %function1(i32 %n) | 
 |  | 
 |   %tramp2 = call i8* @llvm.adjust.trampoline(i8* %gep) | 
 |   %function2 = bitcast i8* %tramp2 to i32(i32)* | 
 |   %ret2 = call i32 %function2(i32 %n) | 
 |  | 
 |   ret i32 %ret2 | 
 |  | 
 | ; CHECK: define i32 @test4(i32 %n) { | 
 | ; CHECK: %ret0 = call i32 @f(i8* nest null, i32 %n) | 
 | ; CHECK: %ret1 = call i32 @f(i8* nest null, i32 %n) | 
 | ; CHECK: %ret2 = call i32 @f(i8* nest null, i32 %n) | 
 | } |