137 changes: 137 additions & 0 deletions llvm/test/CodeGen/AVR/atomics/load16.ll
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
}
124 changes: 124 additions & 0 deletions llvm/test/CodeGen/AVR/atomics/load8.ll
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
}

37 changes: 37 additions & 0 deletions llvm/test/CodeGen/AVR/atomics/store.ll
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
}

25 changes: 25 additions & 0 deletions llvm/test/CodeGen/AVR/atomics/store16.ll
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
}

20 changes: 20 additions & 0 deletions llvm/test/CodeGen/AVR/brind.ll
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
}
211 changes: 211 additions & 0 deletions llvm/test/CodeGen/AVR/call.ll
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
}
148 changes: 148 additions & 0 deletions llvm/test/CodeGen/AVR/cmp.ll
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
}
40 changes: 40 additions & 0 deletions llvm/test/CodeGen/AVR/com.ll
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
}
345 changes: 345 additions & 0 deletions llvm/test/CodeGen/AVR/directmem.ll
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
}
78 changes: 78 additions & 0 deletions llvm/test/CodeGen/AVR/dynalloca.ll
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
}
92 changes: 92 additions & 0 deletions llvm/test/CodeGen/AVR/eor.ll
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
}
56 changes: 56 additions & 0 deletions llvm/test/CodeGen/AVR/error-srcreg-destreg-same.ll
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
}

23 changes: 23 additions & 0 deletions llvm/test/CodeGen/AVR/expand-integer-failure.ll
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
}

65 changes: 65 additions & 0 deletions llvm/test/CodeGen/AVR/frame.ll
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
}
1 change: 1 addition & 0 deletions llvm/test/CodeGen/AVR/high-pressure-on-ptrregs.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
; RUN: llc < %s -march=avr | FileCheck %s
; XFAIL: *

; This tests how LLVM handles IR which puts very high
; presure on the PTRREGS class for the register allocator.
Expand Down
337 changes: 337 additions & 0 deletions llvm/test/CodeGen/AVR/inline-asm.ll
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
}


33 changes: 33 additions & 0 deletions llvm/test/CodeGen/AVR/interrupts.ll
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
}
97 changes: 97 additions & 0 deletions llvm/test/CodeGen/AVR/io.ll
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
}
24 changes: 24 additions & 0 deletions llvm/test/CodeGen/AVR/lit.local.cfg
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()
142 changes: 142 additions & 0 deletions llvm/test/CodeGen/AVR/load.ll
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
}
80 changes: 80 additions & 0 deletions llvm/test/CodeGen/AVR/or.ll
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
}

70 changes: 70 additions & 0 deletions llvm/test/CodeGen/AVR/progmem.ll
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
}
142 changes: 142 additions & 0 deletions llvm/test/CodeGen/AVR/return.ll
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
}
29 changes: 29 additions & 0 deletions llvm/test/CodeGen/AVR/sext.ll
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
}
130 changes: 130 additions & 0 deletions llvm/test/CodeGen/AVR/store.ll
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
}
92 changes: 92 additions & 0 deletions llvm/test/CodeGen/AVR/sub.ll
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
}
59 changes: 59 additions & 0 deletions llvm/test/CodeGen/AVR/varargs.ll
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
}
41 changes: 41 additions & 0 deletions llvm/test/CodeGen/AVR/xor.ll
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
}

31 changes: 31 additions & 0 deletions llvm/test/CodeGen/AVR/zext.ll
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
}