blob: c9f5400018e8cbd5c534f909fc99c5217edc79e6 [file] [log] [blame]
Eugene Zelenko4d060b72017-07-29 00:56:56 +00001//===- HexagonSplitDouble.cpp ---------------------------------------------===//
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00002//
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 "hsdr"
11
Eugene Zelenko58655bb2016-12-17 01:09:05 +000012#include "HexagonInstrInfo.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000013#include "HexagonRegisterInfo.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000014#include "HexagonSubtarget.h"
15#include "llvm/ADT/BitVector.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000016#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000017#include "llvm/ADT/SmallVector.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000018#include "llvm/ADT/StringRef.h"
19#include "llvm/CodeGen/MachineBasicBlock.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000020#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineFunctionPass.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000022#include "llvm/CodeGen/MachineInstr.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000023#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineLoopInfo.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000025#include "llvm/CodeGen/MachineMemOperand.h"
26#include "llvm/CodeGen/MachineOperand.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000027#include "llvm/CodeGen/MachineRegisterInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000028#include "llvm/CodeGen/TargetRegisterInfo.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000029#include "llvm/IR/DebugLoc.h"
Mehdi Aminib550cb12016-04-18 09:17:29 +000030#include "llvm/Pass.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000031#include "llvm/Support/CommandLine.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000032#include "llvm/Support/Compiler.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000033#include "llvm/Support/Debug.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000034#include "llvm/Support/ErrorHandling.h"
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000035#include "llvm/Support/raw_ostream.h"
Eugene Zelenko58655bb2016-12-17 01:09:05 +000036#include <algorithm>
37#include <cassert>
38#include <cstdint>
39#include <limits>
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000040#include <map>
41#include <set>
Eugene Zelenko58655bb2016-12-17 01:09:05 +000042#include <utility>
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000043#include <vector>
44
45using namespace llvm;
46
47namespace llvm {
Eugene Zelenko58655bb2016-12-17 01:09:05 +000048
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000049 FunctionPass *createHexagonSplitDoubleRegs();
50 void initializeHexagonSplitDoubleRegsPass(PassRegistry&);
Eugene Zelenko58655bb2016-12-17 01:09:05 +000051
52} // end namespace llvm
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000053
Eugene Zelenko4d060b72017-07-29 00:56:56 +000054static cl::opt<int> MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1),
55 cl::desc("Maximum number of split partitions"));
56static cl::opt<bool> MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true),
57 cl::desc("Do not split loads or stores"));
Eugene Zelenko58655bb2016-12-17 01:09:05 +000058
Eugene Zelenko4d060b72017-07-29 00:56:56 +000059namespace {
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000060
61 class HexagonSplitDoubleRegs : public MachineFunctionPass {
62 public:
63 static char ID;
Eugene Zelenko58655bb2016-12-17 01:09:05 +000064
Eugene Zelenko4d060b72017-07-29 00:56:56 +000065 HexagonSplitDoubleRegs() : MachineFunctionPass(ID) {
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000066 initializeHexagonSplitDoubleRegsPass(*PassRegistry::getPassRegistry());
67 }
Eugene Zelenko58655bb2016-12-17 01:09:05 +000068
Mehdi Amini117296c2016-10-01 02:56:57 +000069 StringRef getPassName() const override {
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000070 return "Hexagon Split Double Registers";
71 }
Eugene Zelenko58655bb2016-12-17 01:09:05 +000072
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000073 void getAnalysisUsage(AnalysisUsage &AU) const override {
74 AU.addRequired<MachineLoopInfo>();
75 AU.addPreserved<MachineLoopInfo>();
76 MachineFunctionPass::getAnalysisUsage(AU);
77 }
Eugene Zelenko58655bb2016-12-17 01:09:05 +000078
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000079 bool runOnMachineFunction(MachineFunction &MF) override;
80
81 private:
82 static const TargetRegisterClass *const DoubleRC;
83
Eugene Zelenko4d060b72017-07-29 00:56:56 +000084 const HexagonRegisterInfo *TRI = nullptr;
85 const HexagonInstrInfo *TII = nullptr;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000086 const MachineLoopInfo *MLI;
87 MachineRegisterInfo *MRI;
88
Eugene Zelenko4d060b72017-07-29 00:56:56 +000089 using USet = std::set<unsigned>;
90 using UUSetMap = std::map<unsigned, USet>;
91 using UUPair = std::pair<unsigned, unsigned>;
92 using UUPairMap = std::map<unsigned, UUPair>;
93 using LoopRegMap = std::map<const MachineLoop *, USet>;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +000094
95 bool isInduction(unsigned Reg, LoopRegMap &IRM) const;
96 bool isVolatileInstr(const MachineInstr *MI) const;
97 bool isFixedInstr(const MachineInstr *MI) const;
98 void partitionRegisters(UUSetMap &P2Rs);
99 int32_t profit(const MachineInstr *MI) const;
100 bool isProfitable(const USet &Part, LoopRegMap &IRM) const;
101
102 void collectIndRegsForLoop(const MachineLoop *L, USet &Rs);
103 void collectIndRegs(LoopRegMap &IRM);
104
105 void createHalfInstr(unsigned Opc, MachineInstr *MI,
106 const UUPairMap &PairMap, unsigned SubR);
107 void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap);
108 void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap);
109 void splitCombine(MachineInstr *MI, const UUPairMap &PairMap);
110 void splitExt(MachineInstr *MI, const UUPairMap &PairMap);
111 void splitShift(MachineInstr *MI, const UUPairMap &PairMap);
112 void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap);
113 bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap);
114 void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap);
115 void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap);
116 bool splitPartition(const USet &Part);
117
118 static int Counter;
Eugene Zelenko4d060b72017-07-29 00:56:56 +0000119
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000120 static void dump_partition(raw_ostream&, const USet&,
121 const TargetRegisterInfo&);
122 };
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000123
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000124} // end anonymous namespace
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000125
Eugene Zelenko4d060b72017-07-29 00:56:56 +0000126char HexagonSplitDoubleRegs::ID;
127int HexagonSplitDoubleRegs::Counter = 0;
128const TargetRegisterClass *const HexagonSplitDoubleRegs::DoubleRC =
129 &Hexagon::DoubleRegsRegClass;
130
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000131INITIALIZE_PASS(HexagonSplitDoubleRegs, "hexagon-split-double",
132 "Hexagon Split Double Registers", false, false)
133
Aaron Ballman615eb472017-10-15 14:32:27 +0000134#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Matthias Braun8c209aa2017-01-28 02:02:38 +0000135LLVM_DUMP_METHOD void HexagonSplitDoubleRegs::dump_partition(raw_ostream &os,
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000136 const USet &Part, const TargetRegisterInfo &TRI) {
137 dbgs() << '{';
138 for (auto I : Part)
Francis Visoiu Mistrih9d419d32017-11-28 12:42:37 +0000139 dbgs() << ' ' << printReg(I, &TRI);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000140 dbgs() << " }";
141}
Matthias Braun8c209aa2017-01-28 02:02:38 +0000142#endif
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000143
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000144bool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const {
145 for (auto I : IRM) {
146 const USet &Rs = I.second;
147 if (Rs.find(Reg) != Rs.end())
148 return true;
149 }
150 return false;
151}
152
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000153bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const {
154 for (auto &I : MI->memoperands())
155 if (I->isVolatile())
156 return true;
157 return false;
158}
159
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000160bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const {
161 if (MI->mayLoad() || MI->mayStore())
162 if (MemRefsFixed || isVolatileInstr(MI))
163 return true;
164 if (MI->isDebugValue())
165 return false;
166
167 unsigned Opc = MI->getOpcode();
168 switch (Opc) {
169 default:
170 return true;
171
172 case TargetOpcode::PHI:
173 case TargetOpcode::COPY:
174 break;
175
176 case Hexagon::L2_loadrd_io:
177 // Not handling stack stores (only reg-based addresses).
178 if (MI->getOperand(1).isReg())
179 break;
180 return true;
181 case Hexagon::S2_storerd_io:
182 // Not handling stack stores (only reg-based addresses).
183 if (MI->getOperand(0).isReg())
184 break;
185 return true;
186 case Hexagon::L2_loadrd_pi:
187 case Hexagon::S2_storerd_pi:
188
189 case Hexagon::A2_tfrpi:
190 case Hexagon::A2_combineii:
191 case Hexagon::A4_combineir:
192 case Hexagon::A4_combineii:
193 case Hexagon::A4_combineri:
194 case Hexagon::A2_combinew:
Krzysztof Parzyszeka3386502016-08-10 16:46:36 +0000195 case Hexagon::CONST64:
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000196
197 case Hexagon::A2_sxtw:
198
199 case Hexagon::A2_andp:
200 case Hexagon::A2_orp:
201 case Hexagon::A2_xorp:
202 case Hexagon::S2_asl_i_p_or:
203 case Hexagon::S2_asl_i_p:
204 case Hexagon::S2_asr_i_p:
205 case Hexagon::S2_lsr_i_p:
206 break;
207 }
208
209 for (auto &Op : MI->operands()) {
210 if (!Op.isReg())
211 continue;
212 unsigned R = Op.getReg();
213 if (!TargetRegisterInfo::isVirtualRegister(R))
214 return true;
215 }
216 return false;
217}
218
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000219void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {
Eugene Zelenko4d060b72017-07-29 00:56:56 +0000220 using UUMap = std::map<unsigned, unsigned>;
221 using UVect = std::vector<unsigned>;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000222
223 unsigned NumRegs = MRI->getNumVirtRegs();
224 BitVector DoubleRegs(NumRegs);
225 for (unsigned i = 0; i < NumRegs; ++i) {
226 unsigned R = TargetRegisterInfo::index2VirtReg(i);
227 if (MRI->getRegClass(R) == DoubleRC)
228 DoubleRegs.set(i);
229 }
230
231 BitVector FixedRegs(NumRegs);
232 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
233 unsigned R = TargetRegisterInfo::index2VirtReg(x);
234 MachineInstr *DefI = MRI->getVRegDef(R);
235 // In some cases a register may exist, but never be defined or used.
236 // It should never appear anywhere, but mark it as "fixed", just to be
237 // safe.
238 if (!DefI || isFixedInstr(DefI))
239 FixedRegs.set(x);
240 }
241
242 UUSetMap AssocMap;
243 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
244 if (FixedRegs[x])
245 continue;
246 unsigned R = TargetRegisterInfo::index2VirtReg(x);
Francis Visoiu Mistrih9d419d32017-11-28 12:42:37 +0000247 DEBUG(dbgs() << printReg(R, TRI) << " ~~");
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000248 USet &Asc = AssocMap[R];
249 for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end();
250 U != Z; ++U) {
251 MachineOperand &Op = *U;
252 MachineInstr *UseI = Op.getParent();
253 if (isFixedInstr(UseI))
254 continue;
255 for (unsigned i = 0, n = UseI->getNumOperands(); i < n; ++i) {
256 MachineOperand &MO = UseI->getOperand(i);
257 // Skip non-registers or registers with subregisters.
258 if (&MO == &Op || !MO.isReg() || MO.getSubReg())
259 continue;
260 unsigned T = MO.getReg();
261 if (!TargetRegisterInfo::isVirtualRegister(T)) {
262 FixedRegs.set(x);
263 continue;
264 }
265 if (MRI->getRegClass(T) != DoubleRC)
266 continue;
267 unsigned u = TargetRegisterInfo::virtReg2Index(T);
268 if (FixedRegs[u])
269 continue;
Francis Visoiu Mistrih9d419d32017-11-28 12:42:37 +0000270 DEBUG(dbgs() << ' ' << printReg(T, TRI));
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000271 Asc.insert(T);
272 // Make it symmetric.
273 AssocMap[T].insert(R);
274 }
275 }
276 DEBUG(dbgs() << '\n');
277 }
278
279 UUMap R2P;
280 unsigned NextP = 1;
281 USet Visited;
282 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
283 unsigned R = TargetRegisterInfo::index2VirtReg(x);
284 if (Visited.count(R))
285 continue;
286 // Create a new partition for R.
287 unsigned ThisP = FixedRegs[x] ? 0 : NextP++;
288 UVect WorkQ;
289 WorkQ.push_back(R);
290 for (unsigned i = 0; i < WorkQ.size(); ++i) {
291 unsigned T = WorkQ[i];
292 if (Visited.count(T))
293 continue;
294 R2P[T] = ThisP;
295 Visited.insert(T);
296 // Add all registers associated with T.
297 USet &Asc = AssocMap[T];
298 for (USet::iterator J = Asc.begin(), F = Asc.end(); J != F; ++J)
299 WorkQ.push_back(*J);
300 }
301 }
302
303 for (auto I : R2P)
304 P2Rs[I.second].insert(I.first);
305}
306
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000307static inline int32_t profitImm(unsigned Lo, unsigned Hi) {
308 int32_t P = 0;
309 bool LoZ1 = false, HiZ1 = false;
310 if (Lo == 0 || Lo == 0xFFFFFFFF)
311 P += 10, LoZ1 = true;
312 if (Hi == 0 || Hi == 0xFFFFFFFF)
313 P += 10, HiZ1 = true;
314 if (!LoZ1 && !HiZ1 && Lo == Hi)
315 P += 3;
316 return P;
317}
318
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000319int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const {
320 unsigned ImmX = 0;
321 unsigned Opc = MI->getOpcode();
322 switch (Opc) {
323 case TargetOpcode::PHI:
324 for (const auto &Op : MI->operands())
325 if (!Op.getSubReg())
326 return 0;
327 return 10;
328 case TargetOpcode::COPY:
329 if (MI->getOperand(1).getSubReg() != 0)
330 return 10;
331 return 0;
332
333 case Hexagon::L2_loadrd_io:
334 case Hexagon::S2_storerd_io:
335 return -1;
336 case Hexagon::L2_loadrd_pi:
337 case Hexagon::S2_storerd_pi:
338 return 2;
339
340 case Hexagon::A2_tfrpi:
Krzysztof Parzyszeka3386502016-08-10 16:46:36 +0000341 case Hexagon::CONST64: {
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000342 uint64_t D = MI->getOperand(1).getImm();
343 unsigned Lo = D & 0xFFFFFFFFULL;
344 unsigned Hi = D >> 32;
345 return profitImm(Lo, Hi);
346 }
347 case Hexagon::A2_combineii:
348 case Hexagon::A4_combineii:
349 return profitImm(MI->getOperand(1).getImm(),
350 MI->getOperand(2).getImm());
351 case Hexagon::A4_combineri:
352 ImmX++;
Simon Pilgrim087e87d2017-07-07 13:21:43 +0000353 // Fall through into A4_combineir.
354 LLVM_FALLTHROUGH;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000355 case Hexagon::A4_combineir: {
356 ImmX++;
357 int64_t V = MI->getOperand(ImmX).getImm();
358 if (V == 0 || V == -1)
359 return 10;
360 // Fall through into A2_combinew.
Justin Bognercd1d5aa2016-08-17 20:30:52 +0000361 LLVM_FALLTHROUGH;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000362 }
363 case Hexagon::A2_combinew:
364 return 2;
365
366 case Hexagon::A2_sxtw:
367 return 3;
368
369 case Hexagon::A2_andp:
370 case Hexagon::A2_orp:
371 case Hexagon::A2_xorp:
372 return 1;
373
374 case Hexagon::S2_asl_i_p_or: {
375 unsigned S = MI->getOperand(3).getImm();
376 if (S == 0 || S == 32)
377 return 10;
378 return -1;
379 }
380 case Hexagon::S2_asl_i_p:
381 case Hexagon::S2_asr_i_p:
382 case Hexagon::S2_lsr_i_p:
383 unsigned S = MI->getOperand(2).getImm();
384 if (S == 0 || S == 32)
385 return 10;
386 if (S == 16)
387 return 5;
388 if (S == 48)
389 return 7;
390 return -10;
391 }
392
393 return 0;
394}
395
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000396bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM)
397 const {
Krzysztof Parzyszekd04c9b92017-03-31 21:03:59 +0000398 unsigned FixedNum = 0, LoopPhiNum = 0;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000399 int32_t TotalP = 0;
400
401 for (unsigned DR : Part) {
402 MachineInstr *DefI = MRI->getVRegDef(DR);
403 int32_t P = profit(DefI);
Malcolm Parsons14bb1f52016-12-19 12:37:26 +0000404 if (P == std::numeric_limits<int>::min())
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000405 return false;
406 TotalP += P;
407 // Reduce the profitability of splitting induction registers.
408 if (isInduction(DR, IRM))
409 TotalP -= 30;
410
411 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
412 U != W; ++U) {
413 MachineInstr *UseI = U->getParent();
414 if (isFixedInstr(UseI)) {
415 FixedNum++;
416 // Calculate the cost of generating REG_SEQUENCE instructions.
417 for (auto &Op : UseI->operands()) {
418 if (Op.isReg() && Part.count(Op.getReg()))
419 if (Op.getSubReg())
420 TotalP -= 2;
421 }
422 continue;
423 }
424 // If a register from this partition is used in a fixed instruction,
425 // and there is also a register in this partition that is used in
426 // a loop phi node, then decrease the splitting profit as this can
427 // confuse the modulo scheduler.
428 if (UseI->isPHI()) {
429 const MachineBasicBlock *PB = UseI->getParent();
430 const MachineLoop *L = MLI->getLoopFor(PB);
431 if (L && L->getHeader() == PB)
432 LoopPhiNum++;
433 }
434 // Splittable instruction.
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000435 int32_t P = profit(UseI);
Malcolm Parsons14bb1f52016-12-19 12:37:26 +0000436 if (P == std::numeric_limits<int>::min())
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000437 return false;
438 TotalP += P;
439 }
440 }
441
442 if (FixedNum > 0 && LoopPhiNum > 0)
443 TotalP -= 20*LoopPhiNum;
444
445 DEBUG(dbgs() << "Partition profit: " << TotalP << '\n');
446 return TotalP > 0;
447}
448
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000449void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L,
450 USet &Rs) {
451 const MachineBasicBlock *HB = L->getHeader();
452 const MachineBasicBlock *LB = L->getLoopLatch();
453 if (!HB || !LB)
454 return;
455
456 // Examine the latch branch. Expect it to be a conditional branch to
457 // the header (either "br-cond header" or "br-cond exit; br header").
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000458 MachineBasicBlock *TB = nullptr, *FB = nullptr;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000459 MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB);
460 SmallVector<MachineOperand,2> Cond;
Jacques Pienaar71c30a12016-07-15 14:41:04 +0000461 bool BadLB = TII->analyzeBranch(*TmpLB, TB, FB, Cond, false);
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000462 // Only analyzable conditional branches. HII::analyzeBranch will put
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000463 // the branch opcode as the first element of Cond, and the predicate
464 // operand as the second.
465 if (BadLB || Cond.size() != 2)
466 return;
467 // Only simple jump-conditional (with or without negation).
468 if (!TII->PredOpcodeHasJMP_c(Cond[0].getImm()))
469 return;
470 // Must go to the header.
471 if (TB != HB && FB != HB)
472 return;
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000473 assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch");
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000474 // Expect a predicate register.
475 unsigned PR = Cond[1].getReg();
476 assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);
477
478 // Get the registers on which the loop controlling compare instruction
479 // depends.
480 unsigned CmpR1 = 0, CmpR2 = 0;
481 const MachineInstr *CmpI = MRI->getVRegDef(PR);
482 while (CmpI->getOpcode() == Hexagon::C2_not)
483 CmpI = MRI->getVRegDef(CmpI->getOperand(1).getReg());
484
485 int Mask = 0, Val = 0;
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000486 bool OkCI = TII->analyzeCompare(*CmpI, CmpR1, CmpR2, Mask, Val);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000487 if (!OkCI)
488 return;
489 // Eliminate non-double input registers.
490 if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC)
491 CmpR1 = 0;
492 if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC)
493 CmpR2 = 0;
494 if (!CmpR1 && !CmpR2)
495 return;
496
497 // Now examine the top of the loop: the phi nodes that could poten-
498 // tially define loop induction registers. The registers defined by
499 // such a phi node would be used in a 64-bit add, which then would
500 // be used in the loop compare instruction.
501
502 // Get the set of all double registers defined by phi nodes in the
503 // loop header.
Eugene Zelenko4d060b72017-07-29 00:56:56 +0000504 using UVect = std::vector<unsigned>;
505
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000506 UVect DP;
507 for (auto &MI : *HB) {
508 if (!MI.isPHI())
509 break;
510 const MachineOperand &MD = MI.getOperand(0);
511 unsigned R = MD.getReg();
512 if (MRI->getRegClass(R) == DoubleRC)
513 DP.push_back(R);
514 }
515 if (DP.empty())
516 return;
517
518 auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool {
519 for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end();
520 I != E; ++I) {
521 const MachineInstr *UseI = I->getParent();
522 if (UseI->getOpcode() != Hexagon::A2_addp)
523 continue;
524 // Get the output from the add. If it is one of the inputs to the
525 // loop-controlling compare instruction, then R is likely an induc-
526 // tion register.
527 unsigned T = UseI->getOperand(0).getReg();
528 if (T == CmpR1 || T == CmpR2)
529 return false;
530 }
531 return true;
532 };
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000533 UVect::iterator End = llvm::remove_if(DP, NoIndOp);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000534 Rs.insert(DP.begin(), End);
535 Rs.insert(CmpR1);
536 Rs.insert(CmpR2);
537
538 DEBUG({
Francis Visoiu Mistrih25528d62017-12-04 17:18:51 +0000539 dbgs() << "For loop at " << printMBBReference(*HB) << " ind regs: ";
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000540 dump_partition(dbgs(), Rs, *TRI);
541 dbgs() << '\n';
542 });
543}
544
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000545void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {
Eugene Zelenko4d060b72017-07-29 00:56:56 +0000546 using LoopVector = std::vector<MachineLoop *>;
547
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000548 LoopVector WorkQ;
549
550 for (auto I : *MLI)
551 WorkQ.push_back(I);
552 for (unsigned i = 0; i < WorkQ.size(); ++i) {
553 for (auto I : *WorkQ[i])
554 WorkQ.push_back(I);
555 }
556
557 USet Rs;
558 for (unsigned i = 0, n = WorkQ.size(); i < n; ++i) {
559 MachineLoop *L = WorkQ[i];
560 Rs.clear();
561 collectIndRegsForLoop(L, Rs);
562 if (!Rs.empty())
563 IRM.insert(std::make_pair(L, Rs));
564 }
565}
566
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000567void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI,
568 const UUPairMap &PairMap, unsigned SubR) {
569 MachineBasicBlock &B = *MI->getParent();
570 DebugLoc DL = MI->getDebugLoc();
571 MachineInstr *NewI = BuildMI(B, MI, DL, TII->get(Opc));
572
573 for (auto &Op : MI->operands()) {
574 if (!Op.isReg()) {
575 NewI->addOperand(Op);
576 continue;
577 }
578 // For register operands, set the subregister.
579 unsigned R = Op.getReg();
580 unsigned SR = Op.getSubReg();
581 bool isVirtReg = TargetRegisterInfo::isVirtualRegister(R);
582 bool isKill = Op.isKill();
583 if (isVirtReg && MRI->getRegClass(R) == DoubleRC) {
584 isKill = false;
585 UUPairMap::const_iterator F = PairMap.find(R);
586 if (F == PairMap.end()) {
587 SR = SubR;
588 } else {
589 const UUPair &P = F->second;
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000590 R = (SubR == Hexagon::isub_lo) ? P.first : P.second;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000591 SR = 0;
592 }
593 }
594 auto CO = MachineOperand::CreateReg(R, Op.isDef(), Op.isImplicit(), isKill,
595 Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(),
596 Op.isInternalRead());
597 NewI->addOperand(CO);
598 }
599}
600
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000601void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI,
602 const UUPairMap &PairMap) {
603 bool Load = MI->mayLoad();
604 unsigned OrigOpc = MI->getOpcode();
605 bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||
606 OrigOpc == Hexagon::S2_storerd_pi);
607 MachineInstr *LowI, *HighI;
608 MachineBasicBlock &B = *MI->getParent();
609 DebugLoc DL = MI->getDebugLoc();
610
611 // Index of the base-address-register operand.
612 unsigned AdrX = PostInc ? (Load ? 2 : 1)
613 : (Load ? 1 : 0);
614 MachineOperand &AdrOp = MI->getOperand(AdrX);
615 unsigned RSA = getRegState(AdrOp);
616 MachineOperand &ValOp = Load ? MI->getOperand(0)
617 : (PostInc ? MI->getOperand(3)
618 : MI->getOperand(2));
619 UUPairMap::const_iterator F = PairMap.find(ValOp.getReg());
620 assert(F != PairMap.end());
621
622 if (Load) {
623 const UUPair &P = F->second;
624 int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm();
625 LowI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.first)
626 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
627 .addImm(Off);
628 HighI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.second)
629 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
630 .addImm(Off+4);
631 } else {
632 const UUPair &P = F->second;
633 int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm();
634 LowI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
635 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
636 .addImm(Off)
637 .addReg(P.first);
638 HighI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
639 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
640 .addImm(Off+4)
641 .addReg(P.second);
642 }
643
644 if (PostInc) {
645 // Create the increment of the address register.
646 int64_t Inc = Load ? MI->getOperand(3).getImm()
647 : MI->getOperand(2).getImm();
648 MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0);
649 const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg());
650 unsigned NewR = MRI->createVirtualRegister(RC);
651 assert(!UpdOp.getSubReg() && "Def operand with subreg");
652 BuildMI(B, MI, DL, TII->get(Hexagon::A2_addi), NewR)
653 .addReg(AdrOp.getReg(), RSA)
654 .addImm(Inc);
655 MRI->replaceRegWith(UpdOp.getReg(), NewR);
656 // The original instruction will be deleted later.
657 }
658
659 // Generate a new pair of memory-operands.
660 MachineFunction &MF = *B.getParent();
661 for (auto &MO : MI->memoperands()) {
662 const MachinePointerInfo &Ptr = MO->getPointerInfo();
Justin Lebar0af80cd2016-07-15 18:26:59 +0000663 MachineMemOperand::Flags F = MO->getFlags();
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000664 int A = MO->getAlignment();
665
666 auto *Tmp1 = MF.getMachineMemOperand(Ptr, F, 4/*size*/, A);
667 LowI->addMemOperand(MF, Tmp1);
668 auto *Tmp2 = MF.getMachineMemOperand(Ptr, F, 4/*size*/, std::min(A, 4));
669 HighI->addMemOperand(MF, Tmp2);
670 }
671}
672
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000673void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI,
674 const UUPairMap &PairMap) {
675 MachineOperand &Op0 = MI->getOperand(0);
676 MachineOperand &Op1 = MI->getOperand(1);
677 assert(Op0.isReg() && Op1.isImm());
678 uint64_t V = Op1.getImm();
679
680 MachineBasicBlock &B = *MI->getParent();
681 DebugLoc DL = MI->getDebugLoc();
682 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
683 assert(F != PairMap.end());
684 const UUPair &P = F->second;
685
686 // The operand to A2_tfrsi can only have 32 significant bits. Immediate
687 // values in MachineOperand are stored as 64-bit integers, and so the
688 // value -1 may be represented either as 64-bit -1, or 4294967295. Both
689 // will have the 32 higher bits truncated in the end, but -1 will remain
690 // as -1, while the latter may appear to be a large unsigned value
691 // requiring a constant extender. The casting to int32_t will select the
692 // former representation. (The same reasoning applies to all 32-bit
693 // values.)
694 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
695 .addImm(int32_t(V & 0xFFFFFFFFULL));
696 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
697 .addImm(int32_t(V >> 32));
698}
699
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000700void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI,
701 const UUPairMap &PairMap) {
702 MachineOperand &Op0 = MI->getOperand(0);
703 MachineOperand &Op1 = MI->getOperand(1);
704 MachineOperand &Op2 = MI->getOperand(2);
705 assert(Op0.isReg());
706
707 MachineBasicBlock &B = *MI->getParent();
708 DebugLoc DL = MI->getDebugLoc();
709 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
710 assert(F != PairMap.end());
711 const UUPair &P = F->second;
712
713 if (Op1.isImm()) {
714 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
715 .addImm(Op1.getImm());
716 } else if (Op1.isReg()) {
717 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.second)
718 .addReg(Op1.getReg(), getRegState(Op1), Op1.getSubReg());
719 } else
720 llvm_unreachable("Unexpected operand");
721
722 if (Op2.isImm()) {
723 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
724 .addImm(Op2.getImm());
725 } else if (Op2.isReg()) {
726 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
727 .addReg(Op2.getReg(), getRegState(Op2), Op2.getSubReg());
728 } else
729 llvm_unreachable("Unexpected operand");
730}
731
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000732void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI,
733 const UUPairMap &PairMap) {
734 MachineOperand &Op0 = MI->getOperand(0);
735 MachineOperand &Op1 = MI->getOperand(1);
736 assert(Op0.isReg() && Op1.isReg());
737
738 MachineBasicBlock &B = *MI->getParent();
739 DebugLoc DL = MI->getDebugLoc();
740 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
741 assert(F != PairMap.end());
742 const UUPair &P = F->second;
743 unsigned RS = getRegState(Op1);
744
745 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
746 .addReg(Op1.getReg(), RS & ~RegState::Kill, Op1.getSubReg());
747 BuildMI(B, MI, DL, TII->get(Hexagon::S2_asr_i_r), P.second)
748 .addReg(Op1.getReg(), RS, Op1.getSubReg())
749 .addImm(31);
750}
751
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000752void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI,
753 const UUPairMap &PairMap) {
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000754 using namespace Hexagon;
755
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000756 MachineOperand &Op0 = MI->getOperand(0);
757 MachineOperand &Op1 = MI->getOperand(1);
758 MachineOperand &Op2 = MI->getOperand(2);
759 assert(Op0.isReg() && Op1.isReg() && Op2.isImm());
760 int64_t Sh64 = Op2.getImm();
761 assert(Sh64 >= 0 && Sh64 < 64);
762 unsigned S = Sh64;
763
764 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
765 assert(F != PairMap.end());
766 const UUPair &P = F->second;
767 unsigned LoR = P.first;
768 unsigned HiR = P.second;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000769
770 unsigned Opc = MI->getOpcode();
771 bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);
772 bool Left = !Right;
773 bool Signed = (Opc == S2_asr_i_p);
774
775 MachineBasicBlock &B = *MI->getParent();
776 DebugLoc DL = MI->getDebugLoc();
777 unsigned RS = getRegState(Op1);
778 unsigned ShiftOpc = Left ? S2_asl_i_r
779 : (Signed ? S2_asr_i_r : S2_lsr_i_r);
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000780 unsigned LoSR = isub_lo;
781 unsigned HiSR = isub_hi;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000782
783 if (S == 0) {
784 // No shift, subregister copy.
785 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
786 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
787 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), HiR)
788 .addReg(Op1.getReg(), RS, HiSR);
789 } else if (S < 32) {
790 const TargetRegisterClass *IntRC = &IntRegsRegClass;
791 unsigned TmpR = MRI->createVirtualRegister(IntRC);
792 // Expansion:
793 // Shift left: DR = shl R, #s
794 // LoR = shl R.lo, #s
795 // TmpR = extractu R.lo, #s, #32-s
796 // HiR = or (TmpR, asl(R.hi, #s))
797 // Shift right: DR = shr R, #s
798 // HiR = shr R.hi, #s
799 // TmpR = shr R.lo, #s
800 // LoR = insert TmpR, R.hi, #s, #32-s
801
802 // Shift left:
803 // LoR = shl R.lo, #s
804 // Shift right:
805 // TmpR = shr R.lo, #s
806
807 // Make a special case for A2_aslh and A2_asrh (they are predicable as
808 // opposed to S2_asl_i_r/S2_asr_i_r).
809 if (S == 16 && Left)
810 BuildMI(B, MI, DL, TII->get(A2_aslh), LoR)
811 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
812 else if (S == 16 && Signed)
813 BuildMI(B, MI, DL, TII->get(A2_asrh), TmpR)
814 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
815 else
816 BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? LoR : TmpR))
817 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
818 .addImm(S);
819
820 if (Left) {
821 // TmpR = extractu R.lo, #s, #32-s
822 BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR)
823 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
824 .addImm(S)
825 .addImm(32-S);
826 // HiR = or (TmpR, asl(R.hi, #s))
827 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
828 .addReg(TmpR)
829 .addReg(Op1.getReg(), RS, HiSR)
830 .addImm(S);
831 } else {
832 // HiR = shr R.hi, #s
833 BuildMI(B, MI, DL, TII->get(ShiftOpc), HiR)
834 .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR)
835 .addImm(S);
836 // LoR = insert TmpR, R.hi, #s, #32-s
837 BuildMI(B, MI, DL, TII->get(S2_insert), LoR)
838 .addReg(TmpR)
839 .addReg(Op1.getReg(), RS, HiSR)
840 .addImm(S)
841 .addImm(32-S);
842 }
843 } else if (S == 32) {
844 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), (Left ? HiR : LoR))
845 .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR));
846 if (!Signed)
847 BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
848 .addImm(0);
849 else // Must be right shift.
850 BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
851 .addReg(Op1.getReg(), RS, HiSR)
852 .addImm(31);
853 } else if (S < 64) {
854 S -= 32;
855 if (S == 16 && Left)
856 BuildMI(B, MI, DL, TII->get(A2_aslh), HiR)
857 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
858 else if (S == 16 && Signed)
859 BuildMI(B, MI, DL, TII->get(A2_asrh), LoR)
860 .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR);
861 else
862 BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? HiR : LoR))
863 .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR))
864 .addImm(S);
865
866 if (Signed)
867 BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
868 .addReg(Op1.getReg(), RS, HiSR)
869 .addImm(31);
870 else
871 BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
872 .addImm(0);
873 }
874}
875
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000876void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI,
877 const UUPairMap &PairMap) {
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000878 using namespace Hexagon;
879
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000880 MachineOperand &Op0 = MI->getOperand(0);
881 MachineOperand &Op1 = MI->getOperand(1);
882 MachineOperand &Op2 = MI->getOperand(2);
883 MachineOperand &Op3 = MI->getOperand(3);
884 assert(Op0.isReg() && Op1.isReg() && Op2.isReg() && Op3.isImm());
885 int64_t Sh64 = Op3.getImm();
886 assert(Sh64 >= 0 && Sh64 < 64);
887 unsigned S = Sh64;
888
889 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
890 assert(F != PairMap.end());
891 const UUPair &P = F->second;
892 unsigned LoR = P.first;
893 unsigned HiR = P.second;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000894
895 MachineBasicBlock &B = *MI->getParent();
896 DebugLoc DL = MI->getDebugLoc();
897 unsigned RS1 = getRegState(Op1);
898 unsigned RS2 = getRegState(Op2);
899 const TargetRegisterClass *IntRC = &IntRegsRegClass;
900
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000901 unsigned LoSR = isub_lo;
902 unsigned HiSR = isub_hi;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000903
904 // Op0 = S2_asl_i_p_or Op1, Op2, Op3
905 // means: Op0 = or (Op1, asl(Op2, Op3))
906
907 // Expansion of
908 // DR = or (R1, asl(R2, #s))
909 //
910 // LoR = or (R1.lo, asl(R2.lo, #s))
911 // Tmp1 = extractu R2.lo, #s, #32-s
912 // Tmp2 = or R1.hi, Tmp1
913 // HiR = or (Tmp2, asl(R2.hi, #s))
914
915 if (S == 0) {
916 // DR = or (R1, asl(R2, #0))
917 // -> or (R1, R2)
918 // i.e. LoR = or R1.lo, R2.lo
919 // HiR = or R1.hi, R2.hi
920 BuildMI(B, MI, DL, TII->get(A2_or), LoR)
921 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
922 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR);
923 BuildMI(B, MI, DL, TII->get(A2_or), HiR)
924 .addReg(Op1.getReg(), RS1, HiSR)
925 .addReg(Op2.getReg(), RS2, HiSR);
926 } else if (S < 32) {
927 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), LoR)
928 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
929 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
930 .addImm(S);
931 unsigned TmpR1 = MRI->createVirtualRegister(IntRC);
932 BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR1)
933 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
934 .addImm(S)
935 .addImm(32-S);
936 unsigned TmpR2 = MRI->createVirtualRegister(IntRC);
937 BuildMI(B, MI, DL, TII->get(A2_or), TmpR2)
938 .addReg(Op1.getReg(), RS1, HiSR)
939 .addReg(TmpR1);
940 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
941 .addReg(TmpR2)
942 .addReg(Op2.getReg(), RS2, HiSR)
943 .addImm(S);
944 } else if (S == 32) {
945 // DR = or (R1, asl(R2, #32))
946 // -> or R1, R2.lo
947 // LoR = R1.lo
948 // HiR = or R1.hi, R2.lo
949 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
950 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
951 BuildMI(B, MI, DL, TII->get(A2_or), HiR)
952 .addReg(Op1.getReg(), RS1, HiSR)
953 .addReg(Op2.getReg(), RS2, LoSR);
954 } else if (S < 64) {
955 // DR = or (R1, asl(R2, #s))
956 //
957 // LoR = R1:lo
958 // HiR = or (R1:hi, asl(R2:lo, #s-32))
959 S -= 32;
960 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
961 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
962 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
963 .addReg(Op1.getReg(), RS1, HiSR)
964 .addReg(Op2.getReg(), RS2, LoSR)
965 .addImm(S);
966 }
967}
968
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000969bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI,
970 const UUPairMap &PairMap) {
Eugene Zelenko58655bb2016-12-17 01:09:05 +0000971 using namespace Hexagon;
972
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000973 DEBUG(dbgs() << "Splitting: " << *MI);
974 bool Split = false;
975 unsigned Opc = MI->getOpcode();
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000976
977 switch (Opc) {
978 case TargetOpcode::PHI:
979 case TargetOpcode::COPY: {
980 unsigned DstR = MI->getOperand(0).getReg();
981 if (MRI->getRegClass(DstR) == DoubleRC) {
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000982 createHalfInstr(Opc, MI, PairMap, isub_lo);
983 createHalfInstr(Opc, MI, PairMap, isub_hi);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000984 Split = true;
985 }
986 break;
987 }
988 case A2_andp:
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000989 createHalfInstr(A2_and, MI, PairMap, isub_lo);
990 createHalfInstr(A2_and, MI, PairMap, isub_hi);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000991 Split = true;
992 break;
993 case A2_orp:
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000994 createHalfInstr(A2_or, MI, PairMap, isub_lo);
995 createHalfInstr(A2_or, MI, PairMap, isub_hi);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +0000996 Split = true;
997 break;
998 case A2_xorp:
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +0000999 createHalfInstr(A2_xor, MI, PairMap, isub_lo);
1000 createHalfInstr(A2_xor, MI, PairMap, isub_hi);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001001 Split = true;
1002 break;
1003
1004 case L2_loadrd_io:
1005 case L2_loadrd_pi:
1006 case S2_storerd_io:
1007 case S2_storerd_pi:
1008 splitMemRef(MI, PairMap);
1009 Split = true;
1010 break;
1011
1012 case A2_tfrpi:
Krzysztof Parzyszeka3386502016-08-10 16:46:36 +00001013 case CONST64:
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001014 splitImmediate(MI, PairMap);
1015 Split = true;
1016 break;
1017
1018 case A2_combineii:
1019 case A4_combineir:
1020 case A4_combineii:
1021 case A4_combineri:
1022 case A2_combinew:
1023 splitCombine(MI, PairMap);
1024 Split = true;
1025 break;
1026
1027 case A2_sxtw:
1028 splitExt(MI, PairMap);
1029 Split = true;
1030 break;
1031
1032 case S2_asl_i_p:
1033 case S2_asr_i_p:
1034 case S2_lsr_i_p:
1035 splitShift(MI, PairMap);
1036 Split = true;
1037 break;
1038
1039 case S2_asl_i_p_or:
1040 splitAslOr(MI, PairMap);
1041 Split = true;
1042 break;
1043
1044 default:
1045 llvm_unreachable("Instruction not splitable");
1046 return false;
1047 }
1048
1049 return Split;
1050}
1051
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001052void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI,
1053 const UUPairMap &PairMap) {
1054 for (auto &Op : MI->operands()) {
1055 if (!Op.isReg() || !Op.isUse() || !Op.getSubReg())
1056 continue;
1057 unsigned R = Op.getReg();
1058 UUPairMap::const_iterator F = PairMap.find(R);
1059 if (F == PairMap.end())
1060 continue;
1061 const UUPair &P = F->second;
1062 switch (Op.getSubReg()) {
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +00001063 case Hexagon::isub_lo:
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001064 Op.setReg(P.first);
1065 break;
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +00001066 case Hexagon::isub_hi:
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001067 Op.setReg(P.second);
1068 break;
1069 }
1070 Op.setSubReg(0);
1071 }
1072}
1073
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001074void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI,
1075 const UUPairMap &PairMap) {
1076 MachineBasicBlock &B = *MI->getParent();
1077 DebugLoc DL = MI->getDebugLoc();
1078
1079 for (auto &Op : MI->operands()) {
1080 if (!Op.isReg() || !Op.isUse())
1081 continue;
1082 unsigned R = Op.getReg();
1083 if (!TargetRegisterInfo::isVirtualRegister(R))
1084 continue;
1085 if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg())
1086 continue;
1087 UUPairMap::const_iterator F = PairMap.find(R);
1088 if (F == PairMap.end())
1089 continue;
1090 const UUPair &Pr = F->second;
1091 unsigned NewDR = MRI->createVirtualRegister(DoubleRC);
1092 BuildMI(B, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), NewDR)
1093 .addReg(Pr.first)
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +00001094 .addImm(Hexagon::isub_lo)
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001095 .addReg(Pr.second)
Krzysztof Parzyszeka5409972016-11-09 16:19:08 +00001096 .addImm(Hexagon::isub_hi);
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001097 Op.setReg(NewDR);
1098 }
1099}
1100
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001101bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) {
Eugene Zelenko4d060b72017-07-29 00:56:56 +00001102 using MISet = std::set<MachineInstr *>;
1103
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001104 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001105 bool Changed = false;
1106
1107 DEBUG(dbgs() << "Splitting partition: "; dump_partition(dbgs(), Part, *TRI);
1108 dbgs() << '\n');
1109
1110 UUPairMap PairMap;
1111
1112 MISet SplitIns;
1113 for (unsigned DR : Part) {
1114 MachineInstr *DefI = MRI->getVRegDef(DR);
1115 SplitIns.insert(DefI);
1116
1117 // Collect all instructions, including fixed ones. We won't split them,
1118 // but we need to visit them again to insert the REG_SEQUENCE instructions.
1119 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
1120 U != W; ++U)
1121 SplitIns.insert(U->getParent());
1122
1123 unsigned LoR = MRI->createVirtualRegister(IntRC);
1124 unsigned HiR = MRI->createVirtualRegister(IntRC);
Francis Visoiu Mistrih9d419d32017-11-28 12:42:37 +00001125 DEBUG(dbgs() << "Created mapping: " << printReg(DR, TRI) << " -> "
1126 << printReg(HiR, TRI) << ':' << printReg(LoR, TRI) << '\n');
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001127 PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));
1128 }
1129
1130 MISet Erase;
1131 for (auto MI : SplitIns) {
1132 if (isFixedInstr(MI)) {
1133 collapseRegPairs(MI, PairMap);
1134 } else {
1135 bool Done = splitInstr(MI, PairMap);
1136 if (Done)
1137 Erase.insert(MI);
1138 Changed |= Done;
1139 }
1140 }
1141
1142 for (unsigned DR : Part) {
1143 // Before erasing "double" instructions, revisit all uses of the double
1144 // registers in this partition, and replace all uses of them with subre-
1145 // gisters, with the corresponding single registers.
1146 MISet Uses;
1147 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
1148 U != W; ++U)
1149 Uses.insert(U->getParent());
1150 for (auto M : Uses)
1151 replaceSubregUses(M, PairMap);
1152 }
1153
1154 for (auto MI : Erase) {
1155 MachineBasicBlock *B = MI->getParent();
1156 B->erase(MI);
1157 }
1158
1159 return Changed;
1160}
1161
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001162bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) {
1163 DEBUG(dbgs() << "Splitting double registers in function: "
1164 << MF.getName() << '\n');
1165
Matthias Braunf1caa282017-12-15 22:22:58 +00001166 if (skipFunction(MF.getFunction()))
Andrew Kaylor5b444a22016-04-26 19:46:28 +00001167 return false;
1168
Krzysztof Parzyszeka7c5f042015-10-16 20:38:54 +00001169 auto &ST = MF.getSubtarget<HexagonSubtarget>();
1170 TRI = ST.getRegisterInfo();
1171 TII = ST.getInstrInfo();
1172 MRI = &MF.getRegInfo();
1173 MLI = &getAnalysis<MachineLoopInfo>();
1174
1175 UUSetMap P2Rs;
1176 LoopRegMap IRM;
1177
1178 collectIndRegs(IRM);
1179 partitionRegisters(P2Rs);
1180
1181 DEBUG({
1182 dbgs() << "Register partitioning: (partition #0 is fixed)\n";
1183 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
1184 dbgs() << '#' << I->first << " -> ";
1185 dump_partition(dbgs(), I->second, *TRI);
1186 dbgs() << '\n';
1187 }
1188 });
1189
1190 bool Changed = false;
1191 int Limit = MaxHSDR;
1192
1193 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
1194 if (I->first == 0)
1195 continue;
1196 if (Limit >= 0 && Counter >= Limit)
1197 break;
1198 USet &Part = I->second;
1199 DEBUG(dbgs() << "Calculating profit for partition #" << I->first << '\n');
1200 if (!isProfitable(Part, IRM))
1201 continue;
1202 Counter++;
1203 Changed |= splitPartition(Part);
1204 }
1205
1206 return Changed;
1207}
1208
1209FunctionPass *llvm::createHexagonSplitDoubleRegs() {
1210 return new HexagonSplitDoubleRegs();
1211}