blob: 69380130428b73af53d5a46bf6fd6948be489931 [file] [log] [blame]
Bob Wilson70cd88f2009-08-05 23:12:45 +00001//===-- NEONPreAllocPass.cpp - Allocate adjacent NEON registers--*- C++ -*-===//
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#define DEBUG_TYPE "neon-prealloc"
11#include "ARM.h"
12#include "ARMInstrInfo.h"
13#include "llvm/CodeGen/MachineInstr.h"
14#include "llvm/CodeGen/MachineInstrBuilder.h"
15#include "llvm/CodeGen/MachineFunctionPass.h"
16using namespace llvm;
17
18namespace {
19 class VISIBILITY_HIDDEN NEONPreAllocPass : public MachineFunctionPass {
20 const TargetInstrInfo *TII;
21
22 public:
23 static char ID;
24 NEONPreAllocPass() : MachineFunctionPass(&ID) {}
25
26 virtual bool runOnMachineFunction(MachineFunction &MF);
27
28 virtual const char *getPassName() const {
29 return "NEON register pre-allocation pass";
30 }
31
32 private:
33 bool PreAllocNEONRegisters(MachineBasicBlock &MBB);
34 };
35
36 char NEONPreAllocPass::ID = 0;
37}
38
39static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd,
40 unsigned &NumRegs) {
41 switch (Opcode) {
42 default:
43 break;
44
45 case ARM::VLD2d8:
46 case ARM::VLD2d16:
47 case ARM::VLD2d32:
Bob Wilson243fcc52009-09-01 04:26:28 +000048 case ARM::VLD2LNd8:
49 case ARM::VLD2LNd16:
50 case ARM::VLD2LNd32:
Bob Wilson70cd88f2009-08-05 23:12:45 +000051 FirstOpnd = 0;
52 NumRegs = 2;
53 return true;
54
55 case ARM::VLD3d8:
56 case ARM::VLD3d16:
57 case ARM::VLD3d32:
Bob Wilson243fcc52009-09-01 04:26:28 +000058 case ARM::VLD3LNd8:
59 case ARM::VLD3LNd16:
60 case ARM::VLD3LNd32:
Bob Wilson70cd88f2009-08-05 23:12:45 +000061 FirstOpnd = 0;
62 NumRegs = 3;
63 return true;
64
65 case ARM::VLD4d8:
66 case ARM::VLD4d16:
67 case ARM::VLD4d32:
Bob Wilson243fcc52009-09-01 04:26:28 +000068 case ARM::VLD4LNd8:
69 case ARM::VLD4LNd16:
70 case ARM::VLD4LNd32:
Bob Wilson70cd88f2009-08-05 23:12:45 +000071 FirstOpnd = 0;
72 NumRegs = 4;
73 return true;
Bob Wilsonb36ec862009-08-06 18:47:44 +000074
75 case ARM::VST2d8:
76 case ARM::VST2d16:
77 case ARM::VST2d32:
78 FirstOpnd = 3;
79 NumRegs = 2;
80 return true;
81
82 case ARM::VST3d8:
83 case ARM::VST3d16:
84 case ARM::VST3d32:
85 FirstOpnd = 3;
86 NumRegs = 3;
87 return true;
88
89 case ARM::VST4d8:
90 case ARM::VST4d16:
91 case ARM::VST4d32:
92 FirstOpnd = 3;
93 NumRegs = 4;
94 return true;
Bob Wilson114a2662009-08-12 20:51:55 +000095
96 case ARM::VTBL2:
97 FirstOpnd = 1;
98 NumRegs = 2;
99 return true;
100
101 case ARM::VTBL3:
102 FirstOpnd = 1;
103 NumRegs = 3;
104 return true;
105
106 case ARM::VTBL4:
107 FirstOpnd = 1;
108 NumRegs = 4;
109 return true;
110
111 case ARM::VTBX2:
112 FirstOpnd = 2;
113 NumRegs = 2;
114 return true;
115
116 case ARM::VTBX3:
117 FirstOpnd = 2;
118 NumRegs = 3;
119 return true;
120
121 case ARM::VTBX4:
122 FirstOpnd = 2;
123 NumRegs = 4;
124 return true;
Bob Wilson70cd88f2009-08-05 23:12:45 +0000125 }
126
127 return false;
128}
129
130bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
131 bool Modified = false;
132
133 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
134 for (; MBBI != E; ++MBBI) {
135 MachineInstr *MI = &*MBBI;
136 unsigned FirstOpnd, NumRegs;
137 if (!isNEONMultiRegOp(MI->getOpcode(), FirstOpnd, NumRegs))
138 continue;
139
140 MachineBasicBlock::iterator NextI = next(MBBI);
141 for (unsigned R = 0; R < NumRegs; ++R) {
142 MachineOperand &MO = MI->getOperand(FirstOpnd + R);
143 assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand");
144 unsigned VirtReg = MO.getReg();
145 assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
146 "expected a virtual register");
147
148 // For now, just assign a fixed set of adjacent registers.
149 // This leaves plenty of room for future improvements.
150 static const unsigned NEONDRegs[] = {
151 ARM::D0, ARM::D1, ARM::D2, ARM::D3
152 };
153 MO.setReg(NEONDRegs[R]);
154
155 if (MO.isUse()) {
156 // Insert a copy from VirtReg.
157 AddDefaultPred(BuildMI(MBB, MBBI, MI->getDebugLoc(),
158 TII->get(ARM::FCPYD), MO.getReg())
159 .addReg(VirtReg));
160 if (MO.isKill()) {
161 MachineInstr *CopyMI = prior(MBBI);
162 CopyMI->findRegisterUseOperand(VirtReg)->setIsKill();
163 }
164 MO.setIsKill();
165 } else if (MO.isDef() && !MO.isDead()) {
166 // Add a copy to VirtReg.
167 AddDefaultPred(BuildMI(MBB, NextI, MI->getDebugLoc(),
168 TII->get(ARM::FCPYD), VirtReg)
169 .addReg(MO.getReg()));
170 }
171 }
172 }
173
174 return Modified;
175}
176
177bool NEONPreAllocPass::runOnMachineFunction(MachineFunction &MF) {
178 TII = MF.getTarget().getInstrInfo();
179
180 bool Modified = false;
181 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
182 ++MFI) {
183 MachineBasicBlock &MBB = *MFI;
184 Modified |= PreAllocNEONRegisters(MBB);
185 }
186
187 return Modified;
188}
189
190/// createNEONPreAllocPass - returns an instance of the NEON register
191/// pre-allocation pass.
192FunctionPass *llvm::createNEONPreAllocPass() {
193 return new NEONPreAllocPass();
194}