Imported Upstream version 5.18.0.207

Former-commit-id: 3b152f462918d427ce18620a2cbe4f8b79650449
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-11-17 08:23:10 +00:00
parent 8e12397d70
commit eb85e2fc17
28480 changed files with 72 additions and 3866936 deletions

View File

@ -1,35 +0,0 @@
; RUN: llc < %s -march=avr | FileCheck %s
; Unit test for: PR 31344
define i16 @or16_reg_imm_0xff00(i16 %a) {
; CHECK-LABEL: or16_reg_imm_0xff00
; CHECK-NOT: ori {{r[0-9]+}}, 0
; CHECK: ori {{r[0-9]+}}, 255
%result = or i16 %a, 65280
ret i16 %result
}
define i16 @or16_reg_imm_0xffb3(i16 %a) {
; CHECK-LABEL: or16_reg_imm_0xffb3
; CHECK: ori {{r[0-9]+}}, 179
; CHECK: ori {{r[0-9]+}}, 255
%result = or i16 %a, 65459
ret i16 %result
}
define i16 @or16_reg_imm_0x00ff(i16 %a) {
; CHECK-LABEL: or16_reg_imm_0x00ff
; CHECK: ori {{r[0-9]+}}, 255
; CHECK-NOT: ori {{r[0-9]+}}, 0
%result = or i16 %a, 255
ret i16 %result
}
define i16 @or16_reg_imm_0xb3ff(i16 %a) {
; CHECK-LABEL: or16_reg_imm_0xb3ff
; CHECK: ori {{r[0-9]+}}, 255
; CHECK: ori {{r[0-9]+}}, 179
%result = or i16 %a, 46079
ret i16 %result
}

View File

@ -1,51 +0,0 @@
; RUN: llc < %s -march=avr | FileCheck %s
; Unit test for: PR 31345
define i16 @and16_reg_imm_0xff00(i16 %a) {
; CHECK-LABEL: and16_reg_imm_0xff00
; CHECK: andi {{r[0-9]+}}, 0
; CHECK-NOT: andi {{r[0-9]+}}, 255
%result = and i16 %a, 65280
ret i16 %result
}
define i16 @and16_reg_imm_0xffb3(i16 %a) {
; CHECK-LABEL: and16_reg_imm_0xffb3
; CHECK: andi {{r[0-9]+}}, 179
; CHECK-NOT: andi {{r[0-9]+}}, 255
%result = and i16 %a, 65459
ret i16 %result
}
define i16 @and16_reg_imm_0x00ff(i16 %a) {
; CHECK-LABEL: and16_reg_imm_0x00ff
; CHECK-NOT: andi {{r[0-9]+}}, 255
; CHECK: andi {{r[0-9]+}}, 0
%result = and i16 %a, 255
ret i16 %result
}
define i16 @and16_reg_imm_0xb3ff(i16 %a) {
; CHECK-LABEL: and16_reg_imm_0xb3ff
; CHECK-NOT: andi {{r[0-9]+}}, 255
; CHECK: andi {{r[0-9]+}}, 179
%result = and i16 %a, 46079
ret i16 %result
}
define i16 @and16_reg_imm_0xffff(i16 %a) {
; CHECK-LABEL: and16_reg_imm_0xffff
; CHECK-NOT: andi {{r[0-9]+}}, 255
; CHECK-NOT: andi {{r[0-9]+}}, 255
%result = and i16 %a, 65535
ret i16 %result
}
define i16 @and16_reg_imm_0xabcd(i16 %a) {
; CHECK-LABEL: and16_reg_imm_0xabcd
; CHECK: andi {{r[0-9]+}}, 205
; CHECK: andi {{r[0-9]+}}, 171
%result = and i16 %a, 43981
ret i16 %result
}

View File

@ -1,93 +0,0 @@
; RUN: llc -mattr=addsubiw < %s -march=avr | FileCheck %s
define i8 @add8_reg_reg(i8 %a, i8 %b) {
; CHECK-LABEL: add8_reg_reg:
; CHECK: add r24, r22
%result = add i8 %a, %b
ret i8 %result
}
define i8 @add8_reg_imm(i8 %a) {
; CHECK-LABEL: add8_reg_imm:
; CHECK: subi r24, -5
%result = add i8 %a, 5
ret i8 %result
}
define i8 @add8_reg_increment(i8 %a) {
; CHECK-LABEL: add8_reg_increment:
; CHECK: inc r24
%result = add i8 %a, 1
ret i8 %result
}
define i16 @add16_reg_reg(i16 %a, i16 %b) {
; CHECK-LABEL: add16_reg_reg:
; CHECK: add r24, r22
; CHECK: adc r25, r23
%result = add i16 %a, %b
ret i16 %result
}
define i16 @add16_reg_imm(i16 %a) {
; CHECK-LABEL: add16_reg_imm:
; CHECK: adiw r24, 63
%result = add i16 %a, 63
ret i16 %result
}
define i16 @add16_reg_imm_subi(i16 %a) {
; CHECK-LABEL: add16_reg_imm_subi:
; CHECK: subi r24, 133
; CHECK: sbci r25, 255
%result = add i16 %a, 123
ret i16 %result
}
define i32 @add32_reg_reg(i32 %a, i32 %b) {
; CHECK-LABEL: add32_reg_reg:
; CHECK: add r22, r18
; CHECK: adc r23, r19
; CHECK: adc r24, r20
; CHECK: adc r25, r21
%result = add i32 %a, %b
ret i32 %result
}
define i32 @add32_reg_imm(i32 %a) {
; CHECK-LABEL: add32_reg_imm:
; CHECK: subi r22, 251
; CHECK: sbci r23, 255
; CHECK: sbci r24, 255
; CHECK: sbci r25, 255
%result = add i32 %a, 5
ret i32 %result
}
define i64 @add64_reg_reg(i64 %a, i64 %b) {
; CHECK-LABEL: add64_reg_reg:
; CHECK: add r18, r10
; CHECK: adc r20, r12
; CHECK: adc r21, r13
; CHECK: adc r22, r14
; CHECK: adc r23, r15
; CHECK: adc r24, r16
; CHECK: adc r25, r17
%result = add i64 %a, %b
ret i64 %result
}
define i64 @add64_reg_imm(i64 %a) {
; CHECK-LABEL: add64_reg_imm:
; CHECK: subi r18, 251
; CHECK: sbci r19, 255
; CHECK: sbci r20, 255
; CHECK: sbci r21, 255
; CHECK: sbci r22, 255
; CHECK: sbci r23, 255
; CHECK: sbci r24, 255
; CHECK: sbci r25, 255
%result = add i64 %a, 5
ret i64 %result
}

View File

@ -1,84 +0,0 @@
; RUN: llc < %s -march=avr -mattr=avr6 | FileCheck %s
declare i16 @allocate(i16*, i16*)
; Test taking an address of an alloca with a small offset (adiw)
define i16 @alloca_addressof_small() {
entry:
; CHECK-LABEL: alloca_addressof_small:
; Test that Y is saved
; CHECK: push r28
; CHECK: push r29
; CHECK: movw r24, r28
; CHECK: adiw r24, 17
; CHECK: movw {{.*}}, r28
; CHECK: adiw {{.*}}, 39
; CHECK: movw r22, {{.*}}
; CHECK: pop r29
; CHECK: pop r28
%p = alloca [18 x i16]
%k = alloca [14 x i16]
%arrayidx = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16 0, i16 8
%arrayidx1 = getelementptr inbounds [18 x i16], [18 x i16]* %p, i16 0, i16 5
%call = call i16 @allocate(i16* %arrayidx, i16* %arrayidx1)
ret i16 %call
}
; Test taking an address of an alloca with a big offset (subi/sbci pair)
define i16 @alloca_addressof_big() {
entry:
; CHECK-LABEL: alloca_addressof_big:
; CHECK: movw r24, r28
; CHECK: adiw r24, 17
; CHECK: movw r22, r28
; CHECK: subi r22, 145
; CHECK: sbci r23, 255
%p = alloca [55 x i16]
%k = alloca [14 x i16]
%arrayidx = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16 0, i16 8
%arrayidx1 = getelementptr inbounds [55 x i16], [55 x i16]* %p, i16 0, i16 41
%call = call i16 @allocate(i16* %arrayidx, i16* %arrayidx1)
ret i16 %call
}
; Test writing to an allocated variable with a small and a big offset
define i16 @alloca_write(i16 %x) {
entry:
; CHECK-LABEL: alloca_write:
; Small offset here
; CHECK: std Y+23, {{.*}}
; CHECK: std Y+24, {{.*}}
; Big offset here
; CHECK: adiw r28, 57
; CHECK: std Y+62, {{.*}}
; CHECK: std Y+63, {{.*}}
; CHECK: sbiw r28, 57
%p = alloca [15 x i16]
%k = alloca [14 x i16]
%arrayidx = getelementptr inbounds [15 x i16], [15 x i16]* %p, i16 0, i16 45
store i16 22, i16* %arrayidx
%arrayidx1 = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16 0, i16 11
store i16 42, i16* %arrayidx1
%arrayidx2 = getelementptr inbounds [14 x i16], [14 x i16]* %k, i16 0, i16 0
%arrayidx3 = getelementptr inbounds [15 x i16], [15 x i16]* %p, i16 0, i16 0
%call = call i16 @allocate(i16* %arrayidx2, i16* %arrayidx3)
ret i16 %call
}
; Test writing to an allocated variable with a huge offset that cant be
; materialized with adiw/sbiw but with a subi/sbci pair.
define void @alloca_write_huge() {
; CHECK-LABEL: alloca_write_huge:
; CHECK: subi r28, 41
; CHECK: sbci r29, 255
; CHECK: std Y+62, {{.*}}
; CHECK: std Y+63, {{.*}}
; CHECK: subi r28, 215
; CHECK: sbci r29, 0
%k = alloca [140 x i16]
%arrayidx = getelementptr inbounds [140 x i16], [140 x i16]* %k, i16 0, i16 138
store i16 22, i16* %arrayidx
%arraydecay = getelementptr inbounds [140 x i16], [140 x i16]* %k, i16 0, i16 0
call i16 @allocate(i16* %arraydecay, i16* null)
ret void
}

View File

@ -1,81 +0,0 @@
; RUN: llc < %s -march=avr | FileCheck %s
define i8 @and8_reg_reg(i8 %a, i8 %b) {
; CHECK-LABEL: and8_reg_reg:
; CHECK: and r24, r22
%result = and i8 %a, %b
ret i8 %result
}
define i8 @and8_reg_imm(i8 %a) {
; CHECK-LABEL: and8_reg_imm:
; CHECK: andi r24, 5
%result = and i8 %a, 5
ret i8 %result
}
define i16 @and16_reg_reg(i16 %a, i16 %b) {
; CHECK-LABEL: and16_reg_reg:
; CHECK: and r24, r22
; CHECK: and r25, r23
%result = and i16 %a, %b
ret i16 %result
}
define i16 @and16_reg_imm(i16 %a) {
; CHECK-LABEL: and16_reg_imm:
; CHECK: andi r24, 210
; CHECK: andi r25, 4
%result = and i16 %a, 1234
ret i16 %result
}
define i32 @and32_reg_reg(i32 %a, i32 %b) {
; CHECK-LABEL: and32_reg_reg:
; CHECK: and r22, r18
; CHECK: and r23, r19
; CHECK: and r24, r20
; CHECK: and r25, r21
%result = and i32 %a, %b
ret i32 %result
}
define i32 @and32_reg_imm(i32 %a) {
; CHECK-LABEL: and32_reg_imm:
; CHECK: andi r22, 21
; CHECK: andi r23, 205
; CHECK: andi r24, 91
; CHECK: andi r25, 7
%result = and i32 %a, 123456789
ret i32 %result
}
define i64 @and64_reg_reg(i64 %a, i64 %b) {
; CHECK-LABEL: and64_reg_reg:
; CHECK: and r18, r10
; CHECK: and r19, r11
; CHECK: and r20, r12
; CHECK: and r21, r13
; CHECK: and r22, r14
; CHECK: and r23, r15
; CHECK: and r24, r16
; CHECK: and r25, r17
%result = and i64 %a, %b
ret i64 %result
}
define i64 @and64_reg_imm(i64 %a) {
; CHECK-LABEL: and64_reg_imm:
; CHECK: andi r18, 253
; Per PR 31345, we optimize away ANDI Rd, 0xff
; CHECK-NOT: andi r19, 255
; CHECK: andi r20, 155
; CHECK: andi r21, 88
; CHECK: andi r22, 76
; CHECK: andi r23, 73
; CHECK: andi r24, 31
; CHECK: andi r25, 242
%result = and i64 %a, 17446744073709551613
ret i64 %result
}

View File

@ -1,13 +0,0 @@
; 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

@ -1,23 +0,0 @@
; 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

@ -1,137 +0,0 @@
; 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

@ -1,16 +0,0 @@
; 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

@ -1,16 +0,0 @@
; 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

@ -1,124 +0,0 @@
; 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

@ -1,37 +0,0 @@
; 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

@ -1,25 +0,0 @@
; 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

@ -1,30 +0,0 @@
; 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
}

View File

@ -1 +0,0 @@
2cfc7e812ebcc6aed585b6852a24c4a69adf76a5

View File

@ -1,96 +0,0 @@
; RUN: llc < %s -march=avr | FileCheck %s
; CHECK-LABEL: relax_breq
; CHECK: cpi r{{[0-9]+}}, 0
; CHECK: brne LBB0_1
; CHECK: rjmp LBB0_2
; LBB0_1:
define i8 @relax_breq(i1 %a) {
entry-block:
br i1 %a, label %hello, label %finished
hello:
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
br label %finished
finished:
ret i8 3
}
; CHECK-LABEL: no_relax_breq
; CHECK: cpi r{{[0-9]+}}, 0
; CHECK: breq [[END_BB:LBB[0-9]+_[0-9]+]]
; CHECK: nop
; ...
; LBB0_1:
define i8 @no_relax_breq(i1 %a) {
entry-block:
br i1 %a, label %hello, label %finished
hello:
; There are not enough NOPs to require relaxation.
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
call void asm sideeffect "nop", ""()
br label %finished
finished:
ret i8 3
}

View File

@ -1,18 +0,0 @@
; RUN: llc -mattr=sram,eijmpcall < %s -march=avr | FileCheck %s
@brind.k = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@brind, %return), i8* blockaddress(@brind, %b)], align 1
define i8 @brind(i8 %p) {
; CHECK-LABEL: brind:
; CHECK: ijmp
entry:
%idxprom = sext i8 %p to i16
%arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @brind.k, i16 0, i16 %idxprom
%s = load i8*, i8** %arrayidx
indirectbr i8* %s, [label %return, label %b]
b:
br label %return
return:
%retval.0 = phi i8 [ 4, %b ], [ 2, %entry ]
ret i8 %retval.0
}

View File

@ -1,212 +0,0 @@
; RUN: llc < %s -march=avr -mattr=avr6 | FileCheck %s
; TODO: test returning byval structs
declare i8 @foo8_1(i8)
declare i8 @foo8_2(i8, i8, i8)
declare i8 @foo8_3(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8)
declare i16 @foo16_1(i16, i16)
declare i16 @foo16_2(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16)
declare i32 @foo32_1(i32, i32)
declare i32 @foo32_2(i32, i32, i32, i32, i32)
declare i64 @foo64_1(i64)
declare i64 @foo64_2(i64, i64, i64)
define i8 @calli8_reg() {
; CHECK-LABEL: calli8_reg:
; CHECK: ldi r24, 12
; CHECK: call foo8_1
; CHECK: ldi r24, 12
; CHECK: ldi r22, 13
; CHECK: ldi r20, 14
; CHECK: call foo8_2
%result1 = call i8 @foo8_1(i8 12)
%result2 = call i8 @foo8_2(i8 12, i8 13, i8 14)
ret i8 %result2
}
define i8 @calli8_stack() {
; CHECK-LABEL: calli8_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 10
; CHECK: ldi [[REG2:r[0-9]+]], 11
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: call foo8_3
%result1 = call i8 @foo8_3(i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11)
ret i8 %result1
}
define i16 @calli16_reg() {
; CHECK-LABEL: calli16_reg:
; CHECK: ldi r24, 1
; CHECK: ldi r25, 2
; CHECK: ldi r22, 2
; CHECK: ldi r23, 2
; CHECK: call foo16_1
%result1 = call i16 @foo16_1(i16 513, i16 514)
ret i16 %result1
}
define i16 @calli16_stack() {
; CHECK-LABEL: calli16_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 9
; CHECK: ldi [[REG2:r[0-9]+]], 2
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 10
; CHECK: ldi [[REG2:r[0-9]+]], 2
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: call foo16_2
%result1 = call i16 @foo16_2(i16 512, i16 513, i16 514, i16 515, i16 516, i16 517, i16 518, i16 519, i16 520, i16 521, i16 522)
ret i16 %result1
}
define i32 @calli32_reg() {
; CHECK-LABEL: calli32_reg:
; CHECK: ldi r22, 64
; CHECK: ldi r23, 66
; CHECK: ldi r24, 15
; CHECK: ldi r25, 2
; CHECK: ldi r18, 128
; CHECK: ldi r19, 132
; CHECK: ldi r20, 30
; CHECK: ldi r21, 2
; CHECK: call foo32_1
%result1 = call i32 @foo32_1(i32 34554432, i32 35554432)
ret i32 %result1
}
define i32 @calli32_stack() {
; CHECK-LABEL: calli32_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 64
; CHECK: ldi [[REG2:r[0-9]+]], 66
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 15
; CHECK: ldi [[REG2:r[0-9]+]], 2
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: call foo32_2
%result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432)
ret i32 %result1
}
define i64 @calli64_reg() {
; CHECK-LABEL: calli64_reg:
; CHECK: ldi r18, 255
; CHECK: ldi r19, 255
; CHECK: ldi r20, 155
; CHECK: ldi r21, 88
; CHECK: ldi r22, 76
; CHECK: ldi r23, 73
; CHECK: ldi r24, 31
; CHECK: ldi r25, 242
; CHECK: call foo64_1
%result1 = call i64 @foo64_1(i64 17446744073709551615)
ret i64 %result1
}
define i64 @calli64_stack() {
; CHECK-LABEL: calli64_stack:
; CHECK: ldi [[REG1:r[0-9]+]], 76
; CHECK: ldi [[REG2:r[0-9]+]], 73
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 31
; CHECK: ldi [[REG2:r[0-9]+]], 242
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 155
; CHECK: ldi [[REG2:r[0-9]+]], 88
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 255
; CHECK: ldi [[REG2:r[0-9]+]], 255
; CHECK: push [[REG2]]
; CHECK: push [[REG1]]
; CHECK: call foo64_2
%result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615)
ret i64 %result1
}
; Test passing arguments through the stack when the call frame is allocated
; in the prologue.
declare void @foo64_3(i64, i64, i64, i8, i16*)
define void @testcallprologue() {
; CHECK-LABEL: testcallprologue:
; CHECK: push r28
; CHECK: push r29
; CHECK: sbiw r28, 27
; CHECK: ldi [[REG1:r[0-9]+]], 88
; CHECK: std Y+9, [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 11
; CHECK: ldi [[REG2:r[0-9]+]], 10
; CHECK: std Y+7, [[REG1]]
; CHECK: std Y+8, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 13
; CHECK: ldi [[REG2:r[0-9]+]], 12
; CHECK: std Y+5, [[REG1]]
; CHECK: std Y+6, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 15
; CHECK: ldi [[REG2:r[0-9]+]], 14
; CHECK: std Y+3, [[REG1]]
; CHECK: std Y+4, [[REG2]]
; CHECK: ldi [[REG1:r[0-9]+]], 8
; CHECK: ldi [[REG2:r[0-9]+]], 9
; CHECK: std Y+1, [[REG1]]
; CHECK: std Y+2, [[REG2]]
; CHECK: pop r29
; CHECK: pop r28
%p = alloca [8 x i16]
%arraydecay = getelementptr inbounds [8 x i16], [8 x i16]* %p, i16 0, i16 0
call void @foo64_3(i64 723685415333071112, i64 723685415333071112, i64 723685415333071112, i8 88, i16* %arraydecay)
ret void
}
define i32 @icall(i32 (i32)* %foo) {
; CHECK-LABEL: icall:
; CHECK: movw [[REG:r[0-9]+]], r24
; CHECK: ldi r22, 147
; CHECK: ldi r23, 248
; CHECK: ldi r24, 214
; CHECK: ldi r25, 198
; CHECK: movw r30, [[REG]]
; CHECK: icall
; CHECK: subi r22, 251
; CHECK: sbci r23, 255
; CHECK: sbci r24, 255
; CHECK: sbci r25, 255
%1 = call i32 %foo(i32 3335977107)
%2 = add nsw i32 %1, 5
ret i32 %2
}
; Calling external functions (like __divsf3) require extra processing for
; arguments and return values in the LowerCall function.
declare i32 @foofloat(float)
define i32 @externcall(float %a, float %b) {
; CHECK-LABEL: externcall:
; CHECK: movw [[REG1:(r[0-9]+|[XYZ])]], r24
; CHECK: movw [[REG2:(r[0-9]+|[XYZ])]], r22
; CHECK: movw r22, r18
; CHECK: movw r24, r20
; CHECK: movw r18, [[REG2]]
; CHECK: movw r20, [[REG1]]
; CHECK: call __divsf3
; CHECK: call foofloat
; CHECK: subi r22, 251
; CHECK: sbci r23, 255
; CHECK: sbci r24, 255
; CHECK: sbci r25, 255
%1 = fdiv float %b, %a
%2 = call i32 @foofloat(float %1)
%3 = add nsw i32 %2, 5
ret i32 %3
}

View File

@ -1,99 +0,0 @@
; RUN: llc < %s -march=avr | FileCheck %s
; CHECK-LABEL: ret_void_args_i8
define void @ret_void_args_i8(i8 %a) {
; CHECK: sts 4, r24
store volatile i8 %a, i8* inttoptr (i64 4 to i8*)
ret void
}
; CHECK-LABEL: ret_void_args_i8_i32
define void @ret_void_args_i8_i32(i8 %a, i32 %b) {
; CHECK: sts 4, r24
store volatile i8 %a, i8* inttoptr (i64 4 to i8*)
; CHECK-NEXT: sts 8, r23
; CHECK-NEXT: sts 7, r22
; CHECK-NEXT: sts 6, r21
; CHECK-NEXT: sts 5, r20
store volatile i32 %b, i32* inttoptr (i64 5 to i32*)
ret void
}
; CHECK-LABEL: ret_void_args_i8_i8_i8_i8
define void @ret_void_args_i8_i8_i8_i8(i8 %a, i8 %b, i8 %c, i8 %d) {
; CHECK: sts 4, r24
store volatile i8 %a, i8* inttoptr (i64 4 to i8*)
; CHECK-NEXT: sts 5, r22
store volatile i8 %b, i8* inttoptr (i64 5 to i8*)
; CHECK-NEXT: sts 6, r20
store volatile i8 %c, i8* inttoptr (i64 6 to i8*)
; CHECK-NEXT: sts 7, r18
store volatile i8 %d, i8* inttoptr (i64 7 to i8*)
ret void
}
; CHECK-LABEL: ret_void_args_i32_16_i8
define void @ret_void_args_i32_16_i8(i32 %a, i16 %b, i8 %c) {
; CHECK: sts 7, r25
; CHECK-NEXT: sts 6, r24
; CHECK-NEXT: sts 5, r23
; CHECK-NEXT: sts 4, r22
store volatile i32 %a, i32* inttoptr (i64 4 to i32*)
; CHECK-NEXT: sts 5, r21
; CHECK-NEXT: sts 4, r20
store volatile i16 %b, i16* inttoptr (i64 4 to i16*)
; CHECK-NEXT: sts 4, r18
store volatile i8 %c, i8* inttoptr (i64 4 to i8*)
ret void
}
; CHECK-LABEL: ret_void_args_i64
define void @ret_void_args_i64(i64 %a) {
; CHECK: sts 11, r25
; CHECK-NEXT: sts 10, r24
; CHECK-NEXT: sts 9, r23
; CHECK-NEXT: sts 8, r22
; CHECK-NEXT: sts 7, r21
; CHECK-NEXT: sts 6, r20
; CHECK-NEXT: sts 5, r19
; CHECK-NEXT: sts 4, r18
store volatile i64 %a, i64* inttoptr (i64 4 to i64*)
ret void
}
; CHECK-LABEL: ret_void_args_i64_i64
define void @ret_void_args_i64_i64(i64 %a, i64 %b) {
; CHECK: sts 11, r25
; CHECK-NEXT: sts 10, r24
; CHECK-NEXT: sts 9, r23
; CHECK-NEXT: sts 8, r22
; CHECK-NEXT: sts 7, r21
; CHECK-NEXT: sts 6, r20
; CHECK-NEXT: sts 5, r19
; CHECK-NEXT: sts 4, r18
store volatile i64 %a, i64* inttoptr (i64 4 to i64*)
; CHECK-NEXT: sts 11, r17
; CHECK-NEXT: sts 10, r16
; CHECK-NEXT: sts 9, r15
; CHECK-NEXT: sts 8, r14
; CHECK-NEXT: sts 7, r13
; CHECK-NEXT: sts 6, r12
; CHECK-NEXT: sts 5, r11
; CHECK-NEXT: sts 4, r10
store volatile i64 %b, i64* inttoptr (i64 4 to i64*)
ret void
}
; This is exactly enough to hit the limit of what can be passed
; completely in registers.
; CHECK-LABEL: ret_void_args_i64_i64_i16
define void @ret_void_args_i64_i64_i16(i64 %a, i64 %b, i16 %c) {
; CHECK: sts 5, r9
; CHECK-NEXT: sts 4, r8
store volatile i16 %c, i16* inttoptr (i64 4 to i16*)
ret void
}

View File

@ -1,36 +0,0 @@
; RUN: llc < %s -march=avr | FileCheck %s
; CHECK-LABEL: ret_i8
define i8 @ret_i8() {
; CHECK: ldi r24, 64
ret i8 64
}
; CHECK-LABEL: ret_i16
define i16 @ret_i16() {
; CHECK: ldi r24, 0
; CHECK-NEXT: ldi r25, 4
ret i16 1024
}
; CHECK-LABEL: ret_i32
define i32 @ret_i32() {
; CHECK: ldi r22, 78
; CHECK-NEXT: ldi r23, 97
; CHECK-NEXT: ldi r24, 188
; CHECK-NEXT: ldi r25, 0
ret i32 12345678
}
; CHECK-LABEL: ret_i64
define i64 @ret_i64() {
; CHECK: ldi r18, 0
; CHECK-NEXT: ldi r19, 255
; CHECK-NEXT: mov r20, r18
; CHECK-NEXT: mov r21, r19
; CHECK-NEXT: mov r22, r18
; CHECK-NEXT: mov r23, r19
; CHECK-NEXT: mov r24, r18
; CHECK-NEXT: mov r25, r19
ret i64 18374966859414961920
}

Some files were not shown because too many files have changed in this diff Show More