HexagonExpandPredSpillCode.cpp revision 296417
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"
21#include "HexagonMachineFunctionInfo.h"
22#include "HexagonSubtarget.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/CodeGen/LatencyPriorityQueue.h"
25#include "llvm/CodeGen/MachineDominators.h"
26#include "llvm/CodeGen/MachineFunctionPass.h"
27#include "llvm/CodeGen/MachineInstrBuilder.h"
28#include "llvm/CodeGen/MachineLoopInfo.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"
30#include "llvm/CodeGen/Passes.h"
31#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
32#include "llvm/CodeGen/SchedulerRegistry.h"
33#include "llvm/Support/Compiler.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Support/MathExtras.h"
36#include "llvm/Target/TargetInstrInfo.h"
37#include "llvm/Target/TargetMachine.h"
38#include "llvm/Target/TargetRegisterInfo.h"
39
40using namespace llvm;
41
42
43namespace llvm {
44  FunctionPass *createHexagonExpandPredSpillCode();
45  void initializeHexagonExpandPredSpillCodePass(PassRegistry&);
46}
47
48
49namespace {
50
51class HexagonExpandPredSpillCode : public MachineFunctionPass {
52 public:
53    static char ID;
54    HexagonExpandPredSpillCode() : MachineFunctionPass(ID) {
55      PassRegistry &Registry = *PassRegistry::getPassRegistry();
56      initializeHexagonExpandPredSpillCodePass(Registry);
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
66char HexagonExpandPredSpillCode::ID = 0;
67
68
69bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
70
71  const HexagonSubtarget &QST = Fn.getSubtarget<HexagonSubtarget>();
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),
258                    HEXAGON_RESERVED_REG_1)
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)
265              .addImm(0).addReg(HEXAGON_RESERVED_REG_2);
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)
275              .addReg(HEXAGON_RESERVED_REG_2);
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),
302                    HEXAGON_RESERVED_REG_1)
303              .addReg(FP)
304              .addReg(HEXAGON_RESERVED_REG_1);
305            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
306                      HEXAGON_RESERVED_REG_2)
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),
315                      HEXAGON_RESERVED_REG_2)
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
342static void initializePassOnce(PassRegistry &Registry) {
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
350void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) {
351  CALL_ONCE_INITIALIZATION(initializePassOnce)
352}
353
354FunctionPass*
355llvm::createHexagonExpandPredSpillCode() {
356  return new HexagonExpandPredSpillCode();
357}
358