--- /dev/null
+; RUN: llc < %s -march=avr -mcpu=atmega328p | FileCheck %s
+
+; This test checks a basic 'blinking led' program.
+; It is written for the ATmega328P
+
+; Derived from the following C program (with some cleanups):
+; #include <avr/io.h>
+;
+; void setup_ddr() {
+; DDRB |= _BV(PB5);
+; }
+;
+; void turn_on() {
+; PORTB |= _BV(PB5);
+; }
+;
+; void turn_off() {
+; PORTB &= ~_BV(PB5);
+; }
+;
+; int main() {
+; setup_ddr();
+;
+; while(1) {
+; turn_on();
+; turn_off();
+; }
+;
+; return 0;
+; }
+
+; Sets up the data direction register.
+; CHECK-LABEL: setup_ddr
+define void @setup_ddr() {
+entry:
+
+ ; This should load the value of DDRB, OR it with the bit number and store
+ ; the result back to DDRB.
+
+ ; CHECK: in [[TMPREG:r[0-9]+]], 4
+ ; CHECK-NEXT: ori [[TMPREG]], 32
+
+ ; This next line is unnecessary, but we CodeGen it anyway. We should probably optimize this out (PR31344).
+ ; CHECK-NEXT: ori {{r[0-9]+}}, 0
+
+ ; CHECK-NEXT: out 4, [[TMPREG]]
+ ; CHECK-NEXT: ret
+
+ %0 = load volatile i8, i8* inttoptr (i16 36 to i8*), align 1
+ %conv = zext i8 %0 to i16
+ %or = or i16 %conv, 32
+ %conv1 = trunc i16 %or to i8
+ store volatile i8 %conv1, i8* inttoptr (i16 36 to i8*), align 1
+ ret void
+}
+
+; Turns on the LED.
+; CHECK-LABEL: turn_on
+define void @turn_on() {
+entry:
+
+ ; This should load the value of PORTB, OR it with the bit number and store
+ ; the result back to DDRB.
+
+ ; CHECK: in [[TMPREG:r[0-9]+]], 5
+ ; CHECK-NEXT: ori [[TMPREG]], 32
+
+ ; This next line is unnecessary, but we CodeGen it anyway. We should probably optimize this out (PR31344).
+ ; CHECK-NEXT: ori {{r[0-9]+}}, 0
+
+ ; CHECK-NEXT: out 5, [[TMPREG]]
+ ; CHECK-NEXT: ret
+
+ %0 = load volatile i8, i8* inttoptr (i16 37 to i8*), align 1
+ %conv = zext i8 %0 to i16
+ %or = or i16 %conv, 32
+ %conv1 = trunc i16 %or to i8
+ store volatile i8 %conv1, i8* inttoptr (i16 37 to i8*), align 1
+ ret void
+}
+
+; Turns off the LED.
+; CHECK-LABEL: turn_off
+define void @turn_off() {
+entry:
+
+ ; This should load the value of PORTB, OR it with the bit number and store
+ ; the result back to DDRB.
+
+
+ ; CHECK: in [[TMPREG:r[0-9]+]], 5
+ ; CHECK-NEXT: andi [[TMPREG]], 223
+ ; CHECK-NEXT: andi {{r[0-9]+}}, 0
+ ; CHECK-NEXT: out 5, [[TMPREG]]
+ ; CHECK-NEXT: ret
+
+ %0 = load volatile i8, i8* inttoptr (i16 37 to i8*), align 1
+ %conv = zext i8 %0 to i16
+ %and = and i16 %conv, -33
+ %conv1 = trunc i16 %and to i8
+ store volatile i8 %conv1, i8* inttoptr (i16 37 to i8*), align 1
+ ret void
+}
+
+; CHECK-LABEL: main
+define i16 @main() {
+entry:
+
+ ; CHECK: call setup_ddr
+ call void @setup_ddr()
+
+ br label %while.body
+
+; CHECK-LABEL: LBB3_1
+while.body:
+
+ ; CHECK: call turn_on
+ call void @turn_on()
+
+ ; CHECK-NEXT: call turn_off
+ call void @turn_off()
+
+ ; CHECK-NEXT: rjmp LBB3_1
+ br label %while.body
+}