]> granicus.if.org Git - llvm/commitdiff
[AVR] Disable register coalescing to the PTRDISPREGS class
authorDylan McKay <me@dylanmckay.io>
Sat, 1 Jun 2019 12:38:56 +0000 (12:38 +0000)
committerDylan McKay <me@dylanmckay.io>
Sat, 1 Jun 2019 12:38:56 +0000 (12:38 +0000)
If we would allow register coalescing on PTRDISPREGS class then register
allocator can lock Z register to some virtual register. Larger instructions
requiring a memory acces then fail during the register allocation phase since
there is no available register to hold a pointer if Y register was already
taken for a stack frame. This patch prevents it by keeping Z register
spillable. It does it by not allowing coalescer to lock it.

Original discussion on https://github.com/avr-rust/rust/issues/128.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362298 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AVR/AVRRegisterInfo.cpp
lib/Target/AVR/AVRRegisterInfo.h
test/CodeGen/AVR/PR37143.ll
test/CodeGen/AVR/store.ll

index 8dc31fe066b96b34d1101e5c5c953e6b0a312f2b..0aae34d7dfd0f3e779620ede913e172c6438a345 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/IR/Function.h"
 #include "llvm/CodeGen/TargetFrameLowering.h"
 
@@ -272,4 +273,18 @@ void AVRRegisterInfo::splitReg(unsigned Reg,
     HiReg = getSubReg(Reg, AVR::sub_hi);
 }
 
+bool AVRRegisterInfo::shouldCoalesce(MachineInstr *MI,
+                                     const TargetRegisterClass *SrcRC,
+                                     unsigned SubReg,
+                                     const TargetRegisterClass *DstRC,
+                                     unsigned DstSubReg,
+                                     const TargetRegisterClass *NewRC,
+                                     LiveIntervals &LIS) const {
+  if(this->getRegClass(AVR::PTRDISPREGSRegClassID)->hasSubClassEq(NewRC)) {
+    return false;
+  }
+
+  return TargetRegisterInfo::shouldCoalesce(MI, SrcRC, SubReg, DstRC, DstSubReg, NewRC, LIS);
+}
+
 } // end of namespace llvm
index 2365039dbe32acdccf44aaf4959bf5184bcdab77..e8354925fed882c6c258bbf54b1b3f1138cd2367 100644 (file)
@@ -55,6 +55,13 @@ public:
     return true;
   }
 
+  bool shouldCoalesce(MachineInstr *MI,
+                      const TargetRegisterClass *SrcRC,
+                      unsigned SubReg,
+                      const TargetRegisterClass *DstRC,
+                      unsigned DstSubReg,
+                      const TargetRegisterClass *NewRC,
+                      LiveIntervals &LIS) const override;
 };
 
 } // end namespace llvm
index db157edc22f08723abc86de030a1f5df2f3e6ec5..72f4a2fd3722c35a66abcf20abd1bbd6848732c0 100644 (file)
@@ -1,9 +1,9 @@
 ; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s
 
-; CHECK: ld {{r[0-9]+}}, [[PTR:[YZ]]]
+; CHECK: ld {{r[0-9]+}}, [[PTR:[XYZ]]]
 ; CHECK: ldd {{r[0-9]+}}, [[PTR]]+1
-; CHECK: st [[PTR]], {{r[0-9]+}}
-; CHECK: std [[PTR]]+1, {{r[0-9]+}}
+; CHECK: st [[PTR2:[XYZ]]], {{r[0-9]+}}
+; CHECK: std [[PTR2]]+1, {{r[0-9]+}}
 define void @load_store_16(i16* nocapture %ptr) local_unnamed_addr #1 {
 entry:
   %0 = load i16, i16* %ptr, align 2
index bad3f61a0135c359bef4c9f9987fe829a1fa9c55..81bad77538745e895ff25f56e172c8a90047a3e5 100644 (file)
@@ -45,9 +45,9 @@ define void @store16disp(i16* %x, i16 %y) {
 
 define void @store16nodisp(i16* %x, i16 %y) {
 ; CHECK-LABEL: store16nodisp:
+; CHECK: subi r24, 192
+; CHECK: sbci r25, 255
 ; CHECK: movw r30, r24
-; CHECK: subi r30, 192
-; CHECK: sbci r31, 255
 ; CHECK: st {{[YZ]}}, r22
 ; CHECK: std {{[YZ]}}+1, r23
   %arrayidx = getelementptr inbounds i16, i16* %x, i16 32