Files
clang-p2996/llvm/test/Transforms/AtomicExpand/PowerPC/cmpxchg.ll
Kai Luo 18679ac0d7 [PowerPC] Adjust MaxAtomicSizeInBitsSupported on PPC64
AtomicExpandPass uses this variable to determine emitting libcalls or not. The default value is 1024 and if we don't specify it for PPC64 explicitly, AtomicExpandPass won't emit `__atomic_*` libcalls for those target unable to inline atomic ops and finally the backend emits `__sync_*` libcalls. Thanks @efriedma for pointing it out.

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D122868
2022-04-09 00:03:09 +00:00

60 lines
3.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -atomic-expand -S -mtriple=powerpc64-unknown-unknown \
; RUN: -ppc-quadword-atomics -mcpu=pwr8 %s | FileCheck %s
; RUN: opt -atomic-expand -S -mtriple=powerpc64-unknown-unknown \
; RUN: -mcpu=pwr7 %s | FileCheck --check-prefix=PWR7 %s
define i1 @test_cmpxchg_seq_cst(i128* %addr, i128 %desire, i128 %new) {
; CHECK-LABEL: @test_cmpxchg_seq_cst(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMPVAL_SHIFTED:%.*]] = shl i128 [[DESIRE:%.*]], 0
; CHECK-NEXT: [[NEWVAL_SHIFTED:%.*]] = shl i128 [[NEW:%.*]], 0
; CHECK-NEXT: [[CMP_LO:%.*]] = trunc i128 [[CMPVAL_SHIFTED]] to i64
; CHECK-NEXT: [[TMP0:%.*]] = lshr i128 [[CMPVAL_SHIFTED]], 64
; CHECK-NEXT: [[CMP_HI:%.*]] = trunc i128 [[TMP0]] to i64
; CHECK-NEXT: [[NEW_LO:%.*]] = trunc i128 [[NEWVAL_SHIFTED]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = lshr i128 [[NEWVAL_SHIFTED]], 64
; CHECK-NEXT: [[NEW_HI:%.*]] = trunc i128 [[TMP1]] to i64
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i128* [[ADDR:%.*]] to i8*
; CHECK-NEXT: call void @llvm.ppc.sync()
; CHECK-NEXT: [[TMP3:%.*]] = call { i64, i64 } @llvm.ppc.cmpxchg.i128(i8* [[TMP2]], i64 [[CMP_LO]], i64 [[CMP_HI]], i64 [[NEW_LO]], i64 [[NEW_HI]])
; CHECK-NEXT: call void @llvm.ppc.lwsync()
; CHECK-NEXT: [[LO:%.*]] = extractvalue { i64, i64 } [[TMP3]], 0
; CHECK-NEXT: [[HI:%.*]] = extractvalue { i64, i64 } [[TMP3]], 1
; CHECK-NEXT: [[LO64:%.*]] = zext i64 [[LO]] to i128
; CHECK-NEXT: [[HI64:%.*]] = zext i64 [[HI]] to i128
; CHECK-NEXT: [[TMP4:%.*]] = shl i128 [[HI64]], 64
; CHECK-NEXT: [[VAL64:%.*]] = or i128 [[LO64]], [[TMP4]]
; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i128, i1 } undef, i128 [[VAL64]], 0
; CHECK-NEXT: [[TMP6:%.*]] = and i128 [[VAL64]], -1
; CHECK-NEXT: [[SUCCESS:%.*]] = icmp eq i128 [[CMPVAL_SHIFTED]], [[TMP6]]
; CHECK-NEXT: [[TMP7:%.*]] = insertvalue { i128, i1 } [[TMP5]], i1 [[SUCCESS]], 1
; CHECK-NEXT: [[SUCC:%.*]] = extractvalue { i128, i1 } [[TMP7]], 1
; CHECK-NEXT: ret i1 [[SUCC]]
;
; PWR7-LABEL: @test_cmpxchg_seq_cst(
; PWR7-NEXT: entry:
; PWR7-NEXT: [[TMP0:%.*]] = bitcast i128* [[ADDR:%.*]] to i8*
; PWR7-NEXT: [[TMP1:%.*]] = alloca i128, align 8
; PWR7-NEXT: [[TMP2:%.*]] = bitcast i128* [[TMP1]] to i8*
; PWR7-NEXT: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[TMP2]])
; PWR7-NEXT: store i128 [[DESIRE:%.*]], i128* [[TMP1]], align 8
; PWR7-NEXT: [[TMP3:%.*]] = alloca i128, align 8
; PWR7-NEXT: [[TMP4:%.*]] = bitcast i128* [[TMP3]] to i8*
; PWR7-NEXT: call void @llvm.lifetime.start.p0i8(i64 16, i8* [[TMP4]])
; PWR7-NEXT: store i128 [[NEW:%.*]], i128* [[TMP3]], align 8
; PWR7-NEXT: [[TMP5:%.*]] = call zeroext i1 @__atomic_compare_exchange(i64 16, i8* [[TMP0]], i8* [[TMP2]], i8* [[TMP4]], i32 5, i32 5)
; PWR7-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* [[TMP4]])
; PWR7-NEXT: [[TMP6:%.*]] = load i128, i128* [[TMP1]], align 8
; PWR7-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* [[TMP2]])
; PWR7-NEXT: [[TMP7:%.*]] = insertvalue { i128, i1 } undef, i128 [[TMP6]], 0
; PWR7-NEXT: [[TMP8:%.*]] = insertvalue { i128, i1 } [[TMP7]], i1 [[TMP5]], 1
; PWR7-NEXT: [[SUCC:%.*]] = extractvalue { i128, i1 } [[TMP8]], 1
; PWR7-NEXT: ret i1 [[SUCC]]
;
entry:
%pair = cmpxchg weak i128* %addr, i128 %desire, i128 %new seq_cst seq_cst
%succ = extractvalue {i128, i1} %pair, 1
ret i1 %succ
}