1; RUN: llc < %s -mcpu=generic -mtriple=i686-pc-linux-gnu -relocation-model=pic -asm-verbose=false -post-RA-scheduler=false -verify-machineinstrs | FileCheck %s -check-prefixes=CHECK,CHECK-I686
2; RUN: llc < %s -mcpu=generic -mtriple=x86_64-pc-linux-gnux32 -relocation-model=pic -asm-verbose=false -post-RA-scheduler=false -verify-machineinstrs | FileCheck %s -check-prefixes=CHECK,CHECK-X32
3; RUN: llc < %s -mcpu=generic -mtriple=x86_64-pc-linux-gnux32 -relocation-model=pic -asm-verbose=false -post-RA-scheduler=false -fast-isel -verify-machineinstrs | FileCheck %s -check-prefixes=CHECK,CHECK-X32
4
5@ptr = external global i32*
6@dst = external global i32
7@src = external global i32
8
9define void @test0() nounwind {
10entry:
11    store i32* @dst, i32** @ptr
12    %tmp.s = load i32, i32* @src
13    store i32 %tmp.s, i32* @dst
14    ret void
15
16; CHECK-LABEL:	test0:
17; CHECK-I686:	calll	.L0$pb
18; CHECK-I686-NEXT:	.L0$pb:
19; CHECK-I686-NEXT:	popl
20; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L0$pb),
21; CHECK-I686:	movl	dst@GOT(%eax),
22; CHECK-I686:	movl	ptr@GOT(%eax),
23; CHECK-I686:	movl	src@GOT(%eax),
24; CHECK-I686:	ret
25; CHECK-X32-DAG:	movl	dst@GOTPCREL(%rip),
26; CHECK-X32-DAG:	movl	ptr@GOTPCREL(%rip),
27; CHECK-X32-DAG:	movl	src@GOTPCREL(%rip),
28; CHECK-X32:	retq
29}
30
31@ptr2 = global i32* null
32@dst2 = global i32 0
33@src2 = global i32 0
34
35define void @test1() nounwind {
36entry:
37    store i32* @dst2, i32** @ptr2
38    %tmp.s = load i32, i32* @src2
39    store i32 %tmp.s, i32* @dst2
40    ret void
41
42; CHECK-LABEL:	test1:
43; CHECK-I686:	calll	.L1$pb
44; CHECK-I686-NEXT:	.L1$pb:
45; CHECK-I686-NEXT:	popl
46; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L1$pb), %eax
47; CHECK-I686:	movl	dst2@GOT(%eax),
48; CHECK-I686:	movl	ptr2@GOT(%eax),
49; CHECK-I686:	movl	src2@GOT(%eax),
50; CHECK-I686:	ret
51; CHECK-X32-DAG:	movl	dst2@GOTPCREL(%rip),
52; CHECK-X32-DAG:	movl	ptr2@GOTPCREL(%rip),
53; CHECK-X32-DAG:	movl	src2@GOTPCREL(%rip),
54; CHECK-X32:	retq
55
56}
57
58declare i8* @malloc(i32)
59
60define void @test2() nounwind {
61entry:
62    %ptr = call i8* @malloc(i32 40)
63    ret void
64; CHECK-LABEL:	test2:
65; CHECK-I686:	pushl	%ebx
66; CHECK-I686-NEXT:	subl	$8, %esp
67; CHECK-I686-NEXT:	calll	.L2$pb
68; CHECK-I686-NEXT:	.L2$pb:
69; CHECK-I686-NEXT:	popl	%ebx
70; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L2$pb), %ebx
71; CHECK-I686:	movl	$40, (%esp)
72; CHECK-I686:	calll	malloc@PLT
73; CHECK-I686:	addl	$8, %esp
74; CHECK-I686:	popl	%ebx
75; CHECK-I686:	ret
76; CHECK-X32:	pushq	%rax
77; CHECK-X32:	movl	$40, %edi
78; CHECK-X32:	callq	malloc@PLT
79; CHECK-X32:	popq	%rax
80; CHECK-X32:	retq
81
82}
83
84@pfoo = external global void(...)*
85
86define void @test3() nounwind {
87entry:
88    %tmp = call void(...)*(...) @afoo()
89    store void(...)* %tmp, void(...)** @pfoo
90    %tmp1 = load void(...)*, void(...)** @pfoo
91    call void(...) %tmp1()
92    ret void
93; CHECK-LABEL:	test3:
94; CHECK-I686:	calll	.L3$pb
95; CHECK-I686-NEXT:	.L3$pb:
96; CHECK-I686:	popl
97; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L3$pb), %[[REG3:e..]]
98; CHECK-I686:	calll	afoo@PLT
99; CHECK-I686:	movl	pfoo@GOT(%[[REG3]]),
100; CHECK-I686:	calll	*
101; CHECK-X32:	callq	afoo@PLT
102; CHECK-X32:	movl	pfoo@GOTPCREL(%rip),
103; CHECK-X32:	callq	*
104}
105
106declare void(...)* @afoo(...)
107
108define void @test4() nounwind {
109entry:
110    call void(...) @foo()
111    ret void
112; CHECK-LABEL:	test4:
113; CHECK-I686:	calll	.L4$pb
114; CHECK-I686:	popl	%ebx
115; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L4$pb), %ebx
116; CHECK-I686:	calll	foo@PLT
117; CHECK-X32:	callq	foo@PLT
118
119}
120
121declare void @foo(...)
122
123
124@ptr6 = internal global i32* null
125@dst6 = internal global i32 0
126@src6 = internal global i32 0
127
128define void @test5() nounwind {
129entry:
130    store i32* @dst6, i32** @ptr6
131    %tmp.s = load i32, i32* @src6
132    store i32 %tmp.s, i32* @dst6
133    ret void
134
135; CHECK-LABEL:	test5:
136; CHECK-I686:	calll	.L5$pb
137; CHECK-I686-NEXT:	.L5$pb:
138; CHECK-I686-NEXT:	popl	%eax
139; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L5$pb), %eax
140; CHECK-I686:	leal	dst6@GOTOFF(%eax), %ecx
141; CHECK-I686:	movl	%ecx, ptr6@GOTOFF(%eax)
142; CHECK-I686:	movl	src6@GOTOFF(%eax), %ecx
143; CHECK-I686:	movl	%ecx, dst6@GOTOFF(%eax)
144; CHECK-I686:	ret
145; CHECK-X32:	leal	dst6(%rip), %eax
146; CHECK-X32:	movl	%eax, ptr6(%rip)
147; CHECK-X32:	movl	src6(%rip), %eax
148; CHECK-X32:	movl	%eax, dst6(%rip)
149; CHECK-X32:	retq
150}
151
152
153;; Test constant pool references.
154define double @test6(i32 %a.u) nounwind {
155entry:
156    %tmp = icmp eq i32 %a.u,0
157    %retval = select i1 %tmp, double 4.561230e+02, double 1.234560e+02
158    ret double %retval
159
160; CHECK:	.LCPI6_0:
161
162; CHECK-LABEL:	test6:
163; CHECK-I686:	calll .L6$pb
164; CHECK-I686:	.L6$pb:
165; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L6$pb),
166; CHECK-I686:	fldl	.LCPI6_0@GOTOFF(
167; CHECK-X32:		.LCPI6_0(%rip),
168}
169
170
171;; Test jump table references.
172define void @test7(i32 %n.u) nounwind {
173entry:
174    switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ]
175bb:
176    tail call void(...) @foo1()
177    ret void
178bb1:
179    tail call void(...) @foo2()
180    ret void
181bb2:
182    tail call void(...) @foo6()
183    ret void
184bb3:
185    tail call void(...) @foo3()
186    ret void
187bb4:
188    tail call void(...) @foo4()
189    ret void
190bb5:
191    tail call void(...) @foo5()
192    ret void
193bb6:
194    tail call void(...) @foo1()
195    ret void
196bb7:
197    tail call void(...) @foo2()
198    ret void
199bb8:
200    tail call void(...) @foo6()
201    ret void
202bb9:
203    tail call void(...) @foo3()
204    ret void
205bb10:
206    tail call void(...) @foo4()
207    ret void
208bb11:
209    tail call void(...) @foo5()
210    ret void
211bb12:
212    tail call void(...) @foo6()
213    ret void
214
215; CHECK-LABEL:	test7:
216; CHECK-I686:	calll	.L7$pb
217; CHECK-I686:	.L7$pb:
218; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L7$pb),
219; CHECK-I686:	.LJTI7_0@GOTOFF(
220; CHECK-I686:	jmpl	*
221; CHECK-X32:	leal	.LJTI7_0(%rip), %eax
222; CHECK-X32:	addl	(%eax,%edi,4), %eax
223; CHECK-X32:	jmpq	*%rax
224
225; CHECK:	.p2align 2
226; CHECK-NEXT:	.LJTI7_0:
227; CHECK-I686:	.long	 .LBB7_2@GOTOFF
228; CHECK-I686:	.long	 .LBB7_8@GOTOFF
229; CHECK-I686:	.long	 .LBB7_4@GOTOFF
230; CHECK-I686:	.long	 .LBB7_6@GOTOFF
231; CHECK-I686:	.long	 .LBB7_5@GOTOFF
232; CHECK-I686:	.long	 .LBB7_8@GOTOFF
233; CHECK-I686:	.long	 .LBB7_7@GOTOFF
234; CHECK-X32:	.long	.LBB7_3-.LJTI7_0
235; CHECK-X32:	.long	.LBB7_3-.LJTI7_0
236; CHECK-X32:	.long	.LBB7_12-.LJTI7_0
237; CHECK-X32:	.long	.LBB7_8-.LJTI7_0
238; CHECK-X32:	.long	.LBB7_12-.LJTI7_0
239; CHECK-X32:	.long	.LBB7_10-.LJTI7_0
240; CHECK-X32:	.long	.LBB7_8-.LJTI7_0
241; CHECK-X32:	.long	.LBB7_9-.LJTI7_0
242; CHECK-X32:	.long	.LBB7_10-.LJTI7_0
243; CHECK-X32:	.long	.LBB7_9-.LJTI7_0
244; CHECK-X32:	.long	.LBB7_12-.LJTI7_0
245; CHECK-X32:	.long	.LBB7_14-.LJTI7_0
246; CHECK-X32:	.long	.LBB7_14-.LJTI7_0
247}
248
249declare void @foo1(...)
250declare void @foo2(...)
251declare void @foo6(...)
252declare void @foo3(...)
253declare void @foo4(...)
254declare void @foo5(...)
255
256;; Check TLS references
257@tlsptrgd = thread_local global i32* null
258@tlsdstgd = thread_local global i32 0
259@tlssrcgd = thread_local global i32 0
260@tlsptrld = thread_local(localdynamic) global i32* null
261@tlsdstld = thread_local(localdynamic) global i32 0
262@tlssrcld = thread_local(localdynamic) global i32 0
263@tlsptrie = thread_local(initialexec) global i32* null
264@tlsdstie = thread_local(initialexec) global i32 0
265@tlssrcie = thread_local(initialexec) global i32 0
266@tlsptrle = thread_local(localexec) global i32* null
267@tlsdstle = thread_local(localexec) global i32 0
268@tlssrcle = thread_local(localexec) global i32 0
269
270define void @test8() nounwind {
271entry:
272    store i32* @tlsdstgd, i32** @tlsptrgd
273    %tmp.s = load i32, i32* @tlssrcgd
274    store i32 %tmp.s, i32* @tlsdstgd
275    ret void
276
277; CHECK-LABEL:	test8:
278; CHECK-I686:	calll	.L8$pb
279; CHECK-I686-NEXT:	.L8$pb:
280; CHECK-I686-NEXT:	popl
281; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L8$pb), %ebx
282; CHECK-I686-DAG:	leal	tlsdstgd@TLSGD(,%ebx), %eax
283; CHECK-I686-DAG:	calll	___tls_get_addr@PLT
284; CHECK-I686-DAG:	leal	tlsptrgd@TLSGD(,%ebx), %eax
285; CHECK-I686-DAG:	calll	___tls_get_addr@PLT
286; CHECK-I686-DAG:	leal	tlssrcgd@TLSGD(,%ebx), %eax
287; CHECK-I686-DAG:	calll	___tls_get_addr@PLT
288; CHECK-X32-NOT:	data16
289; CHECK-X32-DAG:	leaq	tlsdstgd@TLSGD(%rip), %rdi
290; CHECK-X32-DAG:	callq	__tls_get_addr@PLT
291; CHECK-X32-DAG:	leaq	tlsptrgd@TLSGD(%rip), %rdi
292; CHECK-X32-DAG:	callq	__tls_get_addr@PLT
293; CHECK-X32-DAG:	leaq	tlssrcgd@TLSGD(%rip), %rdi
294; CHECK-X32-DAG:	callq	__tls_get_addr@PLT
295; CHECK-I686:	ret
296; CHECK-X32:	retq
297}
298
299define void @test9() nounwind {
300entry:
301    store i32* @tlsdstld, i32** @tlsptrld
302    %tmp.s = load i32, i32* @tlssrcld
303    store i32 %tmp.s, i32* @tlsdstld
304    ret void
305
306; CHECK-LABEL:	test9:
307; CHECK-I686:	calll	.L9$pb
308; CHECK-I686-NEXT:	.L9$pb:
309; CHECK-I686-NEXT:	popl
310; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L9$pb), %ebx
311; CHECK-I686:	leal	tlsdstld@TLSLDM(%ebx), %eax
312; CHECK-X32:	leaq	tlsdstld@TLSLD(%rip), %rdi
313; CHECK-I686:	calll	___tls_get_addr@PLT
314; CHECK-X32:	callq	__tls_get_addr@PLT
315; CHECK:	leal	tlsdstld@DTPOFF(
316; CHECK:	movl	{{%.*}}, tlsptrld@DTPOFF(
317; CHECK:	movl	tlssrcld@DTPOFF(
318; CHECK:	movl	{{%.*}}, tlsdstld@DTPOFF(
319; CHECK-I686:	ret
320; CHECK-X32:	retq
321}
322
323define void @test10() nounwind {
324entry:
325    store i32* @tlsdstie, i32** @tlsptrie
326    %tmp.s = load i32, i32* @tlssrcie
327    store i32 %tmp.s, i32* @tlsdstie
328    ret void
329
330; CHECK-LABEL:	test10:
331; CHECK-I686:	calll	.L10$pb
332; CHECK-I686-NEXT:	.L10$pb:
333; CHECK-I686-NEXT:	popl
334; CHECK-I686:	addl	$_GLOBAL_OFFSET_TABLE_+(.L{{.*}}-.L10$pb),
335; CHECK-I686-DAG:	movl	tlsdstie@GOTNTPOFF(
336; CHECK-I686-DAG:	movl	%gs:0,
337; CHECK-X32-DAG:	movl	tlsdstie@GOTTPOFF(%rip),
338; CHECK-X32-DAG:	movl	%fs:0,
339; CHECK-I686:	addl
340; CHECK-X32:	leal	({{%.*,%.*}}),
341; CHECK-I686:	movl	tlsptrie@GOTNTPOFF(
342; CHECK-X32:	movl	tlsptrie@GOTTPOFF(%rip),
343; CHECK-I686:	movl	{{%.*}}, %gs:(
344; CHECK-X32:	movl	{{%.*}}, ({{%.*,%.*}})
345; CHECK-I686:	movl	tlssrcie@GOTNTPOFF(
346; CHECK-X32:	movl	tlssrcie@GOTTPOFF(%rip),
347; CHECK-I686:	movl	%gs:(
348; CHECK-X32:	movl	({{%.*,%.*}}),
349; CHECK-I686:	movl	{{%.*}}, %gs:(
350; CHECK-X32:	movl	{{%.*}}, ({{%.*,%.*}})
351; CHECK-I686:	ret
352; CHECK-X32:	retq
353}
354
355define void @test11() nounwind {
356entry:
357    store i32* @tlsdstle, i32** @tlsptrle
358    %tmp.s = load i32, i32* @tlssrcle
359    store i32 %tmp.s, i32* @tlsdstle
360    ret void
361
362; CHECK-LABEL:	test11:
363; CHECK-I686:	movl	%gs:0,
364; CHECK-X32:	movl	%fs:0,
365; CHECK-I686:	leal	tlsdstle@NTPOFF(
366; CHECK-X32:	leal	tlsdstle@TPOFF(
367; CHECK-I686:	movl	{{%.*}}, %gs:tlsptrle@NTPOFF
368; CHECK-X32:	movl	{{%.*}}, %fs:tlsptrle@TPOFF
369; CHECK-I686:	movl	%gs:tlssrcle@NTPOFF,
370; CHECK-X32:	movl	%fs:tlssrcle@TPOFF,
371; CHECK-I686:	movl	{{%.*}}, %gs:tlsdstle@NTPOFF
372; CHECK-X32:	movl	{{%.*}}, %fs:tlsdstle@TPOFF
373; CHECK-I686:	ret
374; CHECK-X32:	retq
375}
376