1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=i386-linux-generic -verify-machineinstrs -mattr=sse2 | FileCheck %s --check-prefix=X86 --check-prefix=X86-SSE 3; RUN: llc < %s -mtriple=i386-linux-generic -verify-machineinstrs | FileCheck %s --check-prefix=X86 --check-prefix=X86-NOSSE 4; RUN: llc < %s -mtriple=x86_64-linux-generic -verify-machineinstrs -mattr=sse2 | FileCheck %s --check-prefix=X64 5 6; Note: This test is testing that the lowering for atomics matches what we 7; currently emit for non-atomics + the atomic restriction. The presence of 8; particular lowering detail in these tests should not be read as requiring 9; that detail for correctness unless it's related to the atomicity itself. 10; (Specifically, there were reviewer questions about the lowering for halfs 11; and their calling convention which remain unresolved.) 12 13define void @store_half(half* %fptr, half %v) { 14; X86-SSE-LABEL: store_half: 15; X86-SSE: # %bb.0: 16; X86-SSE-NEXT: pushl %esi 17; X86-SSE-NEXT: .cfi_def_cfa_offset 8 18; X86-SSE-NEXT: subl $8, %esp 19; X86-SSE-NEXT: .cfi_def_cfa_offset 16 20; X86-SSE-NEXT: .cfi_offset %esi, -8 21; X86-SSE-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero 22; X86-SSE-NEXT: movss %xmm0, (%esp) 23; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %esi 24; X86-SSE-NEXT: calll __gnu_f2h_ieee 25; X86-SSE-NEXT: movw %ax, (%esi) 26; X86-SSE-NEXT: addl $8, %esp 27; X86-SSE-NEXT: .cfi_def_cfa_offset 8 28; X86-SSE-NEXT: popl %esi 29; X86-SSE-NEXT: .cfi_def_cfa_offset 4 30; X86-SSE-NEXT: retl 31; 32; X86-NOSSE-LABEL: store_half: 33; X86-NOSSE: # %bb.0: 34; X86-NOSSE-NEXT: pushl %esi 35; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 36; X86-NOSSE-NEXT: subl $8, %esp 37; X86-NOSSE-NEXT: .cfi_def_cfa_offset 16 38; X86-NOSSE-NEXT: .cfi_offset %esi, -8 39; X86-NOSSE-NEXT: flds {{[0-9]+}}(%esp) 40; X86-NOSSE-NEXT: fstps (%esp) 41; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi 42; X86-NOSSE-NEXT: calll __gnu_f2h_ieee 43; X86-NOSSE-NEXT: movw %ax, (%esi) 44; X86-NOSSE-NEXT: addl $8, %esp 45; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 46; X86-NOSSE-NEXT: popl %esi 47; X86-NOSSE-NEXT: .cfi_def_cfa_offset 4 48; X86-NOSSE-NEXT: retl 49; 50; X64-LABEL: store_half: 51; X64: # %bb.0: 52; X64-NEXT: pushq %rbx 53; X64-NEXT: .cfi_def_cfa_offset 16 54; X64-NEXT: .cfi_offset %rbx, -16 55; X64-NEXT: movq %rdi, %rbx 56; X64-NEXT: callq __gnu_f2h_ieee 57; X64-NEXT: movw %ax, (%rbx) 58; X64-NEXT: popq %rbx 59; X64-NEXT: .cfi_def_cfa_offset 8 60; X64-NEXT: retq 61 store atomic half %v, half* %fptr unordered, align 2 62 ret void 63} 64 65define void @store_float(float* %fptr, float %v) { 66; X86-LABEL: store_float: 67; X86: # %bb.0: 68; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 69; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 70; X86-NEXT: movl %ecx, (%eax) 71; X86-NEXT: retl 72; 73; X64-LABEL: store_float: 74; X64: # %bb.0: 75; X64-NEXT: movd %xmm0, %eax 76; X64-NEXT: movl %eax, (%rdi) 77; X64-NEXT: retq 78 store atomic float %v, float* %fptr unordered, align 4 79 ret void 80} 81 82define void @store_double(double* %fptr, double %v) { 83; X86-LABEL: store_double: 84; X86: # %bb.0: 85; X86-NEXT: pushl %ebx 86; X86-NEXT: .cfi_def_cfa_offset 8 87; X86-NEXT: pushl %esi 88; X86-NEXT: .cfi_def_cfa_offset 12 89; X86-NEXT: .cfi_offset %esi, -12 90; X86-NEXT: .cfi_offset %ebx, -8 91; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 92; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx 93; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 94; X86-NEXT: movl (%esi), %eax 95; X86-NEXT: movl 4(%esi), %edx 96; X86-NEXT: .p2align 4, 0x90 97; X86-NEXT: .LBB2_1: # %atomicrmw.start 98; X86-NEXT: # =>This Inner Loop Header: Depth=1 99; X86-NEXT: lock cmpxchg8b (%esi) 100; X86-NEXT: jne .LBB2_1 101; X86-NEXT: # %bb.2: # %atomicrmw.end 102; X86-NEXT: popl %esi 103; X86-NEXT: .cfi_def_cfa_offset 8 104; X86-NEXT: popl %ebx 105; X86-NEXT: .cfi_def_cfa_offset 4 106; X86-NEXT: retl 107; 108; X64-LABEL: store_double: 109; X64: # %bb.0: 110; X64-NEXT: movq %xmm0, %rax 111; X64-NEXT: movq %rax, (%rdi) 112; X64-NEXT: retq 113 store atomic double %v, double* %fptr unordered, align 8 114 ret void 115} 116 117define void @store_fp128(fp128* %fptr, fp128 %v) { 118; X86-LABEL: store_fp128: 119; X86: # %bb.0: 120; X86-NEXT: subl $36, %esp 121; X86-NEXT: .cfi_adjust_cfa_offset 36 122; X86-NEXT: leal {{[0-9]+}}(%esp), %eax 123; X86-NEXT: pushl {{[0-9]+}}(%esp) 124; X86-NEXT: .cfi_adjust_cfa_offset 4 125; X86-NEXT: pushl {{[0-9]+}}(%esp) 126; X86-NEXT: .cfi_adjust_cfa_offset 4 127; X86-NEXT: pushl {{[0-9]+}}(%esp) 128; X86-NEXT: .cfi_adjust_cfa_offset 4 129; X86-NEXT: pushl {{[0-9]+}}(%esp) 130; X86-NEXT: .cfi_adjust_cfa_offset 4 131; X86-NEXT: pushl {{[0-9]+}}(%esp) 132; X86-NEXT: .cfi_adjust_cfa_offset 4 133; X86-NEXT: pushl %eax 134; X86-NEXT: .cfi_adjust_cfa_offset 4 135; X86-NEXT: calll __sync_lock_test_and_set_16 136; X86-NEXT: .cfi_adjust_cfa_offset -4 137; X86-NEXT: addl $56, %esp 138; X86-NEXT: .cfi_adjust_cfa_offset -56 139; X86-NEXT: retl 140; 141; X64-LABEL: store_fp128: 142; X64: # %bb.0: 143; X64-NEXT: pushq %rax 144; X64-NEXT: .cfi_def_cfa_offset 16 145; X64-NEXT: callq __sync_lock_test_and_set_16 146; X64-NEXT: popq %rax 147; X64-NEXT: .cfi_def_cfa_offset 8 148; X64-NEXT: retq 149 store atomic fp128 %v, fp128* %fptr unordered, align 16 150 ret void 151} 152 153define half @load_half(half* %fptr) { 154; X86-LABEL: load_half: 155; X86: # %bb.0: 156; X86-NEXT: subl $12, %esp 157; X86-NEXT: .cfi_def_cfa_offset 16 158; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 159; X86-NEXT: movzwl (%eax), %eax 160; X86-NEXT: movl %eax, (%esp) 161; X86-NEXT: calll __gnu_h2f_ieee 162; X86-NEXT: addl $12, %esp 163; X86-NEXT: .cfi_def_cfa_offset 4 164; X86-NEXT: retl 165; 166; X64-LABEL: load_half: 167; X64: # %bb.0: 168; X64-NEXT: pushq %rax 169; X64-NEXT: .cfi_def_cfa_offset 16 170; X64-NEXT: movzwl (%rdi), %edi 171; X64-NEXT: callq __gnu_h2f_ieee 172; X64-NEXT: popq %rax 173; X64-NEXT: .cfi_def_cfa_offset 8 174; X64-NEXT: retq 175 %v = load atomic half, half* %fptr unordered, align 2 176 ret half %v 177} 178 179define float @load_float(float* %fptr) { 180; X86-SSE-LABEL: load_float: 181; X86-SSE: # %bb.0: 182; X86-SSE-NEXT: pushl %eax 183; X86-SSE-NEXT: .cfi_def_cfa_offset 8 184; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax 185; X86-SSE-NEXT: movd (%eax), %xmm0 186; X86-SSE-NEXT: movd %xmm0, (%esp) 187; X86-SSE-NEXT: flds (%esp) 188; X86-SSE-NEXT: popl %eax 189; X86-SSE-NEXT: .cfi_def_cfa_offset 4 190; X86-SSE-NEXT: retl 191; 192; X86-NOSSE-LABEL: load_float: 193; X86-NOSSE: # %bb.0: 194; X86-NOSSE-NEXT: pushl %eax 195; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 196; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax 197; X86-NOSSE-NEXT: movl (%eax), %eax 198; X86-NOSSE-NEXT: movl %eax, (%esp) 199; X86-NOSSE-NEXT: flds (%esp) 200; X86-NOSSE-NEXT: popl %eax 201; X86-NOSSE-NEXT: .cfi_def_cfa_offset 4 202; X86-NOSSE-NEXT: retl 203; 204; X64-LABEL: load_float: 205; X64: # %bb.0: 206; X64-NEXT: movd (%rdi), %xmm0 207; X64-NEXT: retq 208 %v = load atomic float, float* %fptr unordered, align 4 209 ret float %v 210} 211 212define double @load_double(double* %fptr) { 213; X86-SSE-LABEL: load_double: 214; X86-SSE: # %bb.0: 215; X86-SSE-NEXT: subl $12, %esp 216; X86-SSE-NEXT: .cfi_def_cfa_offset 16 217; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax 218; X86-SSE-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 219; X86-SSE-NEXT: movlps %xmm0, (%esp) 220; X86-SSE-NEXT: fldl (%esp) 221; X86-SSE-NEXT: addl $12, %esp 222; X86-SSE-NEXT: .cfi_def_cfa_offset 4 223; X86-SSE-NEXT: retl 224; 225; X86-NOSSE-LABEL: load_double: 226; X86-NOSSE: # %bb.0: 227; X86-NOSSE-NEXT: pushl %ebx 228; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 229; X86-NOSSE-NEXT: pushl %esi 230; X86-NOSSE-NEXT: .cfi_def_cfa_offset 12 231; X86-NOSSE-NEXT: subl $12, %esp 232; X86-NOSSE-NEXT: .cfi_def_cfa_offset 24 233; X86-NOSSE-NEXT: .cfi_offset %esi, -12 234; X86-NOSSE-NEXT: .cfi_offset %ebx, -8 235; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi 236; X86-NOSSE-NEXT: xorl %eax, %eax 237; X86-NOSSE-NEXT: xorl %edx, %edx 238; X86-NOSSE-NEXT: xorl %ecx, %ecx 239; X86-NOSSE-NEXT: xorl %ebx, %ebx 240; X86-NOSSE-NEXT: lock cmpxchg8b (%esi) 241; X86-NOSSE-NEXT: movl %edx, {{[0-9]+}}(%esp) 242; X86-NOSSE-NEXT: movl %eax, (%esp) 243; X86-NOSSE-NEXT: fldl (%esp) 244; X86-NOSSE-NEXT: addl $12, %esp 245; X86-NOSSE-NEXT: .cfi_def_cfa_offset 12 246; X86-NOSSE-NEXT: popl %esi 247; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 248; X86-NOSSE-NEXT: popl %ebx 249; X86-NOSSE-NEXT: .cfi_def_cfa_offset 4 250; X86-NOSSE-NEXT: retl 251; 252; X64-LABEL: load_double: 253; X64: # %bb.0: 254; X64-NEXT: movq (%rdi), %xmm0 255; X64-NEXT: retq 256 %v = load atomic double, double* %fptr unordered, align 8 257 ret double %v 258} 259 260define fp128 @load_fp128(fp128* %fptr) { 261; X86-LABEL: load_fp128: 262; X86: # %bb.0: 263; X86-NEXT: pushl %edi 264; X86-NEXT: .cfi_def_cfa_offset 8 265; X86-NEXT: pushl %esi 266; X86-NEXT: .cfi_def_cfa_offset 12 267; X86-NEXT: subl $20, %esp 268; X86-NEXT: .cfi_def_cfa_offset 32 269; X86-NEXT: .cfi_offset %esi, -12 270; X86-NEXT: .cfi_offset %edi, -8 271; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 272; X86-NEXT: subl $8, %esp 273; X86-NEXT: .cfi_adjust_cfa_offset 8 274; X86-NEXT: leal {{[0-9]+}}(%esp), %eax 275; X86-NEXT: pushl $0 276; X86-NEXT: .cfi_adjust_cfa_offset 4 277; X86-NEXT: pushl $0 278; X86-NEXT: .cfi_adjust_cfa_offset 4 279; X86-NEXT: pushl $0 280; X86-NEXT: .cfi_adjust_cfa_offset 4 281; X86-NEXT: pushl $0 282; X86-NEXT: .cfi_adjust_cfa_offset 4 283; X86-NEXT: pushl $0 284; X86-NEXT: .cfi_adjust_cfa_offset 4 285; X86-NEXT: pushl $0 286; X86-NEXT: .cfi_adjust_cfa_offset 4 287; X86-NEXT: pushl $0 288; X86-NEXT: .cfi_adjust_cfa_offset 4 289; X86-NEXT: pushl $0 290; X86-NEXT: .cfi_adjust_cfa_offset 4 291; X86-NEXT: pushl {{[0-9]+}}(%esp) 292; X86-NEXT: .cfi_adjust_cfa_offset 4 293; X86-NEXT: pushl %eax 294; X86-NEXT: .cfi_adjust_cfa_offset 4 295; X86-NEXT: calll __sync_val_compare_and_swap_16 296; X86-NEXT: .cfi_adjust_cfa_offset -4 297; X86-NEXT: addl $44, %esp 298; X86-NEXT: .cfi_adjust_cfa_offset -44 299; X86-NEXT: movl (%esp), %eax 300; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 301; X86-NEXT: movl {{[0-9]+}}(%esp), %edx 302; X86-NEXT: movl {{[0-9]+}}(%esp), %edi 303; X86-NEXT: movl %edi, 8(%esi) 304; X86-NEXT: movl %edx, 12(%esi) 305; X86-NEXT: movl %eax, (%esi) 306; X86-NEXT: movl %ecx, 4(%esi) 307; X86-NEXT: movl %esi, %eax 308; X86-NEXT: addl $20, %esp 309; X86-NEXT: .cfi_def_cfa_offset 12 310; X86-NEXT: popl %esi 311; X86-NEXT: .cfi_def_cfa_offset 8 312; X86-NEXT: popl %edi 313; X86-NEXT: .cfi_def_cfa_offset 4 314; X86-NEXT: retl $4 315; 316; X64-LABEL: load_fp128: 317; X64: # %bb.0: 318; X64-NEXT: pushq %rax 319; X64-NEXT: .cfi_def_cfa_offset 16 320; X64-NEXT: xorl %esi, %esi 321; X64-NEXT: xorl %edx, %edx 322; X64-NEXT: xorl %ecx, %ecx 323; X64-NEXT: xorl %r8d, %r8d 324; X64-NEXT: callq __sync_val_compare_and_swap_16 325; X64-NEXT: popq %rcx 326; X64-NEXT: .cfi_def_cfa_offset 8 327; X64-NEXT: retq 328 %v = load atomic fp128, fp128* %fptr unordered, align 16 329 ret fp128 %v 330} 331 332 333; sanity check the seq_cst lowering since that's the 334; interesting one from an ordering perspective on x86. 335 336define void @store_float_seq_cst(float* %fptr, float %v) { 337; X86-LABEL: store_float_seq_cst: 338; X86: # %bb.0: 339; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 340; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 341; X86-NEXT: xchgl %ecx, (%eax) 342; X86-NEXT: retl 343; 344; X64-LABEL: store_float_seq_cst: 345; X64: # %bb.0: 346; X64-NEXT: movd %xmm0, %eax 347; X64-NEXT: xchgl %eax, (%rdi) 348; X64-NEXT: retq 349 store atomic float %v, float* %fptr seq_cst, align 4 350 ret void 351} 352 353define void @store_double_seq_cst(double* %fptr, double %v) { 354; X86-LABEL: store_double_seq_cst: 355; X86: # %bb.0: 356; X86-NEXT: pushl %ebx 357; X86-NEXT: .cfi_def_cfa_offset 8 358; X86-NEXT: pushl %esi 359; X86-NEXT: .cfi_def_cfa_offset 12 360; X86-NEXT: .cfi_offset %esi, -12 361; X86-NEXT: .cfi_offset %ebx, -8 362; X86-NEXT: movl {{[0-9]+}}(%esp), %esi 363; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx 364; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 365; X86-NEXT: movl (%esi), %eax 366; X86-NEXT: movl 4(%esi), %edx 367; X86-NEXT: .p2align 4, 0x90 368; X86-NEXT: .LBB9_1: # %atomicrmw.start 369; X86-NEXT: # =>This Inner Loop Header: Depth=1 370; X86-NEXT: lock cmpxchg8b (%esi) 371; X86-NEXT: jne .LBB9_1 372; X86-NEXT: # %bb.2: # %atomicrmw.end 373; X86-NEXT: popl %esi 374; X86-NEXT: .cfi_def_cfa_offset 8 375; X86-NEXT: popl %ebx 376; X86-NEXT: .cfi_def_cfa_offset 4 377; X86-NEXT: retl 378; 379; X64-LABEL: store_double_seq_cst: 380; X64: # %bb.0: 381; X64-NEXT: movq %xmm0, %rax 382; X64-NEXT: xchgq %rax, (%rdi) 383; X64-NEXT: retq 384 store atomic double %v, double* %fptr seq_cst, align 8 385 ret void 386} 387 388define float @load_float_seq_cst(float* %fptr) { 389; X86-SSE-LABEL: load_float_seq_cst: 390; X86-SSE: # %bb.0: 391; X86-SSE-NEXT: pushl %eax 392; X86-SSE-NEXT: .cfi_def_cfa_offset 8 393; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax 394; X86-SSE-NEXT: movl (%eax), %eax 395; X86-SSE-NEXT: movd %eax, %xmm0 396; X86-SSE-NEXT: movd %xmm0, (%esp) 397; X86-SSE-NEXT: flds (%esp) 398; X86-SSE-NEXT: popl %eax 399; X86-SSE-NEXT: .cfi_def_cfa_offset 4 400; X86-SSE-NEXT: retl 401; 402; X86-NOSSE-LABEL: load_float_seq_cst: 403; X86-NOSSE: # %bb.0: 404; X86-NOSSE-NEXT: pushl %eax 405; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 406; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax 407; X86-NOSSE-NEXT: movl (%eax), %eax 408; X86-NOSSE-NEXT: movl %eax, (%esp) 409; X86-NOSSE-NEXT: flds (%esp) 410; X86-NOSSE-NEXT: popl %eax 411; X86-NOSSE-NEXT: .cfi_def_cfa_offset 4 412; X86-NOSSE-NEXT: retl 413; 414; X64-LABEL: load_float_seq_cst: 415; X64: # %bb.0: 416; X64-NEXT: movl (%rdi), %eax 417; X64-NEXT: movd %eax, %xmm0 418; X64-NEXT: retq 419 %v = load atomic float, float* %fptr seq_cst, align 4 420 ret float %v 421} 422 423define double @load_double_seq_cst(double* %fptr) { 424; X86-SSE-LABEL: load_double_seq_cst: 425; X86-SSE: # %bb.0: 426; X86-SSE-NEXT: subl $12, %esp 427; X86-SSE-NEXT: .cfi_def_cfa_offset 16 428; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax 429; X86-SSE-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 430; X86-SSE-NEXT: movlps %xmm0, (%esp) 431; X86-SSE-NEXT: fldl (%esp) 432; X86-SSE-NEXT: addl $12, %esp 433; X86-SSE-NEXT: .cfi_def_cfa_offset 4 434; X86-SSE-NEXT: retl 435; 436; X86-NOSSE-LABEL: load_double_seq_cst: 437; X86-NOSSE: # %bb.0: 438; X86-NOSSE-NEXT: pushl %ebx 439; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 440; X86-NOSSE-NEXT: pushl %esi 441; X86-NOSSE-NEXT: .cfi_def_cfa_offset 12 442; X86-NOSSE-NEXT: subl $12, %esp 443; X86-NOSSE-NEXT: .cfi_def_cfa_offset 24 444; X86-NOSSE-NEXT: .cfi_offset %esi, -12 445; X86-NOSSE-NEXT: .cfi_offset %ebx, -8 446; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi 447; X86-NOSSE-NEXT: xorl %eax, %eax 448; X86-NOSSE-NEXT: xorl %edx, %edx 449; X86-NOSSE-NEXT: xorl %ecx, %ecx 450; X86-NOSSE-NEXT: xorl %ebx, %ebx 451; X86-NOSSE-NEXT: lock cmpxchg8b (%esi) 452; X86-NOSSE-NEXT: movl %edx, {{[0-9]+}}(%esp) 453; X86-NOSSE-NEXT: movl %eax, (%esp) 454; X86-NOSSE-NEXT: fldl (%esp) 455; X86-NOSSE-NEXT: addl $12, %esp 456; X86-NOSSE-NEXT: .cfi_def_cfa_offset 12 457; X86-NOSSE-NEXT: popl %esi 458; X86-NOSSE-NEXT: .cfi_def_cfa_offset 8 459; X86-NOSSE-NEXT: popl %ebx 460; X86-NOSSE-NEXT: .cfi_def_cfa_offset 4 461; X86-NOSSE-NEXT: retl 462; 463; X64-LABEL: load_double_seq_cst: 464; X64: # %bb.0: 465; X64-NEXT: movq (%rdi), %rax 466; X64-NEXT: movq %rax, %xmm0 467; X64-NEXT: retq 468 %v = load atomic double, double* %fptr seq_cst, align 8 469 ret double %v 470} 471