2014-08-22 05:50:01 +08:00
|
|
|
; RUN: opt -S -o - -mtriple=armv7-apple-ios7.0 -atomic-expand %s | FileCheck %s
|
2014-04-18 02:22:47 +08:00
|
|
|
|
|
|
|
define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_xchg_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw xchg i8* %ptr, i8 %xchgend monotonic
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_add_i16
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i16 [[OLDVAL]]
|
|
|
|
%res = atomicrmw add i16* %ptr, i16 %addend seq_cst
|
|
|
|
ret i16 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_sub_i32
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr)
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i32 [[OLDVAL]]
|
|
|
|
%res = atomicrmw sub i32* %ptr, i32 %subend acquire
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_and_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = and i8 [[OLDVAL]], %andend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw and i8* %ptr, i8 %andend release
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_nand_i16
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16
|
2014-07-07 17:06:35 +08:00
|
|
|
; CHECK: [[NEWVAL_TMP:%.*]] = and i16 [[OLDVAL]], %nandend
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = xor i16 [[NEWVAL_TMP]], -1
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i16 [[OLDVAL]]
|
|
|
|
%res = atomicrmw nand i16* %ptr, i16 %nandend seq_cst
|
|
|
|
ret i16 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_or_i64
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8*
|
|
|
|
; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]])
|
|
|
|
; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
|
|
|
|
; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
|
|
|
|
; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64
|
|
|
|
; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64
|
|
|
|
; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]]
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = or i64 [[OLDVAL]], %orend
|
|
|
|
; CHECK: [[NEWLO:%.*]] = trunc i64 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 [[NEWVAL]], 32
|
|
|
|
; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32
|
|
|
|
; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8*
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]])
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i64 [[OLDVAL]]
|
|
|
|
%res = atomicrmw or i64* %ptr, i64 %orend seq_cst
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_xor_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = xor i8 [[OLDVAL]], %xorend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw xor i8* %ptr, i8 %xorend seq_cst
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_max_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[WANT_OLD:%.*]] = icmp sgt i8 [[OLDVAL]], %maxend
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %maxend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw max i8* %ptr, i8 %maxend seq_cst
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_min_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[WANT_OLD:%.*]] = icmp sle i8 [[OLDVAL]], %minend
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %minend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw min i8* %ptr, i8 %minend seq_cst
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_umax_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[WANT_OLD:%.*]] = icmp ugt i8 [[OLDVAL]], %umaxend
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %umaxend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw umax i8* %ptr, i8 %umaxend seq_cst
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) {
|
|
|
|
; CHECK-LABEL: @test_atomic_umin_i8
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8
|
|
|
|
; CHECK: [[WANT_OLD:%.*]] = icmp ule i8 [[OLDVAL]], %uminend
|
|
|
|
; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %uminend
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
|
|
|
; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0
|
|
|
|
; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]
|
|
|
|
; CHECK: [[END]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
%res = atomicrmw umin i8* %ptr, i8 %uminend seq_cst
|
|
|
|
ret i8 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) {
|
|
|
|
; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i8
|
|
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr)
|
2014-06-14 00:45:36 +08:00
|
|
|
; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[DONE:.*]]
|
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[FAILURE_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br label %[[DONE]]
|
|
|
|
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: [[DONE]]:
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i8 [[OLDVAL]]
|
|
|
|
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
%pairold = cmpxchg i8* %ptr, i8 %desired, i8 %newval seq_cst seq_cst
|
|
|
|
%old = extractvalue { i8, i1 } %pairold, 0
|
2014-04-18 02:22:47 +08:00
|
|
|
ret i8 %old
|
|
|
|
}
|
|
|
|
|
|
|
|
define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newval) {
|
|
|
|
; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr)
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16
|
|
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
|
|
; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr)
|
2014-06-14 00:45:36 +08:00
|
|
|
; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[DONE:.*]]
|
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[FAILURE_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br label %[[DONE]]
|
|
|
|
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: [[DONE]]:
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i16 [[OLDVAL]]
|
|
|
|
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
%pairold = cmpxchg i16* %ptr, i16 %desired, i16 %newval seq_cst monotonic
|
|
|
|
%old = extractvalue { i16, i1 } %pairold, 0
|
2014-04-18 02:22:47 +08:00
|
|
|
ret i16 %old
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newval) {
|
|
|
|
; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr)
|
|
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr)
|
2014-06-14 00:45:36 +08:00
|
|
|
; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[DONE:.*]]
|
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[FAILURE_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK: call void @llvm.arm.dmb(i32 11)
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br label %[[DONE]]
|
|
|
|
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: [[DONE]]:
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i32 [[OLDVAL]]
|
|
|
|
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
%pairold = cmpxchg i32* %ptr, i32 %desired, i32 %newval acquire acquire
|
|
|
|
%old = extractvalue { i32, i1 } %pairold, 0
|
2014-04-18 02:22:47 +08:00
|
|
|
ret i32 %old
|
|
|
|
}
|
|
|
|
|
|
|
|
define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %newval) {
|
|
|
|
; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[LOOP:.*]]
|
|
|
|
|
|
|
|
; CHECK: [[LOOP]]:
|
|
|
|
; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8*
|
|
|
|
; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]])
|
|
|
|
; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
|
|
|
|
; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
|
|
|
|
; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64
|
|
|
|
; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64
|
|
|
|
; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32
|
|
|
|
; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]]
|
|
|
|
; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i64 [[OLDVAL]], %desired
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
|
|
|
; CHECK: [[TRY_STORE]]:
|
|
|
|
; CHECK: [[NEWLO:%.*]] = trunc i64 %newval to i32
|
|
|
|
; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 %newval, 32
|
|
|
|
; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32
|
|
|
|
; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8*
|
|
|
|
; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]])
|
2014-06-14 00:45:36 +08:00
|
|
|
; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]
|
2014-04-18 02:22:47 +08:00
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: br label %[[DONE:.*]]
|
|
|
|
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[FAILURE_BB]]:
|
2014-09-04 05:01:03 +08:00
|
|
|
; CHECK-NOT: dmb
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: br label %[[DONE]]
|
|
|
|
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: [[DONE]]:
|
2014-06-14 00:45:52 +08:00
|
|
|
; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]
|
2014-04-18 02:22:47 +08:00
|
|
|
; CHECK: ret i64 [[OLDVAL]]
|
|
|
|
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
%pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic
|
|
|
|
%old = extractvalue { i64, i1 } %pairold, 0
|
2014-04-18 02:22:47 +08:00
|
|
|
ret i64 %old
|
2014-08-22 05:50:01 +08:00
|
|
|
}
|