1; RUN: llc < %s -march=avr -mcpu=atmega328p | FileCheck %s 2 3; This test checks a basic 'blinking led' program. 4; It is written for the ATmega328P 5 6; Derived from the following C program (with some cleanups): 7; #include <avr/io.h> 8; 9; void setup_ddr() { 10; DDRB |= _BV(PB5); 11; } 12; 13; void turn_on() { 14; PORTB |= _BV(PB5); 15; } 16; 17; void turn_off() { 18; PORTB &= ~_BV(PB5); 19; } 20; 21; int main() { 22; setup_ddr(); 23; 24; while(1) { 25; turn_on(); 26; turn_off(); 27; } 28; 29; return 0; 30; } 31 32; Sets up the data direction register. 33; CHECK-LABEL: setup_ddr 34define void @setup_ddr() { 35entry: 36 37 ; This should load the value of DDRB, OR it with the bit number and store 38 ; the result back to DDRB. 39 40 ; CHECK: in [[TMPREG:r[0-9]+]], 4 41 ; CHECK-NEXT: ori [[TMPREG]], 32 42 43 ; This next line is unnecessary, but we CodeGen it anyway. We should probably optimize this out (PR31344). 44 ; CHECK-NEXT: ori {{r[0-9]+}}, 0 45 46 ; CHECK-NEXT: out 4, [[TMPREG]] 47 ; CHECK-NEXT: ret 48 49 %0 = load volatile i8, i8* inttoptr (i16 36 to i8*), align 1 50 %conv = zext i8 %0 to i16 51 %or = or i16 %conv, 32 52 %conv1 = trunc i16 %or to i8 53 store volatile i8 %conv1, i8* inttoptr (i16 36 to i8*), align 1 54 ret void 55} 56 57; Turns on the LED. 58; CHECK-LABEL: turn_on 59define void @turn_on() { 60entry: 61 62 ; This should load the value of PORTB, OR it with the bit number and store 63 ; the result back to DDRB. 64 65 ; CHECK: in [[TMPREG:r[0-9]+]], 5 66 ; CHECK-NEXT: ori [[TMPREG]], 32 67 68 ; This next line is unnecessary, but we CodeGen it anyway. We should probably optimize this out (PR31344). 69 ; CHECK-NEXT: ori {{r[0-9]+}}, 0 70 71 ; CHECK-NEXT: out 5, [[TMPREG]] 72 ; CHECK-NEXT: ret 73 74 %0 = load volatile i8, i8* inttoptr (i16 37 to i8*), align 1 75 %conv = zext i8 %0 to i16 76 %or = or i16 %conv, 32 77 %conv1 = trunc i16 %or to i8 78 store volatile i8 %conv1, i8* inttoptr (i16 37 to i8*), align 1 79 ret void 80} 81 82; Turns off the LED. 83; CHECK-LABEL: turn_off 84define void @turn_off() { 85entry: 86 87 ; This should load the value of PORTB, OR it with the bit number and store 88 ; the result back to DDRB. 89 90 91 ; CHECK: in [[TMPREG:r[0-9]+]], 5 92 ; CHECK-NEXT: andi [[TMPREG]], 223 93 ; CHECK-NEXT: andi {{r[0-9]+}}, 0 94 ; CHECK-NEXT: out 5, [[TMPREG]] 95 ; CHECK-NEXT: ret 96 97 %0 = load volatile i8, i8* inttoptr (i16 37 to i8*), align 1 98 %conv = zext i8 %0 to i16 99 %and = and i16 %conv, -33 100 %conv1 = trunc i16 %and to i8 101 store volatile i8 %conv1, i8* inttoptr (i16 37 to i8*), align 1 102 ret void 103} 104 105; CHECK-LABEL: main 106define i16 @main() { 107entry: 108 109 ; CHECK: call setup_ddr 110 call void @setup_ddr() 111 112 br label %while.body 113 114; CHECK-LABEL: LBB3_1 115while.body: 116 117 ; CHECK: call turn_on 118 call void @turn_on() 119 120 ; CHECK-NEXT: call turn_off 121 call void @turn_off() 122 123 ; CHECK-NEXT: rjmp LBB3_1 124 br label %while.body 125} 126