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 AVRRelaxMem() : MachineFunctionPass(ID) { 36 initializeAVRRelaxMemPass(*PassRegistry::getPassRegistry()); 37 } 38 39 bool runOnMachineFunction(MachineFunction &MF) override; 40 41 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 MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) { 55 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode)); 56 } 57 }; 58 59 char AVRRelaxMem::ID = 0; 60 61 bool AVRRelaxMem::runOnMachineFunction(MachineFunction &MF) { 62 bool Modified = false; 63 64 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>(); 65 TII = STI.getInstrInfo(); 66 67 for (Block &MBB : MF) { 68 bool BlockModified = runOnBasicBlock(MBB); 69 Modified |= BlockModified; 70 } 71 72 return Modified; 73 } 74 75 bool AVRRelaxMem::runOnBasicBlock(Block &MBB) { 76 bool Modified = false; 77 78 BlockIt MBBI = MBB.begin(), E = MBB.end(); 79 while (MBBI != E) { 80 BlockIt NMBBI = std::next(MBBI); 81 Modified |= runOnInstruction(MBB, MBBI); 82 MBBI = NMBBI; 83 } 84 85 return Modified; 86 } 87 88 template <> 89 bool AVRRelaxMem::relax<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) { 90 MachineInstr &MI = *MBBI; 91 92 MachineOperand &Ptr = MI.getOperand(0); 93 MachineOperand &Src = MI.getOperand(2); 94 int64_t Imm = MI.getOperand(1).getImm(); 95 96 // We can definitely optimise this better. 97 if (Imm > 63) { 98 // Push the previous state of the pointer register. 99 // This instruction must preserve the value. 100 buildMI(MBB, MBBI, AVR::PUSHWRr) 101 .addReg(Ptr.getReg()); 102 103 // Add the immediate to the pointer register. 104 buildMI(MBB, MBBI, AVR::SBCIWRdK) 105 .addReg(Ptr.getReg(), RegState::Define) 106 .addReg(Ptr.getReg()) 107 .addImm(-Imm); 108 109 // Store the value in the source register to the address 110 // pointed to by the pointer register. 111 buildMI(MBB, MBBI, AVR::STWPtrRr) 112 .addReg(Ptr.getReg()) 113 .addReg(Src.getReg(), getKillRegState(Src.isKill())); 114 115 // Pop the original state of the pointer register. 116 buildMI(MBB, MBBI, AVR::POPWRd) 117 .addReg(Ptr.getReg(), getKillRegState(Ptr.isKill())); 118 119 MI.removeFromParent(); 120 } 121 122 return false; 123 } 124 125 bool AVRRelaxMem::runOnInstruction(Block &MBB, BlockIt MBBI) { 126 MachineInstr &MI = *MBBI; 127 int Opcode = MBBI->getOpcode(); 128 129 #define RELAX(Op) \ 130 case Op: \ 131 return relax<Op>(MBB, MI) 132 133 switch (Opcode) { 134 RELAX(AVR::STDWPtrQRr); 135 } 136 #undef RELAX 137 return false; 138 } 139 140 } // end of anonymous namespace 141 142 INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem", 143 AVR_RELAX_MEM_OPS_NAME, false, false) 144 145 namespace llvm { 146 147 FunctionPass *createAVRRelaxMemPass() { return new AVRRelaxMem(); } 148 149 } // end of namespace llvm 150