[llvm] r289517 - [AVR] Add an 'relax memory operation' pass

Dylan McKay via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 12 21:53:15 PST 2016


Author: dylanmckay
Date: Mon Dec 12 23:53:14 2016
New Revision: 289517

URL: http://llvm.org/viewvc/llvm-project?rev=289517&view=rev
Log:
[AVR] Add an 'relax memory operation' pass

Summary:
This pass will be used to relax instructions which use out of bounds
memory accesses to equivalent operations that can work with the
addresses.

The pass currently implements relaxation for the STDWPtrQRr instruction.

Without this pass, an assertion error would be hit in the pseudo expansion pass.

In the future, we will need to add more instructions to this pass. We can do
that on a case-by-case basic.

Reviewers: arsenm, kparzysz

Subscribers: wdng, llvm-commits, mgorny

Differential Revision: https://reviews.llvm.org/D27650

Added:
    llvm/trunk/lib/Target/AVR/AVRRelaxMemOperations.cpp
    llvm/trunk/test/CodeGen/AVR/relax-mem/
    llvm/trunk/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir
Modified:
    llvm/trunk/lib/Target/AVR/AVR.h
    llvm/trunk/lib/Target/AVR/AVRFrameLowering.cpp
    llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp
    llvm/trunk/lib/Target/AVR/CMakeLists.txt

Modified: llvm/trunk/lib/Target/AVR/AVR.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVR.h?rev=289517&r1=289516&r2=289517&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVR.h (original)
+++ llvm/trunk/lib/Target/AVR/AVR.h Mon Dec 12 23:53:14 2016
@@ -27,10 +27,12 @@ FunctionPass *createAVRISelDag(AVRTarget
                                CodeGenOpt::Level OptLevel);
 FunctionPass *createAVRExpandPseudoPass();
 FunctionPass *createAVRFrameAnalyzerPass();
+FunctionPass *createAVRRelaxMemPass();
 FunctionPass *createAVRDynAllocaSRPass();
 FunctionPass *createAVRBranchSelectionPass();
 
 void initializeAVRExpandPseudoPass(PassRegistry&);
+void initializeAVRRelaxMemPass(PassRegistry&);
 
 /// Contains the AVR backend.
 namespace AVR {

Modified: llvm/trunk/lib/Target/AVR/AVRFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRFrameLowering.cpp?rev=289517&r1=289516&r2=289517&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRFrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/AVR/AVRFrameLowering.cpp Mon Dec 12 23:53:14 2016
@@ -338,7 +338,6 @@ static void fixStackStores(MachineBasicB
     // pointer since it is guaranteed to contain a copy of SP.
     unsigned STOpc =
         (Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr;
-    assert(isUInt<6>(MI.getOperand(1).getImm()) && "Offset is out of range");
 
     MI.setDesc(TII.get(STOpc));
     MI.getOperand(0).setReg(AVR::R29R28);

Added: llvm/trunk/lib/Target/AVR/AVRRelaxMemOperations.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRRelaxMemOperations.cpp?rev=289517&view=auto
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRRelaxMemOperations.cpp (added)
+++ llvm/trunk/lib/Target/AVR/AVRRelaxMemOperations.cpp Mon Dec 12 23:53:14 2016
@@ -0,0 +1,149 @@
+//===-- AVRRelaxMemOperations.cpp - Relax out of range loads/stores -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass which relaxes out of range memory operations into
+// equivalent operations which handle bigger addresses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AVR.h"
+#include "AVRInstrInfo.h"
+#include "AVRTargetMachine.h"
+#include "MCTargetDesc/AVRMCTargetDesc.h"
+
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+
+using namespace llvm;
+
+#define AVR_RELAX_MEM_OPS_NAME "AVR memory operation relaxation pass"
+
+namespace {
+
+class AVRRelaxMem : public MachineFunctionPass {
+public:
+  static char ID;
+
+  AVRRelaxMem() : MachineFunctionPass(ID) {
+    initializeAVRRelaxMemPass(*PassRegistry::getPassRegistry());
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  StringRef getPassName() const override { return AVR_RELAX_MEM_OPS_NAME; }
+
+private:
+  typedef MachineBasicBlock Block;
+  typedef Block::iterator BlockIt;
+
+  const TargetInstrInfo *TII;
+
+  template <unsigned OP> bool relax(Block &MBB, BlockIt MBBI);
+
+  bool runOnBasicBlock(Block &MBB);
+  bool runOnInstruction(Block &MBB, BlockIt MBBI);
+
+  MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
+    return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
+  }
+};
+
+char AVRRelaxMem::ID = 0;
+
+bool AVRRelaxMem::runOnMachineFunction(MachineFunction &MF) {
+  bool Modified = false;
+
+  const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
+  TII = STI.getInstrInfo();
+
+  for (Block &MBB : MF) {
+    bool BlockModified = runOnBasicBlock(MBB);
+    Modified |= BlockModified;
+  }
+
+  return Modified;
+}
+
+bool AVRRelaxMem::runOnBasicBlock(Block &MBB) {
+  bool Modified = false;
+
+  BlockIt MBBI = MBB.begin(), E = MBB.end();
+  while (MBBI != E) {
+    BlockIt NMBBI = std::next(MBBI);
+    Modified |= runOnInstruction(MBB, MBBI);
+    MBBI = NMBBI;
+  }
+
+  return Modified;
+}
+
+template <>
+bool AVRRelaxMem::relax<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+
+  MachineOperand &Ptr = MI.getOperand(0);
+  MachineOperand &Src = MI.getOperand(2);
+  int64_t Imm = MI.getOperand(1).getImm();
+
+  // We can definitely optimise this better.
+  if (Imm > 63) {
+    // Push the previous state of the pointer register.
+    // This instruction must preserve the value.
+    buildMI(MBB, MBBI, AVR::PUSHWRr)
+      .addReg(Ptr.getReg());
+
+    // Add the immediate to the pointer register.
+    buildMI(MBB, MBBI, AVR::SBCIWRdK)
+      .addReg(Ptr.getReg(), RegState::Define)
+      .addReg(Ptr.getReg())
+      .addImm(-Imm);
+
+    // Store the value in the source register to the address
+    // pointed to by the pointer register.
+    buildMI(MBB, MBBI, AVR::STWPtrRr)
+      .addReg(Ptr.getReg())
+      .addReg(Src.getReg(), getKillRegState(Src.isKill()));
+
+    // Pop the original state of the pointer register.
+    buildMI(MBB, MBBI, AVR::POPWRd)
+      .addReg(Ptr.getReg(), getKillRegState(Ptr.isKill()));
+
+    MI.removeFromParent();
+  }
+
+  return false;
+}
+
+bool AVRRelaxMem::runOnInstruction(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+  int Opcode = MBBI->getOpcode();
+
+#define RELAX(Op)                \
+  case Op:                       \
+    return relax<Op>(MBB, MI)
+
+  switch (Opcode) {
+    RELAX(AVR::STDWPtrQRr);
+  }
+#undef RELAX
+  return false;
+}
+
+} // end of anonymous namespace
+
+INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem",
+                AVR_RELAX_MEM_OPS_NAME, false, false)
+
+namespace llvm {
+
+FunctionPass *createAVRRelaxMemPass() { return new AVRRelaxMem(); }
+
+} // end of namespace llvm

Modified: llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp?rev=289517&r1=289516&r2=289517&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/AVR/AVRTargetMachine.cpp Mon Dec 12 23:53:14 2016
@@ -80,6 +80,7 @@ extern "C" void LLVMInitializeAVRTarget(
 
   auto &PR = *PassRegistry::getPassRegistry();
   initializeAVRExpandPseudoPass(PR);
+  initializeAVRRelaxMemPass(PR);
 }
 
 const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {
@@ -108,6 +109,9 @@ void AVRPassConfig::addPreRegAlloc() {
   addPass(createAVRDynAllocaSRPass());
 }
 
-void AVRPassConfig::addPreSched2() { addPass(createAVRExpandPseudoPass()); }
+void AVRPassConfig::addPreSched2() {
+  addPass(createAVRRelaxMemPass());
+  addPass(createAVRExpandPseudoPass());
+}
 
 } // end of namespace llvm

Modified: llvm/trunk/lib/Target/AVR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AVR/CMakeLists.txt?rev=289517&r1=289516&r2=289517&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AVR/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/AVR/CMakeLists.txt Mon Dec 12 23:53:14 2016
@@ -24,6 +24,7 @@ add_llvm_target(AVRCodeGen
   AVRISelDAGToDAG.cpp
   AVRISelLowering.cpp
   AVRMCInstLower.cpp
+  AVRRelaxMemOperations.cpp
   AVRRegisterInfo.cpp
   AVRSubtarget.cpp
   AVRTargetMachine.cpp

Added: llvm/trunk/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir?rev=289517&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir (added)
+++ llvm/trunk/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir Mon Dec 12 23:53:14 2016
@@ -0,0 +1,31 @@
+# RUN: llc -O0 -run-pass=avr-relax-mem %s -o - 2>&1 | FileCheck %s
+
+--- |
+  target triple = "avr--"
+  define void @test() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test
+body: |
+  bb.0.entry:
+
+    ; CHECK-LABEL: test
+
+    ; We shouldn't expand things which already have 6-bit imms.
+    ; CHECK: STDWPtrQRr %r29r28, 63, %r1r0
+    STDWPtrQRr %r29r28, 63, %r1r0
+
+    ; We shouldn't expand things which already have 6-bit imms.
+    ; CHECK-NEXT: STDWPtrQRr %r29r28, 0, %r1r0
+    STDWPtrQRr %r29r28, 0, %r1r0
+
+    ; CHECK-NEXT: PUSHWRr %r29r28, implicit-def %sp, implicit %sp
+    ; CHECK-NEXT: %r29r28 = SBCIWRdK %r29r28, -64, implicit-def %sreg, implicit %sreg
+    ; CHECK-NEXT: STWPtrRr %r29r28, %r1r0
+    ; CHECK-NEXT: POPWRd %r29r28, implicit-def %sp, implicit %sp
+    STDWPtrQRr %r29r28, 64, %r1r0
+...




More information about the llvm-commits mailing list