blob: da1c662edb6701fd1f8b5f0ea0fdfdaf33db13ee [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
Bob Wilson3bf12ab2009-10-06 22:01:59 +000055 case ARM::VLD2q8:
56 case ARM::VLD2q16:
57 case ARM::VLD2q32:
58 FirstOpnd = 0;
59 NumRegs = 4;
60 return true;
61
Bob Wilson70cd88f2009-08-05 23:12:45 +000062 case ARM::VLD3d8:
63 case ARM::VLD3d16:
64 case ARM::VLD3d32:
Bob Wilson243fcc52009-09-01 04:26:28 +000065 case ARM::VLD3LNd8:
66 case ARM::VLD3LNd16:
67 case ARM::VLD3LNd32:
Bob Wilson70cd88f2009-08-05 23:12:45 +000068 FirstOpnd = 0;
69 NumRegs = 3;
70 return true;
71
72 case ARM::VLD4d8:
73 case ARM::VLD4d16:
74 case ARM::VLD4d32:
Bob Wilson243fcc52009-09-01 04:26:28 +000075 case ARM::VLD4LNd8:
76 case ARM::VLD4LNd16:
77 case ARM::VLD4LNd32:
Bob Wilson70cd88f2009-08-05 23:12:45 +000078 FirstOpnd = 0;
79 NumRegs = 4;
80 return true;
Bob Wilsonb36ec862009-08-06 18:47:44 +000081
82 case ARM::VST2d8:
83 case ARM::VST2d16:
84 case ARM::VST2d32:
Bob Wilson8a3198b2009-09-01 18:51:56 +000085 case ARM::VST2LNd8:
86 case ARM::VST2LNd16:
87 case ARM::VST2LNd32:
Bob Wilsonb36ec862009-08-06 18:47:44 +000088 FirstOpnd = 3;
89 NumRegs = 2;
90 return true;
91
92 case ARM::VST3d8:
93 case ARM::VST3d16:
94 case ARM::VST3d32:
Bob Wilson8a3198b2009-09-01 18:51:56 +000095 case ARM::VST3LNd8:
96 case ARM::VST3LNd16:
97 case ARM::VST3LNd32:
Bob Wilsonb36ec862009-08-06 18:47:44 +000098 FirstOpnd = 3;
99 NumRegs = 3;
100 return true;
101
102 case ARM::VST4d8:
103 case ARM::VST4d16:
104 case ARM::VST4d32:
Bob Wilson8a3198b2009-09-01 18:51:56 +0000105 case ARM::VST4LNd8:
106 case ARM::VST4LNd16:
107 case ARM::VST4LNd32:
Bob Wilsonb36ec862009-08-06 18:47:44 +0000108 FirstOpnd = 3;
109 NumRegs = 4;
110 return true;
Bob Wilson114a2662009-08-12 20:51:55 +0000111
112 case ARM::VTBL2:
113 FirstOpnd = 1;
114 NumRegs = 2;
115 return true;
116
117 case ARM::VTBL3:
118 FirstOpnd = 1;
119 NumRegs = 3;
120 return true;
121
122 case ARM::VTBL4:
123 FirstOpnd = 1;
124 NumRegs = 4;
125 return true;
126
127 case ARM::VTBX2:
128 FirstOpnd = 2;
129 NumRegs = 2;
130 return true;
131
132 case ARM::VTBX3:
133 FirstOpnd = 2;
134 NumRegs = 3;
135 return true;
136
137 case ARM::VTBX4:
138 FirstOpnd = 2;
139 NumRegs = 4;
140 return true;
Bob Wilson70cd88f2009-08-05 23:12:45 +0000141 }
142
143 return false;
144}
145
146bool NEONPreAllocPass::PreAllocNEONRegisters(MachineBasicBlock &MBB) {
147 bool Modified = false;
148
149 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
150 for (; MBBI != E; ++MBBI) {
151 MachineInstr *MI = &*MBBI;
152 unsigned FirstOpnd, NumRegs;
153 if (!isNEONMultiRegOp(MI->getOpcode(), FirstOpnd, NumRegs))
154 continue;
155
156 MachineBasicBlock::iterator NextI = next(MBBI);
157 for (unsigned R = 0; R < NumRegs; ++R) {
158 MachineOperand &MO = MI->getOperand(FirstOpnd + R);
159 assert(MO.isReg() && MO.getSubReg() == 0 && "unexpected operand");
160 unsigned VirtReg = MO.getReg();
161 assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
162 "expected a virtual register");
163
164 // For now, just assign a fixed set of adjacent registers.
165 // This leaves plenty of room for future improvements.
166 static const unsigned NEONDRegs[] = {
167 ARM::D0, ARM::D1, ARM::D2, ARM::D3
168 };
169 MO.setReg(NEONDRegs[R]);
170
171 if (MO.isUse()) {
172 // Insert a copy from VirtReg.
Bob Wilson349d82d2009-10-06 22:01:15 +0000173 TII->copyRegToReg(MBB, MBBI, MO.getReg(), VirtReg,
174 ARM::DPRRegisterClass, ARM::DPRRegisterClass);
Bob Wilson70cd88f2009-08-05 23:12:45 +0000175 if (MO.isKill()) {
176 MachineInstr *CopyMI = prior(MBBI);
177 CopyMI->findRegisterUseOperand(VirtReg)->setIsKill();
178 }
179 MO.setIsKill();
180 } else if (MO.isDef() && !MO.isDead()) {
181 // Add a copy to VirtReg.
Bob Wilson349d82d2009-10-06 22:01:15 +0000182 TII->copyRegToReg(MBB, NextI, VirtReg, MO.getReg(),
183 ARM::DPRRegisterClass, ARM::DPRRegisterClass);
Bob Wilson70cd88f2009-08-05 23:12:45 +0000184 }
185 }
186 }
187
188 return Modified;
189}
190
191bool NEONPreAllocPass::runOnMachineFunction(MachineFunction &MF) {
192 TII = MF.getTarget().getInstrInfo();
193
194 bool Modified = false;
195 for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E;
196 ++MFI) {
197 MachineBasicBlock &MBB = *MFI;
198 Modified |= PreAllocNEONRegisters(MBB);
199 }
200
201 return Modified;
202}
203
204/// createNEONPreAllocPass - returns an instance of the NEON register
205/// pre-allocation pass.
206FunctionPass *llvm::createNEONPreAllocPass() {
207 return new NEONPreAllocPass();
208}