1; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=core2 | FileCheck %s -check-prefix=LINUX
2; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=core2 | FileCheck %s -check-prefix=DARWIN
3
4declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
5
6
7; Variable memcpy's should lower to calls.
8define i8* @test1(i8* %a, i8* %b, i64 %n) nounwind {
9entry:
10	tail call void @llvm.memcpy.p0i8.p0i8.i64( i8* %a, i8* %b, i64 %n, i32 1, i1 0 )
11	ret i8* %a
12
13; LINUX-LABEL: test1:
14; LINUX: memcpy
15}
16
17; Variable memcpy's should lower to calls.
18define i8* @test2(i64* %a, i64* %b, i64 %n) nounwind {
19entry:
20	%tmp14 = bitcast i64* %a to i8*
21	%tmp25 = bitcast i64* %b to i8*
22	tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp14, i8* %tmp25, i64 %n, i32 8, i1 0 )
23	ret i8* %tmp14
24
25; LINUX-LABEL: test2:
26; LINUX: memcpy
27}
28
29; Large constant memcpy's should lower to a call when optimizing for size.
30; PR6623
31
32; On the other hand, Darwin's definition of -Os is optimizing for size without
33; hurting performance so it should just ignore optsize when expanding memcpy.
34; rdar://8821501
35define void @test3(i8* nocapture %A, i8* nocapture %B) nounwind optsize noredzone {
36entry:
37  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 64, i32 1, i1 false)
38  ret void
39; LINUX-LABEL: test3:
40; LINUX: memcpy
41
42; DARWIN-LABEL: test3:
43; DARWIN-NOT: memcpy
44; DARWIN: movq
45; DARWIN: movq
46; DARWIN: movq
47; DARWIN: movq
48; DARWIN: movq
49; DARWIN: movq
50; DARWIN: movq
51; DARWIN: movq
52; DARWIN: movq
53; DARWIN: movq
54; DARWIN: movq
55; DARWIN: movq
56; DARWIN: movq
57; DARWIN: movq
58; DARWIN: movq
59; DARWIN: movq
60}
61
62; Large constant memcpy's should be inlined when not optimizing for size.
63define void @test4(i8* nocapture %A, i8* nocapture %B) nounwind noredzone {
64entry:
65  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 64, i32 1, i1 false)
66  ret void
67; LINUX-LABEL: test4:
68; LINUX: movq
69; LINUX: movq
70; LINUX: movq
71; LINUX: movq
72; LINUX: movq
73; LINUX: movq
74; LINUX: movq
75; LINUX: movq
76; LINUX: movq
77; LINUX: movq
78; LINUX: movq
79; LINUX: movq
80}
81
82
83@.str = private unnamed_addr constant [30 x i8] c"\00aaaaaaaaaaaaaaaaaaaaaaaaaaaa\00", align 1
84
85define void @test5(i8* nocapture %C) nounwind uwtable ssp {
86entry:
87  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([30 x i8]* @.str, i64 0, i64 0), i64 16, i32 1, i1 false)
88  ret void
89
90; DARWIN-LABEL: test5:
91; DARWIN: movabsq	$7016996765293437281
92; DARWIN: movabsq	$7016996765293437184
93}
94
95
96; PR14896
97@.str2 = private unnamed_addr constant [2 x i8] c"x\00", align 1
98
99define void @test6() nounwind uwtable {
100entry:
101; DARWIN: test6
102; DARWIN: movw $0, 8
103; DARWIN: movq $120, 0
104  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* null, i8* getelementptr inbounds ([2 x i8]* @.str2, i64 0, i64 0), i64 10, i32 1, i1 false)
105  ret void
106}
107
108define void @PR15348(i8* %a, i8* %b) {
109; Ensure that alignment of '0' in an @llvm.memcpy intrinsic results in
110; unaligned loads and stores.
111; LINUX: PR15348
112; LINUX: movb
113; LINUX: movb
114; LINUX: movq
115; LINUX: movq
116; LINUX: movq
117; LINUX: movq
118  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 17, i32 0, i1 false)
119  ret void
120}
121