[llvm] r288897 - [AVR] Allow loading from stack slots where src and dest registers are identical

Dylan McKay via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 7 03:08:56 PST 2016


Author: dylanmckay
Date: Wed Dec  7 05:08:56 2016
New Revision: 288897

URL: http://llvm.org/viewvc/llvm-project?rev=288897&view=rev
Log:
[AVR] Allow loading from stack slots where src and dest registers are identical

Fixes PR 31256

Added:
    llvm/trunk/test/CodeGen/AVR/expand-lddw-dst-src-same.mir
Removed:
    llvm/trunk/test/CodeGen/AVR/error-srcreg-destreg-same.ll
Modified:
    llvm/trunk/lib/Target/AVR/AVR.h
    llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp
    llvm/trunk/lib/Target/AVR/AVRInstrInfo.td
    llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp

Modified: llvm/trunk/lib/Target/AVR/AVR.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVR.h?rev=288897&r1=288896&r2=288897&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVR.h (original)
+++ llvm/trunk/lib/Target/AVR/AVR.h Wed Dec  7 05:08:56 2016
@@ -30,6 +30,8 @@ FunctionPass *createAVRFrameAnalyzerPass
 FunctionPass *createAVRDynAllocaSRPass();
 FunctionPass *createAVRBranchSelectionPass();
 
+void initializeAVRExpandPseudoPass(PassRegistry&);
+
 /// Contains the AVR backend.
 namespace AVR {
 

Modified: llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp?rev=288897&r1=288896&r2=288897&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp (original)
+++ llvm/trunk/lib/Target/AVR/AVRExpandPseudoInsts.cpp Wed Dec  7 05:08:56 2016
@@ -25,6 +25,8 @@
 
 using namespace llvm;
 
+#define AVR_EXPAND_PSEUDO_NAME "AVR pseudo instruction expansion pass"
+
 namespace {
 
 /// Expands "placeholder" instructions marked as pseudo into
@@ -33,13 +35,13 @@ class AVRExpandPseudo : public MachineFu
 public:
   static char ID;
 
-  AVRExpandPseudo() : MachineFunctionPass(ID) {}
+  AVRExpandPseudo() : MachineFunctionPass(ID) {
+    initializeAVRExpandPseudoPass(*PassRegistry::getPassRegistry());
+  }
 
   bool runOnMachineFunction(MachineFunction &MF) override;
 
-  StringRef getPassName() const override {
-    return "AVR pseudo instruction expansion pass";
-  }
+  StringRef getPassName() const override { return AVR_EXPAND_PSEUDO_NAME; }
 
 private:
   typedef MachineBasicBlock Block;
@@ -653,18 +655,47 @@ bool AVRExpandPseudo::expand<AVR::LDDWRd
   TRI->splitReg(DstReg, DstLoReg, DstHiReg);
 
   assert(Imm < 63 && "Offset is out of range");
-  assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
+
+  unsigned TmpLoReg = DstLoReg;
+  unsigned TmpHiReg = DstHiReg;
+
+  // HACK: We shouldn't have instances of this instruction
+  // where src==dest because the instruction itself is
+  // marked earlyclobber. We do however get this instruction when
+  // loading from stack slots where the earlyclobber isn't useful.
+  //
+  // In this case, just use a temporary register.
+  if (DstReg == SrcReg) {
+    TmpLoReg = SCRATCH_REGISTER;
+    TmpHiReg = SCRATCH_REGISTER;
+  }
 
   auto MIBLO = buildMI(MBB, MBBI, OpLo)
-    .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+    .addReg(TmpLoReg, RegState::Define | getDeadRegState(DstIsDead))
     .addReg(SrcReg)
     .addImm(Imm);
 
+  // Push the low part of the temporary register to the stack.
+  if (TmpLoReg != DstLoReg)
+    buildMI(MBB, MBBI, AVR::PUSHRr)
+      .addReg(AVR::R0);
+
   auto MIBHI = buildMI(MBB, MBBI, OpHi)
-    .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+    .addReg(TmpHiReg, RegState::Define | getDeadRegState(DstIsDead))
     .addReg(SrcReg, getKillRegState(SrcIsKill))
     .addImm(Imm + 1);
 
+  // If we need to use a temporary register.
+  if (TmpHiReg != DstHiReg) {
+    // Move the hi result from the tmp register to the destination.
+    buildMI(MBB, MBBI, AVR::MOVRdRr)
+      .addReg(DstHiReg).addReg(SCRATCH_REGISTER);
+
+    // Pop the lo result calculated previously and put it into
+    // the lo destination.
+    buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
+  }
+
   MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
   MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
 
@@ -1424,6 +1455,8 @@ bool AVRExpandPseudo::expandMI(Block &MB
 
 } // end of anonymous namespace
 
+INITIALIZE_PASS(AVRExpandPseudo, "avr-expand-pseudo",
+                AVR_EXPAND_PSEUDO_NAME, false, false)
 namespace llvm {
 
 FunctionPass *createAVRExpandPseudoPass() { return new AVRExpandPseudo(); }

Modified: llvm/trunk/lib/Target/AVR/AVRInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRInstrInfo.td?rev=288897&r1=288896&r2=288897&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRInstrInfo.td (original)
+++ llvm/trunk/lib/Target/AVR/AVRInstrInfo.td Wed Dec  7 05:08:56 2016
@@ -1207,6 +1207,7 @@ Constraints = "$ptrreg = $base_wb, at early
 let canFoldAsLoad = 1,
 isReMaterializable = 1 in
 {
+  let Constraints = "@earlyclobber $reg" in
   def LDDRdPtrQ : FSTDLDD<0,
                           (outs GPR8:$reg),
                           (ins memri:$memri),
@@ -1227,7 +1228,8 @@ isReMaterializable = 1 in
                    Requires<[HasSRAM]>;
 
   let mayLoad = 1,
-  hasSideEffects = 0 in
+  hasSideEffects = 0,
+  Constraints = "@earlyclobber $dst" in
   def LDDWRdYQ : Pseudo<(outs DREGS:$dst),
                         (ins memri:$memri),
                         "lddw\t$dst, $memri",

Modified: llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp?rev=288897&r1=288896&r2=288897&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp Wed Dec  7 05:08:56 2016
@@ -77,6 +77,9 @@ TargetPassConfig *AVRTargetMachine::crea
 extern "C" void LLVMInitializeAVRTarget() {
   // Register the target.
   RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
+
+  auto &PR = *PassRegistry::getPassRegistry();
+  initializeAVRExpandPseudoPass(PR);
 }
 
 const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {

Removed: llvm/trunk/test/CodeGen/AVR/error-srcreg-destreg-same.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AVR/error-srcreg-destreg-same.ll?rev=288896&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AVR/error-srcreg-destreg-same.ll (original)
+++ llvm/trunk/test/CodeGen/AVR/error-srcreg-destreg-same.ll (removed)
@@ -1,56 +0,0 @@
-; RUN: llc < %s -march=avr | FileCheck %s
-; XFAIL: *
-
-; This occurs when compiling Rust libcore.
-;
-; Assertion failed:
-; (DstReg != SrcReg && "SrcReg and DstReg cannot be the same")
-;   lib/Target/AVR/AVRExpandPseudoInsts.cpp, line 817
-;
-; https://github.com/avr-llvm/llvm/issues/229
-
-; CHECK-LABEL: rust_eh_personality
-declare void @rust_eh_personality()
-
-; CHECK-LABEL: __udivmoddi4
-define void @__udivmoddi4(i64 %arg, i64 %arg1) personality i32 (...)* bitcast (void ()* @rust_eh_personality to i32 (...)*) {
-entry-block:
-  %tmp = lshr i64 %arg, 32
-  %tmp2 = trunc i64 %tmp to i32
-  %tmp3 = trunc i64 %arg to i32
-  %tmp4 = add i64 %arg1, -1
-  br label %bb135
-
-bb133.loopexit:
-  ret void
-
-bb135:
-  %carry.0120 = phi i64 [ 0, %entry-block ], [ %phitmp, %bb135 ]
-  %q.sroa.12.1119 = phi i32 [ %tmp3, %entry-block ], [ %q.sroa.12.0.extract.trunc, %bb135 ]
-  %q.sroa.0.1118 = phi i32 [ 0, %entry-block ], [ %q.sroa.0.0.extract.trunc, %bb135 ]
-  %r.sroa.0.1116 = phi i32 [ %tmp2, %entry-block ], [ undef, %bb135 ]
-  %r.sroa.0.0.insert.ext62 = zext i32 %r.sroa.0.1116 to i64
-  %r.sroa.0.0.insert.insert64 = or i64 0, %r.sroa.0.0.insert.ext62
-  %tmp5 = shl nuw nsw i64 %r.sroa.0.0.insert.ext62, 1
-  %q.sroa.12.0.insert.ext101 = zext i32 %q.sroa.12.1119 to i64
-  %q.sroa.12.0.insert.shift102 = shl nuw i64 %q.sroa.12.0.insert.ext101, 32
-  %q.sroa.0.0.insert.ext87 = zext i32 %q.sroa.0.1118 to i64
-  %q.sroa.0.0.insert.insert89 = or i64 %q.sroa.12.0.insert.shift102, %q.sroa.0.0.insert.ext87
-  %tmp6 = lshr i64 %q.sroa.12.0.insert.ext101, 31
-  %tmp7 = lshr i64 %r.sroa.0.0.insert.insert64, 31
-  %tmp8 = shl nuw nsw i64 %q.sroa.0.0.insert.ext87, 1
-  %tmp9 = or i64 %tmp8, %carry.0120
-  %q.sroa.0.0.extract.trunc = trunc i64 %tmp9 to i32
-  %tmp10 = lshr i64 %q.sroa.0.0.insert.insert89, 31
-  %q.sroa.12.0.extract.trunc = trunc i64 %tmp10 to i32
-  %r.sroa.13.0.insert.shift72 = shl i64 %tmp7, 32
-  %.masked114 = and i64 %tmp5, 4294967294
-  %r.sroa.0.0.insert.ext57 = or i64 %tmp6, %.masked114
-  %r.sroa.0.0.insert.insert59 = or i64 %r.sroa.0.0.insert.ext57, %r.sroa.13.0.insert.shift72
-  %tmp11 = sub i64 %tmp4, %r.sroa.0.0.insert.insert59
-  %tmp12 = ashr i64 %tmp11, 63
-  %phitmp = and i64 %tmp12, 1
-  %tmp13 = icmp ult i32 undef, 32
-  br i1 %tmp13, label %bb135, label %bb133.loopexit
-}
-

Added: llvm/trunk/test/CodeGen/AVR/expand-lddw-dst-src-same.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AVR/expand-lddw-dst-src-same.mir?rev=288897&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AVR/expand-lddw-dst-src-same.mir (added)
+++ llvm/trunk/test/CodeGen/AVR/expand-lddw-dst-src-same.mir Wed Dec  7 05:08:56 2016
@@ -0,0 +1,33 @@
+# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - 2>&1 | FileCheck %s
+
+# This test ensures that the pseudo expander can correctly handle the case
+# where we are expanding a 16-bit LDD instruction where the source and
+# destination registers are the same.
+#
+# The instruction itself is earlyclobber and so ISel will never produce an
+# instruction like this, but the stack slot loading can and will.
+
+--- |
+  target triple = "avr--"
+  define void @test_lddw() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test_lddw
+registers:
+  - { id: 0, class: _ }
+body: |
+  ; CHECK-LABEL: bb.0.entry
+  bb.0.entry:
+
+    ; CHECK-NEXT: early-clobber %r0 = LDDRdPtrQ %r29r28, 1
+    ; CHECK-NEXT: PUSHRr %r0, implicit-def %sp, implicit %sp
+    ; CHECK-NEXT: early-clobber %r0 = LDDRdPtrQ %r29r28, 2
+    ; CHECK-NEXT: MOVRdRr %r29, %r0
+    ; CHECK-NEXT: POPRd %r28, implicit-def %sp, implicit %sp
+
+    early-clobber %r29r28 = LDDWRdYQ %r29r28, 1
+...




More information about the llvm-commits mailing list