xref: /llvm-project/llvm/test/Transforms/InstCombine/2011-09-03-Trampoline.ll (revision 32a4566fbb43f7195fd51fbe453b980897cec3fc)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare void @llvm.init.trampoline(ptr, ptr, ptr)
5declare ptr @llvm.adjust.trampoline(ptr)
6declare i32 @f(ptr nest, i32)
7
8; Most common case
9define i32 @test0(i32 %n) !dbg !4 {
10; CHECK-LABEL: define i32 @test0
11; CHECK-SAME: (i32 [[N:%.*]]) !dbg [[DBG4:![0-9]+]] {
12; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [10 x i8], align 16
13; CHECK-NEXT:    call void @llvm.init.trampoline(ptr nonnull [[ALLOCA]], ptr nonnull @f, ptr null)
14; CHECK-NEXT:    [[RET:%.*]] = call i32 @f(ptr nest null, i32 [[N]]), !dbg [[DBG10:![0-9]+]]
15; CHECK-NEXT:    ret i32 [[RET]]
16;
17  %alloca = alloca [10 x i8], align 16
18  call void @llvm.init.trampoline(ptr %alloca, ptr @f,
19  ptr null)
20  %tramp = call ptr @llvm.adjust.trampoline(ptr %alloca)
21  %ret = call i32 %tramp(i32 %n), !dbg !10
22  ret i32 %ret
23
24}
25
26define i32 @test1(i32 %n, ptr %trampmem) {
27; CHECK-LABEL: define i32 @test1
28; CHECK-SAME: (i32 [[N:%.*]], ptr [[TRAMPMEM:%.*]]) {
29; CHECK-NEXT:    call void @llvm.init.trampoline(ptr [[TRAMPMEM]], ptr nonnull @f, ptr null)
30; CHECK-NEXT:    [[RET:%.*]] = call i32 @f(ptr nest null, i32 [[N]])
31; CHECK-NEXT:    ret i32 [[RET]]
32;
33  call void @llvm.init.trampoline(ptr %trampmem,
34  ptr @f,
35  ptr null)
36  %tramp = call ptr @llvm.adjust.trampoline(ptr %trampmem)
37  %ret = call i32 %tramp(i32 %n)
38  ret i32 %ret
39}
40
41define i32 @test2(i32 %n, ptr %trampmem) {
42; CHECK-LABEL: define i32 @test2
43; CHECK-SAME: (i32 [[N:%.*]], ptr [[TRAMPMEM:%.*]]) {
44; CHECK-NEXT:    [[TRAMP:%.*]] = call ptr @llvm.adjust.trampoline(ptr [[TRAMPMEM]])
45; CHECK-NEXT:    [[RET:%.*]] = call i32 [[TRAMP]](i32 [[N]])
46; CHECK-NEXT:    ret i32 [[RET]]
47;
48  %tramp = call ptr @llvm.adjust.trampoline(ptr %trampmem)
49  %ret = call i32 %tramp(i32 %n)
50  ret i32 %ret
51}
52
53define i32 @test3(i32 %n, ptr %trampmem) {
54; CHECK-LABEL: define i32 @test3
55; CHECK-SAME: (i32 [[N:%.*]], ptr [[TRAMPMEM:%.*]]) {
56; CHECK-NEXT:    call void @llvm.init.trampoline(ptr [[TRAMPMEM]], ptr nonnull @f, ptr null)
57; CHECK-NEXT:    [[RET0:%.*]] = call i32 @f(ptr nest null, i32 [[N]])
58; CHECK-NEXT:    [[TRAMP1:%.*]] = call ptr @llvm.adjust.trampoline(ptr [[TRAMPMEM]])
59; CHECK-NEXT:    [[RET1:%.*]] = call i32 [[TRAMP1]](i32 [[N]])
60; CHECK-NEXT:    ret i32 [[RET1]]
61;
62  call void @llvm.init.trampoline(ptr %trampmem,
63  ptr @f,
64  ptr null)
65
66  %tramp0 = call ptr @llvm.adjust.trampoline(ptr %trampmem)
67  %ret0 = call i32 %tramp0(i32 %n)
68
69  ;; Not optimized since previous call could be writing.
70  %tramp1 = call ptr @llvm.adjust.trampoline(ptr %trampmem)
71  %ret1 = call i32 %tramp1(i32 %n)
72
73  ret i32 %ret1
74}
75
76define i32 @test4(i32 %n) {
77; CHECK-LABEL: define i32 @test4
78; CHECK-SAME: (i32 [[N:%.*]]) {
79; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [10 x i8], align 16
80; CHECK-NEXT:    call void @llvm.init.trampoline(ptr nonnull [[ALLOCA]], ptr nonnull @f, ptr null)
81; CHECK-NEXT:    [[RET0:%.*]] = call i32 @f(ptr nest null, i32 [[N]])
82; CHECK-NEXT:    [[RET1:%.*]] = call i32 @f(ptr nest null, i32 [[N]])
83; CHECK-NEXT:    [[RET2:%.*]] = call i32 @f(ptr nest null, i32 [[N]])
84; CHECK-NEXT:    ret i32 [[RET2]]
85;
86  %alloca = alloca [10 x i8], align 16
87  call void @llvm.init.trampoline(ptr %alloca, ptr @f,
88  ptr null)
89
90  %tramp0 = call ptr @llvm.adjust.trampoline(ptr %alloca)
91  %ret0 = call i32 %tramp0(i32 %n)
92
93  %tramp1 = call ptr @llvm.adjust.trampoline(ptr %alloca)
94  %ret1 = call i32 %tramp0(i32 %n)
95
96  %tramp2 = call ptr @llvm.adjust.trampoline(ptr %alloca)
97  %ret2 = call i32 %tramp2(i32 %n)
98
99  ret i32 %ret2
100
101}
102
103!llvm.dbg.cu = !{!0}
104!llvm.module.flags = !{!3}
105
106!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0 (trunk 127710)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2)
107!1 = !DIFile(filename: "string.h", directory: "Game")
108!2 = !{}
109!3 = !{i32 1, !"Debug Info Version", i32 3}
110!4 = distinct !DISubprogram(name: "passthru", scope: !1, file: !1, line: 79, type: !5, isLocal: true, isDefinition: true, scopeLine: 79, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !8)
111!5 = !DISubroutineType(types: !6)
112!6 = !{!7}
113!7 = !DIDerivedType(tag: DW_TAG_pointer_type, scope: !0, baseType: null, size: 64, align: 64)
114!8 = !{!9}
115!9 = !DILocalVariable(name: "a", arg: 1, scope: !4, file: !1, line: 78, type: !7)
116!10 = !DILocation(line: 78, column: 28, scope: !4)
117