; CHECK-NOT: cmp
; CHECK: sete %al
; CHECK: retq
- %old = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
- %success = icmp eq i32 %old, %desired
+ %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
+ %success = extractvalue { i32, i1 } %pair, 1
ret i1 %success
}
; CHECK-NOT: cmp
; CHECK-NOT: set
; CHECK: {{jne|jeq}}
- %old = cmpxchg i64* %addr, i64 %desired, i64 %new seq_cst seq_cst
- %success = icmp eq i64 %old, %desired
+ %pair = cmpxchg i64* %addr, i64 %desired, i64 %new seq_cst seq_cst
+ %success = extractvalue { i64, i1 } %pair, 1
br i1 %success, label %true, label %false
true:
ret void
}
-define i1 @cmpxchg_arithcmp(i16* %addr, i16 %desired, i16 %new) {
-; CHECK-LABEL: cmpxchg_arithcmp:
-; CHECK: cmpxchgw
-; CHECK-NOT: cmp
-; CHECK: setbe %al
-; CHECK: retq
- %old = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst seq_cst
- %success = icmp uge i16 %old, %desired
- ret i1 %success
-}
-
-define i1 @cmpxchg_arithcmp_swapped(i8* %addr, i8 %desired, i8 %new) {
-; CHECK-LABEL: cmpxchg_arithcmp_swapped:
-; CHECK: cmpxchgb
-; CHECK-NOT: cmp
-; CHECK: setge %al
-; CHECK: retq
- %old = cmpxchg i8* %addr, i8 %desired, i8 %new seq_cst seq_cst
- %success = icmp sge i8 %desired, %old
- ret i1 %success
-}
-
define i64 @cmpxchg_sext(i32* %addr, i32 %desired, i32 %new) {
; CHECK-LABEL: cmpxchg_sext:
; CHECK-DAG: cmpxchgl
-; CHECK-DAG: movq $-1, %rax
-; CHECK-DAG: xorl %e[[ZERO:[a-z0-9]+]], %e[[ZERO]]
; CHECK-NOT: cmpl
-; CHECK: cmovneq %r[[ZERO]], %rax
+; CHECK: sete %al
; CHECK: retq
- %old = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
- %success = icmp eq i32 %old, %desired
+ %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
+ %success = extractvalue { i32, i1 } %pair, 1
%mask = sext i1 %success to i64
ret i64 %mask
}
; CHECK-NOT: cmp
; CHECK: sete [[BYTE:%[a-z0-9]+]]
; CHECK: movzbl [[BYTE]], %eax
- %old = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
- %success = icmp eq i32 %old, %desired
+ %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst
+ %success = extractvalue { i32, i1 } %pair, 1
%mask = zext i1 %success to i32
ret i32 %mask
}
+
+define i32 @cmpxchg_use_eflags_and_val(i32* %addr, i32 %offset) {
+; CHECK-LABEL: cmpxchg_use_eflags_and_val:
+; CHECK: movl (%rdi), %e[[OLDVAL:[a-z0-9]+]]
+
+; CHECK: [[LOOPBB:.?LBB[0-9]+_[0-9]+]]:
+; CHECK: leal (%r[[OLDVAL]],%rsi), [[NEW:%[a-z0-9]+]]
+; CHECK: cmpxchgl [[NEW]], (%rdi)
+; CHECK-NOT: cmpl
+; CHECK: jne [[LOOPBB]]
+
+ ; Result already in %eax
+; CHECK: retq
+entry:
+ %init = load atomic i32, i32* %addr seq_cst, align 4
+ br label %loop
+
+loop:
+ %old = phi i32 [%init, %entry], [%oldval, %loop]
+ %new = add i32 %old, %offset
+ %pair = cmpxchg i32* %addr, i32 %old, i32 %new seq_cst seq_cst
+ %oldval = extractvalue { i32, i1 } %pair, 0
+ %success = extractvalue { i32, i1 } %pair, 1
+ br i1 %success, label %done, label %loop
+
+done:
+ ret i32 %oldval
+}
+
declare void @foo()
declare void @bar()