| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ldd [[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: ldd [[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: ldd [[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: ldd [[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: ldd [[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: ldd [[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 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| ; 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: ld r30 | ||
| ; CHECK: ldd r31 | ||
| ; 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 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,211 @@ | ||
| ; 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]+]], 11 | ||
| ; CHECK: push [[REG1]] | ||
| ; CHECK: ldi [[REG1]], 10 | ||
| ; 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]+]], 10 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 2 | ||
| ; CHECK: push [[REG2]] | ||
| ; CHECK: push [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 9 | ||
| ; 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]+]], 15 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 2 | ||
| ; CHECK: push [[REG2]] | ||
| ; CHECK: push [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 64 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 66 | ||
| ; 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]+]], 31 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 242 | ||
| ; CHECK: push [[REG2]] | ||
| ; CHECK: push [[REG1]] | ||
| ; 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]+]], 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, 28 | ||
| ; 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 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| declare void @f1(i8) | ||
| declare void @f2(i8) | ||
| define void @cmp8(i8 %a, i8 %b) { | ||
| ; CHECK-LABEL: cmp8: | ||
| ; CHECK: cp | ||
| ; CHECK-NOT: cpc | ||
| %cmp = icmp eq i8 %a, %b | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f1(i8 %a) | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f2(i8 %b) | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| declare void @f3(i16) | ||
| declare void @f4(i16) | ||
| define void @cmp16(i16 %a, i16 %b) { | ||
| ; CHECK-LABEL: cmp16: | ||
| ; CHECK: cp | ||
| ; CHECK-NEXT: cpc | ||
| %cmp = icmp eq i16 %a, %b | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f3(i16 %a) | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f4(i16 %b) | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| declare void @f5(i32) | ||
| declare void @f6(i32) | ||
| define void @cmp32(i32 %a, i32 %b) { | ||
| ; CHECK-LABEL: cmp32: | ||
| ; CHECK: cp | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| %cmp = icmp eq i32 %a, %b | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f5(i32 %a) | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f6(i32 %b) | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| declare void @f7(i64) | ||
| declare void @f8(i64) | ||
| define void @cmp64(i64 %a, i64 %b) { | ||
| ; CHECK-LABEL: cmp64: | ||
| ; CHECK: cp | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| ; CHECK-NEXT: cpc | ||
| %cmp = icmp eq i64 %a, %b | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f7(i64 %a) | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f8(i64 %b) | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| declare void @f9() | ||
| declare void @f10() | ||
|
|
||
| define void @tst8(i8 %a) { | ||
| ; CHECK-LABEL: tst8: | ||
| ; CHECK: tst r24 | ||
| ; CHECK-NEXT: brmi | ||
| %cmp = icmp sgt i8 %a, -1 | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f9() | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f10() | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| define void @tst16(i16 %a) { | ||
| ; CHECK-LABEL: tst16: | ||
| ; CHECK: tst r25 | ||
| ; CHECK-NEXT: brmi | ||
| %cmp = icmp sgt i16 %a, -1 | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f9() | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f10() | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| define void @tst32(i32 %a) { | ||
| ; CHECK-LABEL: tst32: | ||
| ; CHECK: tst r25 | ||
| ; CHECK-NEXT: brmi | ||
| %cmp = icmp sgt i32 %a, -1 | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f9() | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f10() | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } | ||
|
|
||
| define void @tst64(i64 %a) { | ||
| ; CHECK-LABEL: tst64: | ||
| ; CHECK: tst r25 | ||
| ; CHECK-NEXT: brmi | ||
| %cmp = icmp sgt i64 %a, -1 | ||
| br i1 %cmp, label %if.then, label %if.else | ||
| if.then: | ||
| tail call void @f9() | ||
| br label %if.end | ||
| if.else: | ||
| tail call void @f10() | ||
| br label %if.end | ||
| if.end: | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| define i8 @com8(i8 %x) { | ||
| ; CHECK-LABEL: com8: | ||
| ; CHECK: com r24 | ||
| %neg = xor i8 %x, -1 | ||
| ret i8 %neg | ||
| } | ||
|
|
||
| define i16 @com16(i16 %x) { | ||
| ; CHECK-LABEL: com16: | ||
| ; CHECK: com r24 | ||
| ; CHECK: com r25 | ||
| %neg = xor i16 %x, -1 | ||
| ret i16 %neg | ||
| } | ||
|
|
||
| define i32 @com32(i32 %x) { | ||
| ; CHECK-LABEL: com32: | ||
| ; CHECK: com r22 | ||
| ; CHECK: com r23 | ||
| ; CHECK: com r24 | ||
| ; CHECK: com r25 | ||
| %neg = xor i32 %x, -1 | ||
| ret i32 %neg | ||
| } | ||
|
|
||
| define i64 @com64(i64 %x) { | ||
| ; CHECK-LABEL: com64: | ||
| ; CHECK: com r18 | ||
| ; CHECK: com r19 | ||
| ; CHECK: com r20 | ||
| ; CHECK: com r21 | ||
| ; CHECK: com r22 | ||
| ; CHECK: com r23 | ||
| ; CHECK: com r24 | ||
| ; CHECK: com r25 | ||
| %neg = xor i64 %x, -1 | ||
| ret i64 %neg | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,345 @@ | ||
| ; RUN: llc -mattr=sram,addsubiw < %s -march=avr | FileCheck %s | ||
|
|
||
| @char = common global i8 0 | ||
| @char.array = common global [3 x i8] zeroinitializer | ||
| @char.static = internal global i8 0 | ||
|
|
||
| @int = common global i16 0 | ||
| @int.array = common global [3 x i16] zeroinitializer | ||
| @int.static = internal global i16 0 | ||
|
|
||
| @long = common global i32 0 | ||
| @long.array = common global [3 x i32] zeroinitializer | ||
| @long.static = internal global i32 0 | ||
|
|
||
| @longlong = common global i64 0 | ||
| @longlong.array = common global [3 x i64] zeroinitializer | ||
| @longlong.static = internal global i64 0 | ||
|
|
||
| define void @global8_store() { | ||
| ; CHECK-LABEL: global8_store: | ||
| ; CHECK: ldi [[REG:r[0-9]+]], 6 | ||
| ; CHECK: sts char, [[REG]] | ||
| store i8 6, i8* @char | ||
| ret void | ||
| } | ||
|
|
||
| define i8 @global8_load() { | ||
| ; CHECK-LABEL: global8_load: | ||
| ; CHECK: lds r24, char | ||
| %result = load i8, i8* @char | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define void @array8_store() { | ||
| ; CHECK-LABEL: array8_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 1 | ||
| ; CHECK: sts char.array, [[REG1]] | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 2 | ||
| ; CHECK: sts char.array+1, [[REG2]] | ||
| ; CHECK: ldi [[REG:r[0-9]+]], 3 | ||
| ; CHECK: sts char.array+2, [[REG]] | ||
| store i8 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @char.array, i32 0, i64 0) | ||
| store i8 2, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @char.array, i32 0, i64 1) | ||
| store i8 3, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @char.array, i32 0, i64 2) | ||
| ret void | ||
| } | ||
|
|
||
| define i8 @array8_load() { | ||
| ; CHECK-LABEL: array8_load: | ||
| ; CHECK: lds r24, char.array+2 | ||
| %result = load i8, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @char.array, i32 0, i64 2) | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i8 @static8_inc() { | ||
| ; CHECK-LABEL: static8_inc: | ||
| ; CHECK: lds r24, char.static | ||
| ; CHECK: inc r24 | ||
| ; CHECK: sts char.static, r24 | ||
| %1 = load i8, i8* @char.static | ||
| %inc = add nsw i8 %1, 1 | ||
| store i8 %inc, i8* @char.static | ||
| ret i8 %inc | ||
| } | ||
|
|
||
| define void @global16_store() { | ||
| ; CHECK-LABEL: global16_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 187 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 170 | ||
| ; CHECK: sts int+1, [[REG2]] | ||
| ; CHECK: sts int, [[REG1]] | ||
| store i16 43707, i16* @int | ||
| ret void | ||
| } | ||
|
|
||
| define i16 @global16_load() { | ||
| ; CHECK-LABEL: global16_load: | ||
| ; CHECK: lds r24, int | ||
| ; CHECK: lds r25, int+1 | ||
| %result = load i16, i16* @int | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define void @array16_store() { | ||
| ; CHECK-LABEL: array16_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 187 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 170 | ||
| ; CHECK: sts int.array+1, [[REG2]] | ||
| ; CHECK: sts int.array, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 204 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 170 | ||
| ; CHECK: sts int.array+3, [[REG2]] | ||
| ; CHECK: sts int.array+2, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 221 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 170 | ||
| ; CHECK: sts int.array+5, [[REG2]] | ||
| ; CHECK: sts int.array+4, [[REG1]] | ||
| store i16 43707, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 0) | ||
| store i16 43724, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 1) | ||
| store i16 43741, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 2) | ||
| ret void | ||
| } | ||
|
|
||
| define i16 @array16_load() { | ||
| ; CHECK-LABEL: array16_load: | ||
| ; CHECK: lds r24, int.array+4 | ||
| ; CHECK: lds r25, int.array+5 | ||
| %result = load i16, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 2) | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i16 @static16_inc() { | ||
| ; CHECK-LABEL: static16_inc: | ||
| ; CHECK: lds r24, int.static | ||
| ; CHECK: lds r25, int.static+1 | ||
| ; CHECK: adiw r24, 1 | ||
| ; CHECK: sts int.static+1, r25 | ||
| ; CHECK: sts int.static, r24 | ||
| %1 = load i16, i16* @int.static | ||
| %inc = add nsw i16 %1, 1 | ||
| store i16 %inc, i16* @int.static | ||
| ret i16 %inc | ||
| } | ||
|
|
||
| define void @global32_store() { | ||
| ; CHECK-LABEL: global32_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 187 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 170 | ||
| ; CHECK: sts long+3, [[REG2]] | ||
| ; CHECK: sts long+2, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 221 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 204 | ||
| ; CHECK: sts long+1, [[REG2]] | ||
| ; CHECK: sts long, [[REG1]] | ||
| store i32 2864434397, i32* @long | ||
| ret void | ||
| } | ||
|
|
||
| define i32 @global32_load() { | ||
| ; CHECK-LABEL: global32_load: | ||
| ; CHECK: lds r22, long | ||
| ; CHECK: lds r23, long+1 | ||
| ; CHECK: lds r24, long+2 | ||
| ; CHECK: lds r25, long+3 | ||
| %result = load i32, i32* @long | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define void @array32_store() { | ||
| ; CHECK-LABEL: array32_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 27 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 172 | ||
| ; CHECK: sts long.array+3, [[REG2]] | ||
| ; CHECK: sts long.array+2, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 68 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 13 | ||
| ; CHECK: sts long.array+1, [[REG2]] | ||
| ; CHECK: sts long.array, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 102 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 85 | ||
| ; CHECK: sts long.array+7, [[REG2]] | ||
| ; CHECK: sts long.array+6, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 136 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 119 | ||
| ; CHECK: sts long.array+5, [[REG2]] | ||
| ; CHECK: sts long.array+4, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 170 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 153 | ||
| ; CHECK: sts long.array+11, [[REG2]] | ||
| ; CHECK: sts long.array+10, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 204 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 187 | ||
| ; CHECK: sts long.array+9, [[REG2]] | ||
| ; CHECK: sts long.array+8, [[REG1]] | ||
| store i32 2887454020, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 0) | ||
| store i32 1432778632, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 1) | ||
| store i32 2578103244, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 2) | ||
| ret void | ||
| } | ||
|
|
||
| define i32 @array32_load() { | ||
| ; CHECK-LABEL: array32_load: | ||
| ; CHECK: lds r22, long.array+8 | ||
| ; CHECK: lds r23, long.array+9 | ||
| ; CHECK: lds r24, long.array+10 | ||
| ; CHECK: lds r25, long.array+11 | ||
| %result = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 2) | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i32 @static32_inc() { | ||
| ; CHECK-LABEL: static32_inc: | ||
| ; CHECK: lds r22, long.static | ||
| ; CHECK: lds r23, long.static+1 | ||
| ; CHECK: lds r24, long.static+2 | ||
| ; CHECK: lds r25, long.static+3 | ||
| ; CHECK: subi r22, 255 | ||
| ; CHECK: sbci r23, 255 | ||
| ; CHECK: sbci r24, 255 | ||
| ; CHECK: sbci r25, 255 | ||
| ; CHECK: sts long.static+3, r25 | ||
| ; CHECK: sts long.static+2, r24 | ||
| ; CHECK: sts long.static+1, r23 | ||
| ; CHECK: sts long.static, r22 | ||
| %1 = load i32, i32* @long.static | ||
| %inc = add nsw i32 %1, 1 | ||
| store i32 %inc, i32* @long.static | ||
| ret i32 %inc | ||
| } | ||
|
|
||
| define void @global64_store() { | ||
| ; CHECK-LABEL: global64_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 34 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 17 | ||
| ; CHECK: sts longlong+7, [[REG2]] | ||
| ; CHECK: sts longlong+6, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 68 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 51 | ||
| ; CHECK: sts longlong+5, [[REG2]] | ||
| ; CHECK: sts longlong+4, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 102 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 85 | ||
| ; CHECK: sts longlong+3, [[REG2]] | ||
| ; CHECK: sts longlong+2, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 136 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 119 | ||
| ; CHECK: sts longlong+1, [[REG2]] | ||
| ; CHECK: sts longlong, [[REG1]] | ||
| store i64 1234605616436508552, i64* @longlong | ||
| ret void | ||
| } | ||
|
|
||
| define i64 @global64_load() { | ||
| ; CHECK-LABEL: global64_load: | ||
| ; CHECK: lds r18, longlong | ||
| ; CHECK: lds r19, longlong+1 | ||
| ; CHECK: lds r20, longlong+2 | ||
| ; CHECK: lds r21, longlong+3 | ||
| ; CHECK: lds r22, longlong+4 | ||
| ; CHECK: lds r23, longlong+5 | ||
| ; CHECK: lds r24, longlong+6 | ||
| ; CHECK: lds r25, longlong+7 | ||
| %result = load i64, i64* @longlong | ||
| ret i64 %result | ||
| } | ||
|
|
||
| define void @array64_store() { | ||
| ; CHECK-LABEL: array64_store: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 34 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 17 | ||
| ; CHECK: sts longlong.array+7, [[REG2]] | ||
| ; CHECK: sts longlong.array+6, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 68 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 51 | ||
| ; CHECK: sts longlong.array+5, [[REG2]] | ||
| ; CHECK: sts longlong.array+4, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 102 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 85 | ||
| ; CHECK: sts longlong.array+3, [[REG2]] | ||
| ; CHECK: sts longlong.array+2, [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 136 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 119 | ||
| ; CHECK: sts longlong.array+1, [[REG2]] | ||
| ; CHECK: sts longlong.array, [[REG1]] | ||
| store i64 1234605616436508552, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @longlong.array, i64 0, i64 0) | ||
| store i64 81985529216486895, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @longlong.array, i64 0, i64 1) | ||
| store i64 1836475854449306472, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @longlong.array, i64 0, i64 2) | ||
| ret void | ||
| } | ||
|
|
||
| define i64 @array64_load() { | ||
| ; CHECK-LABEL: array64_load: | ||
| ; CHECK: lds r18, longlong.array+16 | ||
| ; CHECK: lds r19, longlong.array+17 | ||
| ; CHECK: lds r20, longlong.array+18 | ||
| ; CHECK: lds r21, longlong.array+19 | ||
| ; CHECK: lds r22, longlong.array+20 | ||
| ; CHECK: lds r23, longlong.array+21 | ||
| ; CHECK: lds r24, longlong.array+22 | ||
| ; CHECK: lds r25, longlong.array+23 | ||
| %result = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @longlong.array, i64 0, i64 2) | ||
| ret i64 %result | ||
| } | ||
|
|
||
| define i64 @static64_inc() { | ||
| ; CHECK-LABEL: static64_inc: | ||
| ; CHECK: lds r18, longlong.static | ||
| ; CHECK: lds r19, longlong.static+1 | ||
| ; CHECK: lds r20, longlong.static+2 | ||
| ; CHECK: lds r21, longlong.static+3 | ||
| ; CHECK: lds r22, longlong.static+4 | ||
| ; CHECK: lds r23, longlong.static+5 | ||
| ; CHECK: lds r24, longlong.static+6 | ||
| ; CHECK: lds r25, longlong.static+7 | ||
| ; CHECK: subi r18, 255 | ||
| ; 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 | ||
| ; CHECK: sts longlong.static+7, r25 | ||
| ; CHECK: sts longlong.static+6, r24 | ||
| ; CHECK: sts longlong.static+5, r23 | ||
| ; CHECK: sts longlong.static+4, r22 | ||
| ; CHECK: sts longlong.static+3, r21 | ||
| ; CHECK: sts longlong.static+2, r20 | ||
| ; CHECK: sts longlong.static+1, r19 | ||
| ; CHECK: sts longlong.static, r18 | ||
| %1 = load i64, i64* @longlong.static | ||
| %inc = add nsw i64 %1, 1 | ||
| store i64 %inc, i64* @longlong.static | ||
| ret i64 %inc | ||
| } | ||
|
|
||
| define i8 @constantaddr_read8() { | ||
| ; CHECK-LABEL: constantaddr_read8: | ||
| ; CHECK: lds r24, 1234 | ||
| %1 = load i8, i8* inttoptr (i16 1234 to i8*) | ||
| ret i8 %1 | ||
| } | ||
|
|
||
| define i16 @constantaddr_read16() { | ||
| ; CHECK-LABEL: constantaddr_read16: | ||
| ; CHECK: lds r24, 1234 | ||
| ; CHECK: lds r25, 1235 | ||
| %1 = load i16, i16* inttoptr (i16 1234 to i16*) | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| define void @constantaddr_write8() { | ||
| ; CHECK-LABEL: constantaddr_write8: | ||
| ; CHECK: sts 1234 | ||
| store i8 22, i8* inttoptr (i16 1234 to i8*) | ||
| ret void | ||
| } | ||
|
|
||
| define void @constantaddr_write16() { | ||
| ; CHECK-LABEL: constantaddr_write16: | ||
| ; CHECK: sts 1235 | ||
| ; CHECK: sts 1234 | ||
| store i16 2222, i16* inttoptr (i16 1234 to i16*) | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| declare void @foo(i16*, i16*, i8*) | ||
|
|
||
| define void @test1(i16 %x) { | ||
| ; CHECK-LABEL: test1: | ||
| ; CHECK: out 61, r28 | ||
| ; SP copy | ||
| ; CHECK-NEXT: in [[SPCOPY1:r[0-9]+]], 61 | ||
| ; CHECK-NEXT: in [[SPCOPY2:r[0-9]+]], 62 | ||
| ; allocate first dynalloca | ||
| ; CHECK: in {{.*}}, 61 | ||
| ; CHECK: in {{.*}}, 62 | ||
| ; CHECK: sub | ||
| ; CHECK: sbc | ||
| ; CHECK: in r0, 63 | ||
| ; CHECK-NEXT: cli | ||
| ; CHECK-NEXT: out 62, {{.*}} | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: out 61, {{.*}} | ||
| ; Test writes | ||
| ; CHECK: std Z+12, {{.*}} | ||
| ; CHECK: std Z+13, {{.*}} | ||
| ; CHECK: std Z+7, {{.*}} | ||
| ; CHECK-NOT: std | ||
| ; Test SP restore | ||
| ; CHECK: in r0, 63 | ||
| ; CHECK-NEXT: cli | ||
| ; CHECK-NEXT: out 62, [[SPCOPY2]] | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: out 61, [[SPCOPY1]] | ||
| %a = alloca [8 x i16] | ||
| %vla = alloca i16, i16 %x | ||
| %add = shl nsw i16 %x, 1 | ||
| %vla1 = alloca i8, i16 %add | ||
| %arrayidx = getelementptr inbounds [8 x i16], [8 x i16]* %a, i16 0, i16 2 | ||
| store i16 3, i16* %arrayidx | ||
| %arrayidx2 = getelementptr inbounds i16, i16* %vla, i16 6 | ||
| store i16 4, i16* %arrayidx2 | ||
| %arrayidx3 = getelementptr inbounds i8, i8* %vla1, i16 7 | ||
| store i8 44, i8* %arrayidx3 | ||
| %arraydecay = getelementptr inbounds [8 x i16], [8 x i16]* %a, i16 0, i16 0 | ||
| call void @foo(i16* %arraydecay, i16* %vla, i8* %vla1) | ||
| ret void | ||
| } | ||
|
|
||
| declare void @foo2(i16*, i64, i64, i64) | ||
|
|
||
| ; Test that arguments are passed through pushes into the call instead of | ||
| ; allocating the call frame space in the prologue. Also test that SP is restored | ||
| ; after the call frame is restored and not before. | ||
| define void @dynalloca2(i16 %x) { | ||
| ; CHECK-LABEL: dynalloca2: | ||
| ; CHECK: in [[SPCOPY1:r[0-9]+]], 61 | ||
| ; CHECK: in [[SPCOPY2:r[0-9]+]], 62 | ||
| ; CHECK: push | ||
| ; CHECK-NOT: st | ||
| ; CHECK-NOT: std | ||
| ; CHECK: call | ||
| ; Call frame restore | ||
| ; CHECK-NEXT: in r30, 61 | ||
| ; CHECK-NEXT: in r31, 62 | ||
| ; CHECK-NEXT: adiw r30, 8 | ||
| ; CHECK-NEXT: in r0, 63 | ||
| ; CHECK-NEXT: cli | ||
| ; CHECK-NEXT: out 62, r31 | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: out 61, r30 | ||
| ; SP restore | ||
| ; CHECK: in r0, 63 | ||
| ; CHECK-NEXT: cli | ||
| ; CHECK-NEXT: out 62, r29 | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: out 61, r28 | ||
| %vla = alloca i16, i16 %x | ||
| call void @foo2(i16* %vla, i64 0, i64 0, i64 0) | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| ; Tests for the exclusive OR operation. | ||
|
|
||
| define i8 @eor8_reg_reg(i8 %a, i8 %b) { | ||
| ; CHECK-LABEL: eor8_reg_reg: | ||
| ; CHECK: eor r24, r22 | ||
| %result = xor i8 %a, %b | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i8 @eor8_reg_imm(i8 %a) { | ||
| ; CHECK-LABEL: eor8_reg_imm: | ||
| ; CHECK: ldi r25, 5 | ||
| ; CHECK: eor r24, r25 | ||
| %result = xor i8 %a, 5 | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i16 @eor16_reg_reg(i16 %a, i16 %b) { | ||
| ; CHECK-LABEL: eor16_reg_reg: | ||
| ; CHECK: eor r24, r22 | ||
| ; CHECK: eor r25, r23 | ||
| %result = xor i16 %a, %b | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i16 @eor16_reg_imm(i16 %a) { | ||
| ; CHECK-LABEL: eor16_reg_imm: | ||
| ; CHECK: ldi r18, 210 | ||
| ; CHECK: ldi r19, 4 | ||
| ; CHECK: eor r24, r18 | ||
| ; CHECK: eor r25, r19 | ||
| %result = xor i16 %a, 1234 | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i32 @eor32_reg_reg(i32 %a, i32 %b) { | ||
| ; CHECK-LABEL: eor32_reg_reg: | ||
| ; CHECK: eor r22, r18 | ||
| ; CHECK: eor r23, r19 | ||
| ; CHECK: eor r24, r20 | ||
| ; CHECK: eor r25, r21 | ||
| %result = xor i32 %a, %b | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i32 @eor32_reg_imm(i32 %a) { | ||
| ; CHECK-LABEL: eor32_reg_imm: | ||
| ; CHECK: ldi r18, 210 | ||
| ; CHECK: ldi r19, 4 | ||
| ; CHECK: eor r22, r18 | ||
| ; CHECK: eor r23, r19 | ||
| %result = xor i32 %a, 1234 | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i64 @eor64_reg_reg(i64 %a, i64 %b) { | ||
| ; CHECK-LABEL: eor64_reg_reg: | ||
| ; CHECK: eor r18, r10 | ||
| ; CHECK: eor r19, r11 | ||
| ; CHECK: eor r20, r12 | ||
| ; CHECK: eor r21, r13 | ||
| ; CHECK: eor r22, r14 | ||
| ; CHECK: eor r23, r15 | ||
| ; CHECK: eor r24, r16 | ||
| ; CHECK: eor r25, r17 | ||
| %result = xor i64 %a, %b | ||
| ret i64 %result | ||
| } | ||
|
|
||
| define i64 @eor64_reg_imm(i64 %a) { | ||
| ; CHECK-LABEL: eor64_reg_imm: | ||
| ; CHECK: ldi r30, 253 | ||
| ; CHECK: ldi r31, 255 | ||
| ; CHECK: eor r18, r30 | ||
| ; CHECK: eor r19, r31 | ||
| ; CHECK: ldi r30, 155 | ||
| ; CHECK: ldi r31, 88 | ||
| ; CHECK: eor r20, r30 | ||
| ; CHECK: eor r21, r31 | ||
| ; CHECK: ldi r30, 76 | ||
| ; CHECK: ldi r31, 73 | ||
| ; CHECK: eor r22, r30 | ||
| ; CHECK: eor r23, r31 | ||
| ; CHECK: ldi r30, 31 | ||
| ; CHECK: ldi r31, 242 | ||
| ; CHECK: eor r24, r30 | ||
| ; CHECK: eor r25, r31 | ||
| %result = xor i64 %a, 17446744073709551613 | ||
| ret i64 %result | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
| ; XFAIL: * | ||
|
|
||
| ; This occurs when compiling Rust libcore. | ||
| ; | ||
| ; Assertion failed: | ||
| ; (DstReg != SrcReg && "SrcReg and DstReg cannot be the same") | ||
| ; lib/Target/AVR/AVRExpandPseudoInsts.cpp, line 817 | ||
| ; | ||
| ; https://github.com/avr-llvm/llvm/issues/229 | ||
|
|
||
| ; CHECK-LABEL: rust_eh_personality | ||
| declare void @rust_eh_personality() | ||
|
|
||
| ; CHECK-LABEL: __udivmoddi4 | ||
| define void @__udivmoddi4(i64 %arg, i64 %arg1) personality i32 (...)* bitcast (void ()* @rust_eh_personality to i32 (...)*) { | ||
| entry-block: | ||
| %tmp = lshr i64 %arg, 32 | ||
| %tmp2 = trunc i64 %tmp to i32 | ||
| %tmp3 = trunc i64 %arg to i32 | ||
| %tmp4 = add i64 %arg1, -1 | ||
| br label %bb135 | ||
|
|
||
| bb133.loopexit: | ||
| ret void | ||
|
|
||
| bb135: | ||
| %carry.0120 = phi i64 [ 0, %entry-block ], [ %phitmp, %bb135 ] | ||
| %q.sroa.12.1119 = phi i32 [ %tmp3, %entry-block ], [ %q.sroa.12.0.extract.trunc, %bb135 ] | ||
| %q.sroa.0.1118 = phi i32 [ 0, %entry-block ], [ %q.sroa.0.0.extract.trunc, %bb135 ] | ||
| %r.sroa.0.1116 = phi i32 [ %tmp2, %entry-block ], [ undef, %bb135 ] | ||
| %r.sroa.0.0.insert.ext62 = zext i32 %r.sroa.0.1116 to i64 | ||
| %r.sroa.0.0.insert.insert64 = or i64 0, %r.sroa.0.0.insert.ext62 | ||
| %tmp5 = shl nuw nsw i64 %r.sroa.0.0.insert.ext62, 1 | ||
| %q.sroa.12.0.insert.ext101 = zext i32 %q.sroa.12.1119 to i64 | ||
| %q.sroa.12.0.insert.shift102 = shl nuw i64 %q.sroa.12.0.insert.ext101, 32 | ||
| %q.sroa.0.0.insert.ext87 = zext i32 %q.sroa.0.1118 to i64 | ||
| %q.sroa.0.0.insert.insert89 = or i64 %q.sroa.12.0.insert.shift102, %q.sroa.0.0.insert.ext87 | ||
| %tmp6 = lshr i64 %q.sroa.12.0.insert.ext101, 31 | ||
| %tmp7 = lshr i64 %r.sroa.0.0.insert.insert64, 31 | ||
| %tmp8 = shl nuw nsw i64 %q.sroa.0.0.insert.ext87, 1 | ||
| %tmp9 = or i64 %tmp8, %carry.0120 | ||
| %q.sroa.0.0.extract.trunc = trunc i64 %tmp9 to i32 | ||
| %tmp10 = lshr i64 %q.sroa.0.0.insert.insert89, 31 | ||
| %q.sroa.12.0.extract.trunc = trunc i64 %tmp10 to i32 | ||
| %r.sroa.13.0.insert.shift72 = shl i64 %tmp7, 32 | ||
| %.masked114 = and i64 %tmp5, 4294967294 | ||
| %r.sroa.0.0.insert.ext57 = or i64 %tmp6, %.masked114 | ||
| %r.sroa.0.0.insert.insert59 = or i64 %r.sroa.0.0.insert.ext57, %r.sroa.13.0.insert.shift72 | ||
| %tmp11 = sub i64 %tmp4, %r.sroa.0.0.insert.insert59 | ||
| %tmp12 = ashr i64 %tmp11, 63 | ||
| %phitmp = and i64 %tmp12, 1 | ||
| %tmp13 = icmp ult i32 undef, 32 | ||
| br i1 %tmp13, label %bb135, label %bb133.loopexit | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
| ; XFAIL: * | ||
|
|
||
| ; Causes an assertion error | ||
| ; Assertion failed: (Lo.getValueType() == TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && | ||
| ; Hi.getValueType() == Lo.getValueType() && | ||
| ; "Invalid type for expanded integer"), | ||
| ; function SetExpandedInteger | ||
| ; file lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | ||
|
|
||
| ; CHECK-LABEL: foo | ||
| define void @foo(i16 %a) { | ||
| ifcont: | ||
| %cmp_result = icmp eq i16 %a, 255 | ||
| %bool_result = uitofp i1 %cmp_result to double | ||
| %result = fcmp one double 0.000000e+00, %bool_result | ||
| br i1 %result, label %then, label %else | ||
| then: | ||
| ret void | ||
| else: | ||
| ret void | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| ; RUN: llc -mattr=mul < %s -march=avr | FileCheck %s | ||
|
|
||
| declare float @dsin(float) | ||
| declare float @dcos(float) | ||
| declare float @dasin(float) | ||
|
|
||
| ; Test prologue and epilogue insertion | ||
| define float @f3(float %days) { | ||
| entry: | ||
| ; CHECK-LABEL: f3: | ||
| ; prologue code: | ||
| ; CHECK: push r28 | ||
| ; CHECK: push r29 | ||
| ; CHECK: in r28, 61 | ||
| ; CHECK-NEXT: in r29, 62 | ||
| ; CHECK-NEXT: sbiw r28, [[SIZE:[0-9]+]] | ||
| ; CHECK-NEXT: in r0, 63 | ||
| ; CHECK-NEXT: cli | ||
| ; CHECK-NEXT: out 62, r29 | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: out 61, r28 | ||
| ; epilogue code: | ||
| ; CHECK: adiw r28, [[SIZE]] | ||
| ; CHECK-NEXT: in r0, 63 | ||
| ; CHECK-NEXT: cli | ||
| ; CHECK-NEXT: out 62, r29 | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: out 61, r28 | ||
| ; CHECK: pop r29 | ||
| ; CHECK: pop r28 | ||
| %mul = fmul float %days, 0x3FEF8A6C60000000 | ||
| %add = fadd float %mul, 0x40718776A0000000 | ||
| %mul1 = fmul float %days, 0x3FEF8A09A0000000 | ||
| %add2 = fadd float %mul1, 0x4076587740000000 | ||
| %mul3 = fmul float %days, 0x3E81B35CC0000000 | ||
| %sub = fsub float 0x3FFEA235C0000000, %mul3 | ||
| %call = call float @dsin(float %add2) | ||
| %mul4 = fmul float %sub, %call | ||
| %mul5 = fmul float %days, 0x3E27C04CA0000000 | ||
| %sub6 = fsub float 0x3F94790B80000000, %mul5 | ||
| %mul7 = fmul float %add2, 2.000000e+00 | ||
| %call8 = call float @dsin(float %mul7) | ||
| %mul9 = fmul float %sub6, %call8 | ||
| %add10 = fadd float %mul4, %mul9 | ||
| %add11 = fadd float %add, %add10 | ||
| %mul12 = fmul float %days, 0x3E13C5B640000000 | ||
| %sub13 = fsub float 0x3F911C1180000000, %mul12 | ||
| %mul14 = fmul float %add, 2.000000e+00 | ||
| %call15 = call float @dsin(float %mul14) | ||
| %mul16 = fmul float %call15, 0x3FF1F736C0000000 | ||
| %mul17 = fmul float %sub13, 2.000000e+00 | ||
| %mul19 = fmul float %mul17, %call | ||
| %sub20 = fsub float %mul16, %mul19 | ||
| %mul21 = fmul float %sub13, 4.000000e+00 | ||
| %mul22 = fmul float %mul21, 0x3FF1F736C0000000 | ||
| %mul24 = fmul float %mul22, %call | ||
| %call26 = call float @dcos(float %mul14) | ||
| %mul27 = fmul float %mul24, %call26 | ||
| %add28 = fadd float %sub20, %mul27 | ||
| %call29 = call float @dsin(float %add11) | ||
| %mul30 = fmul float %call29, 0x3FF0AB6960000000 | ||
| %call31 = call float @dasin(float %mul30) | ||
| %add32 = fadd float %call31, %add28 | ||
| ret float %add32 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,337 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
| ; XFAIL: * | ||
|
|
||
| ;CHECK-LABEL: no_operands: | ||
| define void @no_operands() { | ||
| ;CHECK: add r24, r22 | ||
| call void asm sideeffect "add r24, r22", ""() nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: input_operand: | ||
| define void @input_operand(i8 %a) { | ||
| ;CHECK: add r24, r24 | ||
| call void asm sideeffect "add $0, $0", "r"(i8 %a) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: simple_upper_regs: | ||
| define void @simple_upper_regs(i8 %p0, i8 %p1, i8 %p2, i8 %p3, | ||
| i8 %p4, i8 %p5, i8 %p6, i8 %p7) { | ||
| ;CHECK: some_instr r17, r22, r20, r18, r16, r19, r21, r23 | ||
| call void asm sideeffect "some_instr $0, $1, $2, $3, $4, $5, $6, $7", | ||
| "a,a,a,a,a,a,a,a" (i8 %p0, i8 %p1, i8 %p2, i8 %p3, | ||
| i8 %p4, i8 %p5, i8 %p6, i8 %p7) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: upper_regs: | ||
| define void @upper_regs(i8 %p0) { | ||
| ;CHECK: some_instr r24 | ||
| call void asm sideeffect "some_instr $0", "d" (i8 %p0) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: lower_regs: | ||
| define void @lower_regs(i8 %p0) { | ||
| ;CHECK: some_instr r15 | ||
| call void asm sideeffect "some_instr $0", "l" (i8 %p0) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: special_upper_regs: | ||
| define void @special_upper_regs(i8 %p0, i8 %p1, i8 %p2, i8 %p3) { | ||
| ;CHECK: some_instr r24,r28,r26,r30 | ||
| call void asm sideeffect "some_instr $0,$1,$2,$3", "w,w,w,w" (i8 %p0, i8 %p1, i8 %p2, i8 %p3) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: xyz_reg: | ||
| define void @xyz_reg(i16 %var) { | ||
| ;CHECK: some_instr r26, r28, r30 | ||
| call void asm sideeffect "some_instr $0, $1, $2", "x,y,z" (i16 %var, i16 %var, i16 %var) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;TODO | ||
| ; How to use SP reg properly in inline asm?? | ||
| ; define void @sp_reg(i16 %var) | ||
|
|
||
| ;CHECK-LABEL: ptr_reg: | ||
| define void @ptr_reg(i16 %var0, i16 %var1, i16 %var2) { | ||
| ;CHECK: some_instr r28, r26, r30 | ||
| call void asm sideeffect "some_instr $0, $1, $2", "e,e,e" (i16 %var0, i16 %var1, i16 %var2) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: base_ptr_reg: | ||
| define void @base_ptr_reg(i16 %var0, i16 %var1) { | ||
| ;CHECK: some_instr r28, r30 | ||
| call void asm sideeffect "some_instr $0, $1", "b,b" (i16 %var0, i16 %var1) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: input_output_operand: | ||
| define i8 @input_output_operand(i8 %a, i8 %b) { | ||
| ;CHECK: add r24, r24 | ||
| %1 = call i8 asm "add $0, $1", "=r,r"(i8 %a) nounwind | ||
| ret i8 %1 | ||
| } | ||
|
|
||
| ;CHECK-LABEL: temp_reg: | ||
| define void @temp_reg(i8 %a) { | ||
| ;CHECK: some_instr r0 | ||
| call void asm sideeffect "some_instr $0", "t" (i8 %a) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_0_63: | ||
| define void @int_0_63() { | ||
| ;CHECK: some_instr 5 | ||
| call void asm sideeffect "some_instr $0", "I" (i8 5) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_minus63_0: | ||
| define void @int_minus63_0() { | ||
| ;CHECK: some_instr -5 | ||
| call void asm sideeffect "some_instr $0", "J" (i8 -5) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_2_2: | ||
| define void @int_2_2() { | ||
| ;CHECK: some_instr 2 | ||
| call void asm sideeffect "some_instr $0", "K" (i8 2) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_0_0: | ||
| define void @int_0_0() { | ||
| ;CHECK: some_instr 0 | ||
| call void asm sideeffect "some_instr $0", "L" (i8 0) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_0_255: | ||
| define void @int_0_255() { | ||
| ;CHECK: some_instr 254 | ||
| call void asm sideeffect "some_instr $0", "M" (i8 254) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_minus1_minus1: | ||
| define void @int_minus1_minus1() { | ||
| ;CHECK: some_instr -1 | ||
| call void asm sideeffect "some_instr $0", "N" (i8 -1) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_8_or_16_or_24: | ||
| define void @int_8_or_16_or_24() { | ||
| ;CHECK: some_instr 8, 16, 24 | ||
| call void asm sideeffect "some_instr $0, $1, $2", "O,O,O" (i8 8, i8 16, i8 24) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_1_1: | ||
| define void @int_1_1() { | ||
| ;CHECK: some_instr 1 | ||
| call void asm sideeffect "some_instr $0", "P" (i8 1) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: int_minus6_5: | ||
| define void @int_minus6_5() { | ||
| ;CHECK: some_instr -6 | ||
| call void asm sideeffect "some_instr $0", "R" (i8 -6) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| ;CHECK-LABEL: float_0_0: | ||
| define void @float_0_0() { | ||
| ;CHECK: some_instr 0 | ||
| call void asm sideeffect "some_instr $0", "G" (float 0.0) nounwind | ||
| ret void | ||
| } | ||
|
|
||
|
|
||
| ; Memory constraint | ||
|
|
||
| @a = internal global i16 0, align 4 | ||
| @b = internal global i16 0, align 4 | ||
|
|
||
| ; CHECK-LABEL: mem_global: | ||
| define void @mem_global() { | ||
| ;CHECK: some_instr Y, Z | ||
| call void asm "some_instr $0, $1", "=*Q,=*Q"(i16* @a, i16* @b) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: mem_params: | ||
| define void @mem_params(i16* %a, i16* %b) { | ||
| ;CHECK: some_instr Y, Z | ||
| call void asm "some_instr $0, $1", "=*Q,=*Q"(i16* %a, i16* %b) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: mem_local: | ||
| define void @mem_local() { | ||
| %a = alloca i16 | ||
| %b = alloca i16 | ||
| ;CHECK: some_instr Y+3, Y+1 | ||
| call void asm "some_instr $0, $1", "=*Q,=*Q"(i16* %a, i16* %b) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: mem_mixed: | ||
| define void @mem_mixed() { | ||
| %a = alloca i16 | ||
| %b = alloca i16 | ||
| ;CHECK: some_instr Z, Y+3, Y+1 | ||
| call void asm "some_instr $0, $1, $2", "=*Q,=*Q,=*Q"(i16* @a, i16* %a, i16* %b) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: mem_gep: | ||
| define i8 @mem_gep(i8* %p) { | ||
| entry: | ||
| ; CHECK: movw r30, r24 | ||
| %arrayidx = getelementptr inbounds i8, i8* %p, i16 1 | ||
| ; CHECK: ld r24, Z+1 | ||
| %0 = tail call i8 asm sideeffect "ld $0, $1\0A\09", "=r,*Q"(i8* %arrayidx) | ||
| ret i8 %0 | ||
| } | ||
|
|
||
| ; Multibyte references | ||
|
|
||
| ; CHECK-LABEL: multibyte_i16 | ||
| define void @multibyte_i16(i16 %a) { | ||
| entry: | ||
| ; CHECK: instr r24 r25 | ||
| call void asm sideeffect "instr ${0:A} ${0:B}", "r"(i16 %a) | ||
| ; CHECK: instr r25 r24 | ||
| call void asm sideeffect "instr ${0:B} ${0:A}", "r"(i16 %a) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_i32 | ||
| define void @multibyte_i32(i32 %a) { | ||
| entry: | ||
| ; CHECK: instr r22 r23 r24 r25 | ||
| call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}", "r"(i32 %a) | ||
| ; CHECK: instr r25 r24 r23 r22 | ||
| call void asm sideeffect "instr ${0:D} ${0:C} ${0:B} ${0:A}", "r"(i32 %a) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_alternative_name | ||
| define void @multibyte_alternative_name(i16* %p) { | ||
| entry: | ||
| ; CHECK: instr Z | ||
| call void asm sideeffect "instr ${0:a}", "e" (i16* %p) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_a_i32 | ||
| define void @multibyte_a_i32() { | ||
| entry: | ||
| %a = alloca i32 | ||
| %0 = load i32, i32* %a | ||
| ; CHECK: instr r20 r21 r22 r23 | ||
| call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}", "a"(i32 %0) | ||
| ret void | ||
| } | ||
|
|
||
| @c = internal global i32 0 | ||
|
|
||
| ; CHECK-LABEL: multibyte_b_i32 | ||
| define void @multibyte_b_i32() { | ||
| entry: | ||
| %0 = load i32, i32* @c | ||
| ; CHECK: instr r28 r29 r30 r31 | ||
| call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}", "b"(i32 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_d_i32 | ||
| define void @multibyte_d_i32() { | ||
| entry: | ||
| %a = alloca i32 | ||
| %0 = load i32, i32* %a | ||
| ; CHECK: instr r18 r19 r24 r25 | ||
| call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}", "d"(i32 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_e_i32 | ||
| define void @multibyte_e_i32() { | ||
| entry: | ||
| %a = alloca i32 | ||
| %0 = load i32, i32* %a | ||
| ; CHECK: instr r26 r27 r30 r31 | ||
| call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}", "e"(i32 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_l_i32 | ||
| define void @multibyte_l_i32() { | ||
| entry: | ||
| %a = alloca i32 | ||
| %0 = load i32, i32* %a | ||
| ; CHECK: instr r12 r13 r14 r15 | ||
| call void asm sideeffect "instr ${0:A} ${0:B} ${0:C} ${0:D}", "l"(i32 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_a_i16 | ||
| define void @multibyte_a_i16() { | ||
| entry: | ||
| %a = alloca i16 | ||
| %0 = load i16, i16* %a | ||
| ; CHECK: instr r22 r23 | ||
| call void asm sideeffect "instr ${0:A} ${0:B}", "a"(i16 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_b_i16 | ||
| define void @multibyte_b_i16() { | ||
| entry: | ||
| %a = alloca i16 | ||
| %0 = load i16, i16* %a | ||
| ; CHECK: instr r30 r31 | ||
| call void asm sideeffect "instr ${0:A} ${0:B}", "b"(i16 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_d_i16 | ||
| define void @multibyte_d_i16() { | ||
| entry: | ||
| %a = alloca i16 | ||
| %0 = load i16, i16* %a | ||
| ; CHECK: instr r24 r25 | ||
| call void asm sideeffect "instr ${0:A} ${0:B}", "d"(i16 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_e_i16 | ||
| define void @multibyte_e_i16() { | ||
| entry: | ||
| %a = alloca i16 | ||
| %0 = load i16, i16* %a | ||
| ; CHECK: instr r30 r31 | ||
| call void asm sideeffect "instr ${0:A} ${0:B}", "e"(i16 %0) | ||
| ret void | ||
| } | ||
|
|
||
| ; CHECK-LABEL: multibyte_l_i16 | ||
| define void @multibyte_l_i16() { | ||
| entry: | ||
| %a = alloca i16 | ||
| %0 = load i16, i16* %a | ||
| ; CHECK: instr r14 r15 | ||
| call void asm sideeffect "instr ${0:A} ${0:B}", "l"(i16 %0) | ||
| ret void | ||
| } | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| define avr_intrcc void @interrupt_handler() { | ||
| ; CHECK-LABEL: interrupt_handler: | ||
| ; CHECK: sei | ||
| ; CHECK-NEXT: push r0 | ||
| ; CHECK-NEXT: push r1 | ||
| ; CHECK-NEXT: in r0, 63 | ||
| ; CHECK-NEXT: push r0 | ||
| ; CHECK: eor r0, r0 | ||
| ; CHECK: pop r0 | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: pop r1 | ||
| ; CHECK-NEXT: pop r0 | ||
| ; CHECK-NEXT: reti | ||
| ret void | ||
| } | ||
|
|
||
| define avr_signalcc void @signal_handler() { | ||
| ; CHECK-LABEL: signal_handler: | ||
| ; CHECK-NOT: sei | ||
| ; CHECK: push r0 | ||
| ; CHECK-NEXT: push r1 | ||
| ; CHECK-NEXT: in r0, 63 | ||
| ; CHECK-NEXT: push r0 | ||
| ; CHECK: eor r0, r0 | ||
| ; CHECK: pop r0 | ||
| ; CHECK-NEXT: out 63, r0 | ||
| ; CHECK-NEXT: pop r1 | ||
| ; CHECK-NEXT: pop r0 | ||
| ; CHECK-NEXT: reti | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| define i8 @read8() { | ||
| ; CHECK-LABEL: read8 | ||
| ; CHECK: in r24, 8 | ||
| %1 = load i8, i8* inttoptr (i16 40 to i8*) | ||
| ret i8 %1 | ||
| } | ||
|
|
||
| define i16 @read16() { | ||
| ; CHECK-LABEL: read16 | ||
| ; CHECK: in r24, 8 | ||
| ; CHECK: in r25, 9 | ||
| %1 = load i16, i16* inttoptr (i16 40 to i16*) | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| define i32 @read32() { | ||
| ; CHECK-LABEL: read32 | ||
| ; CHECK: in r22, 8 | ||
| ; CHECK: in r23, 9 | ||
| ; CHECK: in r24, 10 | ||
| ; CHECK: in r25, 11 | ||
| %1 = load i32, i32* inttoptr (i16 40 to i32*) | ||
| ret i32 %1 | ||
| } | ||
|
|
||
| define i64 @read64() { | ||
| ; CHECK-LABEL: read64 | ||
| ; CHECK: in r18, 8 | ||
| ; CHECK: in r19, 9 | ||
| ; CHECK: in r20, 10 | ||
| ; CHECK: in r21, 11 | ||
| ; CHECK: in r22, 12 | ||
| ; CHECK: in r23, 13 | ||
| ; CHECK: in r24, 14 | ||
| ; CHECK: in r25, 15 | ||
| %1 = load i64, i64* inttoptr (i16 40 to i64*) | ||
| ret i64 %1 | ||
| } | ||
|
|
||
| define void @write8() { | ||
| ; CHECK-LABEL: write8 | ||
| ; CHECK: out 8 | ||
| store i8 22, i8* inttoptr (i16 40 to i8*) | ||
| ret void | ||
| } | ||
|
|
||
| define void @write16() { | ||
| ; CHECK-LABEL: write16 | ||
| ; CHECK: out 9 | ||
| ; CHECK: out 8 | ||
| store i16 1234, i16* inttoptr (i16 40 to i16*) | ||
| ret void | ||
| } | ||
|
|
||
| define void @write32() { | ||
| ; CHECK-LABEL: write32 | ||
| ; CHECK: out 11 | ||
| ; CHECK: out 10 | ||
| ; CHECK: out 9 | ||
| ; CHECK: out 8 | ||
| store i32 12345678, i32* inttoptr (i16 40 to i32*) | ||
| ret void | ||
| } | ||
|
|
||
| define void @write64() { | ||
| ; CHECK-LABEL: write64 | ||
| ; CHECK: out 15 | ||
| ; CHECK: out 14 | ||
| ; CHECK: out 13 | ||
| ; CHECK: out 12 | ||
| ; CHECK: out 11 | ||
| ; CHECK: out 10 | ||
| ; CHECK: out 9 | ||
| ; CHECK: out 8 | ||
| store i64 1234567891234567, i64* inttoptr (i16 40 to i64*) | ||
| ret void | ||
| } | ||
|
|
||
| define void @sbi8() { | ||
| ; CHECK-LABEL: sbi8 | ||
| ; CHECK: sbi 8, 5 | ||
| %1 = load i8, i8* inttoptr (i16 40 to i8*) | ||
| %or = or i8 %1, 32 | ||
| store i8 %or, i8* inttoptr (i16 40 to i8*) | ||
| ret void | ||
| } | ||
|
|
||
| define void @cbi8() { | ||
| ; CHECK-LABEL: cbi8 | ||
| ; CHECK: cbi 8, 5 | ||
| %1 = load volatile i8, i8* inttoptr (i16 40 to i8*) | ||
| %and = and i8 %1, -33 | ||
| store volatile i8 %and, i8* inttoptr (i16 40 to i8*) | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,27 @@ | ||
| if not 'AVR' in config.root.targets: | ||
| config.unsupported = True | ||
|
|
||
| config.suffixes = ['.ll', '.cpp'] | ||
|
|
||
| import os, lit.TestRunner | ||
| from lit.formats import ShTest | ||
|
|
||
| targets = set(config.root.targets_to_build.split()) | ||
| if not 'AVR' in targets: | ||
| config.unsupported = True | ||
|
|
||
| if 'AVRLIT_PORT' in os.environ: | ||
| config.environment['AVRLIT_PORT'] = os.environ['AVRLIT_PORT'] | ||
|
|
||
| class AVRCodeGenTest(ShTest): | ||
| def __init__(self): | ||
| ShTest.__init__(self) | ||
|
|
||
| def execute(self, test, litConfig): | ||
| if test.getSourcePath().endswith('.cpp') and not 'AVRLIT_PORT' in os.environ: | ||
| return (lit.Test.UNSUPPORTED, 'AVRLIT_PORT environment variable is not set') | ||
|
|
||
| return ShTest.execute(self, test, litConfig) | ||
|
|
||
|
|
||
| config.test_format = AVRCodeGenTest() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| ; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s | ||
|
|
||
| define i8 @load8(i8* %x) { | ||
| ; CHECK-LABEL: load8: | ||
| ; CHECK: ld r24, {{[XYZ]}} | ||
| %1 = load i8, i8* %x | ||
| ret i8 %1 | ||
| } | ||
|
|
||
| define i16 @load16(i16* %x) { | ||
| ; CHECK-LABEL: load16: | ||
| ; CHECK: ld r24, {{[YZ]}} | ||
| ; CHECK: ldd r25, {{[YZ]}}+1 | ||
| %1 = load i16, i16* %x | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| define i8 @load8disp(i8* %x) { | ||
| ; CHECK-LABEL: load8disp: | ||
| ; CHECK: ldd r24, {{[YZ]}}+63 | ||
| %1 = getelementptr inbounds i8, i8* %x, i64 63 | ||
| %2 = load i8, i8* %1 | ||
| ret i8 %2 | ||
| } | ||
|
|
||
| define i8 @load8nodisp(i8* %x) { | ||
| ; CHECK-LABEL: load8nodisp: | ||
| ; CHECK: movw r26, r24 | ||
| ; CHECK: subi r26, 192 | ||
| ; CHECK: sbci r27, 255 | ||
| ; CHECK: ld r24, {{[XYZ]}} | ||
| %1 = getelementptr inbounds i8, i8* %x, i64 64 | ||
| %2 = load i8, i8* %1 | ||
| ret i8 %2 | ||
| } | ||
|
|
||
| define i16 @load16disp(i16* %x) { | ||
| ; CHECK-LABEL: load16disp: | ||
| ; CHECK: ldd r24, {{[YZ]}}+62 | ||
| ; CHECK: ldd r25, {{[YZ]}}+63 | ||
| %1 = getelementptr inbounds i16, i16* %x, i64 31 | ||
| %2 = load i16, i16* %1 | ||
| ret i16 %2 | ||
| } | ||
|
|
||
| define i16 @load16nodisp(i16* %x) { | ||
| ; CHECK-LABEL: load16nodisp: | ||
| ; CHECK: movw r30, r24 | ||
| ; CHECK: subi r30, 192 | ||
| ; CHECK: sbci r31, 255 | ||
| ; CHECK: ld r24, {{[YZ]}} | ||
| ; CHECK: ldd r25, {{[YZ]}}+1 | ||
| %1 = getelementptr inbounds i16, i16* %x, i64 32 | ||
| %2 = load i16, i16* %1 | ||
| ret i16 %2 | ||
| } | ||
|
|
||
| define i8 @load8postinc(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: load8postinc: | ||
| ; CHECK: ld {{.*}}, {{[XYZ]}}+ | ||
| entry: | ||
| %tobool6 = icmp eq i8 %y, 0 | ||
| br i1 %tobool6, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %r.09 = phi i8 [ %add, %while.body ], [ 0, %entry ] | ||
| %y.addr.08 = phi i8 [ %dec, %while.body ], [ %y, %entry ] | ||
| %x.addr.07 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec = add i8 %y.addr.08, -1 | ||
| %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.07, i16 1 | ||
| %0 = load i8, i8* %x.addr.07 | ||
| %add = add i8 %0, %r.09 | ||
| %tobool = icmp eq i8 %dec, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| %r.0.lcssa = phi i8 [ 0, %entry ], [ %add, %while.body ] | ||
| ret i8 %r.0.lcssa | ||
| } | ||
|
|
||
| define i16 @load16postinc(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: load16postinc: | ||
| ; CHECK: ld {{.*}}, {{[XYZ]}}+ | ||
| ; CHECK: ld {{.*}}, {{[XYZ]}}+ | ||
| entry: | ||
| %tobool2 = icmp eq i16 %y, 0 | ||
| br i1 %tobool2, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %r.05 = phi i16 [ %add, %while.body ], [ 0, %entry ] | ||
| %y.addr.04 = phi i16 [ %dec, %while.body ], [ %y, %entry ] | ||
| %x.addr.03 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec = add nsw i16 %y.addr.04, -1 | ||
| %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.03, i16 1 | ||
| %0 = load i16, i16* %x.addr.03 | ||
| %add = add nsw i16 %0, %r.05 | ||
| %tobool = icmp eq i16 %dec, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %while.body ] | ||
| ret i16 %r.0.lcssa | ||
| } | ||
|
|
||
| define i8 @load8predec(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: load8predec: | ||
| ; CHECK: ld {{.*}}, -{{[XYZ]}} | ||
| entry: | ||
| %tobool6 = icmp eq i8 %y, 0 | ||
| br i1 %tobool6, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %r.09 = phi i8 [ %add, %while.body ], [ 0, %entry ] | ||
| %y.addr.08 = phi i8 [ %dec, %while.body ], [ %y, %entry ] | ||
| %x.addr.07 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec = add i8 %y.addr.08, -1 | ||
| %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.07, i16 -1 | ||
| %0 = load i8, i8* %incdec.ptr | ||
| %add = add i8 %0, %r.09 | ||
| %tobool = icmp eq i8 %dec, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| %r.0.lcssa = phi i8 [ 0, %entry ], [ %add, %while.body ] | ||
| ret i8 %r.0.lcssa | ||
| } | ||
|
|
||
| define i16 @load16predec(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: load16predec: | ||
| ; CHECK: ld {{.*}}, -{{[XYZ]}} | ||
| ; CHECK: ld {{.*}}, -{{[XYZ]}} | ||
| entry: | ||
| %tobool2 = icmp eq i16 %y, 0 | ||
| br i1 %tobool2, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %r.05 = phi i16 [ %add, %while.body ], [ 0, %entry ] | ||
| %y.addr.04 = phi i16 [ %dec, %while.body ], [ %y, %entry ] | ||
| %x.addr.03 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec = add nsw i16 %y.addr.04, -1 | ||
| %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.03, i16 -1 | ||
| %0 = load i16, i16* %incdec.ptr | ||
| %add = add nsw i16 %0, %r.05 | ||
| %tobool = icmp eq i16 %dec, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %while.body ] | ||
| ret i16 %r.0.lcssa | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| define i8 @or8_reg_reg(i8 %a, i8 %b) { | ||
| ; CHECK-LABEL: or8_reg_reg: | ||
| ; CHECK: or r24, r22 | ||
| %result = or i8 %a, %b | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i8 @or8_reg_imm(i8 %a) { | ||
| ; CHECK-LABEL: or8_reg_imm: | ||
| ; CHECK: ori r24, 5 | ||
| %result = or i8 %a, 5 | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i16 @or16_reg_reg(i16 %a, i16 %b) { | ||
| ; CHECK-LABEL: or16_reg_reg: | ||
| ; CHECK: or r24, r22 | ||
| ; CHECK: or r25, r23 | ||
| %result = or i16 %a, %b | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i16 @or16_reg_imm(i16 %a) { | ||
| ; CHECK-LABEL: or16_reg_imm: | ||
| ; CHECK: ori r24, 210 | ||
| ; CHECK: ori r25, 4 | ||
| %result = or i16 %a, 1234 | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i32 @or32_reg_reg(i32 %a, i32 %b) { | ||
| ; CHECK-LABEL: or32_reg_reg: | ||
| ; CHECK: or r22, r18 | ||
| ; CHECK: or r23, r19 | ||
| ; CHECK: or r24, r20 | ||
| ; CHECK: or r25, r21 | ||
| %result = or i32 %a, %b | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i32 @or32_reg_imm(i32 %a) { | ||
| ; CHECK-LABEL: or32_reg_imm: | ||
| ; CHECK: ori r22, 21 | ||
| ; CHECK: ori r23, 205 | ||
| ; CHECK: ori r24, 91 | ||
| ; CHECK: ori r25, 7 | ||
| %result = or i32 %a, 123456789 | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i64 @or64_reg_reg(i64 %a, i64 %b) { | ||
| ; CHECK-LABEL: or64_reg_reg: | ||
| ; CHECK: or r18, r10 | ||
| ; CHECK: or r19, r11 | ||
| ; CHECK: or r20, r12 | ||
| ; CHECK: or r21, r13 | ||
| ; CHECK: or r22, r14 | ||
| ; CHECK: or r23, r15 | ||
| ; CHECK: or r24, r16 | ||
| ; CHECK: or r25, r17 | ||
| %result = or i64 %a, %b | ||
| ret i64 %result | ||
| } | ||
|
|
||
| define i64 @or64_reg_imm(i64 %a) { | ||
| ; CHECK-LABEL: or64_reg_imm: | ||
| ; CHECK: ori r18, 204 | ||
| ; CHECK: ori r19, 204 | ||
| ; CHECK: ori r20, 204 | ||
| ; CHECK: ori r21, 204 | ||
| ; CHECK: ori r22, 204 | ||
| ; CHECK: ori r23, 204 | ||
| ; CHECK: ori r24, 204 | ||
| ; CHECK: ori r25, 204 | ||
| %result = or i64 %a, 14757395258967641292 | ||
| ret i64 %result | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| ; RUN: llc < %s -march=avr -mattr=movw,lpm | FileCheck %s | ||
| ; XFAIL: * | ||
|
|
||
| ; Tests the standard LPM instruction | ||
|
|
||
| define i8 @test8(i8 addrspace(1)* %p) { | ||
| ; CHECK-LABEL: test8: | ||
| ; CHECK: movw r30, r24 | ||
| ; CHECK: lpm r24, Z | ||
| %1 = load i8, i8 addrspace(1)* %p | ||
| ret i8 %1 | ||
| } | ||
|
|
||
| define i16 @test16(i16 addrspace(1)* %p) { | ||
| ; CHECK-LABEL: test16: | ||
| ; CHECK: movw r30, r24 | ||
| ; CHECK: lpm r24, Z+ | ||
| ; CHECK: lpm r25, Z+ | ||
| %1 = load i16, i16 addrspace(1)* %p | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| define i8 @test8postinc(i8 addrspace(1)* %x, i8 %y) { | ||
| ; CHECK-LABEL: test8postinc: | ||
| ; CHECK: movw r30, r24 | ||
| ; CHECK: lpm {{.*}}, Z+ | ||
| entry: | ||
| %cmp10 = icmp sgt i8 %y, 0 | ||
| br i1 %cmp10, label %for.body, label %for.end | ||
|
|
||
| for.body: ; preds = %entry, %for.body | ||
| %ret.013 = phi i8 [ %add, %for.body ], [ 0, %entry ] | ||
| %i.012 = phi i8 [ %inc, %for.body ], [ 0, %entry ] | ||
| %x.addr.011 = phi i8 addrspace(1)* [ %incdec.ptr, %for.body ], [ %x, %entry ] | ||
| %incdec.ptr = getelementptr inbounds i8, i8 addrspace(1)* %x.addr.011, i16 1 | ||
| %0 = load i8, i8 addrspace(1)* %x.addr.011 | ||
| %add = add i8 %0, %ret.013 | ||
| %inc = add i8 %i.012, 1 | ||
| %exitcond = icmp eq i8 %inc, %y | ||
| br i1 %exitcond, label %for.end, label %for.body | ||
|
|
||
| for.end: ; preds = %for.body, %entry | ||
| %ret.0.lcssa = phi i8 [ 0, %entry ], [ %add, %for.body ] | ||
| ret i8 %ret.0.lcssa | ||
| } | ||
|
|
||
| define i16 @test16postinc(i16 addrspace(1)* %x, i8 %y) { | ||
| ; CHECK-LABEL: test16postinc: | ||
| ; CHECK: movw r30, r24 | ||
| ; CHECK: lpm {{.*}}, Z+ | ||
| ; CHECK: lpm {{.*}}, Z+ | ||
| entry: | ||
| %cmp5 = icmp sgt i8 %y, 0 | ||
| br i1 %cmp5, label %for.body, label %for.end | ||
|
|
||
| for.body: ; preds = %entry, %for.body | ||
| %ret.08 = phi i16 [ %add, %for.body ], [ 0, %entry ] | ||
| %i.07 = phi i8 [ %inc, %for.body ], [ 0, %entry ] | ||
| %x.addr.06 = phi i16 addrspace(1)* [ %incdec.ptr, %for.body ], [ %x, %entry ] | ||
| %incdec.ptr = getelementptr inbounds i16, i16 addrspace(1)* %x.addr.06, i16 1 | ||
| %0 = load i16, i16 addrspace(1)* %x.addr.06 | ||
| %add = add nsw i16 %0, %ret.08 | ||
| %inc = add i8 %i.07, 1 | ||
| %exitcond = icmp eq i8 %inc, %y | ||
| br i1 %exitcond, label %for.end, label %for.body | ||
|
|
||
| for.end: ; preds = %for.body, %entry | ||
| %ret.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] | ||
| ret i16 %ret.0.lcssa | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| ; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s | ||
|
|
||
| ;TODO: test returning byval structs | ||
| ; TODO: test naked functions | ||
|
|
||
| define void @return_void() { | ||
| ; CHECK: return_void:{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: ret | ||
| ret void | ||
| } | ||
|
|
||
| define i8 @return8_imm() { | ||
| ; CHECK-LABEL: return8_imm: | ||
| ; CHECK: ldi r24, 5 | ||
| ret i8 5 | ||
| } | ||
|
|
||
| define i8 @return8_arg(i8 %x) { | ||
| ; CHECK: return8_arg:{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: ret | ||
| ret i8 %x | ||
| } | ||
|
|
||
| define i8 @return8_arg2(i8 %x, i8 %y, i8 %z) { | ||
| ; CHECK-LABEL: return8_arg2: | ||
| ; CHECK: mov r24, r20 | ||
| ret i8 %z | ||
| } | ||
|
|
||
| define i16 @return16_imm() { | ||
| ; CHECK-LABEL: return16_imm: | ||
| ; CHECK: ldi r24, 57 | ||
| ; CHECK: ldi r25, 48 | ||
| ret i16 12345 | ||
| } | ||
|
|
||
| define i16 @return16_arg(i16 %x) { | ||
| ; CHECK: return16_arg:{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: ret | ||
| ret i16 %x | ||
| } | ||
|
|
||
| define i16 @return16_arg2(i16 %x, i16 %y, i16 %z) { | ||
| ; CHECK-LABEL: return16_arg2: | ||
| ; CHECK: movw r24, r20 | ||
| ret i16 %z | ||
| } | ||
|
|
||
| define i32 @return32_imm() { | ||
| ; CHECK-LABEL: return32_imm: | ||
| ; CHECK: ldi r22, 21 | ||
| ; CHECK: ldi r23, 205 | ||
| ; CHECK: ldi r24, 91 | ||
| ; CHECK: ldi r25, 7 | ||
| ret i32 123456789 | ||
| } | ||
|
|
||
| define i32 @return32_arg(i32 %x) { | ||
| ; CHECK: return32_arg:{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: ret | ||
| ret i32 %x | ||
| } | ||
|
|
||
| define i32 @return32_arg2(i32 %x, i32 %y, i32 %z) { | ||
| ; CHECK-LABEL: return32_arg2: | ||
| ; CHECK: movw r22, r14 | ||
| ; CHECK: movw r24, r16 | ||
| ret i32 %z | ||
| } | ||
|
|
||
| define i64 @return64_imm() { | ||
| ; CHECK-LABEL: return64_imm: | ||
| ; CHECK: ldi r18, 204 | ||
| ; CHECK: ldi r19, 204 | ||
| ; CHECK: ldi r20, 104 | ||
| ; CHECK: ldi r21, 37 | ||
| ; CHECK: ldi r22, 25 | ||
| ; CHECK: ldi r23, 22 | ||
| ; CHECK: ldi r24, 236 | ||
| ; CHECK: ldi r25, 190 | ||
| ret i64 13757395258967641292 | ||
| } | ||
|
|
||
| define i64 @return64_arg(i64 %x) { | ||
| ; CHECK: return64_arg:{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: #{{[a-zA-Z0-9 #@]*}} | ||
| ; CHECK-NEXT: ret | ||
| ret i64 %x | ||
| } | ||
|
|
||
| define i64 @return64_arg2(i64 %x, i64 %y, i64 %z) { | ||
| ; CHECK-LABEL: return64_arg2: | ||
| ; CHECK: push r28 | ||
| ; CHECK: push r29 | ||
| ; CHECK: ldd r18, Y+5 | ||
| ; CHECK: ldd r19, Y+6 | ||
| ; CHECK: ldd r20, Y+7 | ||
| ; CHECK: ldd r21, Y+8 | ||
| ; CHECK: ldd r22, Y+9 | ||
| ; CHECK: ldd r23, Y+10 | ||
| ; CHECK: ldd r24, Y+11 | ||
| ; CHECK: ldd r25, Y+12 | ||
| ; CHECK: pop r29 | ||
| ; CHECK: pop r28 | ||
| ret i64 %z | ||
| } | ||
|
|
||
| define i32 @return64_trunc(i32 %a, i32 %b, i32 %c, i64 %d) { | ||
| ; CHECK-LABEL: return64_trunc: | ||
| ; CHECK: push r28 | ||
| ; CHECK: push r29 | ||
| ; CHECK: ldd r22, Y+5 | ||
| ; CHECK: ldd r23, Y+6 | ||
| ; CHECK: ldd r24, Y+7 | ||
| ; CHECK: ldd r25, Y+8 | ||
| ; CHECK: pop r29 | ||
| ; CHECK: pop r28 | ||
| %result = trunc i64 %d to i32 | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i32 @naked(i32 %x) naked { | ||
| ; CHECK-LABEL: naked: | ||
| ; CHECK-NOT: ret | ||
| ret i32 %x | ||
| } | ||
|
|
||
| define avr_intrcc void @interrupt_handler() { | ||
| ; CHECK-LABEL: interrupt_handler: | ||
| ; CHECK: reti | ||
| ret void | ||
| } | ||
|
|
||
| define avr_signalcc void @signal_handler() { | ||
| ; CHECK-LABEL: signal_handler: | ||
| ; CHECK: reti | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| ; sext R17:R16, R13 | ||
| ; mov r16, r13 | ||
| ; mov r17, r13 | ||
| ; lsl r17 | ||
| ; sbc r17, r17 | ||
| define i16 @sext1(i8 %x, i8 %y) { | ||
| ; CHECK-LABEL: sext1: | ||
| ; CHECK: mov r24, r22 | ||
| ; CHECK: mov r25, r22 | ||
| ; CHECK: lsl r25 | ||
| ; CHECK: sbc r25, r25 | ||
| %1 = sext i8 %y to i16 | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| ; sext R17:R16, R16 | ||
| ; mov r17, r16 | ||
| ; lsl r17 | ||
| ; sbc r17, r17 | ||
| define i16 @sext2(i8 %x) { | ||
| ; CHECK-LABEL: sext2: | ||
| ; CHECK: mov r25, r24 | ||
| ; CHECK: lsl r25 | ||
| ; CHECK: sbc r25, r25 | ||
| %1 = sext i8 %x to i16 | ||
| ret i16 %1 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| ; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s | ||
|
|
||
| define void @store8(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: store8: | ||
| ; CHECK: st {{[XYZ]}}, r22 | ||
| store i8 %y, i8* %x | ||
| ret void | ||
| } | ||
|
|
||
| define void @store16(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: store16: | ||
| ; CHECK: st {{[YZ]}}, r22 | ||
| ; CHECK: std {{[YZ]}}+1, r23 | ||
| store i16 %y, i16* %x | ||
| ret void | ||
| } | ||
|
|
||
| define void @store8disp(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: store8disp: | ||
| ; CHECK: std {{[YZ]}}+63, r22 | ||
| %arrayidx = getelementptr inbounds i8, i8* %x, i16 63 | ||
| store i8 %y, i8* %arrayidx | ||
| ret void | ||
| } | ||
|
|
||
| define void @store8nodisp(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: store8nodisp: | ||
| ; CHECK: movw r26, r24 | ||
| ; CHECK: subi r26, 192 | ||
| ; CHECK: sbci r27, 255 | ||
| ; CHECK: st {{[XYZ]}}, r22 | ||
| %arrayidx = getelementptr inbounds i8, i8* %x, i16 64 | ||
| store i8 %y, i8* %arrayidx | ||
| ret void | ||
| } | ||
|
|
||
| define void @store16disp(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: store16disp: | ||
| ; CHECK: std {{[YZ]}}+62, r22 | ||
| ; CHECK: std {{[YZ]}}+63, r23 | ||
| %arrayidx = getelementptr inbounds i16, i16* %x, i16 31 | ||
| store i16 %y, i16* %arrayidx | ||
| ret void | ||
| } | ||
|
|
||
| define void @store16nodisp(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: store16nodisp: | ||
| ; CHECK: movw r30, r24 | ||
| ; CHECK: subi r30, 192 | ||
| ; CHECK: sbci r31, 255 | ||
| ; CHECK: st {{[YZ]}}, r22 | ||
| ; CHECK: std {{[YZ]}}+1, r23 | ||
| %arrayidx = getelementptr inbounds i16, i16* %x, i16 32 | ||
| store i16 %y, i16* %arrayidx | ||
| ret void | ||
| } | ||
|
|
||
| define void @store8postinc(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: store8postinc: | ||
| ; CHECK: st {{[XYZ]}}+, {{.*}} | ||
| entry: | ||
| %tobool3 = icmp eq i8 %y, 0 | ||
| br i1 %tobool3, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %dec5.in = phi i8 [ %dec5, %while.body ], [ %y, %entry ] | ||
| %x.addr.04 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec5 = add i8 %dec5.in, -1 | ||
| %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.04, i16 1 | ||
| store i8 %dec5, i8* %x.addr.04 | ||
| %tobool = icmp eq i8 %dec5, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| ret void | ||
| } | ||
|
|
||
| define void @store16postinc(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: store16postinc: | ||
| ; CHECK: st {{[XYZ]}}+, {{.*}} | ||
| ; CHECK: st {{[XYZ]}}+, {{.*}} | ||
| entry: | ||
| %tobool3 = icmp eq i16 %y, 0 | ||
| br i1 %tobool3, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %dec5.in = phi i16 [ %dec5, %while.body ], [ %y, %entry ] | ||
| %x.addr.04 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec5 = add nsw i16 %dec5.in, -1 | ||
| %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.04, i16 1 | ||
| store i16 %dec5, i16* %x.addr.04 | ||
| %tobool = icmp eq i16 %dec5, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| ret void | ||
| } | ||
|
|
||
| define void @store8predec(i8* %x, i8 %y) { | ||
| ; CHECK-LABEL: store8predec: | ||
| ; CHECK: st -{{[XYZ]}}, {{.*}} | ||
| entry: | ||
| %tobool3 = icmp eq i8 %y, 0 | ||
| br i1 %tobool3, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %dec5.in = phi i8 [ %dec5, %while.body ], [ %y, %entry ] | ||
| %x.addr.04 = phi i8* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec5 = add i8 %dec5.in, -1 | ||
| %incdec.ptr = getelementptr inbounds i8, i8* %x.addr.04, i16 -1 | ||
| store i8 %dec5, i8* %incdec.ptr | ||
| %tobool = icmp eq i8 %dec5, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| ret void | ||
| } | ||
|
|
||
| define void @store16predec(i16* %x, i16 %y) { | ||
| ; CHECK-LABEL: store16predec: | ||
| ; CHECK: st -{{[XYZ]}}, {{.*}} | ||
| ; CHECK: st -{{[XYZ]}}, {{.*}} | ||
| entry: | ||
| %tobool3 = icmp eq i16 %y, 0 | ||
| br i1 %tobool3, label %while.end, label %while.body | ||
| while.body: ; preds = %entry, %while.body | ||
| %dec5.in = phi i16 [ %dec5, %while.body ], [ %y, %entry ] | ||
| %x.addr.04 = phi i16* [ %incdec.ptr, %while.body ], [ %x, %entry ] | ||
| %dec5 = add nsw i16 %dec5.in, -1 | ||
| %incdec.ptr = getelementptr inbounds i16, i16* %x.addr.04, i16 -1 | ||
| store i16 %dec5, i16* %incdec.ptr | ||
| %tobool = icmp eq i16 %dec5, 0 | ||
| br i1 %tobool, label %while.end, label %while.body | ||
| while.end: ; preds = %while.body, %entry | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| define i8 @sub8_reg_reg(i8 %a, i8 %b) { | ||
| ; CHECK-LABEL: sub8_reg_reg: | ||
| ; CHECK: sub r24, r22 | ||
| %result = sub i8 %a, %b | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i8 @sub8_reg_imm(i8 %a) { | ||
| ; CHECK-LABEL: sub8_reg_imm: | ||
| ; CHECK: subi r24, 5 | ||
| %result = sub i8 %a, 5 | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i8 @sub8_reg_decrement(i8 %a) { | ||
| ; CHECK-LABEL: sub8_reg_decrement: | ||
| ; CHECK: dec r24 | ||
| %result = sub i8 %a, 1 | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i16 @sub16_reg_reg(i16 %a, i16 %b) { | ||
| ; CHECK-LABEL: sub16_reg_reg: | ||
| ; CHECK: sub r24, r22 | ||
| ; CHECK: sbc r25, r23 | ||
| %result = sub i16 %a, %b | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i16 @sub16_reg_imm(i16 %a) { | ||
| ; CHECK-LABEL: sub16_reg_imm: | ||
| ; CHECK: sbiw r24, 63 | ||
| %result = sub i16 %a, 63 | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i16 @sub16_reg_imm_subi(i16 %a) { | ||
| ; CHECK-LABEL: sub16_reg_imm_subi: | ||
| ; CHECK: subi r24, 210 | ||
| ; CHECK: sbci r25, 4 | ||
| %result = sub i16 %a, 1234 | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i32 @sub32_reg_reg(i32 %a, i32 %b) { | ||
| ; CHECK-LABEL: sub32_reg_reg: | ||
| ; CHECK: sub r22, r18 | ||
| ; CHECK: sbc r23, r19 | ||
| ; CHECK: sbc r24, r20 | ||
| ; CHECK: sbc r25, r21 | ||
| %result = sub i32 %a, %b | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i32 @sub32_reg_imm(i32 %a) { | ||
| ; CHECK-LABEL: sub32_reg_imm: | ||
| ; CHECK: subi r22, 21 | ||
| ; CHECK: sbci r23, 205 | ||
| ; CHECK: sbci r24, 91 | ||
| ; CHECK: sbci r25, 7 | ||
| %result = sub i32 %a, 123456789 | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i64 @sub64_reg_reg(i64 %a, i64 %b) { | ||
| ; CHECK-LABEL: sub64_reg_reg: | ||
| ; CHECK: sub r18, r10 | ||
| ; CHECK: sbc r20, r12 | ||
| ; CHECK: sbc r21, r13 | ||
| ; CHECK: sbc r22, r14 | ||
| ; CHECK: sbc r23, r15 | ||
| ; CHECK: sbc r24, r16 | ||
| ; CHECK: sbc r25, r17 | ||
| %result = sub i64 %a, %b | ||
| ret i64 %result | ||
| } | ||
|
|
||
| define i64 @sub64_reg_imm(i64 %a) { | ||
| ; CHECK-LABEL: sub64_reg_imm: | ||
| ; CHECK: subi r18, 204 | ||
| ; CHECK: sbci r19, 204 | ||
| ; CHECK: sbci r20, 104 | ||
| ; CHECK: sbci r21, 37 | ||
| ; CHECK: sbci r22, 25 | ||
| ; CHECK: sbci r23, 22 | ||
| ; CHECK: sbci r24, 236 | ||
| ; CHECK: sbci r25, 190 | ||
| %result = sub i64 %a, 13757395258967641292 | ||
| ret i64 %result | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| ; RUN: llc -mattr=sram,movw,addsubiw < %s -march=avr | FileCheck %s | ||
|
|
||
| declare void @llvm.va_start(i8*) | ||
| declare i16 @vsprintf(i8* nocapture, i8* nocapture, i8*) | ||
| declare void @llvm.va_end(i8*) | ||
|
|
||
| define i16 @varargs1(i8* nocapture %x, ...) { | ||
| ; CHECK-LABEL: varargs1: | ||
| ; CHECK: movw r20, r28 | ||
| ; CHECK: subi r20, 215 | ||
| ; CHECK: sbci r21, 255 | ||
| ; CHECK: movw r24, r28 | ||
| ; CHECK: adiw r24, 3 | ||
| ; CHECK: ldd r22, Y+39 | ||
| ; CHECK: ldd r23, Y+40 | ||
| ; CHECK: call | ||
| %buffer = alloca [32 x i8] | ||
| %ap = alloca i8* | ||
| %ap1 = bitcast i8** %ap to i8* | ||
| call void @llvm.va_start(i8* %ap1) | ||
| %arraydecay = getelementptr inbounds [32 x i8], [32 x i8]* %buffer, i16 0, i16 0 | ||
| %1 = load i8*, i8** %ap | ||
| %call = call i16 @vsprintf(i8* %arraydecay, i8* %x, i8* %1) | ||
| call void @llvm.va_end(i8* %ap1) | ||
| ret i16 0 | ||
| } | ||
|
|
||
| define i16 @varargs2(i8* nocapture %x, ...) { | ||
| ; CHECK-LABEL: varargs2: | ||
| ; CHECK: ld r24, Z | ||
| ; CHECK: ldd r25, Z+1 | ||
| %ap = alloca i8* | ||
| %ap1 = bitcast i8** %ap to i8* | ||
| call void @llvm.va_start(i8* %ap1) | ||
| %1 = va_arg i8** %ap, i16 | ||
| call void @llvm.va_end(i8* %ap1) | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| declare void @var1223(i16, ...) | ||
| define void @varargcall() { | ||
| ; CHECK-LABEL: varargcall: | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 191 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 223 | ||
| ; CHECK: push [[REG2]] | ||
| ; CHECK: push [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 189 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 205 | ||
| ; CHECK: push [[REG2]] | ||
| ; CHECK: push [[REG1]] | ||
| ; CHECK: ldi [[REG1:r[0-9]+]], 205 | ||
| ; CHECK: ldi [[REG2:r[0-9]+]], 171 | ||
| ; CHECK: push [[REG2]] | ||
| ; CHECK: push [[REG1]] | ||
| ; CHECK: call | ||
| ; CHECK: adiw r30, 6 | ||
| tail call void (i16, ...) @var1223(i16 -21555, i16 -12867, i16 -8257) | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| define i8 @xor8_reg_reg(i8 %a, i8 %b) { | ||
| ; CHECK-LABEL: xor8_reg_reg: | ||
| ; CHECK: eor r24, r22 | ||
| %result = xor i8 %a, %b | ||
| ret i8 %result | ||
| } | ||
|
|
||
| define i16 @xor16_reg_reg(i16 %a, i16 %b) { | ||
| ; CHECK-LABEL: xor16_reg_reg: | ||
| ; CHECK: eor r24, r22 | ||
| ; CHECK: eor r25, r23 | ||
| %result = xor i16 %a, %b | ||
| ret i16 %result | ||
| } | ||
|
|
||
| define i32 @xor32_reg_reg(i32 %a, i32 %b) { | ||
| ; CHECK-LABEL: xor32_reg_reg: | ||
| ; CHECK: eor r22, r18 | ||
| ; CHECK: eor r23, r19 | ||
| ; CHECK: eor r24, r20 | ||
| ; CHECK: eor r25, r21 | ||
| %result = xor i32 %a, %b | ||
| ret i32 %result | ||
| } | ||
|
|
||
| define i64 @xor64_reg_reg(i64 %a, i64 %b) { | ||
| ; CHECK-LABEL: xor64_reg_reg: | ||
| ; CHECK: eor r18, r10 | ||
| ; CHECK: eor r19, r11 | ||
| ; CHECK: eor r20, r12 | ||
| ; CHECK: eor r21, r13 | ||
| ; CHECK: eor r22, r14 | ||
| ; CHECK: eor r23, r15 | ||
| ; CHECK: eor r24, r16 | ||
| ; CHECK: eor r25, r17 | ||
| %result = xor i64 %a, %b | ||
| ret i64 %result | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ; RUN: llc < %s -march=avr | FileCheck %s | ||
|
|
||
| ; zext R25:R24, R24 | ||
| ; eor R25, R25 | ||
| define i16 @zext1(i8 %x) { | ||
| ; CHECK-LABEL: zext1: | ||
| ; CHECK: eor r25, r25 | ||
| %1 = zext i8 %x to i16 | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| ; zext R25:R24, R20 | ||
| ; mov R24, R20 | ||
| ; eor R25, R25 | ||
| define i16 @zext2(i8 %x, i8 %y) { | ||
| ; CHECK-LABEL: zext2: | ||
| ; CHECK: mov r24, r22 | ||
| ; CHECK: eor r25, r25 | ||
| %1 = zext i8 %y to i16 | ||
| ret i16 %1 | ||
| } | ||
|
|
||
| ; zext R25:R24, R24 | ||
| ; eor R25, R25 | ||
| define i16 @zext_i1(i1 %x) { | ||
| ; CHECK-LABEL: zext_i1: | ||
| ; CHECK: eor r25, r25 | ||
| %1 = zext i1 %x to i16 | ||
| ret i16 %1 | ||
| } | ||
|
|