1; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=ARM --check-prefix=ARM-MACHO
2; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -verify-machineinstrs | FileCheck %s --check-prefix=ARM --check-prefix=ARM-ELF
3; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=THUMB
4; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG --check-prefix=ARM-LONG-MACHO
5; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG --check-prefix=ARM-LONG-ELF
6; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=THUMB-LONG
7
8; Note that some of these tests assume that relocations are either
9; movw/movt or constant pool loads. Different platforms will select
10; different approaches.
11
12@message1 = global [60 x i8] c"The LLVM Compiler Infrastructure\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 1
13@temp = common global [60 x i8] zeroinitializer, align 1
14
15define void @t1() nounwind ssp {
16; ARM-LABEL: t1:
17; ARM: {{(movw r0, :lower16:_?message1)|(ldr r0, .LCPI)}}
18; ARM: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}}
19; ARM-DAG: add r0, r0, #5
20; ARM-DAG: movw r1, #64
21; ARM-DAG: movw r2, #10
22; ARM-DAG: and r1, r1, #255
23; ARM: bl {{_?}}memset
24; ARM-LONG-LABEL: t1:
25
26; ARM-LONG-MACHO: {{(movw r3, :lower16:L_memset\$non_lazy_ptr)|(ldr r3, .LCPI)}}
27; ARM-LONG-MACHO: {{(movt r3, :upper16:L_memset\$non_lazy_ptr)?}}
28; ARM-LONG-MACHO: ldr r3, [r3]
29
30; ARM-LONG-ELF: movw r3, :lower16:memset
31; ARM-LONG-ELF: movt r3, :upper16:memset
32
33; ARM-LONG: blx r3
34; THUMB-LABEL: t1:
35; THUMB: {{(movw r0, :lower16:_?message1)|(ldr.n r0, .LCPI)}}
36; THUMB: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}}
37; THUMB: adds r0, #5
38; THUMB: movs r1, #64
39; THUMB: and r1, r1, #255
40; THUMB: movs r2, #10
41; THUMB: bl {{_?}}memset
42; THUMB-LONG-LABEL: t1:
43; THUMB-LONG: movw r3, :lower16:L_memset$non_lazy_ptr
44; THUMB-LONG: movt r3, :upper16:L_memset$non_lazy_ptr
45; THUMB-LONG: ldr r3, [r3]
46; THUMB-LONG: blx r3
47  call void @llvm.memset.p0i8.i32(i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @message1, i32 0, i32 5), i8 64, i32 10, i1 false)
48  ret void
49}
50
51declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) nounwind
52
53define void @t2() nounwind ssp {
54; ARM-LABEL: t2:
55
56; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
57; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
58; ARM-MACHO: ldr [[REG1:r[0-9]+]], [r0]
59
60; ARM-ELF: movw [[REG1:r[0-9]+]], :lower16:temp
61; ARM-ELF: movt [[REG1]], :upper16:temp
62
63; ARM: add r0, [[REG1]], #4
64; ARM: add r1, [[REG1]], #16
65; ARM: movw r2, #17
66; ARM: bl {{_?}}memcpy
67; ARM-LONG-LABEL: t2:
68
69; ARM-LONG-MACHO: {{(movw r3, :lower16:L_memcpy\$non_lazy_ptr)|(ldr r3, .LCPI)}}
70; ARM-LONG-MACHO: {{(movt r3, :upper16:L_memcpy\$non_lazy_ptr)?}}
71; ARM-LONG-MACHO: ldr r3, [r3]
72
73; ARM-LONG-ELF: movw r3, :lower16:memcpy
74; ARM-LONG-ELF: movt r3, :upper16:memcpy
75
76; ARM-LONG: blx r3
77; THUMB-LABEL: t2:
78; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
79; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
80; THUMB: ldr [[REG1:r[0-9]+]], [r0]
81; THUMB: adds r0, [[REG1]], #4
82; THUMB: adds r1, #16
83; THUMB: movs r2, #17
84; THUMB: bl {{_?}}memcpy
85; THUMB-LONG-LABEL: t2:
86; THUMB-LONG: movw r3, :lower16:L_memcpy$non_lazy_ptr
87; THUMB-LONG: movt r3, :upper16:L_memcpy$non_lazy_ptr
88; THUMB-LONG: ldr r3, [r3]
89; THUMB-LONG: blx r3
90  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 17, i1 false)
91  ret void
92}
93
94declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
95
96define void @t3() nounwind ssp {
97; ARM-LABEL: t3:
98
99; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
100; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
101; ARM-MACHO: ldr [[REG0:r[0-9]+]], [r0]
102
103; ARM-ELF: movw [[REG0:r[0-9]+]], :lower16:temp
104; ARM-ELF: movt [[REG0]], :upper16:temp
105
106
107; ARM: add r0, [[REG0]], #4
108; ARM: add r1, [[REG0]], #16
109; ARM: movw r2, #10
110; ARM: bl {{_?}}memmove
111; ARM-LONG-LABEL: t3:
112
113; ARM-LONG-MACHO: {{(movw r3, :lower16:L_memmove\$non_lazy_ptr)|(ldr r3, .LCPI)}}
114; ARM-LONG-MACHO: {{(movt r3, :upper16:L_memmove\$non_lazy_ptr)?}}
115; ARM-LONG-MACHO: ldr r3, [r3]
116
117; ARM-LONG-ELF: movw r3, :lower16:memmove
118; ARM-LONG-ELF: movt r3, :upper16:memmove
119
120; ARM-LONG: blx r3
121; THUMB-LABEL: t3:
122; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
123; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
124; THUMB: ldr [[REG1:r[0-9]+]], [r0]
125; THUMB: adds r0, [[REG1]], #4
126; THUMB: adds r1, #16
127; THUMB: movs r2, #10
128; THUMB: bl {{_?}}memmove
129; THUMB-LONG-LABEL: t3:
130; THUMB-LONG: movw r3, :lower16:L_memmove$non_lazy_ptr
131; THUMB-LONG: movt r3, :upper16:L_memmove$non_lazy_ptr
132; THUMB-LONG: ldr r3, [r3]
133; THUMB-LONG: blx r3
134  call void @llvm.memmove.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
135  ret void
136}
137
138define void @t4() nounwind ssp {
139; ARM-LABEL: t4:
140
141; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
142; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
143; ARM-MACHO: ldr [[REG0:r[0-9]+]], [r0]
144
145; ARM-ELF: movw [[REG0:r[0-9]+]], :lower16:temp
146; ARM-ELF: movt [[REG0]], :upper16:temp
147
148; ARM: ldr [[REG1:r[0-9]+]], {{\[}}[[REG0]], #16]
149; ARM: str [[REG1]], {{\[}}[[REG0]], #4]
150; ARM: ldr [[REG2:r[0-9]+]], {{\[}}[[REG0]], #20]
151; ARM: str [[REG2]], {{\[}}[[REG0]], #8]
152; ARM: ldrh [[REG3:r[0-9]+]], {{\[}}[[REG0]], #24]
153; ARM: strh [[REG3]], {{\[}}[[REG0]], #12]
154; ARM: bx lr
155; THUMB-LABEL: t4:
156; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
157; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
158; THUMB: ldr [[REG1:r[0-9]+]], [r0]
159; THUMB: ldr [[REG2:r[0-9]+]], {{\[}}[[REG1]], #16]
160; THUMB: str [[REG2]], {{\[}}[[REG1]], #4]
161; THUMB: ldr [[REG3:r[0-9]+]], {{\[}}[[REG1]], #20]
162; THUMB: str [[REG3]], {{\[}}[[REG1]], #8]
163; THUMB: ldrh [[REG4:r[0-9]+]], {{\[}}[[REG1]], #24]
164; THUMB: strh [[REG4]], {{\[}}[[REG1]], #12]
165; THUMB: bx lr
166  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
167  ret void
168}
169
170declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
171
172define void @t5() nounwind ssp {
173; ARM-LABEL: t5:
174
175; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
176; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
177; ARM-MACHO: ldr [[REG0:r[0-9]+]], [r0]
178
179; ARM-ELF: movw [[REG0:r[0-9]+]], :lower16:temp
180; ARM-ELF: movt [[REG0]], :upper16:temp
181
182; ARM: ldrh [[REG1:r[0-9]+]], {{\[}}[[REG0]], #16]
183; ARM: strh [[REG1]], {{\[}}[[REG0]], #4]
184; ARM: ldrh [[REG2:r[0-9]+]], {{\[}}[[REG0]], #18]
185; ARM: strh [[REG2]], {{\[}}[[REG0]], #6]
186; ARM: ldrh [[REG3:r[0-9]+]], {{\[}}[[REG0]], #20]
187; ARM: strh [[REG3]], {{\[}}[[REG0]], #8]
188; ARM: ldrh [[REG4:r[0-9]+]], {{\[}}[[REG0]], #22]
189; ARM: strh [[REG4]], {{\[}}[[REG0]], #10]
190; ARM: ldrh [[REG5:r[0-9]+]], {{\[}}[[REG0]], #24]
191; ARM: strh [[REG5]], {{\[}}[[REG0]], #12]
192; ARM: bx lr
193; THUMB-LABEL: t5:
194; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
195; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
196; THUMB: ldr [[REG1:r[0-9]+]], [r0]
197; THUMB: ldrh [[REG2:r[0-9]+]], {{\[}}[[REG1]], #16]
198; THUMB: strh [[REG2]], {{\[}}[[REG1]], #4]
199; THUMB: ldrh [[REG3:r[0-9]+]], {{\[}}[[REG1]], #18]
200; THUMB: strh [[REG3]], {{\[}}[[REG1]], #6]
201; THUMB: ldrh [[REG4:r[0-9]+]], {{\[}}[[REG1]], #20]
202; THUMB: strh [[REG4]], {{\[}}[[REG1]], #8]
203; THUMB: ldrh [[REG5:r[0-9]+]], {{\[}}[[REG1]], #22]
204; THUMB: strh [[REG5]], {{\[}}[[REG1]], #10]
205; THUMB: ldrh [[REG6:r[0-9]+]], {{\[}}[[REG1]], #24]
206; THUMB: strh [[REG6]], {{\[}}[[REG1]], #12]
207; THUMB: bx lr
208  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
209  ret void
210}
211
212define void @t6() nounwind ssp {
213; ARM-LABEL: t6:
214
215; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
216; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
217; ARM-MACHO: ldr [[REG0:r[0-9]+]], [r0]
218
219; ARM-ELF: movw [[REG0:r[0-9]+]], :lower16:temp
220; ARM-ELF: movt [[REG0]], :upper16:temp
221
222; ARM: ldrb [[REG1:r[0-9]+]], {{\[}}[[REG0]], #16]
223; ARM: strb [[REG1]], {{\[}}[[REG0]], #4]
224; ARM: ldrb [[REG2:r[0-9]+]], {{\[}}[[REG0]], #17]
225; ARM: strb [[REG2]], {{\[}}[[REG0]], #5]
226; ARM: ldrb [[REG3:r[0-9]+]], {{\[}}[[REG0]], #18]
227; ARM: strb [[REG3]], {{\[}}[[REG0]], #6]
228; ARM: ldrb [[REG4:r[0-9]+]], {{\[}}[[REG0]], #19]
229; ARM: strb [[REG4]], {{\[}}[[REG0]], #7]
230; ARM: ldrb [[REG5:r[0-9]+]], {{\[}}[[REG0]], #20]
231; ARM: strb [[REG5]], {{\[}}[[REG0]], #8]
232; ARM: ldrb [[REG6:r[0-9]+]], {{\[}}[[REG0]], #21]
233; ARM: strb [[REG6]], {{\[}}[[REG0]], #9]
234; ARM: ldrb [[REG7:r[0-9]+]], {{\[}}[[REG0]], #22]
235; ARM: strb [[REG7]], {{\[}}[[REG0]], #10]
236; ARM: ldrb [[REG8:r[0-9]+]], {{\[}}[[REG0]], #23]
237; ARM: strb [[REG8]], {{\[}}[[REG0]], #11]
238; ARM: ldrb [[REG9:r[0-9]+]], {{\[}}[[REG0]], #24]
239; ARM: strb [[REG9]], {{\[}}[[REG0]], #12]
240; ARM: ldrb [[REG10:r[0-9]+]], {{\[}}[[REG0]], #25]
241; ARM: strb [[REG10]], {{\[}}[[REG0]], #13]
242; ARM: bx lr
243; THUMB-LABEL: t6:
244; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
245; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
246; THUMB: ldr [[REG0:r[0-9]+]], [r0]
247; THUMB: ldrb [[REG2:r[0-9]+]], {{\[}}[[REG0]], #16]
248; THUMB: strb [[REG2]], {{\[}}[[REG0]], #4]
249; THUMB: ldrb [[REG3:r[0-9]+]], {{\[}}[[REG0]], #17]
250; THUMB: strb [[REG3]], {{\[}}[[REG0]], #5]
251; THUMB: ldrb [[REG4:r[0-9]+]], {{\[}}[[REG0]], #18]
252; THUMB: strb [[REG4]], {{\[}}[[REG0]], #6]
253; THUMB: ldrb [[REG5:r[0-9]+]], {{\[}}[[REG0]], #19]
254; THUMB: strb [[REG5]], {{\[}}[[REG0]], #7]
255; THUMB: ldrb [[REG6:r[0-9]+]], {{\[}}[[REG0]], #20]
256; THUMB: strb [[REG6]], {{\[}}[[REG0]], #8]
257; THUMB: ldrb [[REG7:r[0-9]+]], {{\[}}[[REG0]], #21]
258; THUMB: strb [[REG7]], {{\[}}[[REG0]], #9]
259; THUMB: ldrb [[REG8:r[0-9]+]], {{\[}}[[REG0]], #22]
260; THUMB: strb [[REG8]], {{\[}}[[REG0]], #10]
261; THUMB: ldrb [[REG9:r[0-9]+]], {{\[}}[[REG0]], #23]
262; THUMB: strb [[REG9]], {{\[}}[[REG0]], #11]
263; THUMB: ldrb [[REG10:r[0-9]+]], {{\[}}[[REG0]], #24]
264; THUMB: strb [[REG10]], {{\[}}[[REG0]], #12]
265; THUMB: ldrb [[REG11:r[0-9]+]], {{\[}}[[REG0]], #25]
266; THUMB: strb [[REG11]], {{\[}}[[REG0]], #13]
267; THUMB: bx lr
268  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
269  ret void
270}
271
272; rdar://13202135
273define void @t7() nounwind ssp {
274; Just make sure this doesn't assert when we have an odd length and an alignment of 2.
275  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 3, i1 false)
276  ret void
277}
278
279define i32 @t8(i32 %x) nounwind {
280entry:
281; ARM-LABEL: t8:
282; ARM-NOT: FastISel missed call:   %expval = call i32 @llvm.expect.i32(i32 %x, i32 1)
283; THUMB-LABEL: t8:
284; THUMB-NOT: FastISel missed call:   %expval = call i32 @llvm.expect.i32(i32 %x, i32 1)
285  %expval = call i32 @llvm.expect.i32(i32 %x, i32 1)
286  ret i32 %expval
287}
288
289declare i32 @llvm.expect.i32(i32, i32) nounwind readnone
290