Index: llvm/lib/Target/AVR/AVRInstrInfo.td =================================================================== --- llvm/lib/Target/AVR/AVRInstrInfo.td +++ llvm/lib/Target/AVR/AVRInstrInfo.td @@ -194,6 +194,11 @@ let EncoderMethod = "encodeRelCondBrTarget"; } +def rcalltarget_13 : Operand { + let PrintMethod = "printPCRelImm"; + let EncoderMethod = "encodeRelCondBrTarget"; +} + // The target of a 22 or 16-bit call/jmp instruction. def call_target : Operand { let EncoderMethod = "encodeCallTarget"; @@ -965,10 +970,8 @@ let isCall = 1 in { // SP is marked as a use to prevent stack-pointer assignments that appear // immediately before calls from potentially appearing dead. - let Uses = [SP] in def RCALLk : FBRk<1, (outs), - (ins brtarget_13 - : $target), - "rcall\t$target", []>; + let Uses = [SP] in def RCALLk : FBRk<1, (outs), (ins rcalltarget_13:$k), + "rcall\t$k", [(AVRcall imm:$k)]>; // SP is marked as a use to prevent stack-pointer assignments that appear // immediately before calls from potentially appearing dead. @@ -985,13 +988,10 @@ // SP is marked as a use to prevent stack-pointer assignments that appear // immediately before calls from potentially appearing dead. // - //: TODO: the imm field can be either 16 or 22 bits in devices with more + // TODO: the imm field can be either 16 or 22 bits in devices with more // than 64k of ROM, fix it once we support the largest devices. - let Uses = [SP] in def CALLk : F32BRk<0b111, (outs), - (ins call_target - : $k), - "call\t$k", [(AVRcall imm - : $k)]>, + let Uses = [SP] in def CALLk : F32BRk<0b111, (outs), (ins call_target:$k), + "call\t$k", [(AVRcall imm:$k)]>, Requires<[HasJMPCALL]>; } @@ -2448,8 +2448,12 @@ : $src2))>; // Calls. -def : Pat<(AVRcall(i16 tglobaladdr : $dst)), (CALLk tglobaladdr : $dst)>; -def : Pat<(AVRcall(i16 texternalsym : $dst)), (CALLk texternalsym : $dst)>; +let Predicates = [HasJMPCALL] in { + def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (CALLk tglobaladdr:$dst)>; + def : Pat<(AVRcall(i16 texternalsym:$dst)), (CALLk texternalsym:$dst)>; +} +def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (RCALLk tglobaladdr:$dst)>; +def : Pat<(AVRcall(i16 texternalsym:$dst)), (RCALLk texternalsym:$dst)>; // `anyext` def : Pat<(i16(anyext i8 Index: llvm/test/CodeGen/AVR/call.ll =================================================================== --- llvm/test/CodeGen/AVR/call.ll +++ llvm/test/CodeGen/AVR/call.ll @@ -1,4 +1,5 @@ -; RUN: llc < %s -march=avr -mattr=avr6 | FileCheck %s +; RUN: llc < %s -mtriple=avr -mcpu=avr6 | FileCheck %s --check-prefixes=CHECK,AVR6 +; RUN: llc < %s -mtriple=avr -mcpu=avr2 | FileCheck %s --check-prefixes=CHECK,AVR2 ; TODO: test returning byval structs @@ -18,11 +19,13 @@ define i8 @calli8_reg() { ; CHECK-LABEL: calli8_reg: ; CHECK: ldi r24, 12 -; CHECK: call foo8_1 +; AVR6: call foo8_1 +; AVR2: rcall foo8_1 ; CHECK: ldi r24, 12 ; CHECK: ldi r22, 13 ; CHECK: ldi r20, 14 -; CHECK: call foo8_2 +; AVR6: call foo8_2 +; AVR2: rcall foo8_2 %result1 = call i8 @foo8_1(i8 12) %result2 = call i8 @foo8_2(i8 12, i8 13, i8 14) ret i8 %result2 @@ -34,7 +37,8 @@ ; CHECK: ldi [[REG2:r[0-9]+]], 11 ; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] -; CHECK: call foo8_3 +; AVR6: call foo8_3 +; AVR2: rcall 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 } @@ -45,7 +49,8 @@ ; CHECK: ldi r25, 2 ; CHECK: ldi r22, 2 ; CHECK: ldi r23, 2 -; CHECK: call foo16_1 +; AVR6: call foo16_1 +; AVR2: rcall foo16_1 %result1 = call i16 @foo16_1(i16 513, i16 514) ret i16 %result1 } @@ -60,7 +65,8 @@ ; CHECK: ldi [[REG2:r[0-9]+]], 2 ; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] -; CHECK: call foo16_2 +; AVR6: call foo16_2 +; AVR2: rcall 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 } @@ -75,7 +81,8 @@ ; CHECK: ldi r19, 132 ; CHECK: ldi r20, 30 ; CHECK: ldi r21, 2 -; CHECK: call foo32_1 +; AVR6: call foo32_1 +; AVR2: rcall foo32_1 %result1 = call i32 @foo32_1(i32 34554432, i32 35554432) ret i32 %result1 } @@ -90,7 +97,8 @@ ; CHECK: ldi [[REG2:r[0-9]+]], 66 ; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] -; CHECK: call foo32_2 +; AVR6: call foo32_2 +; AVR2: rcall foo32_2 %result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432) ret i32 %result1 } @@ -105,7 +113,8 @@ ; CHECK: ldi r23, 73 ; CHECK: ldi r24, 31 ; CHECK: ldi r25, 242 -; CHECK: call foo64_1 +; AVR6: call foo64_1 +; AVR2: rcall foo64_1 %result1 = call i64 @foo64_1(i64 17446744073709551615) ret i64 %result1 } @@ -129,7 +138,8 @@ ; CHECK: ldi [[REG2:r[0-9]+]], 255 ; CHECK: std Z+1, [[REG1]] ; CHECK: std Z+2, [[REG2]] -; CHECK: call foo64_2 +; AVR6: call foo64_2 +; AVR2: rcall foo64_2 %result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615) ret i64 %result1 } @@ -171,7 +181,9 @@ define i32 @icall(i32 (i32) addrspace(1)* %foo) { ; CHECK-LABEL: icall: -; CHECK: movw r30, r24 +; AVR6: movw r30, r24 +; AVR2: mov r30, r24 +; AVR2: mov r31, r25 ; CHECK: ldi r22, 147 ; CHECK: ldi r23, 248 ; CHECK: ldi r24, 214 @@ -192,14 +204,28 @@ 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 +; AVR6: movw [[REG0:(r[0-9]+|[XYZ])]], r24 +; AVR6: movw [[REG1:(r[0-9]+|[XYZ])]], r22 +; AVR6: movw r22, r18 +; AVR6: movw r24, r20 +; AVR6: movw r18, [[REG1]] +; AVR6: movw r20, [[REG0]] +; AVR6: call __divsf3 +; AVR6: call foofloat +; AVR2: mov [[REG0:(r[0-9]+)]], r24 +; AVR2: mov [[REG1:(r[0-9]+)]], r25 +; AVR2: mov [[REG2:(r[0-9]+)]], r22 +; AVR2: mov [[REG3:(r[0-9]+)]], r23 +; AVR2: mov r22, r18 +; AVR2: mov r23, r19 +; AVR2: mov r24, r20 +; AVR2: mov r25, r21 +; AVR2: mov r18, [[REG2]] +; AVR2: mov r19, [[REG3]] +; AVR2: mov r20, [[REG0]] +; AVR2: mov r21, [[REG1]] +; AVR2: rcall __divsf3 +; AVR2: rcall foofloat ; CHECK: subi r22, 251 ; CHECK: sbci r23, 255 ; CHECK: sbci r24, 255