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  void initializeHexagonExpandPredSpillCodePass(PassRegistry&);
45}
46
47
48namespace {
49
50class HexagonExpandPredSpillCode : public MachineFunctionPass {
51 public:
52    static char ID;
53    HexagonExpandPredSpillCode() : MachineFunctionPass(ID) {
54      PassRegistry &Registry = *PassRegistry::getPassRegistry();
55      initializeHexagonExpandPredSpillCodePass(Registry);
56    }
57
58    const char *getPassName() const override {
59      return "Hexagon Expand Predicate Spill Code";
60    }
61    bool runOnMachineFunction(MachineFunction &Fn) override;
62};
63
64
65char HexagonExpandPredSpillCode::ID = 0;
66
67
68bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
69
70  const HexagonSubtarget &QST = Fn.getSubtarget<HexagonSubtarget>();
71  const HexagonInstrInfo *TII = QST.getInstrInfo();
72
73  // Loop over all of the basic blocks.
74  for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
75       MBBb != MBBe; ++MBBb) {
76    MachineBasicBlock* MBB = MBBb;
77    // Traverse the basic block.
78    for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
79         ++MII) {
80      MachineInstr *MI = MII;
81      int Opc = MI->getOpcode();
82      if (Opc == Hexagon::S2_storerb_pci_pseudo ||
83          Opc == Hexagon::S2_storerh_pci_pseudo ||
84          Opc == Hexagon::S2_storeri_pci_pseudo ||
85          Opc == Hexagon::S2_storerd_pci_pseudo ||
86          Opc == Hexagon::S2_storerf_pci_pseudo) {
87        unsigned Opcode;
88        if (Opc == Hexagon::S2_storerd_pci_pseudo)
89          Opcode = Hexagon::S2_storerd_pci;
90        else if (Opc == Hexagon::S2_storeri_pci_pseudo)
91          Opcode = Hexagon::S2_storeri_pci;
92        else if (Opc == Hexagon::S2_storerh_pci_pseudo)
93          Opcode = Hexagon::S2_storerh_pci;
94        else if (Opc == Hexagon::S2_storerf_pci_pseudo)
95          Opcode = Hexagon::S2_storerf_pci;
96        else if (Opc == Hexagon::S2_storerb_pci_pseudo)
97          Opcode = Hexagon::S2_storerb_pci;
98        else
99          llvm_unreachable("wrong Opc");
100        MachineOperand &Op0 = MI->getOperand(0);
101        MachineOperand &Op1 = MI->getOperand(1);
102        MachineOperand &Op2 = MI->getOperand(2);
103        MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
104        MachineOperand &Op4 = MI->getOperand(4);
105        // Emit a "C6 = Rn, C6 is the control register for M0".
106        BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
107                Hexagon::C6)->addOperand(Op3);
108        // Replace the pseude circ_ldd by the real circ_ldd.
109        MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
110                                      TII->get(Opcode));
111        NewMI->addOperand(Op0);
112        NewMI->addOperand(Op1);
113        NewMI->addOperand(Op4);
114        NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
115                                                    false, /*isDef*/
116                                                    false, /*isImpl*/
117                                                    true   /*isKill*/));
118        NewMI->addOperand(Op2);
119        MII = MBB->erase(MI);
120        --MII;
121      } else if (Opc == Hexagon::L2_loadrd_pci_pseudo ||
122                 Opc == Hexagon::L2_loadri_pci_pseudo ||
123                 Opc == Hexagon::L2_loadrh_pci_pseudo ||
124                 Opc == Hexagon::L2_loadruh_pci_pseudo||
125                 Opc == Hexagon::L2_loadrb_pci_pseudo ||
126                 Opc == Hexagon::L2_loadrub_pci_pseudo) {
127        unsigned Opcode;
128        if (Opc == Hexagon::L2_loadrd_pci_pseudo)
129          Opcode = Hexagon::L2_loadrd_pci;
130        else if (Opc == Hexagon::L2_loadri_pci_pseudo)
131          Opcode = Hexagon::L2_loadri_pci;
132        else if (Opc == Hexagon::L2_loadrh_pci_pseudo)
133          Opcode = Hexagon::L2_loadrh_pci;
134        else if (Opc == Hexagon::L2_loadruh_pci_pseudo)
135          Opcode = Hexagon::L2_loadruh_pci;
136        else if (Opc == Hexagon::L2_loadrb_pci_pseudo)
137          Opcode = Hexagon::L2_loadrb_pci;
138        else if (Opc == Hexagon::L2_loadrub_pci_pseudo)
139          Opcode = Hexagon::L2_loadrub_pci;
140        else
141          llvm_unreachable("wrong Opc");
142
143        MachineOperand &Op0 = MI->getOperand(0);
144        MachineOperand &Op1 = MI->getOperand(1);
145        MachineOperand &Op2 = MI->getOperand(2);
146        MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
147        MachineOperand &Op5 = MI->getOperand(5);
148        // Emit a "C6 = Rn, C6 is the control register for M0".
149        BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
150                Hexagon::C6)->addOperand(Op4);
151        // Replace the pseude circ_ldd by the real circ_ldd.
152        MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
153                                      TII->get(Opcode));
154        NewMI->addOperand(Op1);
155        NewMI->addOperand(Op0);
156        NewMI->addOperand(Op2);
157        NewMI->addOperand(Op5);
158        NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
159                                                    false, /*isDef*/
160                                                    false, /*isImpl*/
161                                                    true   /*isKill*/));
162        MII = MBB->erase(MI);
163        --MII;
164      } else if (Opc == Hexagon::L2_loadrd_pbr_pseudo ||
165                 Opc == Hexagon::L2_loadri_pbr_pseudo ||
166                 Opc == Hexagon::L2_loadrh_pbr_pseudo ||
167                 Opc == Hexagon::L2_loadruh_pbr_pseudo||
168                 Opc == Hexagon::L2_loadrb_pbr_pseudo ||
169                 Opc == Hexagon::L2_loadrub_pbr_pseudo) {
170        unsigned Opcode;
171        if (Opc == Hexagon::L2_loadrd_pbr_pseudo)
172          Opcode = Hexagon::L2_loadrd_pbr;
173        else if (Opc == Hexagon::L2_loadri_pbr_pseudo)
174          Opcode = Hexagon::L2_loadri_pbr;
175        else if (Opc == Hexagon::L2_loadrh_pbr_pseudo)
176          Opcode = Hexagon::L2_loadrh_pbr;
177        else if (Opc == Hexagon::L2_loadruh_pbr_pseudo)
178          Opcode = Hexagon::L2_loadruh_pbr;
179        else if (Opc == Hexagon::L2_loadrb_pbr_pseudo)
180          Opcode = Hexagon::L2_loadrb_pbr;
181        else if (Opc == Hexagon::L2_loadrub_pbr_pseudo)
182          Opcode = Hexagon::L2_loadrub_pbr;
183        else
184          llvm_unreachable("wrong Opc");
185        MachineOperand &Op0 = MI->getOperand(0);
186        MachineOperand &Op1 = MI->getOperand(1);
187        MachineOperand &Op2 = MI->getOperand(2);
188        MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
189        // Emit a "C6 = Rn, C6 is the control register for M0".
190        BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
191                Hexagon::C6)->addOperand(Op4);
192        // Replace the pseudo brev_ldd by the real brev_ldd.
193        MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
194                                      TII->get(Opcode));
195        NewMI->addOperand(Op1);
196        NewMI->addOperand(Op0);
197        NewMI->addOperand(Op2);
198        NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
199                                                    false, /*isDef*/
200                                                    false, /*isImpl*/
201                                                    true   /*isKill*/));
202        MII = MBB->erase(MI);
203        --MII;
204      } else if (Opc == Hexagon::S2_storerd_pbr_pseudo ||
205                 Opc == Hexagon::S2_storeri_pbr_pseudo ||
206                 Opc == Hexagon::S2_storerh_pbr_pseudo ||
207                 Opc == Hexagon::S2_storerb_pbr_pseudo ||
208                 Opc == Hexagon::S2_storerf_pbr_pseudo) {
209        unsigned Opcode;
210        if (Opc == Hexagon::S2_storerd_pbr_pseudo)
211          Opcode = Hexagon::S2_storerd_pbr;
212        else if (Opc == Hexagon::S2_storeri_pbr_pseudo)
213          Opcode = Hexagon::S2_storeri_pbr;
214        else if (Opc == Hexagon::S2_storerh_pbr_pseudo)
215          Opcode = Hexagon::S2_storerh_pbr;
216        else if (Opc == Hexagon::S2_storerf_pbr_pseudo)
217          Opcode = Hexagon::S2_storerf_pbr;
218        else if (Opc == Hexagon::S2_storerb_pbr_pseudo)
219          Opcode = Hexagon::S2_storerb_pbr;
220        else
221          llvm_unreachable("wrong Opc");
222        MachineOperand &Op0 = MI->getOperand(0);
223        MachineOperand &Op1 = MI->getOperand(1);
224        MachineOperand &Op2 = MI->getOperand(2);
225        MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
226        // Emit a "C6 = Rn, C6 is the control register for M0".
227        BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
228                Hexagon::C6)->addOperand(Op3);
229        // Replace the pseudo brev_ldd by the real brev_ldd.
230        MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
231                                      TII->get(Opcode));
232        NewMI->addOperand(Op0);
233        NewMI->addOperand(Op1);
234        NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
235                                                    false, /*isDef*/
236                                                    false, /*isImpl*/
237                                                    true   /*isKill*/));
238        NewMI->addOperand(Op2);
239        MII = MBB->erase(MI);
240        --MII;
241      } else if (Opc == Hexagon::STriw_pred) {
242        // STriw_pred [R30], ofst, SrcReg;
243        unsigned FP = MI->getOperand(0).getReg();
244        assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
245               "Not a Frame Pointer, Nor a Spill Slot");
246        assert(MI->getOperand(1).isImm() && "Not an offset");
247        int Offset = MI->getOperand(1).getImm();
248        int SrcReg = MI->getOperand(2).getReg();
249        assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
250               "Not a predicate register");
251        if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) {
252          if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
253            BuildMI(*MBB, MII, MI->getDebugLoc(),
254                    TII->get(Hexagon::CONST32_Int_Real),
255                      HEXAGON_RESERVED_REG_1).addImm(Offset);
256            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
257                    HEXAGON_RESERVED_REG_1)
258              .addReg(FP).addReg(HEXAGON_RESERVED_REG_1);
259            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
260                      HEXAGON_RESERVED_REG_2).addReg(SrcReg);
261            BuildMI(*MBB, MII, MI->getDebugLoc(),
262                    TII->get(Hexagon::S2_storeri_io))
263              .addReg(HEXAGON_RESERVED_REG_1)
264              .addImm(0).addReg(HEXAGON_RESERVED_REG_2);
265          } else {
266            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
267                      HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
268            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
269                      HEXAGON_RESERVED_REG_2).addReg(SrcReg);
270            BuildMI(*MBB, MII, MI->getDebugLoc(),
271                          TII->get(Hexagon::S2_storeri_io))
272              .addReg(HEXAGON_RESERVED_REG_1)
273              .addImm(0)
274              .addReg(HEXAGON_RESERVED_REG_2);
275          }
276        } else {
277          BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
278                    HEXAGON_RESERVED_REG_2).addReg(SrcReg);
279          BuildMI(*MBB, MII, MI->getDebugLoc(),
280                        TII->get(Hexagon::S2_storeri_io)).
281                    addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
282        }
283        MII = MBB->erase(MI);
284        --MII;
285      } else if (Opc == Hexagon::LDriw_pred) {
286        // DstReg = LDriw_pred [R30], ofst.
287        int DstReg = MI->getOperand(0).getReg();
288        assert(Hexagon::PredRegsRegClass.contains(DstReg) &&
289               "Not a predicate register");
290        unsigned FP = MI->getOperand(1).getReg();
291        assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
292               "Not a Frame Pointer, Nor a Spill Slot");
293        assert(MI->getOperand(2).isImm() && "Not an offset");
294        int Offset = MI->getOperand(2).getImm();
295        if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) {
296          if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
297            BuildMI(*MBB, MII, MI->getDebugLoc(),
298                    TII->get(Hexagon::CONST32_Int_Real),
299                      HEXAGON_RESERVED_REG_1).addImm(Offset);
300            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
301                    HEXAGON_RESERVED_REG_1)
302              .addReg(FP)
303              .addReg(HEXAGON_RESERVED_REG_1);
304            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
305                      HEXAGON_RESERVED_REG_2)
306              .addReg(HEXAGON_RESERVED_REG_1)
307              .addImm(0);
308            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
309                      DstReg).addReg(HEXAGON_RESERVED_REG_2);
310          } else {
311            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
312                      HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
313            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
314                      HEXAGON_RESERVED_REG_2)
315              .addReg(HEXAGON_RESERVED_REG_1)
316              .addImm(0);
317            BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
318                      DstReg).addReg(HEXAGON_RESERVED_REG_2);
319          }
320        } else {
321          BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
322                    HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset);
323          BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
324                    DstReg).addReg(HEXAGON_RESERVED_REG_2);
325        }
326        MII = MBB->erase(MI);
327        --MII;
328      }
329    }
330  }
331
332  return true;
333}
334
335}
336
337//===----------------------------------------------------------------------===//
338//                         Public Constructor Functions
339//===----------------------------------------------------------------------===//
340
341static void initializePassOnce(PassRegistry &Registry) {
342  const char *Name = "Hexagon Expand Predicate Spill Code";
343  PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred",
344                              &HexagonExpandPredSpillCode::ID,
345                              nullptr, false, false);
346  Registry.registerPass(*PI, true);
347}
348
349void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) {
350  CALL_ONCE_INITIALIZATION(initializePassOnce)
351}
352
353FunctionPass*
354llvm::createHexagonExpandPredSpillCode() {
355  return new HexagonExpandPredSpillCode();
356}
357