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
|