LLVM  10.0.0svn
AVRRelaxMemOperations.cpp
Go to the documentation of this file.
1 //===-- AVRRelaxMemOperations.cpp - Relax out of range loads/stores -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a pass which relaxes out of range memory operations into
10 // equivalent operations which handle bigger addresses.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AVR.h"
15 #include "AVRInstrInfo.h"
16 #include "AVRTargetMachine.h"
18 
23 
24 using namespace llvm;
25 
26 #define AVR_RELAX_MEM_OPS_NAME "AVR memory operation relaxation pass"
27 
28 namespace {
29 
30 class AVRRelaxMem : public MachineFunctionPass {
31 public:
32  static char ID;
33 
34  AVRRelaxMem() : MachineFunctionPass(ID) {
36  }
37 
38  bool runOnMachineFunction(MachineFunction &MF) override;
39 
40  StringRef getPassName() const override { return AVR_RELAX_MEM_OPS_NAME; }
41 
42 private:
43  typedef MachineBasicBlock Block;
44  typedef Block::iterator BlockIt;
45 
46  const TargetInstrInfo *TII;
47 
48  template <unsigned OP> bool relax(Block &MBB, BlockIt MBBI);
49 
50  bool runOnBasicBlock(Block &MBB);
51  bool runOnInstruction(Block &MBB, BlockIt MBBI);
52 
53  MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
54  return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
55  }
56 };
57 
58 char AVRRelaxMem::ID = 0;
59 
60 bool AVRRelaxMem::runOnMachineFunction(MachineFunction &MF) {
61  bool Modified = false;
62 
63  const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
64  TII = STI.getInstrInfo();
65 
66  for (Block &MBB : MF) {
67  bool BlockModified = runOnBasicBlock(MBB);
68  Modified |= BlockModified;
69  }
70 
71  return Modified;
72 }
73 
74 bool AVRRelaxMem::runOnBasicBlock(Block &MBB) {
75  bool Modified = false;
76 
77  BlockIt MBBI = MBB.begin(), E = MBB.end();
78  while (MBBI != E) {
79  BlockIt NMBBI = std::next(MBBI);
80  Modified |= runOnInstruction(MBB, MBBI);
81  MBBI = NMBBI;
82  }
83 
84  return Modified;
85 }
86 
87 template <>
88 bool AVRRelaxMem::relax<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
89  MachineInstr &MI = *MBBI;
90 
91  MachineOperand &Ptr = MI.getOperand(0);
92  MachineOperand &Src = MI.getOperand(2);
93  int64_t Imm = MI.getOperand(1).getImm();
94 
95  // We can definitely optimise this better.
96  if (Imm > 63) {
97  // Push the previous state of the pointer register.
98  // This instruction must preserve the value.
99  buildMI(MBB, MBBI, AVR::PUSHWRr)
100  .addReg(Ptr.getReg());
101 
102  // Add the immediate to the pointer register.
103  buildMI(MBB, MBBI, AVR::SBCIWRdK)
104  .addReg(Ptr.getReg(), RegState::Define)
105  .addReg(Ptr.getReg())
106  .addImm(-Imm);
107 
108  // Store the value in the source register to the address
109  // pointed to by the pointer register.
110  buildMI(MBB, MBBI, AVR::STWPtrRr)
111  .addReg(Ptr.getReg())
112  .addReg(Src.getReg(), getKillRegState(Src.isKill()));
113 
114  // Pop the original state of the pointer register.
115  buildMI(MBB, MBBI, AVR::POPWRd)
116  .addReg(Ptr.getReg(), getKillRegState(Ptr.isKill()));
117 
118  MI.removeFromParent();
119  }
120 
121  return false;
122 }
123 
124 bool AVRRelaxMem::runOnInstruction(Block &MBB, BlockIt MBBI) {
125  MachineInstr &MI = *MBBI;
126  int Opcode = MBBI->getOpcode();
127 
128 #define RELAX(Op) \
129  case Op: \
130  return relax<Op>(MBB, MI)
131 
132  switch (Opcode) {
133  RELAX(AVR::STDWPtrQRr);
134  }
135 #undef RELAX
136  return false;
137 }
138 
139 } // end of anonymous namespace
140 
141 INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem",
142  AVR_RELAX_MEM_OPS_NAME, false, false)
143 
144 namespace llvm {
145 
146 FunctionPass *createAVRRelaxMemPass() { return new AVRRelaxMem(); }
147 
148 } // end of namespace llvm
const AVRInstrInfo * getInstrInfo() const override
Definition: AVRSubtarget.h:41
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#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:284
INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem", AVR_RELAX_MEM_OPS_NAME, false, false) namespace llvm
static bool runOnBasicBlock(MachineBasicBlock *MBB, std::vector< StringRef > &bbNames, unsigned &basicBlockNum, NamedVRegCursor &NVC)
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
A specific AVR target MCU.
Definition: AVRSubtarget.h:31
Representation of each machine instruction.
Definition: MachineInstr.h:63
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:44
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:48
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:415