xref: /llvm-project/llvm/test/CodeGen/X86/memcmp-minsize.ll (revision 95395ee51124792302390305b02cbeace5f07611)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=X64,X64-SSE2
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefixes=X64,X64-AVX,X64-AVX1
4; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefixes=X64,X64-AVX,X64-AVX2
5
6; This tests codegen time inlining/optimization of memcmp
7; rdar://6480398
8
9@.str = private constant [65 x i8] c"0123456789012345678901234567890123456789012345678901234567890123\00", align 1
10
11declare dso_local i32 @memcmp(ptr, ptr, i64)
12
13define i32 @length2(ptr %X, ptr %Y) nounwind minsize {
14; X64-LABEL: length2:
15; X64:       # %bb.0:
16; X64-NEXT:    pushq $2
17; X64-NEXT:    popq %rdx
18; X64-NEXT:    jmp memcmp # TAILCALL
19  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 2) nounwind
20  ret i32 %m
21}
22
23define i1 @length2_eq(ptr %X, ptr %Y) nounwind minsize {
24; X64-LABEL: length2_eq:
25; X64:       # %bb.0:
26; X64-NEXT:    movzwl (%rdi), %eax
27; X64-NEXT:    cmpw (%rsi), %ax
28; X64-NEXT:    sete %al
29; X64-NEXT:    retq
30  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 2) nounwind
31  %c = icmp eq i32 %m, 0
32  ret i1 %c
33}
34
35define i1 @length2_eq_const(ptr %X) nounwind minsize {
36; X64-LABEL: length2_eq_const:
37; X64:       # %bb.0:
38; X64-NEXT:    cmpw $12849, (%rdi) # imm = 0x3231
39; X64-NEXT:    setne %al
40; X64-NEXT:    retq
41  %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([65 x i8], ptr @.str, i32 0, i32 1), i64 2) nounwind
42  %c = icmp ne i32 %m, 0
43  ret i1 %c
44}
45
46define i1 @length2_eq_nobuiltin_attr(ptr %X, ptr %Y) nounwind minsize {
47; X64-LABEL: length2_eq_nobuiltin_attr:
48; X64:       # %bb.0:
49; X64-NEXT:    pushq %rax
50; X64-NEXT:    pushq $2
51; X64-NEXT:    popq %rdx
52; X64-NEXT:    callq memcmp
53; X64-NEXT:    testl %eax, %eax
54; X64-NEXT:    sete %al
55; X64-NEXT:    popq %rcx
56; X64-NEXT:    retq
57  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 2) nounwind nobuiltin
58  %c = icmp eq i32 %m, 0
59  ret i1 %c
60}
61
62define i32 @length3(ptr %X, ptr %Y) nounwind minsize {
63; X64-LABEL: length3:
64; X64:       # %bb.0:
65; X64-NEXT:    pushq $3
66; X64-NEXT:    popq %rdx
67; X64-NEXT:    jmp memcmp # TAILCALL
68  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 3) nounwind
69  ret i32 %m
70}
71
72define i1 @length3_eq(ptr %X, ptr %Y) nounwind minsize {
73; X64-LABEL: length3_eq:
74; X64:       # %bb.0:
75; X64-NEXT:    pushq %rax
76; X64-NEXT:    pushq $3
77; X64-NEXT:    popq %rdx
78; X64-NEXT:    callq memcmp
79; X64-NEXT:    testl %eax, %eax
80; X64-NEXT:    setne %al
81; X64-NEXT:    popq %rcx
82; X64-NEXT:    retq
83  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 3) nounwind
84  %c = icmp ne i32 %m, 0
85  ret i1 %c
86}
87
88define i32 @length4(ptr %X, ptr %Y) nounwind minsize {
89; X64-LABEL: length4:
90; X64:       # %bb.0:
91; X64-NEXT:    pushq $4
92; X64-NEXT:    popq %rdx
93; X64-NEXT:    jmp memcmp # TAILCALL
94  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 4) nounwind
95  ret i32 %m
96}
97
98define i1 @length4_eq(ptr %X, ptr %Y) nounwind minsize {
99; X64-LABEL: length4_eq:
100; X64:       # %bb.0:
101; X64-NEXT:    movl (%rdi), %eax
102; X64-NEXT:    cmpl (%rsi), %eax
103; X64-NEXT:    setne %al
104; X64-NEXT:    retq
105  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 4) nounwind
106  %c = icmp ne i32 %m, 0
107  ret i1 %c
108}
109
110define i1 @length4_eq_const(ptr %X) nounwind minsize {
111; X64-LABEL: length4_eq_const:
112; X64:       # %bb.0:
113; X64-NEXT:    cmpl $875770417, (%rdi) # imm = 0x34333231
114; X64-NEXT:    sete %al
115; X64-NEXT:    retq
116  %m = tail call i32 @memcmp(ptr %X, ptr getelementptr inbounds ([65 x i8], ptr @.str, i32 0, i32 1), i64 4) nounwind
117  %c = icmp eq i32 %m, 0
118  ret i1 %c
119}
120
121define i32 @length5(ptr %X, ptr %Y) nounwind minsize {
122; X64-LABEL: length5:
123; X64:       # %bb.0:
124; X64-NEXT:    pushq $5
125; X64-NEXT:    popq %rdx
126; X64-NEXT:    jmp memcmp # TAILCALL
127  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 5) nounwind
128  ret i32 %m
129}
130
131define i1 @length5_eq(ptr %X, ptr %Y) nounwind minsize {
132; X64-LABEL: length5_eq:
133; X64:       # %bb.0:
134; X64-NEXT:    pushq %rax
135; X64-NEXT:    pushq $5
136; X64-NEXT:    popq %rdx
137; X64-NEXT:    callq memcmp
138; X64-NEXT:    testl %eax, %eax
139; X64-NEXT:    setne %al
140; X64-NEXT:    popq %rcx
141; X64-NEXT:    retq
142  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 5) nounwind
143  %c = icmp ne i32 %m, 0
144  ret i1 %c
145}
146
147define i32 @length8(ptr %X, ptr %Y) nounwind minsize {
148; X64-LABEL: length8:
149; X64:       # %bb.0:
150; X64-NEXT:    pushq $8
151; X64-NEXT:    popq %rdx
152; X64-NEXT:    jmp memcmp # TAILCALL
153  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 8) nounwind
154  ret i32 %m
155}
156
157define i1 @length8_eq(ptr %X, ptr %Y) nounwind minsize {
158; X64-LABEL: length8_eq:
159; X64:       # %bb.0:
160; X64-NEXT:    movq (%rdi), %rax
161; X64-NEXT:    cmpq (%rsi), %rax
162; X64-NEXT:    sete %al
163; X64-NEXT:    retq
164  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 8) nounwind
165  %c = icmp eq i32 %m, 0
166  ret i1 %c
167}
168
169define i1 @length8_eq_const(ptr %X) nounwind minsize {
170; X64-LABEL: length8_eq_const:
171; X64:       # %bb.0:
172; X64-NEXT:    movabsq $3978425819141910832, %rax # imm = 0x3736353433323130
173; X64-NEXT:    cmpq %rax, (%rdi)
174; X64-NEXT:    setne %al
175; X64-NEXT:    retq
176  %m = tail call i32 @memcmp(ptr %X, ptr @.str, i64 8) nounwind
177  %c = icmp ne i32 %m, 0
178  ret i1 %c
179}
180
181define i1 @length12_eq(ptr %X, ptr %Y) nounwind minsize {
182; X64-LABEL: length12_eq:
183; X64:       # %bb.0:
184; X64-NEXT:    pushq %rax
185; X64-NEXT:    pushq $12
186; X64-NEXT:    popq %rdx
187; X64-NEXT:    callq memcmp
188; X64-NEXT:    testl %eax, %eax
189; X64-NEXT:    setne %al
190; X64-NEXT:    popq %rcx
191; X64-NEXT:    retq
192  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 12) nounwind
193  %c = icmp ne i32 %m, 0
194  ret i1 %c
195}
196
197define i32 @length12(ptr %X, ptr %Y) nounwind minsize {
198; X64-LABEL: length12:
199; X64:       # %bb.0:
200; X64-NEXT:    pushq $12
201; X64-NEXT:    popq %rdx
202; X64-NEXT:    jmp memcmp # TAILCALL
203  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 12) nounwind
204  ret i32 %m
205}
206
207; PR33329 - https://bugs.llvm.org/show_bug.cgi?id=33329
208
209define i32 @length16(ptr %X, ptr %Y) nounwind minsize {
210;
211; X64-LABEL: length16:
212; X64:       # %bb.0:
213; X64-NEXT:    pushq $16
214; X64-NEXT:    popq %rdx
215; X64-NEXT:    jmp memcmp # TAILCALL
216  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 16) nounwind
217  ret i32 %m
218}
219
220define i1 @length16_eq(ptr %x, ptr %y) nounwind minsize {
221; X64-SSE2-LABEL: length16_eq:
222; X64-SSE2:       # %bb.0:
223; X64-SSE2-NEXT:    movdqu (%rsi), %xmm0
224; X64-SSE2-NEXT:    movdqu (%rdi), %xmm1
225; X64-SSE2-NEXT:    pcmpeqb %xmm0, %xmm1
226; X64-SSE2-NEXT:    pmovmskb %xmm1, %eax
227; X64-SSE2-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
228; X64-SSE2-NEXT:    setne %al
229; X64-SSE2-NEXT:    retq
230;
231; X64-AVX-LABEL: length16_eq:
232; X64-AVX:       # %bb.0:
233; X64-AVX-NEXT:    vmovdqu (%rdi), %xmm0
234; X64-AVX-NEXT:    vpxor (%rsi), %xmm0, %xmm0
235; X64-AVX-NEXT:    vptest %xmm0, %xmm0
236; X64-AVX-NEXT:    setne %al
237; X64-AVX-NEXT:    retq
238  %call = tail call i32 @memcmp(ptr %x, ptr %y, i64 16) nounwind
239  %cmp = icmp ne i32 %call, 0
240  ret i1 %cmp
241}
242
243define i1 @length16_eq_const(ptr %X) nounwind minsize {
244; X64-SSE2-LABEL: length16_eq_const:
245; X64-SSE2:       # %bb.0:
246; X64-SSE2-NEXT:    movdqu (%rdi), %xmm0
247; X64-SSE2-NEXT:    pcmpeqb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
248; X64-SSE2-NEXT:    pmovmskb %xmm0, %eax
249; X64-SSE2-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
250; X64-SSE2-NEXT:    sete %al
251; X64-SSE2-NEXT:    retq
252;
253; X64-AVX-LABEL: length16_eq_const:
254; X64-AVX:       # %bb.0:
255; X64-AVX-NEXT:    vmovdqu (%rdi), %xmm0
256; X64-AVX-NEXT:    vpxor {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
257; X64-AVX-NEXT:    vptest %xmm0, %xmm0
258; X64-AVX-NEXT:    sete %al
259; X64-AVX-NEXT:    retq
260  %m = tail call i32 @memcmp(ptr %X, ptr @.str, i64 16) nounwind
261  %c = icmp eq i32 %m, 0
262  ret i1 %c
263}
264
265; PR33914 - https://bugs.llvm.org/show_bug.cgi?id=33914
266
267define i32 @length24(ptr %X, ptr %Y) nounwind minsize {
268; X64-LABEL: length24:
269; X64:       # %bb.0:
270; X64-NEXT:    pushq $24
271; X64-NEXT:    popq %rdx
272; X64-NEXT:    jmp memcmp # TAILCALL
273  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 24) nounwind
274  ret i32 %m
275}
276
277define i1 @length24_eq(ptr %x, ptr %y) nounwind minsize {
278; X64-LABEL: length24_eq:
279; X64:       # %bb.0:
280; X64-NEXT:    pushq %rax
281; X64-NEXT:    pushq $24
282; X64-NEXT:    popq %rdx
283; X64-NEXT:    callq memcmp
284; X64-NEXT:    testl %eax, %eax
285; X64-NEXT:    sete %al
286; X64-NEXT:    popq %rcx
287; X64-NEXT:    retq
288  %call = tail call i32 @memcmp(ptr %x, ptr %y, i64 24) nounwind
289  %cmp = icmp eq i32 %call, 0
290  ret i1 %cmp
291}
292
293define i1 @length24_eq_const(ptr %X) nounwind minsize {
294; X64-LABEL: length24_eq_const:
295; X64:       # %bb.0:
296; X64-NEXT:    pushq %rax
297; X64-NEXT:    pushq $24
298; X64-NEXT:    popq %rdx
299; X64-NEXT:    movl $.L.str, %esi
300; X64-NEXT:    callq memcmp
301; X64-NEXT:    testl %eax, %eax
302; X64-NEXT:    setne %al
303; X64-NEXT:    popq %rcx
304; X64-NEXT:    retq
305  %m = tail call i32 @memcmp(ptr %X, ptr @.str, i64 24) nounwind
306  %c = icmp ne i32 %m, 0
307  ret i1 %c
308}
309
310define i32 @length32(ptr %X, ptr %Y) nounwind minsize {
311; X64-LABEL: length32:
312; X64:       # %bb.0:
313; X64-NEXT:    pushq $32
314; X64-NEXT:    popq %rdx
315; X64-NEXT:    jmp memcmp # TAILCALL
316  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 32) nounwind
317  ret i32 %m
318}
319
320; PR33325 - https://bugs.llvm.org/show_bug.cgi?id=33325
321
322define i1 @length32_eq(ptr %x, ptr %y) nounwind minsize {
323; X64-SSE2-LABEL: length32_eq:
324; X64-SSE2:       # %bb.0:
325; X64-SSE2-NEXT:    pushq %rax
326; X64-SSE2-NEXT:    pushq $32
327; X64-SSE2-NEXT:    popq %rdx
328; X64-SSE2-NEXT:    callq memcmp
329; X64-SSE2-NEXT:    testl %eax, %eax
330; X64-SSE2-NEXT:    sete %al
331; X64-SSE2-NEXT:    popq %rcx
332; X64-SSE2-NEXT:    retq
333;
334; X64-AVX1-LABEL: length32_eq:
335; X64-AVX1:       # %bb.0:
336; X64-AVX1-NEXT:    vmovups (%rdi), %ymm0
337; X64-AVX1-NEXT:    vxorps (%rsi), %ymm0, %ymm0
338; X64-AVX1-NEXT:    vptest %ymm0, %ymm0
339; X64-AVX1-NEXT:    sete %al
340; X64-AVX1-NEXT:    vzeroupper
341; X64-AVX1-NEXT:    retq
342;
343; X64-AVX2-LABEL: length32_eq:
344; X64-AVX2:       # %bb.0:
345; X64-AVX2-NEXT:    vmovdqu (%rdi), %ymm0
346; X64-AVX2-NEXT:    vpxor (%rsi), %ymm0, %ymm0
347; X64-AVX2-NEXT:    vptest %ymm0, %ymm0
348; X64-AVX2-NEXT:    sete %al
349; X64-AVX2-NEXT:    vzeroupper
350; X64-AVX2-NEXT:    retq
351  %call = tail call i32 @memcmp(ptr %x, ptr %y, i64 32) nounwind
352  %cmp = icmp eq i32 %call, 0
353  ret i1 %cmp
354}
355
356define i1 @length32_eq_const(ptr %X) nounwind minsize {
357; X64-SSE2-LABEL: length32_eq_const:
358; X64-SSE2:       # %bb.0:
359; X64-SSE2-NEXT:    pushq %rax
360; X64-SSE2-NEXT:    pushq $32
361; X64-SSE2-NEXT:    popq %rdx
362; X64-SSE2-NEXT:    movl $.L.str, %esi
363; X64-SSE2-NEXT:    callq memcmp
364; X64-SSE2-NEXT:    testl %eax, %eax
365; X64-SSE2-NEXT:    setne %al
366; X64-SSE2-NEXT:    popq %rcx
367; X64-SSE2-NEXT:    retq
368;
369; X64-AVX1-LABEL: length32_eq_const:
370; X64-AVX1:       # %bb.0:
371; X64-AVX1-NEXT:    vmovups (%rdi), %ymm0
372; X64-AVX1-NEXT:    vxorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
373; X64-AVX1-NEXT:    vptest %ymm0, %ymm0
374; X64-AVX1-NEXT:    setne %al
375; X64-AVX1-NEXT:    vzeroupper
376; X64-AVX1-NEXT:    retq
377;
378; X64-AVX2-LABEL: length32_eq_const:
379; X64-AVX2:       # %bb.0:
380; X64-AVX2-NEXT:    vmovdqu (%rdi), %ymm0
381; X64-AVX2-NEXT:    vpxor {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
382; X64-AVX2-NEXT:    vptest %ymm0, %ymm0
383; X64-AVX2-NEXT:    setne %al
384; X64-AVX2-NEXT:    vzeroupper
385; X64-AVX2-NEXT:    retq
386  %m = tail call i32 @memcmp(ptr %X, ptr @.str, i64 32) nounwind
387  %c = icmp ne i32 %m, 0
388  ret i1 %c
389}
390
391define i32 @length64(ptr %X, ptr %Y) nounwind minsize {
392; X64-LABEL: length64:
393; X64:       # %bb.0:
394; X64-NEXT:    pushq $64
395; X64-NEXT:    popq %rdx
396; X64-NEXT:    jmp memcmp # TAILCALL
397  %m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 64) nounwind
398  ret i32 %m
399}
400
401define i1 @length64_eq(ptr %x, ptr %y) nounwind minsize {
402; X64-LABEL: length64_eq:
403; X64:       # %bb.0:
404; X64-NEXT:    pushq %rax
405; X64-NEXT:    pushq $64
406; X64-NEXT:    popq %rdx
407; X64-NEXT:    callq memcmp
408; X64-NEXT:    testl %eax, %eax
409; X64-NEXT:    setne %al
410; X64-NEXT:    popq %rcx
411; X64-NEXT:    retq
412  %call = tail call i32 @memcmp(ptr %x, ptr %y, i64 64) nounwind
413  %cmp = icmp ne i32 %call, 0
414  ret i1 %cmp
415}
416
417define i1 @length64_eq_const(ptr %X) nounwind minsize {
418; X64-LABEL: length64_eq_const:
419; X64:       # %bb.0:
420; X64-NEXT:    pushq %rax
421; X64-NEXT:    pushq $64
422; X64-NEXT:    popq %rdx
423; X64-NEXT:    movl $.L.str, %esi
424; X64-NEXT:    callq memcmp
425; X64-NEXT:    testl %eax, %eax
426; X64-NEXT:    sete %al
427; X64-NEXT:    popq %rcx
428; X64-NEXT:    retq
429  %m = tail call i32 @memcmp(ptr %X, ptr @.str, i64 64) nounwind
430  %c = icmp eq i32 %m, 0
431  ret i1 %c
432}
433
434