LLVM  6.0.0svn
AVRRelaxMemOperations.cpp
Go to the documentation of this file.
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"
19 
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) {
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
const AVRInstrInfo * getInstrInfo() const override
Definition: AVRSubtarget.h:42
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
unsigned getReg() const
getReg - Returns the register number.
static bool runOnBasicBlock(BasicBlock &BB)
#define RELAX(Op)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
FunctionPass * createAVRRelaxMemPass()
void initializeAVRRelaxMemPass(PassRegistry &)
#define AVR_RELAX_MEM_OPS_NAME
unsigned getKillRegState(bool B)
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem", AVR_RELAX_MEM_OPS_NAME, false, false) namespace llvm
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
A specific AVR target MCU.
Definition: AVRSubtarget.h:32
Representation of each machine instruction.
Definition: MachineInstr.h:59
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
MachineInstr * removeFromParent()
Unlink &#39;this&#39; from the containing basic block, and return it without deleting it. ...
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:295