33 changes: 33 additions & 0 deletions llvm/test/CodeGen/X86/atomic32.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
; RUN: llc < %s -O0 -mtriple=i686-unknown-unknown -mcpu=corei7 -mattr=-cmov,-sse -verify-machineinstrs | FileCheck %s --check-prefixes=X86,X86-NOCMOV

@sc32 = external global i32
@fsc32 = external global float

define void @atomic_fetch_add32() nounwind {
; X64-LABEL: atomic_fetch_add32:
Expand Down Expand Up @@ -708,3 +709,35 @@ define void @atomic_fetch_swap32(i32 %x) nounwind {
%t1 = atomicrmw xchg i32* @sc32, i32 %x acquire
ret void
}

define void @atomic_fetch_swapf32(float %x) nounwind {
; X64-LABEL: atomic_fetch_swapf32:
; X64: # %bb.0:
; X64-NEXT: movd %xmm0, %eax
; X64-NEXT: xchgl %eax, {{.*}}(%rip)
; X64-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
; X64-NEXT: retq
;
; X86-CMOV-LABEL: atomic_fetch_swapf32:
; X86-CMOV: # %bb.0:
; X86-CMOV-NEXT: pushl %eax
; X86-CMOV-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
; X86-CMOV-NEXT: movd %xmm0, %eax
; X86-CMOV-NEXT: xchgl %eax, fsc32
; X86-CMOV-NEXT: movl %eax, (%esp) # 4-byte Spill
; X86-CMOV-NEXT: popl %eax
; X86-CMOV-NEXT: retl
;
; X86-NOCMOV-LABEL: atomic_fetch_swapf32:
; X86-NOCMOV: # %bb.0:
; X86-NOCMOV-NEXT: subl $8, %esp
; X86-NOCMOV-NEXT: flds {{[0-9]+}}(%esp)
; X86-NOCMOV-NEXT: fstps {{[0-9]+}}(%esp)
; X86-NOCMOV-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NOCMOV-NEXT: xchgl %eax, fsc32
; X86-NOCMOV-NEXT: movl %eax, (%esp) # 4-byte Spill
; X86-NOCMOV-NEXT: addl $8, %esp
; X86-NOCMOV-NEXT: retl
%t1 = atomicrmw xchg float* @fsc32, float %x acquire
ret void
}
14 changes: 14 additions & 0 deletions llvm/test/CodeGen/X86/atomic64.ll
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
; RUN: llc < %s -O0 -mtriple=x86_64-- -mcpu=corei7 -verify-machineinstrs | FileCheck %s --check-prefix X64

@sc64 = external global i64
@fsc64 = external global double

define void @atomic_fetch_add64() nounwind {
; X64-LABEL: atomic_fetch_add64:
Expand Down Expand Up @@ -233,3 +234,16 @@ define void @atomic_fetch_swap64(i64 %x) nounwind {
; X64: ret
; X32: ret
}

define void @atomic_fetch_swapf64(double %x) nounwind {
; X64-LABEL: atomic_fetch_swapf64:
; X32-LABEL: atomic_fetch_swapf64:
%t1 = atomicrmw xchg double* @fsc64, double %x acquire
; X64-NOT: lock
; X64: xchgq
; X32: lock
; X32: xchg8b
ret void
; X64: ret
; X32: ret
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -mtriple=aarch64-- -atomic-expand %s | FileCheck %s

define void @atomic_swap_f16(half* %ptr, half %val) nounwind {
; CHECK-LABEL: @atomic_swap_f16(
; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
; CHECK: atomicrmw.start:
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.aarch64.ldaxr.p0f16(half* [[PTR:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i16
; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half
; CHECK-NEXT: [[TMP4:%.*]] = bitcast half [[VAL:%.*]] to i16
; CHECK-NEXT: [[TMP5:%.*]] = zext i16 [[TMP4]] to i64
; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.aarch64.stxr.p0f16(i64 [[TMP5]], half* [[PTR]])
; CHECK-NEXT: [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP6]], 0
; CHECK-NEXT: br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label [[ATOMICRMW_END:%.*]]
; CHECK: atomicrmw.end:
; CHECK-NEXT: ret void
;
%t1 = atomicrmw xchg half* %ptr, half %val acquire
ret void
}

define void @atomic_swap_f32(float* %ptr, float %val) nounwind {
; CHECK-LABEL: @atomic_swap_f32(
; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
; CHECK: atomicrmw.start:
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.aarch64.ldaxr.p0f32(float* [[PTR:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[VAL:%.*]] to i32
; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP4]] to i64
; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.aarch64.stxr.p0f32(i64 [[TMP5]], float* [[PTR]])
; CHECK-NEXT: [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP6]], 0
; CHECK-NEXT: br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label [[ATOMICRMW_END:%.*]]
; CHECK: atomicrmw.end:
; CHECK-NEXT: ret void
;
%t1 = atomicrmw xchg float* %ptr, float %val acquire
ret void
}

define void @atomic_swap_f64(double* %ptr, double %val) nounwind {
; CHECK-LABEL: @atomic_swap_f64(
; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
; CHECK: atomicrmw.start:
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.aarch64.ldaxr.p0f64(double* [[PTR:%.*]])
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to double
; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[VAL:%.*]] to i64
; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.aarch64.stxr.p0f64(i64 [[TMP3]], double* [[PTR]])
; CHECK-NEXT: [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP4]], 0
; CHECK-NEXT: br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label [[ATOMICRMW_END:%.*]]
; CHECK: atomicrmw.end:
; CHECK-NEXT: ret void
;
%t1 = atomicrmw xchg double* %ptr, double %val acquire
ret void
}
3 changes: 3 additions & 0 deletions llvm/test/Transforms/AtomicExpand/AArch64/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if not 'AArch64' in config.root.targets:
config.unsupported = True

42 changes: 42 additions & 0 deletions llvm/test/Transforms/AtomicExpand/X86/expand-atomic-xchg-fp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -mtriple=i686-linux-gnu -atomic-expand %s | FileCheck %s

define double @atomic_xchg_f64(double* %ptr) nounwind {
; CHECK-LABEL: @atomic_xchg_f64(
; CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[PTR:%.*]], align 8
; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
; CHECK: atomicrmw.start:
; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ]
; CHECK-NEXT: [[TMP2:%.*]] = bitcast double* [[PTR]] to i64*
; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64
; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg i64* [[TMP2]], i64 [[TMP3]], i64 4616189618054758400 seq_cst seq_cst
; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1
; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0
; CHECK-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double
; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
; CHECK: atomicrmw.end:
; CHECK-NEXT: ret double [[TMP5]]
;
%result = atomicrmw xchg double* %ptr, double 4.0 seq_cst
ret double %result
}

define double @atomic_xchg_f64_as1(double addrspace(1)* %ptr) nounwind {
; CHECK-LABEL: @atomic_xchg_f64_as1(
; CHECK-NEXT: [[TMP1:%.*]] = load double, double addrspace(1)* [[PTR:%.*]], align 8
; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
; CHECK: atomicrmw.start:
; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP5:%.*]], [[ATOMICRMW_START]] ]
; CHECK-NEXT: [[TMP2:%.*]] = bitcast double addrspace(1)* [[PTR]] to i64 addrspace(1)*
; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[LOADED]] to i64
; CHECK-NEXT: [[TMP4:%.*]] = cmpxchg i64 addrspace(1)* [[TMP2]], i64 [[TMP3]], i64 4616189618054758400 seq_cst seq_cst
; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP4]], 1
; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP4]], 0
; CHECK-NEXT: [[TMP5]] = bitcast i64 [[NEWLOADED]] to double
; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
; CHECK: atomicrmw.end:
; CHECK-NEXT: ret double [[TMP5]]
;
%result = atomicrmw xchg double addrspace(1)* %ptr, double 4.0 seq_cst
ret double %result
}