aboutsummaryrefslogtreecommitdiffstats
path: root/test/Transforms/Inline/always-inline.ll
blob: 5ad1bde3e2d21b7ec65332ba0e4ed948eaede89a (plain)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
; RUN: opt < %s -inline-threshold=0 -always-inline -S | FileCheck %s
;
; Ensure the threshold has no impact on these decisions.
; RUN: opt < %s -inline-threshold=20000000 -always-inline -S | FileCheck %s
; RUN: opt < %s -inline-threshold=-20000000 -always-inline -S | FileCheck %s

define i32 @inner1() alwaysinline {
  ret i32 1
}
define i32 @outer1() {
; CHECK-LABEL: @outer1(
; CHECK-NOT: call
; CHECK: ret

   %r = call i32 @inner1()
   ret i32 %r
}

; The always inliner can't DCE internal functions. PR2945
; CHECK-LABEL: @pr2945(
define internal i32 @pr2945() nounwind {
  ret i32 0
}

define internal void @inner2(i32 %N) alwaysinline {
  %P = alloca i32, i32 %N
  ret void
}
define void @outer2(i32 %N) {
; The always inliner (unlike the normal one) should be willing to inline
; a function with a dynamic alloca into one without a dynamic alloca.
; rdar://6655932
;
; CHECK-LABEL: @outer2(
; CHECK-NOT: call void @inner2
; CHECK-NOT: call void @inner2
; CHECK: ret void

  call void @inner2( i32 %N )
  ret void
}

declare i32 @a() returns_twice
declare i32 @b() returns_twice

define i32 @inner3() alwaysinline {
entry:
  %call = call i32 @a() returns_twice
  %add = add nsw i32 1, %call
  ret i32 %add
}
define i32 @outer3() {
entry:
; CHECK-LABEL: @outer3(
; CHECK-NOT: call i32 @a
; CHECK: ret

  %call = call i32 @inner3()
  %add = add nsw i32 1, %call
  ret i32 %add
}

define i32 @inner4() alwaysinline returns_twice {
entry:
  %call = call i32 @b() returns_twice
  %add = add nsw i32 1, %call
  ret i32 %add
}

define i32 @outer4() {
entry:
; CHECK-LABEL: @outer4(
; CHECK: call i32 @b()
; CHECK: ret

  %call = call i32 @inner4() returns_twice
  %add = add nsw i32 1, %call
  ret i32 %add
}

define i32 @inner5(i8* %addr) alwaysinline {
entry:
  indirectbr i8* %addr, [ label %one, label %two ]

one:
  ret i32 42

two:
  ret i32 44
}
define i32 @outer5(i32 %x) {
; CHECK-LABEL: @outer5(
; CHECK: call i32 @inner5
; CHECK: ret

  %cmp = icmp slt i32 %x, 42
  %addr = select i1 %cmp, i8* blockaddress(@inner5, %one), i8* blockaddress(@inner5, %two)
  %call = call i32 @inner5(i8* %addr)
  ret i32 %call
}

define void @inner6(i32 %x) alwaysinline {
entry:
  %icmp = icmp slt i32 %x, 0
  br i1 %icmp, label %return, label %bb

bb:
  %sub = sub nsw i32 %x, 1
  call void @inner6(i32 %sub)
  ret void

return:
  ret void
}
define void @outer6() {
; CHECK-LABEL: @outer6(
; CHECK: call void @inner6(i32 42)
; CHECK: ret

entry:
  call void @inner6(i32 42)
  ret void
}

define i32 @inner7() {
  ret i32 1
}
define i32 @outer7() {
; CHECK-LABEL: @outer7(
; CHECK-NOT: call
; CHECK: ret

   %r = call i32 @inner7() alwaysinline
   ret i32 %r
}