Skip to content

Commit c81f3d0

Browse files
benshi001tstellar
authored andcommitted
[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 4563893)
1 parent 5f6fe6b commit c81f3d0

File tree

2 files changed

+61
-31
lines changed

2 files changed

+61
-31
lines changed

llvm/lib/Target/AVR/AVRInstrInfo.td

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ def brtarget_13 : Operand<OtherVT> {
194194
let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
195195
}
196196

197+
def rcalltarget_13 : Operand<i16> {
198+
let PrintMethod = "printPCRelImm";
199+
let EncoderMethod = "encodeRelCondBrTarget<AVR::fixup_13_pcrel>";
200+
}
201+
197202
// The target of a 22 or 16-bit call/jmp instruction.
198203
def call_target : Operand<iPTR> {
199204
let EncoderMethod = "encodeCallTarget";
@@ -965,10 +970,8 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in {
965970
let isCall = 1 in {
966971
// SP is marked as a use to prevent stack-pointer assignments that appear
967972
// immediately before calls from potentially appearing dead.
968-
let Uses = [SP] in def RCALLk : FBRk<1, (outs),
969-
(ins brtarget_13
970-
: $target),
971-
"rcall\t$target", []>;
973+
let Uses = [SP] in def RCALLk : FBRk<1, (outs), (ins rcalltarget_13:$k),
974+
"rcall\t$k", [(AVRcall imm:$k)]>;
972975

973976
// SP is marked as a use to prevent stack-pointer assignments that appear
974977
// immediately before calls from potentially appearing dead.
@@ -985,13 +988,10 @@ let isCall = 1 in {
985988
// SP is marked as a use to prevent stack-pointer assignments that appear
986989
// immediately before calls from potentially appearing dead.
987990
//
988-
//: TODO: the imm field can be either 16 or 22 bits in devices with more
991+
// TODO: the imm field can be either 16 or 22 bits in devices with more
989992
// than 64k of ROM, fix it once we support the largest devices.
990-
let Uses = [SP] in def CALLk : F32BRk<0b111, (outs),
991-
(ins call_target
992-
: $k),
993-
"call\t$k", [(AVRcall imm
994-
: $k)]>,
993+
let Uses = [SP] in def CALLk : F32BRk<0b111, (outs), (ins call_target:$k),
994+
"call\t$k", [(AVRcall imm:$k)]>,
995995
Requires<[HasJMPCALL]>;
996996
}
997997

@@ -2457,8 +2457,12 @@ def : Pat<(adde i8
24572457
: $src2))>;
24582458

24592459
// Calls.
2460-
def : Pat<(AVRcall(i16 tglobaladdr : $dst)), (CALLk tglobaladdr : $dst)>;
2461-
def : Pat<(AVRcall(i16 texternalsym : $dst)), (CALLk texternalsym : $dst)>;
2460+
let Predicates = [HasJMPCALL] in {
2461+
def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (CALLk tglobaladdr:$dst)>;
2462+
def : Pat<(AVRcall(i16 texternalsym:$dst)), (CALLk texternalsym:$dst)>;
2463+
}
2464+
def : Pat<(AVRcall(i16 tglobaladdr:$dst)), (RCALLk tglobaladdr:$dst)>;
2465+
def : Pat<(AVRcall(i16 texternalsym:$dst)), (RCALLk texternalsym:$dst)>;
24622466

24632467
// `anyext`
24642468
def : Pat<(i16(anyext i8

llvm/test/CodeGen/AVR/call.ll

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
; RUN: llc < %s -march=avr -mattr=avr6 | FileCheck %s
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
23

34
; TODO: test returning byval structs
45

@@ -18,11 +19,13 @@ declare i64 @foo64_2(i64, i64, i64)
1819
define i8 @calli8_reg() {
1920
; CHECK-LABEL: calli8_reg:
2021
; CHECK: ldi r24, 12
21-
; CHECK: call foo8_1
22+
; AVR6: call foo8_1
23+
; AVR2: rcall foo8_1
2224
; CHECK: ldi r24, 12
2325
; CHECK: ldi r22, 13
2426
; CHECK: ldi r20, 14
25-
; CHECK: call foo8_2
27+
; AVR6: call foo8_2
28+
; AVR2: rcall foo8_2
2629
%result1 = call i8 @foo8_1(i8 12)
2730
%result2 = call i8 @foo8_2(i8 12, i8 13, i8 14)
2831
ret i8 %result2
@@ -34,7 +37,8 @@ define i8 @calli8_stack() {
3437
; CHECK: ldi [[REG2:r[0-9]+]], 11
3538
; CHECK: std Z+1, [[REG1]]
3639
; CHECK: std Z+2, [[REG2]]
37-
; CHECK: call foo8_3
40+
; AVR6: call foo8_3
41+
; AVR2: rcall foo8_3
3842
%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)
3943
ret i8 %result1
4044
}
@@ -45,7 +49,8 @@ define i16 @calli16_reg() {
4549
; CHECK: ldi r25, 2
4650
; CHECK: ldi r22, 2
4751
; CHECK: ldi r23, 2
48-
; CHECK: call foo16_1
52+
; AVR6: call foo16_1
53+
; AVR2: rcall foo16_1
4954
%result1 = call i16 @foo16_1(i16 513, i16 514)
5055
ret i16 %result1
5156
}
@@ -60,7 +65,8 @@ define i16 @calli16_stack() {
6065
; CHECK: ldi [[REG2:r[0-9]+]], 2
6166
; CHECK: std Z+1, [[REG1]]
6267
; CHECK: std Z+2, [[REG2]]
63-
; CHECK: call foo16_2
68+
; AVR6: call foo16_2
69+
; AVR2: rcall foo16_2
6470
%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)
6571
ret i16 %result1
6672
}
@@ -75,7 +81,8 @@ define i32 @calli32_reg() {
7581
; CHECK: ldi r19, 132
7682
; CHECK: ldi r20, 30
7783
; CHECK: ldi r21, 2
78-
; CHECK: call foo32_1
84+
; AVR6: call foo32_1
85+
; AVR2: rcall foo32_1
7986
%result1 = call i32 @foo32_1(i32 34554432, i32 35554432)
8087
ret i32 %result1
8188
}
@@ -90,7 +97,8 @@ define i32 @calli32_stack() {
9097
; CHECK: ldi [[REG2:r[0-9]+]], 66
9198
; CHECK: std Z+1, [[REG1]]
9299
; CHECK: std Z+2, [[REG2]]
93-
; CHECK: call foo32_2
100+
; AVR6: call foo32_2
101+
; AVR2: rcall foo32_2
94102
%result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432)
95103
ret i32 %result1
96104
}
@@ -105,7 +113,8 @@ define i64 @calli64_reg() {
105113
; CHECK: ldi r23, 73
106114
; CHECK: ldi r24, 31
107115
; CHECK: ldi r25, 242
108-
; CHECK: call foo64_1
116+
; AVR6: call foo64_1
117+
; AVR2: rcall foo64_1
109118
%result1 = call i64 @foo64_1(i64 17446744073709551615)
110119
ret i64 %result1
111120
}
@@ -129,7 +138,8 @@ define i64 @calli64_stack() {
129138
; CHECK: ldi [[REG2:r[0-9]+]], 255
130139
; CHECK: std Z+1, [[REG1]]
131140
; CHECK: std Z+2, [[REG2]]
132-
; CHECK: call foo64_2
141+
; AVR6: call foo64_2
142+
; AVR2: rcall foo64_2
133143
%result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615)
134144
ret i64 %result1
135145
}
@@ -171,7 +181,9 @@ define void @testcallprologue() {
171181

172182
define i32 @icall(i32 (i32) addrspace(1)* %foo) {
173183
; CHECK-LABEL: icall:
174-
; CHECK: movw r30, r24
184+
; AVR6: movw r30, r24
185+
; AVR2: mov r30, r24
186+
; AVR2: mov r31, r25
175187
; CHECK: ldi r22, 147
176188
; CHECK: ldi r23, 248
177189
; CHECK: ldi r24, 214
@@ -192,14 +204,28 @@ declare i32 @foofloat(float)
192204

193205
define i32 @externcall(float %a, float %b) {
194206
; CHECK-LABEL: externcall:
195-
; CHECK: movw [[REG1:(r[0-9]+|[XYZ])]], r24
196-
; CHECK: movw [[REG2:(r[0-9]+|[XYZ])]], r22
197-
; CHECK: movw r22, r18
198-
; CHECK: movw r24, r20
199-
; CHECK: movw r18, [[REG2]]
200-
; CHECK: movw r20, [[REG1]]
201-
; CHECK: call __divsf3
202-
; CHECK: call foofloat
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
203229
; CHECK: subi r22, 251
204230
; CHECK: sbci r23, 255
205231
; CHECK: sbci r24, 255

0 commit comments

Comments
 (0)