Skip to content

Commit 1fc9dfd

Browse files
committed
Merging r314890:
------------------------------------------------------------------------ r314890 | dylanmckay | 2017-10-04 22:51:21 +1300 (Wed, 04 Oct 2017) | 16 lines [AVR] Fix displacement overflow for LDDW/STDW In some cases, the code generator attempts to generate instructions such as: lddw r24, Y+63 which expands to: ldd r24, Y+63 ldd r25, Y+64 # Oops! This is actually ld r25, Y in the binary This commit limits the first offset to 62, and thus the second to 63. It also updates some asserts in AVRExpandPseudoInsts.cpp, including for INW and OUTW, which appear to be unused. Patch by Thomas Backman. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@315832 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 0779919 commit 1fc9dfd

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

lib/Target/AVR/AVRExpandPseudoInsts.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,9 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
699699
OpHi = AVR::LDDRdPtrQ;
700700
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
701701

702-
assert(Imm <= 63 && "Offset is out of range");
702+
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
703+
// allowed for the instruction, 62 is the limit here.
704+
assert(Imm <= 62 && "Offset is out of range");
703705

704706
// Use a temporary register if src and dst registers are the same.
705707
if (DstReg == SrcReg)
@@ -1074,7 +1076,9 @@ bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
10741076
OpHi = AVR::STDPtrQRr;
10751077
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
10761078

1077-
assert(Imm <= 63 && "Offset is out of range");
1079+
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
1080+
// allowed for the instruction, 62 is the limit here.
1081+
assert(Imm <= 62 && "Offset is out of range");
10781082

10791083
auto MIBLO = buildMI(MBB, MBBI, OpLo)
10801084
.addReg(DstReg)
@@ -1104,7 +1108,9 @@ bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
11041108
OpHi = AVR::INRdA;
11051109
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
11061110

1107-
assert(Imm <= 63 && "Address is out of range");
1111+
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
1112+
// allowed for the instruction, 62 is the limit here.
1113+
assert(Imm <= 62 && "Address is out of range");
11081114

11091115
auto MIBLO = buildMI(MBB, MBBI, OpLo)
11101116
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
@@ -1132,7 +1138,9 @@ bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
11321138
OpHi = AVR::OUTARr;
11331139
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
11341140

1135-
assert(Imm <= 63 && "Address is out of range");
1141+
// Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
1142+
// allowed for the instruction, 62 is the limit here.
1143+
assert(Imm <= 62 && "Address is out of range");
11361144

11371145
// 16 bit I/O writes need the high byte first
11381146
auto MIBHI = buildMI(MBB, MBBI, OpHi)

lib/Target/AVR/AVRRegisterInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ void AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
203203
// If the offset is too big we have to adjust and restore the frame pointer
204204
// to materialize a valid load/store with displacement.
205205
//:TODO: consider using only one adiw/sbiw chain for more than one frame index
206-
if (Offset > 63) {
206+
if (Offset > 62) {
207207
unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;
208208
int AddOffset = Offset - 63 + 1;
209209

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
; RUN: llc -O0 < %s -march=avr | FileCheck %s
2+
3+
define i32 @std_ldd_overflow() {
4+
%src = alloca [4 x i8]
5+
%dst = alloca [4 x i8]
6+
%buf = alloca [28 x i16]
7+
%1 = bitcast [4 x i8]* %src to i32*
8+
store i32 0, i32 *%1
9+
%2 = bitcast [4 x i8]* %dst to i8*
10+
%3 = bitcast [4 x i8]* %src to i8*
11+
call void @llvm.memcpy.p0i8.p0i8.i16(i8* %2, i8* %3, i16 4, i32 1, i1 false)
12+
; CHECK-NOT: std {{[XYZ]}}+64, {{r[0-9]+}}
13+
; CHECK-NOT: ldd {{r[0-9]+}}, {{[XYZ]}}+64
14+
15+
ret i32 0
16+
}
17+
18+
declare void @llvm.memcpy.p0i8.p0i8.i16(i8* nocapture writeonly, i8* nocapture readonly, i16, i32, i1)

0 commit comments

Comments
 (0)