1; RUN: llc < %s -mtriple=avr -mcpu=avr6 | FileCheck %s --check-prefixes=CHECK,AVR6 2; RUN: llc < %s -mtriple=avr -mcpu=avr2 | FileCheck %s --check-prefixes=CHECK,AVR2 3 4; TODO: test returning byval structs 5 6declare i8 @foo8_1(i8) 7declare i8 @foo8_2(i8, i8, i8) 8declare i8 @foo8_3(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8) 9 10declare i16 @foo16_1(i16, i16) 11declare i16 @foo16_2(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16) 12 13declare i32 @foo32_1(i32, i32) 14declare i32 @foo32_2(i32, i32, i32, i32, i32) 15 16declare i64 @foo64_1(i64) 17declare i64 @foo64_2(i64, i64, i64) 18 19define i8 @calli8_reg() { 20; CHECK-LABEL: calli8_reg: 21; CHECK: ldi r24, 12 22; AVR6: call foo8_1 23; AVR2: rcall foo8_1 24; CHECK: ldi r24, 12 25; CHECK: ldi r22, 13 26; CHECK: ldi r20, 14 27; AVR6: call foo8_2 28; AVR2: rcall foo8_2 29 %result1 = call i8 @foo8_1(i8 12) 30 %result2 = call i8 @foo8_2(i8 12, i8 13, i8 14) 31 ret i8 %result2 32} 33 34define i8 @calli8_stack() { 35; CHECK-LABEL: calli8_stack: 36; CHECK: ldi [[REG1:r[0-9]+]], 10 37; CHECK: ldi [[REG2:r[0-9]+]], 11 38; CHECK: std Z+2, [[REG2]] 39; CHECK: std Z+1, [[REG1]] 40; AVR6: call foo8_3 41; AVR2: rcall foo8_3 42 %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) 43 ret i8 %result1 44} 45 46define i16 @calli16_reg() { 47; CHECK-LABEL: calli16_reg: 48; CHECK: ldi r24, 1 49; CHECK: ldi r25, 2 50; CHECK: ldi r22, 2 51; CHECK: ldi r23, 2 52; AVR6: call foo16_1 53; AVR2: rcall foo16_1 54 %result1 = call i16 @foo16_1(i16 513, i16 514) 55 ret i16 %result1 56} 57 58define i16 @calli16_stack() { 59; CHECK-LABEL: calli16_stack: 60; CHECK: ldi [[REG1:r[0-9]+]], 10 61; CHECK: ldi [[REG2:r[0-9]+]], 2 62; CHECK: std Z+4, [[REG2]] 63; CHECK: std Z+3, [[REG1]] 64; CHECK: ldi [[REG1:r[0-9]+]], 9 65; CHECK: ldi [[REG2:r[0-9]+]], 2 66; CHECK: std Z+2, [[REG2]] 67; CHECK: std Z+1, [[REG1]] 68; AVR6: call foo16_2 69; AVR2: rcall foo16_2 70 %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) 71 ret i16 %result1 72} 73 74define i32 @calli32_reg() { 75; CHECK-LABEL: calli32_reg: 76; CHECK: ldi r22, 64 77; CHECK: ldi r23, 66 78; CHECK: ldi r24, 15 79; CHECK: ldi r25, 2 80; CHECK: ldi r18, 128 81; CHECK: ldi r19, 132 82; CHECK: ldi r20, 30 83; CHECK: ldi r21, 2 84; AVR6: call foo32_1 85; AVR2: rcall foo32_1 86 %result1 = call i32 @foo32_1(i32 34554432, i32 35554432) 87 ret i32 %result1 88} 89 90define i32 @calli32_stack() { 91; CHECK-LABEL: calli32_stack: 92; CHECK: ldi [[REG1:r[0-9]+]], 15 93; CHECK: ldi [[REG2:r[0-9]+]], 2 94; CHECK: std Z+4, [[REG2]] 95; CHECK: std Z+3, [[REG1]] 96; CHECK: ldi [[REG1:r[0-9]+]], 64 97; CHECK: ldi [[REG2:r[0-9]+]], 66 98; CHECK: std Z+2, [[REG2]] 99; CHECK: std Z+1, [[REG1]] 100; AVR6: call foo32_2 101; AVR2: rcall foo32_2 102 %result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432) 103 ret i32 %result1 104} 105 106define i64 @calli64_reg() { 107; CHECK-LABEL: calli64_reg: 108; CHECK: ldi r18, 255 109; CHECK: ldi r19, 255 110; CHECK: ldi r20, 155 111; CHECK: ldi r21, 88 112; CHECK: ldi r22, 76 113; CHECK: ldi r23, 73 114; CHECK: ldi r24, 31 115; CHECK: ldi r25, 242 116; AVR6: call foo64_1 117; AVR2: rcall foo64_1 118 %result1 = call i64 @foo64_1(i64 17446744073709551615) 119 ret i64 %result1 120} 121 122define i64 @calli64_stack() { 123; CHECK-LABEL: calli64_stack: 124 125; CHECK: ldi [[REG1:r[0-9]+]], 31 126; CHECK: ldi [[REG2:r[0-9]+]], 242 127; CHECK: std Z+8, [[REG2]] 128; CHECK: std Z+7, [[REG1]] 129; CHECK: ldi [[REG1:r[0-9]+]], 76 130; CHECK: ldi [[REG2:r[0-9]+]], 73 131; CHECK: std Z+6, [[REG2]] 132; CHECK: std Z+5, [[REG1]] 133; CHECK: ldi [[REG1:r[0-9]+]], 155 134; CHECK: ldi [[REG2:r[0-9]+]], 88 135; CHECK: std Z+4, [[REG2]] 136; CHECK: std Z+3, [[REG1]] 137; CHECK: ldi [[REG1:r[0-9]+]], 255 138; CHECK: ldi [[REG2:r[0-9]+]], 255 139; CHECK: std Z+2, [[REG2]] 140; CHECK: std Z+1, [[REG1]] 141; AVR6: call foo64_2 142; AVR2: rcall foo64_2 143 %result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615) 144 ret i64 %result1 145} 146 147; Test passing arguments through the stack when the call frame is allocated 148; in the prologue. 149declare void @foo64_3(i64, i64, i64, i8, ptr) 150 151define void @testcallprologue() { 152; CHECK-LABEL: testcallprologue: 153; CHECK: push r28 154; CHECK: push r29 155; CHECK: sbiw r28, 27 156; CHECK: ldi [[REG1:r[0-9]+]], 88 157; CHECK: std Y+9, [[REG1]] 158; CHECK: ldi [[REG1:r[0-9]+]], 11 159; CHECK: ldi [[REG2:r[0-9]+]], 10 160; CHECK: std Y+8, [[REG2]] 161; CHECK: std Y+7, [[REG1]] 162; CHECK: ldi [[REG1:r[0-9]+]], 13 163; CHECK: ldi [[REG2:r[0-9]+]], 12 164; CHECK: std Y+6, [[REG2]] 165; CHECK: std Y+5, [[REG1]] 166; CHECK: ldi [[REG1:r[0-9]+]], 15 167; CHECK: ldi [[REG2:r[0-9]+]], 14 168; CHECK: std Y+4, [[REG2]] 169; CHECK: std Y+3, [[REG1]] 170; CHECK: ldi [[REG1:r[0-9]+]], 8 171; CHECK: ldi [[REG2:r[0-9]+]], 9 172; CHECK: std Y+2, [[REG2]] 173; CHECK: std Y+1, [[REG1]] 174; CHECK: pop r29 175; CHECK: pop r28 176 %p = alloca [8 x i16] 177 %arraydecay = getelementptr inbounds [8 x i16], ptr %p, i16 0, i16 0 178 call void @foo64_3(i64 723685415333071112, i64 723685415333071112, i64 723685415333071112, i8 88, ptr %arraydecay) 179 ret void 180} 181 182define i32 @icall(ptr addrspace(1) %foo) { 183; CHECK-LABEL: icall: 184; AVR6: movw r30, r24 185; AVR2: mov r30, r24 186; AVR2: mov r31, r25 187; CHECK: ldi r22, 147 188; CHECK: ldi r23, 248 189; CHECK: ldi r24, 214 190; CHECK: ldi r25, 198 191; CHECK: icall 192; CHECK: subi r22, 251 193; CHECK: sbci r23, 255 194; CHECK: sbci r24, 255 195; CHECK: sbci r25, 255 196 %1 = call i32 %foo(i32 3335977107) 197 %2 = add nsw i32 %1, 5 198 ret i32 %2 199} 200 201; Calling external functions (like __divsf3) require extra processing for 202; arguments and return values in the LowerCall function. 203declare i32 @foofloat(float) 204 205define i32 @externcall(float %a, float %b) { 206; CHECK-LABEL: externcall: 207; AVR6: movw [[REG0:(r[0-9]+|[XYZ])]], r24 208; AVR6: movw [[REG1:(r[0-9]+|[XYZ])]], r22 209; AVR6: movw r22, r18 210; AVR6: movw r24, r20 211; AVR6: movw r18, [[REG1]] 212; AVR6: movw r20, [[REG0]] 213; AVR6: call __divsf3 214; AVR6: call foofloat 215; AVR2: mov [[REG0:(r[0-9]+)]], r24 216; AVR2: mov [[REG1:(r[0-9]+)]], r25 217; AVR2: mov [[REG2:(r[0-9]+)]], r22 218; AVR2: mov [[REG3:(r[0-9]+)]], r23 219; AVR2: mov r22, r18 220; AVR2: mov r23, r19 221; AVR2: mov r24, r20 222; AVR2: mov r25, r21 223; AVR2: mov r18, [[REG2]] 224; AVR2: mov r19, [[REG3]] 225; AVR2: mov r20, [[REG0]] 226; AVR2: mov r21, [[REG1]] 227; AVR2: rcall __divsf3 228; AVR2: rcall foofloat 229; CHECK: subi r22, 251 230; CHECK: sbci r23, 255 231; CHECK: sbci r24, 255 232; CHECK: sbci r25, 255 233 %1 = fdiv float %b, %a 234 %2 = call i32 @foofloat(float %1) 235 %3 = add nsw i32 %2, 5 236 ret i32 %3 237} 238