summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Shi <ben.shi@streamcomputing.com>2022-03-13 06:35:49 +0000
committerTom Stellard <tstellar@redhat.com>2022-05-24 10:53:49 -0700
commitc81f3d00cbd4f1e6771512f837440d1676fb55ae (patch)
treef21796baad1181f6bd753b443f4e68d6cb4c733a
parent5f6fe6b93e85aa90b92681037f4dd42403368bb4 (diff)
downloadllvm-c81f3d00cbd4f1e6771512f837440d1676fb55ae.tar.gz
[AVR] Generate 'rcall' instead of 'call' on avr2 and avr25
The 'call' (long call) instruction is available on avr3 and above, and devices in avr2 and avr25 should use the 'rcall' (short call) instruction for function calls. Reviewed By: aykevl, dylanmckay Differential Revision: https://reviews.llvm.org/D121539 (cherry picked from commit 45638931fb7c7a1b9c850e47601541b398868538)
-rw-r--r--llvm/lib/Target/AVR/AVRInstrInfo.td28
-rw-r--r--llvm/test/CodeGen/AVR/call.ll64
2 files changed, 61 insertions, 31 deletions
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index 2b96dc0b833a..7e027369f096 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -194,6 +194,11 @@ def brtarget_13 : Operand<OtherVT> {
let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
}
+def rcalltarget_13 : Operand<i16> {
+ let PrintMethod = "printPCRelImm";
+ let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
+}
+
// The target of a 22 or 16-bit call/jmp instruction.
def call_target : Operand<iPTR> {
let EncoderMethod = "encodeCallTarget";
@@ -965,10 +970,8 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in {
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 @@ let isCall = 1 in {
// 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]>;
}
@@ -2457,8 +2457,12 @@ def : Pat<(adde i8
: $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
diff --git a/llvm/test/CodeGen/AVR/call.ll b/llvm/test/CodeGen/AVR/call.ll
index 7d94f9b48878..ec91480163b1 100644
--- a/llvm/test/CodeGen/AVR/call.ll
+++ b/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 @@ declare i64 @foo64_2(i64, i64, i64)
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 @@ define i8 @calli8_stack() {
; 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 @@ define i16 @calli16_reg() {
; 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 @@ define i16 @calli16_stack() {
; 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 @@ define i32 @calli32_reg() {
; 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 @@ define i32 @calli32_stack() {
; 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 @@ define i64 @calli64_reg() {
; 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 @@ define i64 @calli64_stack() {
; 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 void @testcallprologue() {
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 @@ declare i32 @foofloat(float)
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