diff --git a/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/lib/Target/AVR/AVRExpandPseudoInsts.cpp index 540e05a9299..400e9bd8fdc 100644 --- a/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -699,7 +699,9 @@ bool AVRExpandPseudo::expand(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(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(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(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/lib/Target/AVR/AVRRegisterInfo.cpp b/lib/Target/AVR/AVRRegisterInfo.cpp index 249dc5512c2..7099b29a8bc 100644 --- a/lib/Target/AVR/AVRRegisterInfo.cpp +++ b/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/test/CodeGen/AVR/std-ldd-immediate-overflow.ll b/test/CodeGen/AVR/std-ldd-immediate-overflow.ll new file mode 100644 index 00000000000..290e349c534 --- /dev/null +++ b/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)