1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown -mcpu=core-avx2 | FileCheck %s 3 4define i1 @try_cmpxchg(i128* %addr, i128 %desired, i128 %new) { 5; CHECK-LABEL: try_cmpxchg: 6; CHECK: # %bb.0: 7; CHECK-NEXT: pushq %rbx 8; CHECK-NEXT: .cfi_def_cfa_offset 16 9; CHECK-NEXT: .cfi_offset %rbx, -16 10; CHECK-NEXT: movq %rcx, %r9 11; CHECK-NEXT: movq %rsi, %rax 12; CHECK-NEXT: movq %r8, %rcx 13; CHECK-NEXT: movq %r9, %rbx 14; CHECK-NEXT: lock cmpxchg16b (%rdi) 15; CHECK-NEXT: sete %al 16; CHECK-NEXT: popq %rbx 17; CHECK-NEXT: .cfi_def_cfa_offset 8 18; CHECK-NEXT: retq 19 %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst 20 %success = extractvalue { i128, i1 } %pair, 1 21 ret i1 %success 22} 23 24define void @cmpxchg_flow(i128* %addr, i128 %desired, i128 %new) { 25; CHECK-LABEL: cmpxchg_flow: 26; CHECK: # %bb.0: 27; CHECK-NEXT: pushq %rbx 28; CHECK-NEXT: .cfi_def_cfa_offset 16 29; CHECK-NEXT: .cfi_offset %rbx, -16 30; CHECK-NEXT: movq %rcx, %r9 31; CHECK-NEXT: movq %rsi, %rax 32; CHECK-NEXT: movq %r8, %rcx 33; CHECK-NEXT: movq %r9, %rbx 34; CHECK-NEXT: lock cmpxchg16b (%rdi) 35; CHECK-NEXT: jne .LBB1_2 36; CHECK-NEXT: # %bb.1: # %true 37; CHECK-NEXT: callq foo 38; CHECK-NEXT: popq %rbx 39; CHECK-NEXT: .cfi_def_cfa_offset 8 40; CHECK-NEXT: retq 41; CHECK-NEXT: .LBB1_2: # %false 42; CHECK-NEXT: .cfi_def_cfa_offset 16 43; CHECK-NEXT: callq bar 44; CHECK-NEXT: popq %rbx 45; CHECK-NEXT: .cfi_def_cfa_offset 8 46; CHECK-NEXT: retq 47 %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst 48 %success = extractvalue { i128, i1 } %pair, 1 49 br i1 %success, label %true, label %false 50 51true: 52 call void @foo() 53 ret void 54 55false: 56 call void @bar() 57 ret void 58} 59 60; Can't use the flags here because cmpxchg16b only sets ZF. 61define i1 @cmpxchg_arithcmp(i128* %addr, i128 %desired, i128 %new) { 62; CHECK-LABEL: cmpxchg_arithcmp: 63; CHECK: # %bb.0: 64; CHECK-NEXT: pushq %rbx 65; CHECK-NEXT: .cfi_def_cfa_offset 16 66; CHECK-NEXT: .cfi_offset %rbx, -16 67; CHECK-NEXT: movq %rcx, %r9 68; CHECK-NEXT: movq %rdx, %r10 69; CHECK-NEXT: movq %rsi, %rax 70; CHECK-NEXT: movq %r8, %rcx 71; CHECK-NEXT: movq %r9, %rbx 72; CHECK-NEXT: lock cmpxchg16b (%rdi) 73; CHECK-NEXT: cmpq %rsi, %rax 74; CHECK-NEXT: sbbq %r10, %rdx 75; CHECK-NEXT: setge %al 76; CHECK-NEXT: popq %rbx 77; CHECK-NEXT: .cfi_def_cfa_offset 8 78; CHECK-NEXT: retq 79 %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst 80 %oldval = extractvalue { i128, i1 } %pair, 0 81 %success = icmp sge i128 %oldval, %desired 82 ret i1 %success 83} 84 85define i128 @cmpxchg_zext(i128* %addr, i128 %desired, i128 %new) { 86; CHECK-LABEL: cmpxchg_zext: 87; CHECK: # %bb.0: 88; CHECK-NEXT: pushq %rbx 89; CHECK-NEXT: .cfi_def_cfa_offset 16 90; CHECK-NEXT: .cfi_offset %rbx, -16 91; CHECK-NEXT: movq %rcx, %r9 92; CHECK-NEXT: xorl %r10d, %r10d 93; CHECK-NEXT: movq %rsi, %rax 94; CHECK-NEXT: movq %r8, %rcx 95; CHECK-NEXT: movq %r9, %rbx 96; CHECK-NEXT: lock cmpxchg16b (%rdi) 97; CHECK-NEXT: sete %r10b 98; CHECK-NEXT: xorl %edx, %edx 99; CHECK-NEXT: movq %r10, %rax 100; CHECK-NEXT: popq %rbx 101; CHECK-NEXT: .cfi_def_cfa_offset 8 102; CHECK-NEXT: retq 103 %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst 104 %success = extractvalue { i128, i1 } %pair, 1 105 %mask = zext i1 %success to i128 106 ret i128 %mask 107} 108 109 110define i128 @cmpxchg_use_eflags_and_val(i128* %addr, i128 %offset) { 111; CHECK-LABEL: cmpxchg_use_eflags_and_val: 112; CHECK: # %bb.0: # %entry 113; CHECK-NEXT: pushq %rbx 114; CHECK-NEXT: .cfi_def_cfa_offset 16 115; CHECK-NEXT: .cfi_offset %rbx, -16 116; CHECK-NEXT: movq %rdx, %r8 117; CHECK-NEXT: xorl %eax, %eax 118; CHECK-NEXT: xorl %edx, %edx 119; CHECK-NEXT: xorl %ecx, %ecx 120; CHECK-NEXT: xorl %ebx, %ebx 121; CHECK-NEXT: lock cmpxchg16b (%rdi) 122; CHECK-NEXT: .p2align 4, 0x90 123; CHECK-NEXT: .LBB4_1: # %loop 124; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 125; CHECK-NEXT: movq %rdx, %r9 126; CHECK-NEXT: movq %rax, %r10 127; CHECK-NEXT: movq %rax, %rbx 128; CHECK-NEXT: addq %rsi, %rbx 129; CHECK-NEXT: movq %rdx, %rcx 130; CHECK-NEXT: adcq %r8, %rcx 131; CHECK-NEXT: lock cmpxchg16b (%rdi) 132; CHECK-NEXT: jne .LBB4_1 133; CHECK-NEXT: # %bb.2: # %done 134; CHECK-NEXT: movq %r10, %rax 135; CHECK-NEXT: movq %r9, %rdx 136; CHECK-NEXT: popq %rbx 137; CHECK-NEXT: .cfi_def_cfa_offset 8 138; CHECK-NEXT: retq 139entry: 140 %init = load atomic i128, i128* %addr seq_cst, align 16 141 br label %loop 142 143loop: 144 %old = phi i128 [%init, %entry], [%oldval, %loop] 145 %new = add i128 %old, %offset 146 147 %pair = cmpxchg i128* %addr, i128 %old, i128 %new seq_cst seq_cst 148 %oldval = extractvalue { i128, i1 } %pair, 0 149 %success = extractvalue { i128, i1 } %pair, 1 150 151 br i1 %success, label %done, label %loop 152 153done: 154 ret i128 %old 155} 156 157declare void @foo() 158declare void @bar() 159