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 4 define 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 24 define 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 51 true: 52 call void @foo() 53 ret void 54 55 false: 56 call void @bar() 57 ret void 58 } 59 60 ; Can't use the flags here because cmpxchg16b only sets ZF. 61 define 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 85 define 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 110 define 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 139 entry: 140 %init = load atomic i128, i128* %addr seq_cst, align 16 141 br label %loop 142 143 loop: 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 153 done: 154 ret i128 %old 155 } 156 157 declare void @foo() 158 declare void @bar() 159