-
Notifications
You must be signed in to change notification settings - Fork 387
/
always-inline.ll
121 lines (102 loc) · 3.23 KB
/
always-inline.ll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
; RUN: opt < %s -passes=always-inline -S | FileCheck %s --check-prefix=CHECK
;------------------------------------------------------------------------------
; CASE 1: most obvious scenario for inlining
;------------------------------------------------------------------------------
define internal i32 @inner1() alwaysinline {
; CHECK-NOT: @inner1(
ret i32 1
}
define i32 @outer1() {
; CHECK-LABEL: @outer1(
; CHECK-NOT: call
; CHECK: ret
%r = call i32 @inner1()
ret i32 %r
}
;------------------------------------------------------------------------------
; CASE 2: Don't inline functions that would introduce a returns_twice call
;------------------------------------------------------------------------------
declare i32 @a() returns_twice
define internal i32 @inner2() alwaysinline {
; CHECK-LABEL: @inner2(
entry:
%call = call i32 @a() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @outer2() {
entry:
; CHECK-LABEL: @outer2(
; CHECK-NOT: call i32 @a
; CHECK: ret
%call = call i32 @inner2()
%add = add nsw i32 1, %call
ret i32 %add
}
;------------------------------------------------------------------------------
; CASE 3: Do inline functions that would introduce a returns_twice call in
; functions already have a returns_twice attribute
;------------------------------------------------------------------------------
declare i32 @b() returns_twice
define internal i32 @inner3() alwaysinline returns_twice {
; CHECK-NOT: @inner3(
entry:
%call = call i32 @b() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @outer3() {
entry:
; CHECK-LABEL: @outer3(
; CHECK: call i32 @b()
; CHECK: ret
%call = call i32 @inner3() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}
;------------------------------------------------------------------------------
; CASE 4: Recursive functions are not inlined
;------------------------------------------------------------------------------
define i32 @fibonacci(i32) {
; CHECK-LABEL: @fibonacci(
%2 = icmp slt i32 %0, 2
br i1 %2, label %9, label %3
; <label>:3: ; preds = %1
%4 = add nsw i32 %0, -1
%5 = tail call i32 @fibonacci(i32 %4)
%6 = add nsw i32 %0, -2
%7 = tail call i32 @fibonacci(i32 %6)
%8 = add nsw i32 %7, %5
ret i32 %8
; <label>:9: ; preds = %1
ret i32 %0
}
define void @outer4() {
; CHECK-LABEL: @outer4(
; CHECK: call i32 @fibonacci(i32 42)
; CHECK: ret
entry:
call i32 @fibonacci(i32 42)
ret void
}
;------------------------------------------------------------------------------
; CASE 5: `inner6` is inlined, but not deleted.
;------------------------------------------------------------------------------
; The linkage type (https://llvm.org/docs/LangRef.html#linkage-types) of
; `inner6` is not `internal`. Instead, `external` is assumed (i.e. the default),
; which indicates that this function could be used elsewhere. Hence it cannot be
; deleted.
;------------------------------------------------------------------------------
define void @inner6() alwaysinline {
; CHECK-LABEL: @inner6(
entry:
ret void
}
define void @outer6() {
; CHECK-LABEL: @outer6(
entry:
call void @inner6()
; CHECK-NOT: call void @inner6
ret void
; CHECK: ret void
}