1 //===-- AVRRelaxMemOperations.cpp - Relax out of range loads/stores -------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a pass which relaxes out of range memory operations into
11 // equivalent operations which handle bigger addresses.
13 //===----------------------------------------------------------------------===//
16 #include "AVRInstrInfo.h"
17 #include "AVRTargetMachine.h"
18 #include "MCTargetDesc/AVRMCTargetDesc.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/TargetRegisterInfo.h"
27 #define AVR_RELAX_MEM_OPS_NAME "AVR memory operation relaxation pass"
31 class AVRRelaxMem
: public MachineFunctionPass
{
35 AVRRelaxMem() : MachineFunctionPass(ID
) {
36 initializeAVRRelaxMemPass(*PassRegistry::getPassRegistry());
39 bool runOnMachineFunction(MachineFunction
&MF
) override
;
41 StringRef
getPassName() const override
{ return AVR_RELAX_MEM_OPS_NAME
; }
44 typedef MachineBasicBlock Block
;
45 typedef Block::iterator BlockIt
;
47 const TargetInstrInfo
*TII
;
49 template <unsigned OP
> bool relax(Block
&MBB
, BlockIt MBBI
);
51 bool runOnBasicBlock(Block
&MBB
);
52 bool runOnInstruction(Block
&MBB
, BlockIt MBBI
);
54 MachineInstrBuilder
buildMI(Block
&MBB
, BlockIt MBBI
, unsigned Opcode
) {
55 return BuildMI(MBB
, MBBI
, MBBI
->getDebugLoc(), TII
->get(Opcode
));
59 char AVRRelaxMem::ID
= 0;
61 bool AVRRelaxMem::runOnMachineFunction(MachineFunction
&MF
) {
62 bool Modified
= false;
64 const AVRSubtarget
&STI
= MF
.getSubtarget
<AVRSubtarget
>();
65 TII
= STI
.getInstrInfo();
67 for (Block
&MBB
: MF
) {
68 bool BlockModified
= runOnBasicBlock(MBB
);
69 Modified
|= BlockModified
;
75 bool AVRRelaxMem::runOnBasicBlock(Block
&MBB
) {
76 bool Modified
= false;
78 BlockIt MBBI
= MBB
.begin(), E
= MBB
.end();
80 BlockIt NMBBI
= std::next(MBBI
);
81 Modified
|= runOnInstruction(MBB
, MBBI
);
89 bool AVRRelaxMem::relax
<AVR::STDWPtrQRr
>(Block
&MBB
, BlockIt MBBI
) {
90 MachineInstr
&MI
= *MBBI
;
92 MachineOperand
&Ptr
= MI
.getOperand(0);
93 MachineOperand
&Src
= MI
.getOperand(2);
94 int64_t Imm
= MI
.getOperand(1).getImm();
96 // We can definitely optimise this better.
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());
103 // Add the immediate to the pointer register.
104 buildMI(MBB
, MBBI
, AVR::SBCIWRdK
)
105 .addReg(Ptr
.getReg(), RegState::Define
)
106 .addReg(Ptr
.getReg())
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()));
115 // Pop the original state of the pointer register.
116 buildMI(MBB
, MBBI
, AVR::POPWRd
)
117 .addReg(Ptr
.getReg(), getKillRegState(Ptr
.isKill()));
119 MI
.removeFromParent();
125 bool AVRRelaxMem::runOnInstruction(Block
&MBB
, BlockIt MBBI
) {
126 MachineInstr
&MI
= *MBBI
;
127 int Opcode
= MBBI
->getOpcode();
131 return relax<Op>(MBB, MI)
134 RELAX(AVR::STDWPtrQRr
);
140 } // end of anonymous namespace
142 INITIALIZE_PASS(AVRRelaxMem
, "avr-relax-mem",
143 AVR_RELAX_MEM_OPS_NAME
, false, false)
147 FunctionPass
*createAVRRelaxMemPass() { return new AVRRelaxMem(); }
149 } // end of namespace llvm