LCOV - code coverage report
Current view: top level - lib/Target/AVR - AVRRelaxMemOperations.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 39 40 97.5 %
Date: 2018-10-20 13:21:21 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- AVRRelaxMemOperations.cpp - Relax out of range loads/stores -------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file contains a pass which relaxes out of range memory operations into
      11             : // equivalent operations which handle bigger addresses.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "AVR.h"
      16             : #include "AVRInstrInfo.h"
      17             : #include "AVRTargetMachine.h"
      18             : #include "MCTargetDesc/AVRMCTargetDesc.h"
      19             : 
      20             : #include "llvm/CodeGen/MachineFunctionPass.h"
      21             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      22             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      23             : #include "llvm/CodeGen/TargetRegisterInfo.h"
      24             : 
      25             : using namespace llvm;
      26             : 
      27             : #define AVR_RELAX_MEM_OPS_NAME "AVR memory operation relaxation pass"
      28             : 
      29             : namespace {
      30             : 
      31             : class AVRRelaxMem : public MachineFunctionPass {
      32             : public:
      33             :   static char ID;
      34             : 
      35          82 :   AVRRelaxMem() : MachineFunctionPass(ID) {
      36          82 :     initializeAVRRelaxMemPass(*PassRegistry::getPassRegistry());
      37          82 :   }
      38             : 
      39             :   bool runOnMachineFunction(MachineFunction &MF) override;
      40             : 
      41          82 :   StringRef getPassName() const override { return AVR_RELAX_MEM_OPS_NAME; }
      42             : 
      43             : private:
      44             :   typedef MachineBasicBlock Block;
      45             :   typedef Block::iterator BlockIt;
      46             : 
      47             :   const TargetInstrInfo *TII;
      48             : 
      49             :   template <unsigned OP> bool relax(Block &MBB, BlockIt MBBI);
      50             : 
      51             :   bool runOnBasicBlock(Block &MBB);
      52             :   bool runOnInstruction(Block &MBB, BlockIt MBBI);
      53             : 
      54           0 :   MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
      55           4 :     return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
      56             :   }
      57             : };
      58             : 
      59             : char AVRRelaxMem::ID = 0;
      60             : 
      61         305 : bool AVRRelaxMem::runOnMachineFunction(MachineFunction &MF) {
      62             :   bool Modified = false;
      63             : 
      64         305 :   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
      65         305 :   TII = STI.getInstrInfo();
      66             : 
      67         843 :   for (Block &MBB : MF) {
      68         538 :     bool BlockModified = runOnBasicBlock(MBB);
      69         538 :     Modified |= BlockModified;
      70             :   }
      71             : 
      72         305 :   return Modified;
      73             : }
      74             : 
      75         538 : bool AVRRelaxMem::runOnBasicBlock(Block &MBB) {
      76             :   bool Modified = false;
      77             : 
      78             :   BlockIt MBBI = MBB.begin(), E = MBB.end();
      79        8259 :   while (MBBI != E) {
      80        7721 :     BlockIt NMBBI = std::next(MBBI);
      81        7721 :     Modified |= runOnInstruction(MBB, MBBI);
      82             :     MBBI = NMBBI;
      83             :   }
      84             : 
      85         538 :   return Modified;
      86             : }
      87             : 
      88             : template <>
      89          74 : bool AVRRelaxMem::relax<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
      90             :   MachineInstr &MI = *MBBI;
      91             : 
      92          74 :   MachineOperand &Ptr = MI.getOperand(0);
      93             :   MachineOperand &Src = MI.getOperand(2);
      94          74 :   int64_t Imm = MI.getOperand(1).getImm();
      95             : 
      96             :   // We can definitely optimise this better.
      97          74 :   if (Imm > 63) {
      98             :     // Push the previous state of the pointer register.
      99             :     // This instruction must preserve the value.
     100           1 :     buildMI(MBB, MBBI, AVR::PUSHWRr)
     101           1 :       .addReg(Ptr.getReg());
     102             : 
     103             :     // Add the immediate to the pointer register.
     104           1 :     buildMI(MBB, MBBI, AVR::SBCIWRdK)
     105           1 :       .addReg(Ptr.getReg(), RegState::Define)
     106           1 :       .addReg(Ptr.getReg())
     107           1 :       .addImm(-Imm);
     108             : 
     109             :     // Store the value in the source register to the address
     110             :     // pointed to by the pointer register.
     111           1 :     buildMI(MBB, MBBI, AVR::STWPtrRr)
     112           1 :       .addReg(Ptr.getReg())
     113           1 :       .addReg(Src.getReg(), getKillRegState(Src.isKill()));
     114             : 
     115             :     // Pop the original state of the pointer register.
     116           1 :     buildMI(MBB, MBBI, AVR::POPWRd)
     117           1 :       .addReg(Ptr.getReg(), getKillRegState(Ptr.isKill()));
     118             : 
     119           1 :     MI.removeFromParent();
     120             :   }
     121             : 
     122          74 :   return false;
     123             : }
     124             : 
     125             : bool AVRRelaxMem::runOnInstruction(Block &MBB, BlockIt MBBI) {
     126             :   MachineInstr &MI = *MBBI;
     127        7721 :   int Opcode = MBBI->getOpcode();
     128             : 
     129             : #define RELAX(Op)                \
     130             :   case Op:                       \
     131             :     return relax<Op>(MBB, MI)
     132             : 
     133        7721 :   switch (Opcode) {
     134          74 :     RELAX(AVR::STDWPtrQRr);
     135             :   }
     136             : #undef RELAX
     137             :   return false;
     138             : }
     139             : 
     140             : } // end of anonymous namespace
     141             : 
     142      199106 : INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem",
     143             :                 AVR_RELAX_MEM_OPS_NAME, false, false)
     144             : 
     145             : namespace llvm {
     146             : 
     147          81 : FunctionPass *createAVRRelaxMemPass() { return new AVRRelaxMem(); }
     148             : 
     149             : } // end of namespace llvm

Generated by: LCOV version 1.13