llvm.org GIT mirror llvm / 1fc9dfd
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 Dylan McKay 3 years ago
3 changed file(s) with 31 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
698698 OpHi = AVR::LDDRdPtrQ;
699699 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
700700
701 assert(Imm <= 63 && "Offset is out of range");
701 // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
702 // allowed for the instruction, 62 is the limit here.
703 assert(Imm <= 62 && "Offset is out of range");
702704
703705 // Use a temporary register if src and dst registers are the same.
704706 if (DstReg == SrcReg)
10731075 OpHi = AVR::STDPtrQRr;
10741076 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
10751077
1076 assert(Imm <= 63 && "Offset is out of range");
1078 // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
1079 // allowed for the instruction, 62 is the limit here.
1080 assert(Imm <= 62 && "Offset is out of range");
10771081
10781082 auto MIBLO = buildMI(MBB, MBBI, OpLo)
10791083 .addReg(DstReg)
11031107 OpHi = AVR::INRdA;
11041108 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
11051109
1106 assert(Imm <= 63 && "Address is out of range");
1110 // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
1111 // allowed for the instruction, 62 is the limit here.
1112 assert(Imm <= 62 && "Address is out of range");
11071113
11081114 auto MIBLO = buildMI(MBB, MBBI, OpLo)
11091115 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
11311137 OpHi = AVR::OUTARr;
11321138 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
11331139
1134 assert(Imm <= 63 && "Address is out of range");
1140 // Since we add 1 to the Imm value for the high byte below, and 63 is the highest Imm value
1141 // allowed for the instruction, 62 is the limit here.
1142 assert(Imm <= 62 && "Address is out of range");
11351143
11361144 // 16 bit I/O writes need the high byte first
11371145 auto MIBHI = buildMI(MBB, MBBI, OpHi)
202202 // If the offset is too big we have to adjust and restore the frame pointer
203203 // to materialize a valid load/store with displacement.
204204 //:TODO: consider using only one adiw/sbiw chain for more than one frame index
205 if (Offset > 63) {
205 if (Offset > 62) {
206206 unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;
207207 int AddOffset = Offset - 63 + 1;
208208
0 ; RUN: llc -O0 < %s -march=avr | FileCheck %s
1
2 define i32 @std_ldd_overflow() {
3 %src = alloca [4 x i8]
4 %dst = alloca [4 x i8]
5 %buf = alloca [28 x i16]
6 %1 = bitcast [4 x i8]* %src to i32*
7 store i32 0, i32 *%1
8 %2 = bitcast [4 x i8]* %dst to i8*
9 %3 = bitcast [4 x i8]* %src to i8*
10 call void @llvm.memcpy.p0i8.p0i8.i16(i8* %2, i8* %3, i16 4, i32 1, i1 false)
11 ; CHECK-NOT: std {{[XYZ]}}+64, {{r[0-9]+}}
12 ; CHECK-NOT: ldd {{r[0-9]+}}, {{[XYZ]}}+64
13
14 ret i32 0
15 }
16
17 declare void @llvm.memcpy.p0i8.p0i8.i16(i8* nocapture writeonly, i8* nocapture readonly, i16, i32, i1)