90 changes: 70 additions & 20 deletions llvm/test/CodeGen/AVR/interrupts.ll
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
; RUN: llc < %s -march=avr | FileCheck %s

@count = global i8 0
@funcptr = global void () addrspace(1)* null

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-NEXT: clr r1
; CHECK: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
ret void
Expand All @@ -22,13 +20,10 @@ define void @interrupt_handler_via_ir_attribute() #0 {
; CHECK-LABEL: interrupt_handler_via_ir_attribute:
; CHECK: sei
; CHECK-NEXT: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: clr r1
; CHECK: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
ret void
Expand All @@ -38,13 +33,10 @@ 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-NEXT: clr r1
; CHECK: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
ret void
Expand All @@ -54,13 +46,10 @@ define void @signal_handler_via_attribute() #1 {
; CHECK-LABEL: signal_handler_via_attribute:
; CHECK-NOT: sei
; CHECK: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: clr r1
; CHECK: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
ret void
Expand All @@ -70,10 +59,8 @@ define avr_intrcc void @interrupt_alloca() {
; CHECK-LABEL: interrupt_alloca:
; CHECK: sei
; CHECK-NEXT: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: clr r1
; CHECK: push r28
; CHECK-NEXT: push r29
; CHECK-NEXT: in r28, 61
Expand All @@ -94,7 +81,6 @@ define avr_intrcc void @interrupt_alloca() {
; CHECK-NEXT: pop r28
; CHECK: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
alloca i8
Expand All @@ -104,18 +90,15 @@ define avr_intrcc void @interrupt_alloca() {
define void @signal_handler_with_increment() #1 {
; CHECK-LABEL: signal_handler_with_increment:
; CHECK: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: clr r1
; CHECK-NEXT: push r24
; CHECK-NEXT: lds r24, count
; CHECK-NEXT: inc r24
; CHECK-NEXT: sts count, r24
; CHECK-NEXT: pop r24
; CHECK-NEXT: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
%old = load volatile i8, i8* @count
Expand All @@ -124,16 +107,39 @@ define void @signal_handler_with_increment() #1 {
ret void
}

; Check that r1 is saved/restored and set to 0 when using inline assembly.
define void @signal_handler_with_asm() #1 {
; CHECK-LABEL: signal_handler_with_asm:
; CHECK: push r0
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: clr r1
; CHECK-NEXT: push r24
; CHECK-NEXT: ldi
; ;APP
; CHECK: mov
; ;NO_APP
; CHECK: pop r24
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
call i8 asm sideeffect "mov $0, $1", "=r,r"(i8 3) nounwind
ret void
}

declare void @foo()

; When a signal handler calls a function, it must push/pop all call clobbered
; registers.
define void @signal_handler_with_call() #1 {
; CHECK-LABEL: signal_handler_with_call:
; CHECK: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: clr r1
; CHECK-NEXT: push r18
; CHECK-NEXT: push r19
Expand All @@ -160,14 +166,58 @@ define void @signal_handler_with_call() #1 {
; CHECK-NEXT: pop r20
; CHECK-NEXT: pop r19
; CHECK-NEXT: pop r18
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
call void @foo()
ret void
}

define void @signal_handler_with_icall() #1 {
; CHECK-LABEL: signal_handler_with_icall:
; CHECK: push r0
; CHECK-NEXT: in r0, 63
; CHECK-NEXT: push r0
; CHECK-NEXT: push r1
; CHECK-NEXT: clr r1
; CHECK-NEXT: push r18
; CHECK-NEXT: push r19
; CHECK-NEXT: push r20
; CHECK-NEXT: push r21
; CHECK-NEXT: push r22
; CHECK-NEXT: push r23
; CHECK-NEXT: push r24
; CHECK-NEXT: push r25
; CHECK-NEXT: push r26
; CHECK-NEXT: push r27
; CHECK-NEXT: push r30
; CHECK-NEXT: push r31
; CHECK-NEXT: lds r30, funcptr
; CHECK-NEXT: lds r31, funcptr+1
; CHECK-NEXT: icall
; CHECK-NEXT: pop r31
; CHECK-NEXT: pop r30
; CHECK-NEXT: pop r27
; CHECK-NEXT: pop r26
; CHECK-NEXT: pop r25
; CHECK-NEXT: pop r24
; CHECK-NEXT: pop r23
; CHECK-NEXT: pop r22
; CHECK-NEXT: pop r21
; CHECK-NEXT: pop r20
; CHECK-NEXT: pop r19
; CHECK-NEXT: pop r18
; CHECK-NEXT: pop r1
; CHECK-NEXT: pop r0
; CHECK-NEXT: out 63, r0
; CHECK-NEXT: pop r0
; CHECK-NEXT: reti
%ptr = load volatile void() addrspace(1)*, void() addrspace(1)** @funcptr
call void %ptr()
ret void
}

attributes #0 = { "interrupt" }
attributes #1 = { "signal" }
30 changes: 0 additions & 30 deletions llvm/test/CodeGen/AVR/pseudo/LDWRdPtr-same-src-dst.mir

This file was deleted.

2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AVR/pseudo/NEGWRd.mir
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ body: |
; CHECK-NEXT: $r14 = NEGRd $r14
; CHECK-NEXT: $r15 = SBCRdRr $r15, $r1, implicit-def $sreg, implicit killed $sreg
$r15r14 = NEGWRd $r15r14, implicit-def $sreg
$r15r14 = NEGWRd $r15r14, implicit-def $sreg, implicit $r1
...
25 changes: 25 additions & 0 deletions llvm/test/CodeGen/AVR/pseudo/ROLBrd.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s

# This test checks the expansion of the 8-bit ROLB (rotate) pseudo instruction.

--- |
target triple = "avr--"
define void @test_rolbrd() {
entry:
ret void
}
...

---
name: test_rolbrd
body: |
bb.0.entry:
liveins: $r14
; CHECK-LABEL: test_rolbrd
; CHECK: $r14 = ADDRdRr killed $r14, killed $r14, implicit-def $sreg
; CHECK-NEXT: $r14 = ADCRdRr $r14, $r1, implicit-def dead $sreg, implicit killed $sreg
$r14 = ROLBRd $r14, implicit-def $sreg, implicit $r1
...
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
; RUN: llc -mattr=addsubiw < %s -march=avr | FileCheck %s

; This verifies that the middle end can handle an unaligned atomic load.
; This verifies that the backend can handle an unaligned atomic load and store.
;
; In the past, an assertion inside the SelectionDAGBuilder would always
; hit an assertion for unaligned loads and stores.
Expand All @@ -14,6 +14,7 @@ define void @foo(%AtomicI16* %self) {
start:
%a = getelementptr inbounds %AtomicI16, %AtomicI16* %self, i16 0, i32 0, i32 0
load atomic i16, i16* %a seq_cst, align 1
store atomic i16 5, i16* %a seq_cst, align 1
ret void
}

27 changes: 27 additions & 0 deletions llvm/test/CodeGen/AVR/zeroreg.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s

; This file tests whether the compiler correctly works with the r1 register,
; clearing it when needed.

; Test regular use of r1 as a zero register.
; CHECK-LABEL: store8zero:
; CHECK: st {{[XYZ]}}, r1
; CHECK-NEXT: mov r24, r1
; CHECK-NEXT: ret
define i8 @store8zero(i8* %x) {
store i8 0, i8* %x
ret i8 0
}

; Test that mulitplication instructions (mul, muls, etc) clobber r1 and require
; a "clr r1" instruction.
; CHECK-LABEL: mul:
; CHECK: muls
; CHECK-NEXT: clr r1
; CHECK-NEXT: st {{[XYZ]}}, r0
; CHECK-NEXT: ret
define void @mul(i8* %ptr, i8 %n) {
%result = mul i8 %n, 3
store i8 %result, i8* %ptr
ret void
}