Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,13 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; Checks that atomic fences are simply removed from IR.
; AVR is always singlethreaded so fences do nothing.
; CHECK_LABEL: atomic_fence8
; CHECK: ; %bb.0:
; CHECK-NEXT: ret
define void @atomic_fence8() {
fence acquire
ret void
}

View File

@ -0,0 +1,23 @@
; RUN: llc < %s -march=avr | FileCheck %s
; At one point, the 16-vit atomic load/store operations we defined in TableGen
; to use 'PTRREGS', but the pseudo expander would generate LDDW/STDW instructions.
;
; This would sometimes cause codegen to fail because LDDW requires 'PTRDISPREGS', and
; so if we attempted to generate an atomic operation on the X register, it would hit
; an assertion;
%AtomicI16 = type { %UnsafeCell, [0 x i8] }
%UnsafeCell = type { i16, [0 x i8] }
; CHECK-LABEL: foo
define i8 @foo(%AtomicI16*) {
start:
; We should not be generating atomics that use the X register, they will fail when emitting MC.
; CHECK-NOT: X
%1 = getelementptr inbounds %AtomicI16, %AtomicI16* %0, i16 0, i32 0, i32 0
%2 = load atomic i16, i16* %1 seq_cst, align 2
ret i8 0
}

View File

@ -0,0 +1,137 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; CHECK-LABEL: atomic_load16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]+
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
; CHECK-NEXT: out 63, r0
define i16 @atomic_load16(i16* %foo) {
%val = load atomic i16, i16* %foo unordered, align 2
ret i16 %val
}
; CHECK-LABEL: atomic_load_swap16
; CHECK: call __sync_lock_test_and_set_2
define i16 @atomic_load_swap16(i16* %foo) {
%val = atomicrmw xchg i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_cmp_swap16
; CHECK: call __sync_val_compare_and_swap_2
define i16 @atomic_load_cmp_swap16(i16* %foo) {
%val = cmpxchg i16* %foo, i16 5, i16 10 acq_rel monotonic
%value_loaded = extractvalue { i16, i1 } %val, 0
ret i16 %value_loaded
}
; CHECK-LABEL: atomic_load_add16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
; CHECK-NEXT: add [[RR1]], [[TMP:r[0-9]+]]
; CHECK-NEXT: adc [[RR2]], [[TMP:r[0-9]+]]
; CHECK-NEXT: st [[RD1]], [[RR1]]
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define i16 @atomic_load_add16(i16* %foo) {
%val = atomicrmw add i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_sub16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
; CHECK-NEXT: sub [[RR1]], [[TMP:r[0-9]+]]
; CHECK-NEXT: sbc [[RR2]], [[TMP:r[0-9]+]]
; CHECK-NEXT: st [[RD1]], [[RR1]]
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define i16 @atomic_load_sub16(i16* %foo) {
%val = atomicrmw sub i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_and16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
; CHECK-NEXT: and [[RR1]], [[TMP:r[0-9]+]]
; CHECK-NEXT: and [[RR2]], [[TMP:r[0-9]+]]
; CHECK-NEXT: st [[RD1]], [[RR1]]
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define i16 @atomic_load_and16(i16* %foo) {
%val = atomicrmw and i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_or16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
; CHECK-NEXT: or [[RR1]], [[TMP:r[0-9]+]]
; CHECK-NEXT: or [[RR2]], [[TMP:r[0-9]+]]
; CHECK-NEXT: st [[RD1]], [[RR1]]
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define i16 @atomic_load_or16(i16* %foo) {
%val = atomicrmw or i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_xor16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR1:r[0-9]+]], [[RD1:(X|Y|Z)]]+
; CHECK-NEXT: ld [[RR2:r[0-9]+]], [[RD2:(X|Y|Z)]]
; CHECK-NEXT: eor [[RR1]], [[TMP:r[0-9]+]]
; CHECK-NEXT: eor [[RR2]], [[TMP:r[0-9]+]]
; CHECK-NEXT: st [[RD1]], [[RR1]]
; CHECK-NEXT: std [[RD1]]+1, [[A:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define i16 @atomic_load_xor16(i16* %foo) {
%val = atomicrmw xor i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_nand16
; CHECK: call __sync_fetch_and_nand_2
define i16 @atomic_load_nand16(i16* %foo) {
%val = atomicrmw nand i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_max16
; CHECK: call __sync_fetch_and_max_2
define i16 @atomic_load_max16(i16* %foo) {
%val = atomicrmw max i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_min16
; CHECK: call __sync_fetch_and_min_2
define i16 @atomic_load_min16(i16* %foo) {
%val = atomicrmw min i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_umax16
; CHECK: call __sync_fetch_and_umax_2
define i16 @atomic_load_umax16(i16* %foo) {
%val = atomicrmw umax i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_load_umin16
; CHECK: call __sync_fetch_and_umin_2
define i16 @atomic_load_umin16(i16* %foo) {
%val = atomicrmw umin i16* %foo, i16 13 seq_cst
ret i16 %val
}

View File

@ -0,0 +1,16 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; CHECK-LABEL: atomic_load32
; CHECK: call __sync_val_compare_and_swap_4
define i32 @atomic_load32(i32* %foo) {
%val = load atomic i32, i32* %foo unordered, align 4
ret i32 %val
}
; CHECK-LABEL: atomic_load_sub32
; CHECK: call __sync_fetch_and_sub_4
define i32 @atomic_load_sub32(i32* %foo) {
%val = atomicrmw sub i32* %foo, i32 13 seq_cst
ret i32 %val
}

View File

@ -0,0 +1,16 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; CHECK-LABEL: atomic_load64
; CHECK: call __sync_val_compare_and_swap_8
define i64 @atomic_load64(i64* %foo) {
%val = load atomic i64, i64* %foo unordered, align 8
ret i64 %val
}
; CHECK-LABEL: atomic_load_sub64
; CHECK: call __sync_fetch_and_sub_8
define i64 @atomic_load_sub64(i64* %foo) {
%val = atomicrmw sub i64* %foo, i64 13 seq_cst
ret i64 %val
}

View File

@ -0,0 +1,124 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; Tests atomic operations on AVR
; CHECK-LABEL: atomic_load8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
; CHECK-NEXT: out 63, r0
define i8 @atomic_load8(i8* %foo) {
%val = load atomic i8, i8* %foo unordered, align 1
ret i8 %val
}
; CHECK-LABEL: atomic_load_swap8
; CHECK: call __sync_lock_test_and_set_1
define i8 @atomic_load_swap8(i8* %foo) {
%val = atomicrmw xchg i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_cmp_swap8
; CHECK: call __sync_val_compare_and_swap_1
define i8 @atomic_load_cmp_swap8(i8* %foo) {
%val = cmpxchg i8* %foo, i8 5, i8 10 acq_rel monotonic
%value_loaded = extractvalue { i8, i1 } %val, 0
ret i8 %value_loaded
}
; CHECK-LABEL: atomic_load_add8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]
; CHECK-NEXT: add [[RD]], [[RR1:r[0-9]+]]
; CHECK-NEXT: st [[RR]], [[RD]]
; CHECK-NEXT: out 63, r0
define i8 @atomic_load_add8(i8* %foo) {
%val = atomicrmw add i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_sub8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]
; CHECK-NEXT: sub [[RD]], [[RR1:r[0-9]+]]
; CHECK-NEXT: st [[RR]], [[RD]]
; CHECK-NEXT: out 63, r0
define i8 @atomic_load_sub8(i8* %foo) {
%val = atomicrmw sub i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_and8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]
; CHECK-NEXT: and [[RD]], [[RR1:r[0-9]+]]
; CHECK-NEXT: st [[RR]], [[RD]]
; CHECK-NEXT: out 63, r0
define i8 @atomic_load_and8(i8* %foo) {
%val = atomicrmw and i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_or8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]
; CHECK-NEXT: or [[RD]], [[RR1:r[0-9]+]]
; CHECK-NEXT: st [[RR]], [[RD]]
; CHECK-NEXT: out 63, r0
define i8 @atomic_load_or8(i8* %foo) {
%val = atomicrmw or i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_xor8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: ld [[RD:r[0-9]+]], [[RR:(X|Y|Z)]]
; CHECK-NEXT: eor [[RD]], [[RR1:r[0-9]+]]
; CHECK-NEXT: st [[RR]], [[RD]]
; CHECK-NEXT: out 63, r0
define i8 @atomic_load_xor8(i8* %foo) {
%val = atomicrmw xor i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_nand8
; CHECK: call __sync_fetch_and_nand_1
define i8 @atomic_load_nand8(i8* %foo) {
%val = atomicrmw nand i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_max8
; CHECK: call __sync_fetch_and_max_1
define i8 @atomic_load_max8(i8* %foo) {
%val = atomicrmw max i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_min8
; CHECK: call __sync_fetch_and_min_1
define i8 @atomic_load_min8(i8* %foo) {
%val = atomicrmw min i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_umax8
; CHECK: call __sync_fetch_and_umax_1
define i8 @atomic_load_umax8(i8* %foo) {
%val = atomicrmw umax i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_load_umin8
; CHECK: call __sync_fetch_and_umin_1
define i8 @atomic_load_umin8(i8* %foo) {
%val = atomicrmw umin i8* %foo, i8 13 seq_cst
ret i8 %val
}

View File

@ -0,0 +1,37 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; CHECK-LABEL: atomic_store8
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define void @atomic_store8(i8* %foo) {
store atomic i8 1, i8* %foo unordered, align 1
ret void
}
; CHECK-LABEL: atomic_store16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]
; CHECK-NEXT: std [[RD]]+1, [[RR:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define void @atomic_store16(i16* %foo) {
store atomic i16 1, i16* %foo unordered, align 2
ret void
}
; CHECK-LABEL: atomic_store32
; CHECK: call __sync_lock_test_and_set_4
define void @atomic_store32(i32* %foo) {
store atomic i32 1, i32* %foo unordered, align 4
ret void
}
; CHECK-LABEL: atomic_store64
; CHECK: call __sync_lock_test_and_set_8
define void @atomic_store64(i64* %foo) {
store atomic i64 1, i64* %foo unordered, align 8
ret void
}

View File

@ -0,0 +1,25 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; CHECK-LABEL: atomic_store16
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]
; CHECK-NEXT: std [[RD:(X|Y|Z)]]+1, [[RR:r[0-9]+]]
; CHECK-NEXT: out 63, r0
define void @atomic_store16(i16* %foo) {
store atomic i16 1, i16* %foo unordered, align 2
ret void
}
; CHECK-LABEL: monotonic
; CHECK: in r0, 63
; CHECK-NEXT: cli
; CHECK-NEXT: st Z, r24
; CHECK-NEXT: std Z+1, r25
; CHECK-NEXT: out 63, r0
define void @monotonic(i16) {
entry-block:
store atomic i16 %0, i16* undef monotonic, align 2
ret void
}

View File

@ -0,0 +1,30 @@
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
; CHECK-LABEL: atomic_swap8
; CHECK: call __sync_lock_test_and_set_1
define i8 @atomic_swap8(i8* %foo) {
%val = atomicrmw xchg i8* %foo, i8 13 seq_cst
ret i8 %val
}
; CHECK-LABEL: atomic_swap16
; CHECK: call __sync_lock_test_and_set_2
define i16 @atomic_swap16(i16* %foo) {
%val = atomicrmw xchg i16* %foo, i16 13 seq_cst
ret i16 %val
}
; CHECK-LABEL: atomic_swap32
; CHECK: call __sync_lock_test_and_set_4
define i32 @atomic_swap32(i32* %foo) {
%val = atomicrmw xchg i32* %foo, i32 13 seq_cst
ret i32 %val
}
; CHECK-LABEL: atomic_swap64
; CHECK: call __sync_lock_test_and_set_8
define i64 @atomic_swap64(i64* %foo) {
%val = atomicrmw xchg i64* %foo, i64 13 seq_cst
ret i64 %val
}