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