1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=cmov   | FileCheck %s --check-prefix=X86 --check-prefix=X86-NOSSE
3; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse   | FileCheck %s --check-prefix=X86 --check-prefix=SSE --check-prefix=X86-SSE1
4; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse2  | FileCheck %s --check-prefix=X86 --check-prefix=SSE --check-prefix=X86-SSE2
5; RUN: llc < %s -mtriple=x86_64-unknown-unknown             | FileCheck %s --check-prefix=X64 --check-prefix=X64-SSE2
6; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx  | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX --check-prefix=X64-AVX1
7; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=X64 --check-prefix=X64-AVX --check-prefix=X64-AVX2
8
9; This tests codegen time inlining/optimization of memcmp
10; rdar://6480398
11
12@.str = private constant [65 x i8] c"0123456789012345678901234567890123456789012345678901234567890123\00", align 1
13
14declare i32 @memcmp(i8*, i8*, i64)
15
16define i32 @length2(i8* %X, i8* %Y) nounwind {
17; X86-LABEL: length2:
18; X86:       # BB#0:
19; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
20; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
21; X86-NEXT:    movzwl (%ecx), %ecx
22; X86-NEXT:    movzwl (%eax), %edx
23; X86-NEXT:    rolw $8, %cx
24; X86-NEXT:    rolw $8, %dx
25; X86-NEXT:    movzwl %cx, %eax
26; X86-NEXT:    movzwl %dx, %ecx
27; X86-NEXT:    subl %ecx, %eax
28; X86-NEXT:    retl
29;
30; X64-LABEL: length2:
31; X64:       # BB#0:
32; X64-NEXT:    movzwl (%rdi), %eax
33; X64-NEXT:    movzwl (%rsi), %ecx
34; X64-NEXT:    rolw $8, %ax
35; X64-NEXT:    rolw $8, %cx
36; X64-NEXT:    movzwl %ax, %eax
37; X64-NEXT:    movzwl %cx, %ecx
38; X64-NEXT:    subl %ecx, %eax
39; X64-NEXT:    retq
40  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind
41  ret i32 %m
42}
43
44define i1 @length2_eq(i8* %X, i8* %Y) nounwind {
45; X86-LABEL: length2_eq:
46; X86:       # BB#0:
47; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
48; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
49; X86-NEXT:    movzwl (%ecx), %ecx
50; X86-NEXT:    cmpw (%eax), %cx
51; X86-NEXT:    sete %al
52; X86-NEXT:    retl
53;
54; X64-LABEL: length2_eq:
55; X64:       # BB#0:
56; X64-NEXT:    movzwl (%rdi), %eax
57; X64-NEXT:    cmpw (%rsi), %ax
58; X64-NEXT:    sete %al
59; X64-NEXT:    retq
60  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind
61  %c = icmp eq i32 %m, 0
62  ret i1 %c
63}
64
65define i1 @length2_eq_const(i8* %X) nounwind {
66; X86-LABEL: length2_eq_const:
67; X86:       # BB#0:
68; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
69; X86-NEXT:    movzwl (%eax), %eax
70; X86-NEXT:    cmpl $12849, %eax # imm = 0x3231
71; X86-NEXT:    setne %al
72; X86-NEXT:    retl
73;
74; X64-LABEL: length2_eq_const:
75; X64:       # BB#0:
76; X64-NEXT:    movzwl (%rdi), %eax
77; X64-NEXT:    cmpl $12849, %eax # imm = 0x3231
78; X64-NEXT:    setne %al
79; X64-NEXT:    retq
80  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 1), i64 2) nounwind
81  %c = icmp ne i32 %m, 0
82  ret i1 %c
83}
84
85define i1 @length2_eq_nobuiltin_attr(i8* %X, i8* %Y) nounwind {
86; X86-LABEL: length2_eq_nobuiltin_attr:
87; X86:       # BB#0:
88; X86-NEXT:    pushl $0
89; X86-NEXT:    pushl $2
90; X86-NEXT:    pushl {{[0-9]+}}(%esp)
91; X86-NEXT:    pushl {{[0-9]+}}(%esp)
92; X86-NEXT:    calll memcmp
93; X86-NEXT:    addl $16, %esp
94; X86-NEXT:    testl %eax, %eax
95; X86-NEXT:    sete %al
96; X86-NEXT:    retl
97;
98; X64-LABEL: length2_eq_nobuiltin_attr:
99; X64:       # BB#0:
100; X64-NEXT:    pushq %rax
101; X64-NEXT:    movl $2, %edx
102; X64-NEXT:    callq memcmp
103; X64-NEXT:    testl %eax, %eax
104; X64-NEXT:    sete %al
105; X64-NEXT:    popq %rcx
106; X64-NEXT:    retq
107  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind nobuiltin
108  %c = icmp eq i32 %m, 0
109  ret i1 %c
110}
111
112define i32 @length3(i8* %X, i8* %Y) nounwind {
113; X86-LABEL: length3:
114; X86:       # BB#0: # %loadbb
115; X86-NEXT:    pushl %esi
116; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
117; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
118; X86-NEXT:    movzwl (%eax), %edx
119; X86-NEXT:    movzwl (%ecx), %esi
120; X86-NEXT:    rolw $8, %dx
121; X86-NEXT:    rolw $8, %si
122; X86-NEXT:    cmpw %si, %dx
123; X86-NEXT:    jne .LBB4_1
124; X86-NEXT:  # BB#2: # %loadbb1
125; X86-NEXT:    movzbl 2(%eax), %eax
126; X86-NEXT:    movzbl 2(%ecx), %ecx
127; X86-NEXT:    subl %ecx, %eax
128; X86-NEXT:    popl %esi
129; X86-NEXT:    retl
130; X86-NEXT:  .LBB4_1: # %res_block
131; X86-NEXT:    setae %al
132; X86-NEXT:    movzbl %al, %eax
133; X86-NEXT:    leal -1(%eax,%eax), %eax
134; X86-NEXT:    popl %esi
135; X86-NEXT:    retl
136;
137; X64-LABEL: length3:
138; X64:       # BB#0: # %loadbb
139; X64-NEXT:    movzwl (%rdi), %eax
140; X64-NEXT:    movzwl (%rsi), %ecx
141; X64-NEXT:    rolw $8, %ax
142; X64-NEXT:    rolw $8, %cx
143; X64-NEXT:    cmpw %cx, %ax
144; X64-NEXT:    jne .LBB4_1
145; X64-NEXT:  # BB#2: # %loadbb1
146; X64-NEXT:    movzbl 2(%rdi), %eax
147; X64-NEXT:    movzbl 2(%rsi), %ecx
148; X64-NEXT:    subl %ecx, %eax
149; X64-NEXT:    retq
150; X64-NEXT:  .LBB4_1: # %res_block
151; X64-NEXT:    setae %al
152; X64-NEXT:    movzbl %al, %eax
153; X64-NEXT:    leal -1(%rax,%rax), %eax
154; X64-NEXT:    retq
155  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 3) nounwind
156  ret i32 %m
157}
158
159define i1 @length3_eq(i8* %X, i8* %Y) nounwind {
160; X86-LABEL: length3_eq:
161; X86:       # BB#0: # %loadbb
162; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
163; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
164; X86-NEXT:    movzwl (%eax), %edx
165; X86-NEXT:    cmpw (%ecx), %dx
166; X86-NEXT:    jne .LBB5_1
167; X86-NEXT:  # BB#2: # %loadbb1
168; X86-NEXT:    movb 2(%eax), %dl
169; X86-NEXT:    xorl %eax, %eax
170; X86-NEXT:    cmpb 2(%ecx), %dl
171; X86-NEXT:    je .LBB5_3
172; X86-NEXT:  .LBB5_1: # %res_block
173; X86-NEXT:    movl $1, %eax
174; X86-NEXT:  .LBB5_3: # %endblock
175; X86-NEXT:    testl %eax, %eax
176; X86-NEXT:    setne %al
177; X86-NEXT:    retl
178;
179; X64-LABEL: length3_eq:
180; X64:       # BB#0: # %loadbb
181; X64-NEXT:    movzwl (%rdi), %eax
182; X64-NEXT:    cmpw (%rsi), %ax
183; X64-NEXT:    jne .LBB5_1
184; X64-NEXT:  # BB#2: # %loadbb1
185; X64-NEXT:    movb 2(%rdi), %cl
186; X64-NEXT:    xorl %eax, %eax
187; X64-NEXT:    cmpb 2(%rsi), %cl
188; X64-NEXT:    je .LBB5_3
189; X64-NEXT:  .LBB5_1: # %res_block
190; X64-NEXT:    movl $1, %eax
191; X64-NEXT:  .LBB5_3: # %endblock
192; X64-NEXT:    testl %eax, %eax
193; X64-NEXT:    setne %al
194; X64-NEXT:    retq
195  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 3) nounwind
196  %c = icmp ne i32 %m, 0
197  ret i1 %c
198}
199
200define i32 @length4(i8* %X, i8* %Y) nounwind {
201; X86-LABEL: length4:
202; X86:       # BB#0:
203; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
204; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
205; X86-NEXT:    movl (%ecx), %ecx
206; X86-NEXT:    movl (%eax), %edx
207; X86-NEXT:    bswapl %ecx
208; X86-NEXT:    bswapl %edx
209; X86-NEXT:    xorl %eax, %eax
210; X86-NEXT:    cmpl %edx, %ecx
211; X86-NEXT:    seta %al
212; X86-NEXT:    sbbl $0, %eax
213; X86-NEXT:    retl
214;
215; X64-LABEL: length4:
216; X64:       # BB#0:
217; X64-NEXT:    movl (%rdi), %ecx
218; X64-NEXT:    movl (%rsi), %edx
219; X64-NEXT:    bswapl %ecx
220; X64-NEXT:    bswapl %edx
221; X64-NEXT:    xorl %eax, %eax
222; X64-NEXT:    cmpl %edx, %ecx
223; X64-NEXT:    seta %al
224; X64-NEXT:    sbbl $0, %eax
225; X64-NEXT:    retq
226  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 4) nounwind
227  ret i32 %m
228}
229
230define i1 @length4_eq(i8* %X, i8* %Y) nounwind {
231; X86-LABEL: length4_eq:
232; X86:       # BB#0:
233; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
234; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
235; X86-NEXT:    movl (%ecx), %ecx
236; X86-NEXT:    cmpl (%eax), %ecx
237; X86-NEXT:    setne %al
238; X86-NEXT:    retl
239;
240; X64-LABEL: length4_eq:
241; X64:       # BB#0:
242; X64-NEXT:    movl (%rdi), %eax
243; X64-NEXT:    cmpl (%rsi), %eax
244; X64-NEXT:    setne %al
245; X64-NEXT:    retq
246  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 4) nounwind
247  %c = icmp ne i32 %m, 0
248  ret i1 %c
249}
250
251define i1 @length4_eq_const(i8* %X) nounwind {
252; X86-LABEL: length4_eq_const:
253; X86:       # BB#0:
254; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
255; X86-NEXT:    cmpl $875770417, (%eax) # imm = 0x34333231
256; X86-NEXT:    sete %al
257; X86-NEXT:    retl
258;
259; X64-LABEL: length4_eq_const:
260; X64:       # BB#0:
261; X64-NEXT:    cmpl $875770417, (%rdi) # imm = 0x34333231
262; X64-NEXT:    sete %al
263; X64-NEXT:    retq
264  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 1), i64 4) nounwind
265  %c = icmp eq i32 %m, 0
266  ret i1 %c
267}
268
269define i32 @length5(i8* %X, i8* %Y) nounwind {
270; X86-LABEL: length5:
271; X86:       # BB#0: # %loadbb
272; X86-NEXT:    pushl %esi
273; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
274; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
275; X86-NEXT:    movl (%eax), %edx
276; X86-NEXT:    movl (%ecx), %esi
277; X86-NEXT:    bswapl %edx
278; X86-NEXT:    bswapl %esi
279; X86-NEXT:    cmpl %esi, %edx
280; X86-NEXT:    jne .LBB9_1
281; X86-NEXT:  # BB#2: # %loadbb1
282; X86-NEXT:    movzbl 4(%eax), %eax
283; X86-NEXT:    movzbl 4(%ecx), %ecx
284; X86-NEXT:    subl %ecx, %eax
285; X86-NEXT:    popl %esi
286; X86-NEXT:    retl
287; X86-NEXT:  .LBB9_1: # %res_block
288; X86-NEXT:    setae %al
289; X86-NEXT:    movzbl %al, %eax
290; X86-NEXT:    leal -1(%eax,%eax), %eax
291; X86-NEXT:    popl %esi
292; X86-NEXT:    retl
293;
294; X64-LABEL: length5:
295; X64:       # BB#0: # %loadbb
296; X64-NEXT:    movl (%rdi), %eax
297; X64-NEXT:    movl (%rsi), %ecx
298; X64-NEXT:    bswapl %eax
299; X64-NEXT:    bswapl %ecx
300; X64-NEXT:    cmpl %ecx, %eax
301; X64-NEXT:    jne .LBB9_1
302; X64-NEXT:  # BB#2: # %loadbb1
303; X64-NEXT:    movzbl 4(%rdi), %eax
304; X64-NEXT:    movzbl 4(%rsi), %ecx
305; X64-NEXT:    subl %ecx, %eax
306; X64-NEXT:    retq
307; X64-NEXT:  .LBB9_1: # %res_block
308; X64-NEXT:    setae %al
309; X64-NEXT:    movzbl %al, %eax
310; X64-NEXT:    leal -1(%rax,%rax), %eax
311; X64-NEXT:    retq
312  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 5) nounwind
313  ret i32 %m
314}
315
316define i1 @length5_eq(i8* %X, i8* %Y) nounwind {
317; X86-LABEL: length5_eq:
318; X86:       # BB#0: # %loadbb
319; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
320; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
321; X86-NEXT:    movl (%eax), %edx
322; X86-NEXT:    cmpl (%ecx), %edx
323; X86-NEXT:    jne .LBB10_1
324; X86-NEXT:  # BB#2: # %loadbb1
325; X86-NEXT:    movb 4(%eax), %dl
326; X86-NEXT:    xorl %eax, %eax
327; X86-NEXT:    cmpb 4(%ecx), %dl
328; X86-NEXT:    je .LBB10_3
329; X86-NEXT:  .LBB10_1: # %res_block
330; X86-NEXT:    movl $1, %eax
331; X86-NEXT:  .LBB10_3: # %endblock
332; X86-NEXT:    testl %eax, %eax
333; X86-NEXT:    setne %al
334; X86-NEXT:    retl
335;
336; X64-LABEL: length5_eq:
337; X64:       # BB#0: # %loadbb
338; X64-NEXT:    movl (%rdi), %eax
339; X64-NEXT:    cmpl (%rsi), %eax
340; X64-NEXT:    jne .LBB10_1
341; X64-NEXT:  # BB#2: # %loadbb1
342; X64-NEXT:    movb 4(%rdi), %cl
343; X64-NEXT:    xorl %eax, %eax
344; X64-NEXT:    cmpb 4(%rsi), %cl
345; X64-NEXT:    je .LBB10_3
346; X64-NEXT:  .LBB10_1: # %res_block
347; X64-NEXT:    movl $1, %eax
348; X64-NEXT:  .LBB10_3: # %endblock
349; X64-NEXT:    testl %eax, %eax
350; X64-NEXT:    setne %al
351; X64-NEXT:    retq
352  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 5) nounwind
353  %c = icmp ne i32 %m, 0
354  ret i1 %c
355}
356
357define i32 @length8(i8* %X, i8* %Y) nounwind {
358; X86-LABEL: length8:
359; X86:       # BB#0: # %loadbb
360; X86-NEXT:    pushl %esi
361; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
362; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
363; X86-NEXT:    movl (%esi), %ecx
364; X86-NEXT:    movl (%eax), %edx
365; X86-NEXT:    bswapl %ecx
366; X86-NEXT:    bswapl %edx
367; X86-NEXT:    cmpl %edx, %ecx
368; X86-NEXT:    jne .LBB11_1
369; X86-NEXT:  # BB#2: # %loadbb1
370; X86-NEXT:    movl 4(%esi), %ecx
371; X86-NEXT:    movl 4(%eax), %edx
372; X86-NEXT:    bswapl %ecx
373; X86-NEXT:    bswapl %edx
374; X86-NEXT:    xorl %eax, %eax
375; X86-NEXT:    cmpl %edx, %ecx
376; X86-NEXT:    jne .LBB11_1
377; X86-NEXT:  # BB#3: # %endblock
378; X86-NEXT:    popl %esi
379; X86-NEXT:    retl
380; X86-NEXT:  .LBB11_1: # %res_block
381; X86-NEXT:    xorl %eax, %eax
382; X86-NEXT:    cmpl %edx, %ecx
383; X86-NEXT:    setae %al
384; X86-NEXT:    leal -1(%eax,%eax), %eax
385; X86-NEXT:    popl %esi
386; X86-NEXT:    retl
387;
388; X64-LABEL: length8:
389; X64:       # BB#0:
390; X64-NEXT:    movq (%rdi), %rcx
391; X64-NEXT:    movq (%rsi), %rdx
392; X64-NEXT:    bswapq %rcx
393; X64-NEXT:    bswapq %rdx
394; X64-NEXT:    xorl %eax, %eax
395; X64-NEXT:    cmpq %rdx, %rcx
396; X64-NEXT:    seta %al
397; X64-NEXT:    sbbl $0, %eax
398; X64-NEXT:    retq
399  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 8) nounwind
400  ret i32 %m
401}
402
403define i1 @length8_eq(i8* %X, i8* %Y) nounwind {
404; X86-LABEL: length8_eq:
405; X86:       # BB#0: # %loadbb
406; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
407; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
408; X86-NEXT:    movl (%eax), %edx
409; X86-NEXT:    cmpl (%ecx), %edx
410; X86-NEXT:    jne .LBB12_1
411; X86-NEXT:  # BB#2: # %loadbb1
412; X86-NEXT:    movl 4(%eax), %edx
413; X86-NEXT:    xorl %eax, %eax
414; X86-NEXT:    cmpl 4(%ecx), %edx
415; X86-NEXT:    je .LBB12_3
416; X86-NEXT:  .LBB12_1: # %res_block
417; X86-NEXT:    movl $1, %eax
418; X86-NEXT:  .LBB12_3: # %endblock
419; X86-NEXT:    testl %eax, %eax
420; X86-NEXT:    sete %al
421; X86-NEXT:    retl
422;
423; X64-LABEL: length8_eq:
424; X64:       # BB#0:
425; X64-NEXT:    movq (%rdi), %rax
426; X64-NEXT:    cmpq (%rsi), %rax
427; X64-NEXT:    sete %al
428; X64-NEXT:    retq
429  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 8) nounwind
430  %c = icmp eq i32 %m, 0
431  ret i1 %c
432}
433
434define i1 @length8_eq_const(i8* %X) nounwind {
435; X86-LABEL: length8_eq_const:
436; X86:       # BB#0: # %loadbb
437; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
438; X86-NEXT:    cmpl $858927408, (%ecx) # imm = 0x33323130
439; X86-NEXT:    jne .LBB13_1
440; X86-NEXT:  # BB#2: # %loadbb1
441; X86-NEXT:    xorl %eax, %eax
442; X86-NEXT:    cmpl $926299444, 4(%ecx) # imm = 0x37363534
443; X86-NEXT:    je .LBB13_3
444; X86-NEXT:  .LBB13_1: # %res_block
445; X86-NEXT:    movl $1, %eax
446; X86-NEXT:  .LBB13_3: # %endblock
447; X86-NEXT:    testl %eax, %eax
448; X86-NEXT:    setne %al
449; X86-NEXT:    retl
450;
451; X64-LABEL: length8_eq_const:
452; X64:       # BB#0:
453; X64-NEXT:    movabsq $3978425819141910832, %rax # imm = 0x3736353433323130
454; X64-NEXT:    cmpq %rax, (%rdi)
455; X64-NEXT:    setne %al
456; X64-NEXT:    retq
457  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 8) nounwind
458  %c = icmp ne i32 %m, 0
459  ret i1 %c
460}
461
462define i1 @length12_eq(i8* %X, i8* %Y) nounwind {
463; X86-LABEL: length12_eq:
464; X86:       # BB#0:
465; X86-NEXT:    pushl $0
466; X86-NEXT:    pushl $12
467; X86-NEXT:    pushl {{[0-9]+}}(%esp)
468; X86-NEXT:    pushl {{[0-9]+}}(%esp)
469; X86-NEXT:    calll memcmp
470; X86-NEXT:    addl $16, %esp
471; X86-NEXT:    testl %eax, %eax
472; X86-NEXT:    setne %al
473; X86-NEXT:    retl
474;
475; X64-LABEL: length12_eq:
476; X64:       # BB#0: # %loadbb
477; X64-NEXT:    movq (%rdi), %rax
478; X64-NEXT:    cmpq (%rsi), %rax
479; X64-NEXT:    jne .LBB14_1
480; X64-NEXT:  # BB#2: # %loadbb1
481; X64-NEXT:    movl 8(%rdi), %ecx
482; X64-NEXT:    xorl %eax, %eax
483; X64-NEXT:    cmpl 8(%rsi), %ecx
484; X64-NEXT:    je .LBB14_3
485; X64-NEXT:  .LBB14_1: # %res_block
486; X64-NEXT:    movl $1, %eax
487; X64-NEXT:  .LBB14_3: # %endblock
488; X64-NEXT:    testl %eax, %eax
489; X64-NEXT:    setne %al
490; X64-NEXT:    retq
491  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 12) nounwind
492  %c = icmp ne i32 %m, 0
493  ret i1 %c
494}
495
496define i32 @length12(i8* %X, i8* %Y) nounwind {
497; X86-LABEL: length12:
498; X86:       # BB#0:
499; X86-NEXT:    pushl $0
500; X86-NEXT:    pushl $12
501; X86-NEXT:    pushl {{[0-9]+}}(%esp)
502; X86-NEXT:    pushl {{[0-9]+}}(%esp)
503; X86-NEXT:    calll memcmp
504; X86-NEXT:    addl $16, %esp
505; X86-NEXT:    retl
506;
507; X64-LABEL: length12:
508; X64:       # BB#0: # %loadbb
509; X64-NEXT:    movq (%rdi), %rcx
510; X64-NEXT:    movq (%rsi), %rdx
511; X64-NEXT:    bswapq %rcx
512; X64-NEXT:    bswapq %rdx
513; X64-NEXT:    cmpq %rdx, %rcx
514; X64-NEXT:    jne .LBB15_1
515; X64-NEXT:  # BB#2: # %loadbb1
516; X64-NEXT:    movl 8(%rdi), %ecx
517; X64-NEXT:    movl 8(%rsi), %edx
518; X64-NEXT:    bswapl %ecx
519; X64-NEXT:    bswapl %edx
520; X64-NEXT:    xorl %eax, %eax
521; X64-NEXT:    cmpq %rdx, %rcx
522; X64-NEXT:    jne .LBB15_1
523; X64-NEXT:  # BB#3: # %endblock
524; X64-NEXT:    retq
525; X64-NEXT:  .LBB15_1: # %res_block
526; X64-NEXT:    xorl %eax, %eax
527; X64-NEXT:    cmpq %rdx, %rcx
528; X64-NEXT:    setae %al
529; X64-NEXT:    leal -1(%rax,%rax), %eax
530; X64-NEXT:    retq
531  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 12) nounwind
532  ret i32 %m
533}
534
535; PR33329 - https://bugs.llvm.org/show_bug.cgi?id=33329
536
537define i32 @length16(i8* %X, i8* %Y) nounwind {
538; X86-LABEL: length16:
539; X86:       # BB#0:
540; X86-NEXT:    pushl $0
541; X86-NEXT:    pushl $16
542; X86-NEXT:    pushl {{[0-9]+}}(%esp)
543; X86-NEXT:    pushl {{[0-9]+}}(%esp)
544; X86-NEXT:    calll memcmp
545; X86-NEXT:    addl $16, %esp
546; X86-NEXT:    retl
547;
548; X64-LABEL: length16:
549; X64:       # BB#0: # %loadbb
550; X64-NEXT:    movq (%rdi), %rcx
551; X64-NEXT:    movq (%rsi), %rdx
552; X64-NEXT:    bswapq %rcx
553; X64-NEXT:    bswapq %rdx
554; X64-NEXT:    cmpq %rdx, %rcx
555; X64-NEXT:    jne .LBB16_1
556; X64-NEXT:  # BB#2: # %loadbb1
557; X64-NEXT:    movq 8(%rdi), %rcx
558; X64-NEXT:    movq 8(%rsi), %rdx
559; X64-NEXT:    bswapq %rcx
560; X64-NEXT:    bswapq %rdx
561; X64-NEXT:    xorl %eax, %eax
562; X64-NEXT:    cmpq %rdx, %rcx
563; X64-NEXT:    jne .LBB16_1
564; X64-NEXT:  # BB#3: # %endblock
565; X64-NEXT:    retq
566; X64-NEXT:  .LBB16_1: # %res_block
567; X64-NEXT:    xorl %eax, %eax
568; X64-NEXT:    cmpq %rdx, %rcx
569; X64-NEXT:    setae %al
570; X64-NEXT:    leal -1(%rax,%rax), %eax
571; X64-NEXT:    retq
572  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 16) nounwind
573  ret i32 %m
574}
575
576define i1 @length16_eq(i8* %x, i8* %y) nounwind {
577; X86-NOSSE-LABEL: length16_eq:
578; X86-NOSSE:       # BB#0:
579; X86-NOSSE-NEXT:    pushl $0
580; X86-NOSSE-NEXT:    pushl $16
581; X86-NOSSE-NEXT:    pushl {{[0-9]+}}(%esp)
582; X86-NOSSE-NEXT:    pushl {{[0-9]+}}(%esp)
583; X86-NOSSE-NEXT:    calll memcmp
584; X86-NOSSE-NEXT:    addl $16, %esp
585; X86-NOSSE-NEXT:    testl %eax, %eax
586; X86-NOSSE-NEXT:    setne %al
587; X86-NOSSE-NEXT:    retl
588;
589; X86-SSE1-LABEL: length16_eq:
590; X86-SSE1:       # BB#0:
591; X86-SSE1-NEXT:    pushl $0
592; X86-SSE1-NEXT:    pushl $16
593; X86-SSE1-NEXT:    pushl {{[0-9]+}}(%esp)
594; X86-SSE1-NEXT:    pushl {{[0-9]+}}(%esp)
595; X86-SSE1-NEXT:    calll memcmp
596; X86-SSE1-NEXT:    addl $16, %esp
597; X86-SSE1-NEXT:    testl %eax, %eax
598; X86-SSE1-NEXT:    setne %al
599; X86-SSE1-NEXT:    retl
600;
601; X86-SSE2-LABEL: length16_eq:
602; X86-SSE2:       # BB#0:
603; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
604; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %ecx
605; X86-SSE2-NEXT:    movdqu (%ecx), %xmm0
606; X86-SSE2-NEXT:    movdqu (%eax), %xmm1
607; X86-SSE2-NEXT:    pcmpeqb %xmm0, %xmm1
608; X86-SSE2-NEXT:    pmovmskb %xmm1, %eax
609; X86-SSE2-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
610; X86-SSE2-NEXT:    setne %al
611; X86-SSE2-NEXT:    retl
612;
613; X64-LABEL: length16_eq:
614; X64:       # BB#0: # %loadbb
615; X64-NEXT:    movq (%rdi), %rax
616; X64-NEXT:    cmpq (%rsi), %rax
617; X64-NEXT:    jne .LBB17_1
618; X64-NEXT:  # BB#2: # %loadbb1
619; X64-NEXT:    movq 8(%rdi), %rcx
620; X64-NEXT:    xorl %eax, %eax
621; X64-NEXT:    cmpq 8(%rsi), %rcx
622; X64-NEXT:    je .LBB17_3
623; X64-NEXT:  .LBB17_1: # %res_block
624; X64-NEXT:    movl $1, %eax
625; X64-NEXT:  .LBB17_3: # %endblock
626; X64-NEXT:    testl %eax, %eax
627; X64-NEXT:    setne %al
628; X64-NEXT:    retq
629  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 16) nounwind
630  %cmp = icmp ne i32 %call, 0
631  ret i1 %cmp
632}
633
634define i1 @length16_eq_const(i8* %X) nounwind {
635; X86-NOSSE-LABEL: length16_eq_const:
636; X86-NOSSE:       # BB#0:
637; X86-NOSSE-NEXT:    pushl $0
638; X86-NOSSE-NEXT:    pushl $16
639; X86-NOSSE-NEXT:    pushl $.L.str
640; X86-NOSSE-NEXT:    pushl {{[0-9]+}}(%esp)
641; X86-NOSSE-NEXT:    calll memcmp
642; X86-NOSSE-NEXT:    addl $16, %esp
643; X86-NOSSE-NEXT:    testl %eax, %eax
644; X86-NOSSE-NEXT:    sete %al
645; X86-NOSSE-NEXT:    retl
646;
647; X86-SSE1-LABEL: length16_eq_const:
648; X86-SSE1:       # BB#0:
649; X86-SSE1-NEXT:    pushl $0
650; X86-SSE1-NEXT:    pushl $16
651; X86-SSE1-NEXT:    pushl $.L.str
652; X86-SSE1-NEXT:    pushl {{[0-9]+}}(%esp)
653; X86-SSE1-NEXT:    calll memcmp
654; X86-SSE1-NEXT:    addl $16, %esp
655; X86-SSE1-NEXT:    testl %eax, %eax
656; X86-SSE1-NEXT:    sete %al
657; X86-SSE1-NEXT:    retl
658;
659; X86-SSE2-LABEL: length16_eq_const:
660; X86-SSE2:       # BB#0:
661; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
662; X86-SSE2-NEXT:    movdqu (%eax), %xmm0
663; X86-SSE2-NEXT:    pcmpeqb {{\.LCPI.*}}, %xmm0
664; X86-SSE2-NEXT:    pmovmskb %xmm0, %eax
665; X86-SSE2-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
666; X86-SSE2-NEXT:    sete %al
667; X86-SSE2-NEXT:    retl
668;
669; X64-LABEL: length16_eq_const:
670; X64:       # BB#0: # %loadbb
671; X64-NEXT:    movabsq $3978425819141910832, %rax # imm = 0x3736353433323130
672; X64-NEXT:    cmpq %rax, (%rdi)
673; X64-NEXT:    jne .LBB18_1
674; X64-NEXT:  # BB#2: # %loadbb1
675; X64-NEXT:    xorl %eax, %eax
676; X64-NEXT:    movabsq $3833745473465760056, %rcx # imm = 0x3534333231303938
677; X64-NEXT:    cmpq %rcx, 8(%rdi)
678; X64-NEXT:    je .LBB18_3
679; X64-NEXT:  .LBB18_1: # %res_block
680; X64-NEXT:    movl $1, %eax
681; X64-NEXT:  .LBB18_3: # %endblock
682; X64-NEXT:    testl %eax, %eax
683; X64-NEXT:    sete %al
684; X64-NEXT:    retq
685  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 16) nounwind
686  %c = icmp eq i32 %m, 0
687  ret i1 %c
688}
689
690; PR33914 - https://bugs.llvm.org/show_bug.cgi?id=33914
691
692define i32 @length24(i8* %X, i8* %Y) nounwind {
693; X86-LABEL: length24:
694; X86:       # BB#0:
695; X86-NEXT:    pushl $0
696; X86-NEXT:    pushl $24
697; X86-NEXT:    pushl {{[0-9]+}}(%esp)
698; X86-NEXT:    pushl {{[0-9]+}}(%esp)
699; X86-NEXT:    calll memcmp
700; X86-NEXT:    addl $16, %esp
701; X86-NEXT:    retl
702;
703; X64-LABEL: length24:
704; X64:       # BB#0:
705; X64-NEXT:    movl $24, %edx
706; X64-NEXT:    jmp memcmp # TAILCALL
707  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 24) nounwind
708  ret i32 %m
709}
710
711define i1 @length24_eq(i8* %x, i8* %y) nounwind {
712; X86-LABEL: length24_eq:
713; X86:       # BB#0:
714; X86-NEXT:    pushl $0
715; X86-NEXT:    pushl $24
716; X86-NEXT:    pushl {{[0-9]+}}(%esp)
717; X86-NEXT:    pushl {{[0-9]+}}(%esp)
718; X86-NEXT:    calll memcmp
719; X86-NEXT:    addl $16, %esp
720; X86-NEXT:    testl %eax, %eax
721; X86-NEXT:    sete %al
722; X86-NEXT:    retl
723;
724; X64-LABEL: length24_eq:
725; X64:       # BB#0:
726; X64-NEXT:    pushq %rax
727; X64-NEXT:    movl $24, %edx
728; X64-NEXT:    callq memcmp
729; X64-NEXT:    testl %eax, %eax
730; X64-NEXT:    sete %al
731; X64-NEXT:    popq %rcx
732; X64-NEXT:    retq
733  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 24) nounwind
734  %cmp = icmp eq i32 %call, 0
735  ret i1 %cmp
736}
737
738define i1 @length24_eq_const(i8* %X) nounwind {
739; X86-LABEL: length24_eq_const:
740; X86:       # BB#0:
741; X86-NEXT:    pushl $0
742; X86-NEXT:    pushl $24
743; X86-NEXT:    pushl $.L.str
744; X86-NEXT:    pushl {{[0-9]+}}(%esp)
745; X86-NEXT:    calll memcmp
746; X86-NEXT:    addl $16, %esp
747; X86-NEXT:    testl %eax, %eax
748; X86-NEXT:    setne %al
749; X86-NEXT:    retl
750;
751; X64-LABEL: length24_eq_const:
752; X64:       # BB#0:
753; X64-NEXT:    pushq %rax
754; X64-NEXT:    movl $.L.str, %esi
755; X64-NEXT:    movl $24, %edx
756; X64-NEXT:    callq memcmp
757; X64-NEXT:    testl %eax, %eax
758; X64-NEXT:    setne %al
759; X64-NEXT:    popq %rcx
760; X64-NEXT:    retq
761  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 24) nounwind
762  %c = icmp ne i32 %m, 0
763  ret i1 %c
764}
765
766define i32 @length32(i8* %X, i8* %Y) nounwind {
767; X86-LABEL: length32:
768; X86:       # BB#0:
769; X86-NEXT:    pushl $0
770; X86-NEXT:    pushl $32
771; X86-NEXT:    pushl {{[0-9]+}}(%esp)
772; X86-NEXT:    pushl {{[0-9]+}}(%esp)
773; X86-NEXT:    calll memcmp
774; X86-NEXT:    addl $16, %esp
775; X86-NEXT:    retl
776;
777; X64-LABEL: length32:
778; X64:       # BB#0:
779; X64-NEXT:    movl $32, %edx
780; X64-NEXT:    jmp memcmp # TAILCALL
781  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 32) nounwind
782  ret i32 %m
783}
784
785; PR33325 - https://bugs.llvm.org/show_bug.cgi?id=33325
786
787define i1 @length32_eq(i8* %x, i8* %y) nounwind {
788; X86-LABEL: length32_eq:
789; X86:       # BB#0:
790; X86-NEXT:    pushl $0
791; X86-NEXT:    pushl $32
792; X86-NEXT:    pushl {{[0-9]+}}(%esp)
793; X86-NEXT:    pushl {{[0-9]+}}(%esp)
794; X86-NEXT:    calll memcmp
795; X86-NEXT:    addl $16, %esp
796; X86-NEXT:    testl %eax, %eax
797; X86-NEXT:    sete %al
798; X86-NEXT:    retl
799;
800; X64-SSE2-LABEL: length32_eq:
801; X64-SSE2:       # BB#0:
802; X64-SSE2-NEXT:    pushq %rax
803; X64-SSE2-NEXT:    movl $32, %edx
804; X64-SSE2-NEXT:    callq memcmp
805; X64-SSE2-NEXT:    testl %eax, %eax
806; X64-SSE2-NEXT:    sete %al
807; X64-SSE2-NEXT:    popq %rcx
808; X64-SSE2-NEXT:    retq
809;
810; X64-AVX1-LABEL: length32_eq:
811; X64-AVX1:       # BB#0:
812; X64-AVX1-NEXT:    movq 16(%rdi), %rax
813; X64-AVX1-NEXT:    movq (%rdi), %rcx
814; X64-AVX1-NEXT:    movq 8(%rdi), %rdx
815; X64-AVX1-NEXT:    movq 24(%rdi), %rdi
816; X64-AVX1-NEXT:    xorq 24(%rsi), %rdi
817; X64-AVX1-NEXT:    xorq 8(%rsi), %rdx
818; X64-AVX1-NEXT:    orq %rdi, %rdx
819; X64-AVX1-NEXT:    xorq 16(%rsi), %rax
820; X64-AVX1-NEXT:    xorq (%rsi), %rcx
821; X64-AVX1-NEXT:    orq %rax, %rcx
822; X64-AVX1-NEXT:    orq %rdx, %rcx
823; X64-AVX1-NEXT:    sete %al
824; X64-AVX1-NEXT:    retq
825;
826; X64-AVX2-LABEL: length32_eq:
827; X64-AVX2:       # BB#0:
828; X64-AVX2-NEXT:    vmovdqu (%rdi), %ymm0
829; X64-AVX2-NEXT:    vpcmpeqb (%rsi), %ymm0, %ymm0
830; X64-AVX2-NEXT:    vpmovmskb %ymm0, %eax
831; X64-AVX2-NEXT:    cmpl $-1, %eax
832; X64-AVX2-NEXT:    sete %al
833; X64-AVX2-NEXT:    vzeroupper
834; X64-AVX2-NEXT:    retq
835  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 32) nounwind
836  %cmp = icmp eq i32 %call, 0
837  ret i1 %cmp
838}
839
840define i1 @length32_eq_const(i8* %X) nounwind {
841; X86-LABEL: length32_eq_const:
842; X86:       # BB#0:
843; X86-NEXT:    pushl $0
844; X86-NEXT:    pushl $32
845; X86-NEXT:    pushl $.L.str
846; X86-NEXT:    pushl {{[0-9]+}}(%esp)
847; X86-NEXT:    calll memcmp
848; X86-NEXT:    addl $16, %esp
849; X86-NEXT:    testl %eax, %eax
850; X86-NEXT:    setne %al
851; X86-NEXT:    retl
852;
853; X64-SSE2-LABEL: length32_eq_const:
854; X64-SSE2:       # BB#0:
855; X64-SSE2-NEXT:    pushq %rax
856; X64-SSE2-NEXT:    movl $.L.str, %esi
857; X64-SSE2-NEXT:    movl $32, %edx
858; X64-SSE2-NEXT:    callq memcmp
859; X64-SSE2-NEXT:    testl %eax, %eax
860; X64-SSE2-NEXT:    setne %al
861; X64-SSE2-NEXT:    popq %rcx
862; X64-SSE2-NEXT:    retq
863;
864; X64-AVX1-LABEL: length32_eq_const:
865; X64-AVX1:       # BB#0:
866; X64-AVX1-NEXT:    movabsq $3544395820347831604, %rax # imm = 0x3130393837363534
867; X64-AVX1-NEXT:    xorq 24(%rdi), %rax
868; X64-AVX1-NEXT:    movabsq $3833745473465760056, %rcx # imm = 0x3534333231303938
869; X64-AVX1-NEXT:    xorq 8(%rdi), %rcx
870; X64-AVX1-NEXT:    orq %rax, %rcx
871; X64-AVX1-NEXT:    movabsq $3689065127958034230, %rax # imm = 0x3332313039383736
872; X64-AVX1-NEXT:    xorq 16(%rdi), %rax
873; X64-AVX1-NEXT:    movabsq $3978425819141910832, %rdx # imm = 0x3736353433323130
874; X64-AVX1-NEXT:    xorq (%rdi), %rdx
875; X64-AVX1-NEXT:    orq %rax, %rdx
876; X64-AVX1-NEXT:    orq %rcx, %rdx
877; X64-AVX1-NEXT:    setne %al
878; X64-AVX1-NEXT:    retq
879;
880; X64-AVX2-LABEL: length32_eq_const:
881; X64-AVX2:       # BB#0:
882; X64-AVX2-NEXT:    vmovdqu (%rdi), %ymm0
883; X64-AVX2-NEXT:    vpcmpeqb {{.*}}(%rip), %ymm0, %ymm0
884; X64-AVX2-NEXT:    vpmovmskb %ymm0, %eax
885; X64-AVX2-NEXT:    cmpl $-1, %eax
886; X64-AVX2-NEXT:    setne %al
887; X64-AVX2-NEXT:    vzeroupper
888; X64-AVX2-NEXT:    retq
889  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 32) nounwind
890  %c = icmp ne i32 %m, 0
891  ret i1 %c
892}
893
894define i32 @length64(i8* %X, i8* %Y) nounwind {
895; X86-LABEL: length64:
896; X86:       # BB#0:
897; X86-NEXT:    pushl $0
898; X86-NEXT:    pushl $64
899; X86-NEXT:    pushl {{[0-9]+}}(%esp)
900; X86-NEXT:    pushl {{[0-9]+}}(%esp)
901; X86-NEXT:    calll memcmp
902; X86-NEXT:    addl $16, %esp
903; X86-NEXT:    retl
904;
905; X64-LABEL: length64:
906; X64:       # BB#0:
907; X64-NEXT:    movl $64, %edx
908; X64-NEXT:    jmp memcmp # TAILCALL
909  %m = tail call i32 @memcmp(i8* %X, i8* %Y, i64 64) nounwind
910  ret i32 %m
911}
912
913define i1 @length64_eq(i8* %x, i8* %y) nounwind {
914; X86-LABEL: length64_eq:
915; X86:       # BB#0:
916; X86-NEXT:    pushl $0
917; X86-NEXT:    pushl $64
918; X86-NEXT:    pushl {{[0-9]+}}(%esp)
919; X86-NEXT:    pushl {{[0-9]+}}(%esp)
920; X86-NEXT:    calll memcmp
921; X86-NEXT:    addl $16, %esp
922; X86-NEXT:    testl %eax, %eax
923; X86-NEXT:    setne %al
924; X86-NEXT:    retl
925;
926; X64-LABEL: length64_eq:
927; X64:       # BB#0:
928; X64-NEXT:    pushq %rax
929; X64-NEXT:    movl $64, %edx
930; X64-NEXT:    callq memcmp
931; X64-NEXT:    testl %eax, %eax
932; X64-NEXT:    setne %al
933; X64-NEXT:    popq %rcx
934; X64-NEXT:    retq
935  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 64) nounwind
936  %cmp = icmp ne i32 %call, 0
937  ret i1 %cmp
938}
939
940define i1 @length64_eq_const(i8* %X) nounwind {
941; X86-LABEL: length64_eq_const:
942; X86:       # BB#0:
943; X86-NEXT:    pushl $0
944; X86-NEXT:    pushl $64
945; X86-NEXT:    pushl $.L.str
946; X86-NEXT:    pushl {{[0-9]+}}(%esp)
947; X86-NEXT:    calll memcmp
948; X86-NEXT:    addl $16, %esp
949; X86-NEXT:    testl %eax, %eax
950; X86-NEXT:    sete %al
951; X86-NEXT:    retl
952;
953; X64-LABEL: length64_eq_const:
954; X64:       # BB#0:
955; X64-NEXT:    pushq %rax
956; X64-NEXT:    movl $.L.str, %esi
957; X64-NEXT:    movl $64, %edx
958; X64-NEXT:    callq memcmp
959; X64-NEXT:    testl %eax, %eax
960; X64-NEXT:    sete %al
961; X64-NEXT:    popq %rcx
962; X64-NEXT:    retq
963  %m = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([65 x i8], [65 x i8]* @.str, i32 0, i32 0), i64 64) nounwind
964  %c = icmp eq i32 %m, 0
965  ret i1 %c
966}
967
968