LLVM  3.7.0
HexagonExpandPredSpillCode.cpp
Go to the documentation of this file.
1 //===-- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ------===//
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 // The Hexagon processor has no instructions that load or store predicate
10 // registers directly. So, when these registers must be spilled a general
11 // purpose register must be found and the value copied to/from it from/to
12 // the predicate register. This code currently does not use the register
13 // scavenger mechanism available in the allocator. There are two registers
14 // reserved to allow spilling/restoring predicate registers. One is used to
15 // hold the predicate value. The other is used when stack frame offsets are
16 // too large.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "Hexagon.h"
22 #include "HexagonSubtarget.h"
23 #include "llvm/ADT/Statistic.h"
30 #include "llvm/CodeGen/Passes.h"
33 #include "llvm/Support/Compiler.h"
34 #include "llvm/Support/Debug.h"
39 
40 using namespace llvm;
41 
42 
43 namespace llvm {
46 }
47 
48 
49 namespace {
50 
51 class HexagonExpandPredSpillCode : public MachineFunctionPass {
52  public:
53  static char ID;
54  HexagonExpandPredSpillCode() : MachineFunctionPass(ID) {
57  }
58 
59  const char *getPassName() const override {
60  return "Hexagon Expand Predicate Spill Code";
61  }
62  bool runOnMachineFunction(MachineFunction &Fn) override;
63 };
64 
65 
67 
68 
69 bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
70 
72  const HexagonInstrInfo *TII = QST.getInstrInfo();
73 
74  // Loop over all of the basic blocks.
75  for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
76  MBBb != MBBe; ++MBBb) {
77  MachineBasicBlock* MBB = MBBb;
78  // Traverse the basic block.
79  for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
80  ++MII) {
81  MachineInstr *MI = MII;
82  int Opc = MI->getOpcode();
83  if (Opc == Hexagon::S2_storerb_pci_pseudo ||
84  Opc == Hexagon::S2_storerh_pci_pseudo ||
85  Opc == Hexagon::S2_storeri_pci_pseudo ||
86  Opc == Hexagon::S2_storerd_pci_pseudo ||
87  Opc == Hexagon::S2_storerf_pci_pseudo) {
88  unsigned Opcode;
89  if (Opc == Hexagon::S2_storerd_pci_pseudo)
90  Opcode = Hexagon::S2_storerd_pci;
91  else if (Opc == Hexagon::S2_storeri_pci_pseudo)
92  Opcode = Hexagon::S2_storeri_pci;
93  else if (Opc == Hexagon::S2_storerh_pci_pseudo)
94  Opcode = Hexagon::S2_storerh_pci;
95  else if (Opc == Hexagon::S2_storerf_pci_pseudo)
96  Opcode = Hexagon::S2_storerf_pci;
97  else if (Opc == Hexagon::S2_storerb_pci_pseudo)
98  Opcode = Hexagon::S2_storerb_pci;
99  else
100  llvm_unreachable("wrong Opc");
101  MachineOperand &Op0 = MI->getOperand(0);
102  MachineOperand &Op1 = MI->getOperand(1);
103  MachineOperand &Op2 = MI->getOperand(2);
104  MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
105  MachineOperand &Op4 = MI->getOperand(4);
106  // Emit a "C6 = Rn, C6 is the control register for M0".
107  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
108  Hexagon::C6)->addOperand(Op3);
109  // Replace the pseude circ_ldd by the real circ_ldd.
110  MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
111  TII->get(Opcode));
112  NewMI->addOperand(Op0);
113  NewMI->addOperand(Op1);
114  NewMI->addOperand(Op4);
115  NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
116  false, /*isDef*/
117  false, /*isImpl*/
118  true /*isKill*/));
119  NewMI->addOperand(Op2);
120  MII = MBB->erase(MI);
121  --MII;
122  } else if (Opc == Hexagon::L2_loadrd_pci_pseudo ||
123  Opc == Hexagon::L2_loadri_pci_pseudo ||
124  Opc == Hexagon::L2_loadrh_pci_pseudo ||
125  Opc == Hexagon::L2_loadruh_pci_pseudo||
126  Opc == Hexagon::L2_loadrb_pci_pseudo ||
127  Opc == Hexagon::L2_loadrub_pci_pseudo) {
128  unsigned Opcode;
129  if (Opc == Hexagon::L2_loadrd_pci_pseudo)
130  Opcode = Hexagon::L2_loadrd_pci;
131  else if (Opc == Hexagon::L2_loadri_pci_pseudo)
132  Opcode = Hexagon::L2_loadri_pci;
133  else if (Opc == Hexagon::L2_loadrh_pci_pseudo)
134  Opcode = Hexagon::L2_loadrh_pci;
135  else if (Opc == Hexagon::L2_loadruh_pci_pseudo)
136  Opcode = Hexagon::L2_loadruh_pci;
137  else if (Opc == Hexagon::L2_loadrb_pci_pseudo)
138  Opcode = Hexagon::L2_loadrb_pci;
139  else if (Opc == Hexagon::L2_loadrub_pci_pseudo)
140  Opcode = Hexagon::L2_loadrub_pci;
141  else
142  llvm_unreachable("wrong Opc");
143 
144  MachineOperand &Op0 = MI->getOperand(0);
145  MachineOperand &Op1 = MI->getOperand(1);
146  MachineOperand &Op2 = MI->getOperand(2);
147  MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
148  MachineOperand &Op5 = MI->getOperand(5);
149  // Emit a "C6 = Rn, C6 is the control register for M0".
150  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
151  Hexagon::C6)->addOperand(Op4);
152  // Replace the pseude circ_ldd by the real circ_ldd.
153  MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
154  TII->get(Opcode));
155  NewMI->addOperand(Op1);
156  NewMI->addOperand(Op0);
157  NewMI->addOperand(Op2);
158  NewMI->addOperand(Op5);
159  NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
160  false, /*isDef*/
161  false, /*isImpl*/
162  true /*isKill*/));
163  MII = MBB->erase(MI);
164  --MII;
165  } else if (Opc == Hexagon::L2_loadrd_pbr_pseudo ||
166  Opc == Hexagon::L2_loadri_pbr_pseudo ||
167  Opc == Hexagon::L2_loadrh_pbr_pseudo ||
168  Opc == Hexagon::L2_loadruh_pbr_pseudo||
169  Opc == Hexagon::L2_loadrb_pbr_pseudo ||
170  Opc == Hexagon::L2_loadrub_pbr_pseudo) {
171  unsigned Opcode;
172  if (Opc == Hexagon::L2_loadrd_pbr_pseudo)
173  Opcode = Hexagon::L2_loadrd_pbr;
174  else if (Opc == Hexagon::L2_loadri_pbr_pseudo)
175  Opcode = Hexagon::L2_loadri_pbr;
176  else if (Opc == Hexagon::L2_loadrh_pbr_pseudo)
177  Opcode = Hexagon::L2_loadrh_pbr;
178  else if (Opc == Hexagon::L2_loadruh_pbr_pseudo)
179  Opcode = Hexagon::L2_loadruh_pbr;
180  else if (Opc == Hexagon::L2_loadrb_pbr_pseudo)
181  Opcode = Hexagon::L2_loadrb_pbr;
182  else if (Opc == Hexagon::L2_loadrub_pbr_pseudo)
183  Opcode = Hexagon::L2_loadrub_pbr;
184  else
185  llvm_unreachable("wrong Opc");
186  MachineOperand &Op0 = MI->getOperand(0);
187  MachineOperand &Op1 = MI->getOperand(1);
188  MachineOperand &Op2 = MI->getOperand(2);
189  MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
190  // Emit a "C6 = Rn, C6 is the control register for M0".
191  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
192  Hexagon::C6)->addOperand(Op4);
193  // Replace the pseudo brev_ldd by the real brev_ldd.
194  MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
195  TII->get(Opcode));
196  NewMI->addOperand(Op1);
197  NewMI->addOperand(Op0);
198  NewMI->addOperand(Op2);
199  NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
200  false, /*isDef*/
201  false, /*isImpl*/
202  true /*isKill*/));
203  MII = MBB->erase(MI);
204  --MII;
205  } else if (Opc == Hexagon::S2_storerd_pbr_pseudo ||
206  Opc == Hexagon::S2_storeri_pbr_pseudo ||
207  Opc == Hexagon::S2_storerh_pbr_pseudo ||
208  Opc == Hexagon::S2_storerb_pbr_pseudo ||
209  Opc == Hexagon::S2_storerf_pbr_pseudo) {
210  unsigned Opcode;
211  if (Opc == Hexagon::S2_storerd_pbr_pseudo)
212  Opcode = Hexagon::S2_storerd_pbr;
213  else if (Opc == Hexagon::S2_storeri_pbr_pseudo)
214  Opcode = Hexagon::S2_storeri_pbr;
215  else if (Opc == Hexagon::S2_storerh_pbr_pseudo)
216  Opcode = Hexagon::S2_storerh_pbr;
217  else if (Opc == Hexagon::S2_storerf_pbr_pseudo)
218  Opcode = Hexagon::S2_storerf_pbr;
219  else if (Opc == Hexagon::S2_storerb_pbr_pseudo)
220  Opcode = Hexagon::S2_storerb_pbr;
221  else
222  llvm_unreachable("wrong Opc");
223  MachineOperand &Op0 = MI->getOperand(0);
224  MachineOperand &Op1 = MI->getOperand(1);
225  MachineOperand &Op2 = MI->getOperand(2);
226  MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
227  // Emit a "C6 = Rn, C6 is the control register for M0".
228  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
229  Hexagon::C6)->addOperand(Op3);
230  // Replace the pseudo brev_ldd by the real brev_ldd.
231  MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
232  TII->get(Opcode));
233  NewMI->addOperand(Op0);
234  NewMI->addOperand(Op1);
235  NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
236  false, /*isDef*/
237  false, /*isImpl*/
238  true /*isKill*/));
239  NewMI->addOperand(Op2);
240  MII = MBB->erase(MI);
241  --MII;
242  } else if (Opc == Hexagon::STriw_pred) {
243  // STriw_pred [R30], ofst, SrcReg;
244  unsigned FP = MI->getOperand(0).getReg();
245  assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
246  "Not a Frame Pointer, Nor a Spill Slot");
247  assert(MI->getOperand(1).isImm() && "Not an offset");
248  int Offset = MI->getOperand(1).getImm();
249  int SrcReg = MI->getOperand(2).getReg();
250  assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
251  "Not a predicate register");
252  if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) {
253  if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
254  BuildMI(*MBB, MII, MI->getDebugLoc(),
255  TII->get(Hexagon::CONST32_Int_Real),
256  HEXAGON_RESERVED_REG_1).addImm(Offset);
257  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
259  .addReg(FP).addReg(HEXAGON_RESERVED_REG_1);
260  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
261  HEXAGON_RESERVED_REG_2).addReg(SrcReg);
262  BuildMI(*MBB, MII, MI->getDebugLoc(),
263  TII->get(Hexagon::S2_storeri_io))
264  .addReg(HEXAGON_RESERVED_REG_1)
266  } else {
267  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
268  HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
269  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
270  HEXAGON_RESERVED_REG_2).addReg(SrcReg);
271  BuildMI(*MBB, MII, MI->getDebugLoc(),
272  TII->get(Hexagon::S2_storeri_io))
273  .addReg(HEXAGON_RESERVED_REG_1)
274  .addImm(0)
276  }
277  } else {
278  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
279  HEXAGON_RESERVED_REG_2).addReg(SrcReg);
280  BuildMI(*MBB, MII, MI->getDebugLoc(),
281  TII->get(Hexagon::S2_storeri_io)).
282  addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
283  }
284  MII = MBB->erase(MI);
285  --MII;
286  } else if (Opc == Hexagon::LDriw_pred) {
287  // DstReg = LDriw_pred [R30], ofst.
288  int DstReg = MI->getOperand(0).getReg();
289  assert(Hexagon::PredRegsRegClass.contains(DstReg) &&
290  "Not a predicate register");
291  unsigned FP = MI->getOperand(1).getReg();
292  assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
293  "Not a Frame Pointer, Nor a Spill Slot");
294  assert(MI->getOperand(2).isImm() && "Not an offset");
295  int Offset = MI->getOperand(2).getImm();
296  if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) {
297  if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
298  BuildMI(*MBB, MII, MI->getDebugLoc(),
299  TII->get(Hexagon::CONST32_Int_Real),
300  HEXAGON_RESERVED_REG_1).addImm(Offset);
301  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
303  .addReg(FP)
305  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
307  .addReg(HEXAGON_RESERVED_REG_1)
308  .addImm(0);
309  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
310  DstReg).addReg(HEXAGON_RESERVED_REG_2);
311  } else {
312  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
313  HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
314  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
316  .addReg(HEXAGON_RESERVED_REG_1)
317  .addImm(0);
318  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
319  DstReg).addReg(HEXAGON_RESERVED_REG_2);
320  }
321  } else {
322  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
323  HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset);
324  BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
325  DstReg).addReg(HEXAGON_RESERVED_REG_2);
326  }
327  MII = MBB->erase(MI);
328  --MII;
329  }
330  }
331  }
332 
333  return true;
334 }
335 
336 }
337 
338 //===----------------------------------------------------------------------===//
339 // Public Constructor Functions
340 //===----------------------------------------------------------------------===//
341 
343  const char *Name = "Hexagon Expand Predicate Spill Code";
344  PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred",
345  &HexagonExpandPredSpillCode::ID,
346  nullptr, false, false);
347  Registry.registerPass(*PI, true);
348 }
349 
352 }
353 
356  return new HexagonExpandPredSpillCode();
357 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
#define HEXAGON_RESERVED_REG_1
unsigned getFrameRegister(const MachineFunction &MF) const override
A global registry used in conjunction with static constructors to make pluggable components (like tar...
Definition: Registry.h:61
#define HEXAGON_RESERVED_REG_2
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
const HexagonRegisterInfo * getRegisterInfo() const override
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:317
const MachineInstrBuilder & addImm(int64_t Val) const
addImm - Add a new immediate operand.
int64_t getImm() const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
bundle_iterator< MachineInstr, instr_iterator > iterator
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:273
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
PassInfo class - An instance of this class exists for every pass known by the system, and can be obtained from a live Pass by calling its getPassInfo() method.
Definition: PassInfo.h:30
void initializeHexagonExpandPredSpillCodePass(PassRegistry &)
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
MachineOperand class - Representation of each machine instruction operand.
static void initializePassOnce(PassRegistry &Registry)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:238
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1030
Representation of each machine instruction.
Definition: MachineInstr.h:51
FunctionPass * createHexagonExpandPredSpillCode()
unsigned getReg() const
getReg - Returns the register number.
#define CALL_ONCE_INITIALIZATION(function)
Definition: PassSupport.h:36
const HexagonInstrInfo * getInstrInfo() const override
BasicBlockListType::iterator iterator
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:41
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
addReg - Add a new virtual register operand...
void registerPass(const PassInfo &PI, bool ShouldFree=false)
registerPass - Register a pass (by means of its PassInfo) with the registry.