[llvm] r314890 - [AVR] Fix displacement overflow for LDDW/STDW

Dylan McKay via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 4 02:51:21 PDT 2017


Author: dylanmckay
Date: Wed Oct  4 02:51:21 2017
New Revision: 314890

URL: http://llvm.org/viewvc/llvm-project?rev=314890&view=rev
Log:
[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.

Added:
    llvm/trunk/test/CodeGen/AVR/std-ldd-immediate-overflow.ll
Modified:
    llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp
    llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp

Modified: llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp?rev=314890&r1=314889&r2=314890&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp (original)
+++ llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp Wed Oct  4 02:51:21 2017
@@ -699,7 +699,9 @@ bool AVRExpandPseudo::expand<AVR::LDDWRd
   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::STDWPt
   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
   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::OUTWAR
   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)

Modified: llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp?rev=314890&r1=314889&r2=314890&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/AVR/AVRRegisterInfo.cpp Wed Oct  4 02:51:21 2017
@@ -203,7 +203,7 @@ void AVRRegisterInfo::eliminateFrameInde
   // 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;
 

Added: llvm/trunk/test/CodeGen/AVR/std-ldd-immediate-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AVR/std-ldd-immediate-overflow.ll?rev=314890&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AVR/std-ldd-immediate-overflow.ll (added)
+++ llvm/trunk/test/CodeGen/AVR/std-ldd-immediate-overflow.ll Wed Oct  4 02:51:21 2017
@@ -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)




More information about the llvm-commits mailing list