summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp16
-rw-r--r--llvm/lib/Target/AVR/AVRRegisterInfo.cpp2
-rw-r--r--llvm/test/CodeGen/AVR/std-ldd-immediate-overflow.ll18
3 files changed, 31 insertions, 5 deletions
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 540e05a9299..400e9bd8fdc 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -699,7 +699,9 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::LDDRdPtrQ;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
- assert(Imm <= 63 && "Offset is out of range");
+ // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
+ // allowed for the instruction, 62 is the limit here.
+ assert(Imm <= 62 && "Offset is out of range");
// Use a temporary register if src and dst registers are the same.
if (DstReg == SrcReg)
@@ -1074,7 +1076,9 @@ bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::STDPtrQRr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- assert(Imm <= 63 && "Offset is out of range");
+ // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
+ // allowed for the instruction, 62 is the limit here.
+ assert(Imm <= 62 && "Offset is out of range");
auto MIBLO = buildMI(MBB, MBBI, OpLo)
.addReg(DstReg)
@@ -1104,7 +1108,9 @@ bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::INRdA;
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
- assert(Imm <= 63 && "Address is out of range");
+ // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
+ // allowed for the instruction, 62 is the limit here.
+ assert(Imm <= 62 && "Address is out of range");
auto MIBLO = buildMI(MBB, MBBI, OpLo)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
@@ -1132,7 +1138,9 @@ bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
OpHi = AVR::OUTARr;
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- assert(Imm <= 63 && "Address is out of range");
+ // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
+ // allowed for the instruction, 62 is the limit here.
+ assert(Imm <= 62 && "Address is out of range");
// 16 bit I/O writes need the high byte first
auto MIBHI = buildMI(MBB, MBBI, OpHi)
diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
index 249dc5512c2..7099b29a8bc 100644
--- a/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
+++ b/llvm/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -203,7 +203,7 @@ void AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
// If the offset is too big we have to adjust and restore the frame pointer
// to materialize a valid load/store with displacement.
//:TODO: consider using only one adiw/sbiw chain for more than one frame index
- if (Offset > 63) {
+ if (Offset > 62) {
unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;
int AddOffset = Offset - 63 + 1;
diff --git a/llvm/test/CodeGen/AVR/std-ldd-immediate-overflow.ll b/llvm/test/CodeGen/AVR/std-ldd-immediate-overflow.ll
new file mode 100644
index 00000000000..290e349c534
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/std-ldd-immediate-overflow.ll
@@ -0,0 +1,18 @@
+; RUN: llc -O0 < %s -march=avr | FileCheck %s
+
+define i32 @std_ldd_overflow() {
+ %src = alloca [4 x i8]
+ %dst = alloca [4 x i8]
+ %buf = alloca [28 x i16]
+ %1 = bitcast [4 x i8]* %src to i32*
+ store i32 0, i32 *%1
+ %2 = bitcast [4 x i8]* %dst to i8*
+ %3 = bitcast [4 x i8]* %src to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i16(i8* %2, i8* %3, i16 4, i32 1, i1 false)
+; CHECK-NOT: std {{[XYZ]}}+64, {{r[0-9]+}}
+; CHECK-NOT: ldd {{r[0-9]+}}, {{[XYZ]}}+64
+
+ ret i32 0
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i16(i8* nocapture writeonly, i8* nocapture readonly, i16, i32, i1)
OpenPOWER on IntegriCloud