LLVM 24.0.0git
HexagonSplitDouble.cpp
Go to the documentation of this file.
1//===- HexagonSplitDouble.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Hexagon.h"
10#include "HexagonInstrInfo.h"
11#include "HexagonRegisterInfo.h"
12#include "HexagonSubtarget.h"
13#include "llvm/ADT/BitVector.h"
14#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringRef.h"
27#include "llvm/Config/llvm-config.h"
28#include "llvm/IR/DebugLoc.h"
29#include "llvm/Pass.h"
32#include "llvm/Support/Debug.h"
35#include <algorithm>
36#include <cassert>
37#include <cstdint>
38#include <limits>
39#include <map>
40#include <set>
41#include <utility>
42#include <vector>
43
44#define DEBUG_TYPE "hsdr"
45
46using namespace llvm;
47
48static cl::opt<int> MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1),
49 cl::desc("Maximum number of split partitions"));
50static cl::opt<bool> MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true),
51 cl::desc("Do not split loads or stores"));
52 static cl::opt<bool> SplitAll("hsdr-split-all", cl::Hidden, cl::init(false),
53 cl::desc("Split all partitions"));
54
55namespace {
56
57 class HexagonSplitDoubleRegs : public MachineFunctionPass {
58 public:
59 static char ID;
60
61 HexagonSplitDoubleRegs() : MachineFunctionPass(ID) {}
62
63 StringRef getPassName() const override {
64 return "Hexagon Split Double Registers";
65 }
66
67 void getAnalysisUsage(AnalysisUsage &AU) const override {
68 AU.addRequired<MachineLoopInfoWrapperPass>();
69 AU.addPreserved<MachineLoopInfoWrapperPass>();
71 }
72
73 bool runOnMachineFunction(MachineFunction &MF) override;
74
75 private:
76 static const TargetRegisterClass *const DoubleRC;
77
78 const HexagonRegisterInfo *TRI = nullptr;
79 const HexagonInstrInfo *TII = nullptr;
80 const MachineLoopInfo *MLI;
81 MachineRegisterInfo *MRI;
82
83 using USet = std::set<unsigned>;
84 using UUSetMap = std::map<unsigned, USet>;
85 using UUPair = std::pair<unsigned, unsigned>;
86 using UUPairMap = std::map<unsigned, UUPair>;
87 using LoopRegMap = std::map<const MachineLoop *, USet>;
88
89 bool isInduction(unsigned Reg, LoopRegMap &IRM) const;
90 bool isVolatileInstr(const MachineInstr *MI) const;
91 bool isFixedInstr(const MachineInstr *MI) const;
92 void partitionRegisters(UUSetMap &P2Rs);
93 int32_t profit(const MachineInstr *MI) const;
94 int32_t profit(Register Reg) const;
95 bool isProfitable(const USet &Part, LoopRegMap &IRM) const;
96
97 void collectIndRegsForLoop(const MachineLoop *L, USet &Rs);
98 void collectIndRegs(LoopRegMap &IRM);
99
100 void createHalfInstr(unsigned Opc, MachineInstr *MI,
101 const UUPairMap &PairMap, unsigned SubR);
102 void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap);
103 void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap);
104 void splitCombine(MachineInstr *MI, const UUPairMap &PairMap);
105 void splitExt(MachineInstr *MI, const UUPairMap &PairMap);
106 void splitShift(MachineInstr *MI, const UUPairMap &PairMap);
107 void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap);
108 bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap);
109 void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap);
110 void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap);
111 bool splitPartition(const USet &Part);
112
113 static int Counter;
114
115 static void dump_partition(raw_ostream&, const USet&,
116 const TargetRegisterInfo&);
117 };
118
119} // end anonymous namespace
120
121char HexagonSplitDoubleRegs::ID;
122int HexagonSplitDoubleRegs::Counter = 0;
123const TargetRegisterClass *const HexagonSplitDoubleRegs::DoubleRC =
124 &Hexagon::DoubleRegsRegClass;
125
126INITIALIZE_PASS(HexagonSplitDoubleRegs, "hexagon-split-double",
127 "Hexagon Split Double Registers", false, false)
128
129#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
130LLVM_DUMP_METHOD void HexagonSplitDoubleRegs::dump_partition(raw_ostream &os,
131 const USet &Part, const TargetRegisterInfo &TRI) {
132 dbgs() << '{';
133 for (auto I : Part)
134 dbgs() << ' ' << printReg(I, &TRI);
135 dbgs() << " }";
136}
137#endif
138
139bool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const {
140 for (auto I : IRM) {
141 const USet &Rs = I.second;
142 if (Rs.find(Reg) != Rs.end())
143 return true;
144 }
145 return false;
146}
147
148bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const {
149 for (auto &MO : MI->memoperands())
150 if (MO->isVolatile() || MO->isAtomic())
151 return true;
152 return false;
153}
154
155bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const {
156 if (MI->mayLoadOrStore())
157 if (MemRefsFixed || isVolatileInstr(MI))
158 return true;
159 if (MI->isDebugInstr())
160 return false;
161
162 unsigned Opc = MI->getOpcode();
163 switch (Opc) {
164 default:
165 return true;
166
167 case TargetOpcode::PHI:
168 case TargetOpcode::COPY:
169 break;
170
171 case Hexagon::L2_loadrd_io:
172 // Not handling stack stores (only reg-based addresses).
173 if (MI->getOperand(1).isReg())
174 break;
175 return true;
176 case Hexagon::S2_storerd_io:
177 // Not handling stack stores (only reg-based addresses).
178 if (MI->getOperand(0).isReg())
179 break;
180 return true;
181 case Hexagon::L2_loadrd_pi:
182 case Hexagon::S2_storerd_pi:
183
184 case Hexagon::A2_tfrpi:
185 case Hexagon::A2_combineii:
186 case Hexagon::A4_combineir:
187 case Hexagon::A4_combineii:
188 case Hexagon::A4_combineri:
189 case Hexagon::A2_combinew:
190 case Hexagon::CONST64:
191
192 case Hexagon::A2_sxtw:
193
194 case Hexagon::A2_andp:
195 case Hexagon::A2_orp:
196 case Hexagon::A2_xorp:
197 case Hexagon::S2_asl_i_p_or:
198 case Hexagon::S2_asl_i_p:
199 case Hexagon::S2_asr_i_p:
200 case Hexagon::S2_lsr_i_p:
201 break;
202 }
203
204 for (auto &Op : MI->operands()) {
205 if (!Op.isReg())
206 continue;
207 Register R = Op.getReg();
208 if (!R.isVirtual())
209 return true;
210 }
211 return false;
212}
213
214void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {
215 using UUMap = std::map<unsigned, unsigned>;
216 using UVect = std::vector<unsigned>;
217
218 unsigned NumRegs = MRI->getNumVirtRegs();
219 BitVector DoubleRegs(NumRegs);
220 for (unsigned i = 0; i < NumRegs; ++i) {
221 Register R = Register::index2VirtReg(i);
222 if (MRI->getRegClass(R) == DoubleRC)
223 DoubleRegs.set(i);
224 }
225
226 BitVector FixedRegs(NumRegs);
227 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
228 Register R = Register::index2VirtReg(x);
229 MachineInstr *DefI = MRI->getVRegDef(R);
230 // In some cases a register may exist, but never be defined or used.
231 // It should never appear anywhere, but mark it as "fixed", just to be
232 // safe.
233 if (!DefI || isFixedInstr(DefI))
234 FixedRegs.set(x);
235 }
236
237 UUSetMap AssocMap;
238 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
239 if (FixedRegs[x])
240 continue;
241 Register R = Register::index2VirtReg(x);
242 LLVM_DEBUG(dbgs() << printReg(R, TRI) << " ~~");
243 USet &Asc = AssocMap[R];
244 for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end();
245 U != Z; ++U) {
246 MachineOperand &Op = *U;
247 MachineInstr *UseI = Op.getParent();
248 if (isFixedInstr(UseI))
249 continue;
250 for (MachineOperand &MO : UseI->operands()) {
251 // Skip non-registers or registers with subregisters.
252 if (&MO == &Op || !MO.isReg() || MO.getSubReg())
253 continue;
254 Register T = MO.getReg();
255 if (!T.isVirtual()) {
256 FixedRegs.set(x);
257 continue;
258 }
259 if (MRI->getRegClass(T) != DoubleRC)
260 continue;
261 unsigned u = T.virtRegIndex();
262 if (FixedRegs[u])
263 continue;
264 LLVM_DEBUG(dbgs() << ' ' << printReg(T, TRI));
265 Asc.insert(T);
266 // Make it symmetric.
267 AssocMap[T].insert(R);
268 }
269 }
270 LLVM_DEBUG(dbgs() << '\n');
271 }
272
273 UUMap R2P;
274 unsigned NextP = 1;
275 USet Visited;
276 for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
277 Register R = Register::index2VirtReg(x);
278 if (Visited.count(R))
279 continue;
280 // Create a new partition for R.
281 unsigned ThisP = FixedRegs[x] ? 0 : NextP++;
282 UVect WorkQ;
283 WorkQ.push_back(R);
284 for (unsigned i = 0; i < WorkQ.size(); ++i) {
285 unsigned T = WorkQ[i];
286 if (Visited.count(T))
287 continue;
288 R2P[T] = ThisP;
289 Visited.insert(T);
290 // Add all registers associated with T.
291 USet &Asc = AssocMap[T];
292 append_range(WorkQ, Asc);
293 }
294 }
295
296 for (auto I : R2P)
297 P2Rs[I.second].insert(I.first);
298}
299
300static inline int32_t profitImm(unsigned Imm) {
301 int32_t P = 0;
302 if (Imm == 0 || Imm == 0xFFFFFFFF)
303 P += 10;
304 return P;
305}
306
307int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const {
308 unsigned ImmX = 0;
309 unsigned Opc = MI->getOpcode();
310 switch (Opc) {
311 case TargetOpcode::PHI:
312 for (const auto &Op : MI->operands())
313 if (!Op.getSubReg())
314 return 0;
315 return 10;
316 case TargetOpcode::COPY:
317 if (MI->getOperand(1).getSubReg() != 0)
318 return 10;
319 return 0;
320
321 case Hexagon::L2_loadrd_io:
322 case Hexagon::S2_storerd_io:
323 return -1;
324 case Hexagon::L2_loadrd_pi:
325 case Hexagon::S2_storerd_pi:
326 return 2;
327
328 case Hexagon::A2_tfrpi:
329 case Hexagon::CONST64: {
330 uint64_t D = MI->getOperand(1).getImm();
331 unsigned Lo = D & 0xFFFFFFFFULL;
332 unsigned Hi = D >> 32;
333 return profitImm(Lo) + profitImm(Hi);
334 }
335 case Hexagon::A2_combineii:
336 case Hexagon::A4_combineii: {
337 const MachineOperand &Op1 = MI->getOperand(1);
338 const MachineOperand &Op2 = MI->getOperand(2);
339 int32_t Prof1 = Op1.isImm() ? profitImm(Op1.getImm()) : 0;
340 int32_t Prof2 = Op2.isImm() ? profitImm(Op2.getImm()) : 0;
341 return Prof1 + Prof2;
342 }
343 case Hexagon::A4_combineri:
344 ImmX++;
345 // Fall through into A4_combineir.
346 [[fallthrough]];
347 case Hexagon::A4_combineir: {
348 ImmX++;
349 const MachineOperand &OpX = MI->getOperand(ImmX);
350 if (OpX.isImm()) {
351 int64_t V = OpX.getImm();
352 if (V == 0 || V == -1)
353 return 10;
354 }
355 // Fall through into A2_combinew.
356 [[fallthrough]];
357 }
358 case Hexagon::A2_combinew:
359 return 2;
360
361 case Hexagon::A2_sxtw:
362 return 3;
363
364 case Hexagon::A2_andp:
365 case Hexagon::A2_orp:
366 case Hexagon::A2_xorp: {
367 Register Rs = MI->getOperand(1).getReg();
368 Register Rt = MI->getOperand(2).getReg();
369 return profit(Rs) + profit(Rt);
370 }
371
372 case Hexagon::S2_asl_i_p_or: {
373 unsigned S = MI->getOperand(3).getImm();
374 if (S == 0 || S == 32)
375 return 10;
376 return -1;
377 }
378 case Hexagon::S2_asl_i_p:
379 case Hexagon::S2_asr_i_p:
380 case Hexagon::S2_lsr_i_p:
381 unsigned S = MI->getOperand(2).getImm();
382 if (S == 0 || S == 32)
383 return 10;
384 if (S == 16)
385 return 5;
386 if (S == 48)
387 return 7;
388 return -10;
389 }
390
391 return 0;
392}
393
394int32_t HexagonSplitDoubleRegs::profit(Register Reg) const {
396
397 const MachineInstr *DefI = MRI->getVRegDef(Reg);
398 switch (DefI->getOpcode()) {
399 case Hexagon::A2_tfrpi:
400 case Hexagon::CONST64:
401 case Hexagon::A2_combineii:
402 case Hexagon::A4_combineii:
403 case Hexagon::A4_combineri:
404 case Hexagon::A4_combineir:
405 case Hexagon::A2_combinew:
406 return profit(DefI);
407 default:
408 break;
409 }
410 return 0;
411}
412
413bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM)
414 const {
415 unsigned FixedNum = 0, LoopPhiNum = 0;
416 int32_t TotalP = 0;
417
418 for (unsigned DR : Part) {
419 MachineInstr *DefI = MRI->getVRegDef(DR);
420 int32_t P = profit(DefI);
421 if (P == std::numeric_limits<int>::min())
422 return false;
423 TotalP += P;
424 // Reduce the profitability of splitting induction registers.
425 if (isInduction(DR, IRM))
426 TotalP -= 30;
427
428 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
429 U != W; ++U) {
430 MachineInstr *UseI = U->getParent();
431 if (isFixedInstr(UseI)) {
432 FixedNum++;
433 // Calculate the cost of generating REG_SEQUENCE instructions.
434 for (auto &Op : UseI->operands()) {
435 if (Op.isReg() && Part.count(Op.getReg()))
436 if (Op.getSubReg())
437 TotalP -= 2;
438 }
439 continue;
440 }
441 // If a register from this partition is used in a fixed instruction,
442 // and there is also a register in this partition that is used in
443 // a loop phi node, then decrease the splitting profit as this can
444 // confuse the modulo scheduler.
445 if (UseI->isPHI()) {
446 const MachineBasicBlock *PB = UseI->getParent();
447 const MachineLoop *L = MLI->getLoopFor(PB);
448 if (L && L->getHeader() == PB)
449 LoopPhiNum++;
450 }
451 // Splittable instruction.
452 int32_t P = profit(UseI);
453 if (P == std::numeric_limits<int>::min())
454 return false;
455 TotalP += P;
456 }
457 }
458
459 if (FixedNum > 0 && LoopPhiNum > 0)
460 TotalP -= 20*LoopPhiNum;
461
462 LLVM_DEBUG(dbgs() << "Partition profit: " << TotalP << '\n');
463 if (SplitAll)
464 return true;
465 return TotalP > 0;
466}
467
468void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L,
469 USet &Rs) {
470 const MachineBasicBlock *HB = L->getHeader();
471 const MachineBasicBlock *LB = L->getLoopLatch();
472 if (!HB || !LB)
473 return;
474
475 // Examine the latch branch. Expect it to be a conditional branch to
476 // the header (either "br-cond header" or "br-cond exit; br header").
477 const MachineBasicBlock *TB = nullptr, *FB = nullptr;
479 bool BadLB = TII->analyzeBranch(*LB, TB, FB, Cond);
480 // Only analyzable conditional branches. HII::analyzeBranch will put
481 // the branch opcode as the first element of Cond, and the predicate
482 // operand as the second.
483 if (BadLB || Cond.size() != 2)
484 return;
485 // Only simple jump-conditional (with or without negation).
486 if (!TII->PredOpcodeHasJMP_c(Cond[0].getImm()))
487 return;
488 // Must go to the header.
489 if (TB != HB && FB != HB)
490 return;
491 assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch");
492 // Expect a predicate register.
493 Register PR = Cond[1].getReg();
494 assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);
495
496 // Get the registers on which the loop controlling compare instruction
497 // depends.
498 Register CmpR1, CmpR2;
499 const MachineInstr *CmpI = MRI->getVRegDef(PR);
500 while (CmpI->getOpcode() == Hexagon::C2_not)
501 CmpI = MRI->getVRegDef(CmpI->getOperand(1).getReg());
502
503 int64_t Mask = 0, Val = 0;
504 bool OkCI = TII->analyzeCompare(*CmpI, CmpR1, CmpR2, Mask, Val);
505 if (!OkCI)
506 return;
507 // Eliminate non-double input registers.
508 if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC)
509 CmpR1 = 0;
510 if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC)
511 CmpR2 = 0;
512 if (!CmpR1 && !CmpR2)
513 return;
514
515 // Now examine the top of the loop: the phi nodes that could poten-
516 // tially define loop induction registers. The registers defined by
517 // such a phi node would be used in a 64-bit add, which then would
518 // be used in the loop compare instruction.
519
520 // Get the set of all double registers defined by phi nodes in the
521 // loop header.
522 using UVect = std::vector<unsigned>;
523
524 UVect DP;
525 for (auto &MI : *HB) {
526 if (!MI.isPHI())
527 break;
528 const MachineOperand &MD = MI.getOperand(0);
529 Register R = MD.getReg();
530 if (MRI->getRegClass(R) == DoubleRC)
531 DP.push_back(R);
532 }
533 if (DP.empty())
534 return;
535
536 auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool {
537 for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end();
538 I != E; ++I) {
539 const MachineInstr *UseI = I->getParent();
540 if (UseI->getOpcode() != Hexagon::A2_addp)
541 continue;
542 // Get the output from the add. If it is one of the inputs to the
543 // loop-controlling compare instruction, then R is likely an induc-
544 // tion register.
545 Register T = UseI->getOperand(0).getReg();
546 if (T == CmpR1 || T == CmpR2)
547 return false;
548 }
549 return true;
550 };
551 UVect::iterator End = llvm::remove_if(DP, NoIndOp);
552 Rs.insert(DP.begin(), End);
553 Rs.insert(CmpR1);
554 Rs.insert(CmpR2);
555
556 LLVM_DEBUG({
557 dbgs() << "For loop at " << printMBBReference(*HB) << " ind regs: ";
558 dump_partition(dbgs(), Rs, *TRI);
559 dbgs() << '\n';
560 });
561}
562
563void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {
564 using LoopVector = std::vector<MachineLoop *>;
565
566 LoopVector WorkQ;
567
568 append_range(WorkQ, *MLI);
569 for (unsigned i = 0; i < WorkQ.size(); ++i)
570 append_range(WorkQ, *WorkQ[i]);
571
572 USet Rs;
573 for (MachineLoop *L : WorkQ) {
574 Rs.clear();
575 collectIndRegsForLoop(L, Rs);
576 if (!Rs.empty())
577 IRM.insert(std::make_pair(L, Rs));
578 }
579}
580
581void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI,
582 const UUPairMap &PairMap, unsigned SubR) {
583 MachineBasicBlock &B = *MI->getParent();
584 DebugLoc DL = MI->getDebugLoc();
585 MachineInstr *NewI = BuildMI(B, MI, DL, TII->get(Opc));
586
587 for (auto &Op : MI->operands()) {
588 if (!Op.isReg()) {
589 NewI->addOperand(Op);
590 continue;
591 }
592 // For register operands, set the subregister.
593 Register R = Op.getReg();
594 unsigned SR = Op.getSubReg();
595 bool isVirtReg = R.isVirtual();
596 bool isKill = Op.isKill();
597 if (isVirtReg && MRI->getRegClass(R) == DoubleRC) {
598 isKill = false;
599 UUPairMap::const_iterator F = PairMap.find(R);
600 if (F == PairMap.end()) {
601 SR = SubR;
602 } else {
603 const UUPair &P = F->second;
604 R = (SubR == Hexagon::isub_lo) ? P.first : P.second;
605 SR = 0;
606 }
607 }
608 auto CO = MachineOperand::CreateReg(R, Op.isDef(), Op.isImplicit(), isKill,
609 Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(),
610 Op.isInternalRead());
611 NewI->addOperand(CO);
612 }
613}
614
615void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI,
616 const UUPairMap &PairMap) {
617 bool Load = MI->mayLoad();
618 unsigned OrigOpc = MI->getOpcode();
619 bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||
620 OrigOpc == Hexagon::S2_storerd_pi);
621 MachineInstr *LowI, *HighI;
622 MachineBasicBlock &B = *MI->getParent();
623 DebugLoc DL = MI->getDebugLoc();
624
625 // Index of the base-address-register operand.
626 unsigned AdrX = PostInc ? (Load ? 2 : 1)
627 : (Load ? 1 : 0);
628 MachineOperand &AdrOp = MI->getOperand(AdrX);
629 RegState RSA = getRegState(AdrOp);
630 MachineOperand &ValOp = Load ? MI->getOperand(0)
631 : (PostInc ? MI->getOperand(3)
632 : MI->getOperand(2));
633 UUPairMap::const_iterator F = PairMap.find(ValOp.getReg());
634 assert(F != PairMap.end());
635
636 if (Load) {
637 const UUPair &P = F->second;
638 int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm();
639 LowI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.first)
640 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
641 .addImm(Off);
642 HighI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.second)
643 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
644 .addImm(Off+4);
645 } else {
646 const UUPair &P = F->second;
647 int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm();
648 LowI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
649 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
650 .addImm(Off)
651 .addReg(P.first);
652 HighI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
653 .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
654 .addImm(Off+4)
655 .addReg(P.second);
656 }
657
658 if (PostInc) {
659 // Create the increment of the address register.
660 int64_t Inc = Load ? MI->getOperand(3).getImm()
661 : MI->getOperand(2).getImm();
662 MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0);
663 const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg());
664 Register NewR = MRI->createVirtualRegister(RC);
665 assert(!UpdOp.getSubReg() && "Def operand with subreg");
666 BuildMI(B, MI, DL, TII->get(Hexagon::A2_addi), NewR)
667 .addReg(AdrOp.getReg(), RSA)
668 .addImm(Inc);
669 MRI->replaceRegWith(UpdOp.getReg(), NewR);
670 // The original instruction will be deleted later.
671 }
672
673 // Generate a new pair of memory-operands.
674 MachineFunction &MF = *B.getParent();
675 for (auto &MO : MI->memoperands()) {
676 const MachinePointerInfo &Ptr = MO->getPointerInfo();
677 MachineMemOperand::Flags F = MO->getFlags();
678 Align A = MO->getAlign();
679
680 auto *Tmp1 = MF.getMachineMemOperand(Ptr, F, 4 /*size*/, A);
681 LowI->addMemOperand(MF, Tmp1);
682 auto *Tmp2 =
683 MF.getMachineMemOperand(Ptr, F, 4 /*size*/, std::min(A, Align(4)));
684 HighI->addMemOperand(MF, Tmp2);
685 }
686}
687
688void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI,
689 const UUPairMap &PairMap) {
690 MachineOperand &Op0 = MI->getOperand(0);
691 MachineOperand &Op1 = MI->getOperand(1);
692 assert(Op0.isReg() && Op1.isImm());
693 uint64_t V = Op1.getImm();
694
695 MachineBasicBlock &B = *MI->getParent();
696 DebugLoc DL = MI->getDebugLoc();
697 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
698 assert(F != PairMap.end());
699 const UUPair &P = F->second;
700
701 // The operand to A2_tfrsi can only have 32 significant bits. Immediate
702 // values in MachineOperand are stored as 64-bit integers, and so the
703 // value -1 may be represented either as 64-bit -1, or 4294967295. Both
704 // will have the 32 higher bits truncated in the end, but -1 will remain
705 // as -1, while the latter may appear to be a large unsigned value
706 // requiring a constant extender. The casting to int32_t will select the
707 // former representation. (The same reasoning applies to all 32-bit
708 // values.)
709 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
710 .addImm(int32_t(V & 0xFFFFFFFFULL));
711 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
712 .addImm(int32_t(V >> 32));
713}
714
715void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI,
716 const UUPairMap &PairMap) {
717 MachineOperand &Op0 = MI->getOperand(0);
718 MachineOperand &Op1 = MI->getOperand(1);
719 MachineOperand &Op2 = MI->getOperand(2);
720 assert(Op0.isReg());
721
722 MachineBasicBlock &B = *MI->getParent();
723 DebugLoc DL = MI->getDebugLoc();
724 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
725 assert(F != PairMap.end());
726 const UUPair &P = F->second;
727
728 if (!Op1.isReg()) {
729 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
730 .add(Op1);
731 } else {
732 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.second)
733 .addReg(Op1.getReg(), getRegState(Op1), Op1.getSubReg());
734 }
735
736 if (!Op2.isReg()) {
737 BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
738 .add(Op2);
739 } else {
740 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
741 .addReg(Op2.getReg(), getRegState(Op2), Op2.getSubReg());
742 }
743}
744
745void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI,
746 const UUPairMap &PairMap) {
747 MachineOperand &Op0 = MI->getOperand(0);
748 MachineOperand &Op1 = MI->getOperand(1);
749 assert(Op0.isReg() && Op1.isReg());
750
751 MachineBasicBlock &B = *MI->getParent();
752 DebugLoc DL = MI->getDebugLoc();
753 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
754 assert(F != PairMap.end());
755 const UUPair &P = F->second;
756 RegState RS = getRegState(Op1);
757
758 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
759 .addReg(Op1.getReg(), RS & ~RegState::Kill, Op1.getSubReg());
760 BuildMI(B, MI, DL, TII->get(Hexagon::S2_asr_i_r), P.second)
761 .addReg(Op1.getReg(), RS, Op1.getSubReg())
762 .addImm(31);
763}
764
765void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI,
766 const UUPairMap &PairMap) {
767 using namespace Hexagon;
768
769 MachineOperand &Op0 = MI->getOperand(0);
770 MachineOperand &Op1 = MI->getOperand(1);
771 MachineOperand &Op2 = MI->getOperand(2);
772 assert(Op0.isReg() && Op1.isReg() && Op2.isImm());
773 int64_t Sh64 = Op2.getImm();
774 assert(Sh64 >= 0 && Sh64 < 64);
775 unsigned S = Sh64;
776
777 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
778 assert(F != PairMap.end());
779 const UUPair &P = F->second;
780 Register LoR = P.first;
781 Register HiR = P.second;
782
783 unsigned Opc = MI->getOpcode();
784 bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);
785 bool Left = !Right;
786 bool Signed = (Opc == S2_asr_i_p);
787
788 MachineBasicBlock &B = *MI->getParent();
789 DebugLoc DL = MI->getDebugLoc();
790 RegState RS = getRegState(Op1);
791 unsigned ShiftOpc = Left ? S2_asl_i_r
792 : (Signed ? S2_asr_i_r : S2_lsr_i_r);
793 unsigned LoSR = isub_lo;
794 unsigned HiSR = isub_hi;
795
796 if (S == 0) {
797 // No shift, subregister copy.
798 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
799 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
800 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), HiR)
801 .addReg(Op1.getReg(), RS, HiSR);
802 } else if (S < 32) {
803 const TargetRegisterClass *IntRC = &IntRegsRegClass;
804 Register TmpR = MRI->createVirtualRegister(IntRC);
805 // Expansion:
806 // Shift left: DR = shl R, #s
807 // LoR = shl R.lo, #s
808 // TmpR = extractu R.lo, #s, #32-s
809 // HiR = or (TmpR, asl(R.hi, #s))
810 // Shift right: DR = shr R, #s
811 // HiR = shr R.hi, #s
812 // TmpR = shr R.lo, #s
813 // LoR = insert TmpR, R.hi, #s, #32-s
814
815 // Shift left:
816 // LoR = shl R.lo, #s
817 // Shift right:
818 // TmpR = shr R.lo, #s
819
820 // Make a special case for A2_aslh and A2_asrh (they are predicable as
821 // opposed to S2_asl_i_r/S2_asr_i_r).
822 if (S == 16 && Left)
823 BuildMI(B, MI, DL, TII->get(A2_aslh), LoR)
824 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
825 else if (S == 16 && Signed)
826 BuildMI(B, MI, DL, TII->get(A2_asrh), TmpR)
827 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
828 else
829 BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? LoR : TmpR))
830 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
831 .addImm(S);
832
833 if (Left) {
834 // TmpR = extractu R.lo, #s, #32-s
835 BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR)
836 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
837 .addImm(S)
838 .addImm(32-S);
839 // HiR = or (TmpR, asl(R.hi, #s))
840 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
841 .addReg(TmpR)
842 .addReg(Op1.getReg(), RS, HiSR)
843 .addImm(S);
844 } else {
845 // HiR = shr R.hi, #s
846 BuildMI(B, MI, DL, TII->get(ShiftOpc), HiR)
847 .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR)
848 .addImm(S);
849 // LoR = insert TmpR, R.hi, #s, #32-s
850 BuildMI(B, MI, DL, TII->get(S2_insert), LoR)
851 .addReg(TmpR)
852 .addReg(Op1.getReg(), RS, HiSR)
853 .addImm(S)
854 .addImm(32-S);
855 }
856 } else if (S == 32) {
857 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), (Left ? HiR : LoR))
858 .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR));
859 if (!Signed)
860 BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
861 .addImm(0);
862 else // Must be right shift.
863 BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
864 .addReg(Op1.getReg(), RS, HiSR)
865 .addImm(31);
866 } else if (S < 64) {
867 S -= 32;
868 if (S == 16 && Left)
869 BuildMI(B, MI, DL, TII->get(A2_aslh), HiR)
870 .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
871 else if (S == 16 && Signed)
872 BuildMI(B, MI, DL, TII->get(A2_asrh), LoR)
873 .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR);
874 else
875 BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? HiR : LoR))
876 .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR))
877 .addImm(S);
878
879 if (Signed)
880 BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
881 .addReg(Op1.getReg(), RS, HiSR)
882 .addImm(31);
883 else
884 BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
885 .addImm(0);
886 }
887}
888
889void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI,
890 const UUPairMap &PairMap) {
891 using namespace Hexagon;
892
893 MachineOperand &Op0 = MI->getOperand(0);
894 MachineOperand &Op1 = MI->getOperand(1);
895 MachineOperand &Op2 = MI->getOperand(2);
896 MachineOperand &Op3 = MI->getOperand(3);
897 assert(Op0.isReg() && Op1.isReg() && Op2.isReg() && Op3.isImm());
898 int64_t Sh64 = Op3.getImm();
899 assert(Sh64 >= 0 && Sh64 < 64);
900 unsigned S = Sh64;
901
902 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
903 assert(F != PairMap.end());
904 const UUPair &P = F->second;
905 unsigned LoR = P.first;
906 unsigned HiR = P.second;
907
908 MachineBasicBlock &B = *MI->getParent();
909 DebugLoc DL = MI->getDebugLoc();
910 RegState RS1 = getRegState(Op1);
911 RegState RS2 = getRegState(Op2);
912 const TargetRegisterClass *IntRC = &IntRegsRegClass;
913
914 unsigned LoSR = isub_lo;
915 unsigned HiSR = isub_hi;
916
917 // Op0 = S2_asl_i_p_or Op1, Op2, Op3
918 // means: Op0 = or (Op1, asl(Op2, Op3))
919
920 // Expansion of
921 // DR = or (R1, asl(R2, #s))
922 //
923 // LoR = or (R1.lo, asl(R2.lo, #s))
924 // Tmp1 = extractu R2.lo, #s, #32-s
925 // Tmp2 = or R1.hi, Tmp1
926 // HiR = or (Tmp2, asl(R2.hi, #s))
927
928 if (S == 0) {
929 // DR = or (R1, asl(R2, #0))
930 // -> or (R1, R2)
931 // i.e. LoR = or R1.lo, R2.lo
932 // HiR = or R1.hi, R2.hi
933 BuildMI(B, MI, DL, TII->get(A2_or), LoR)
934 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
935 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR);
936 BuildMI(B, MI, DL, TII->get(A2_or), HiR)
937 .addReg(Op1.getReg(), RS1, HiSR)
938 .addReg(Op2.getReg(), RS2, HiSR);
939 } else if (S < 32) {
940 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), LoR)
941 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
942 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
943 .addImm(S);
944 Register TmpR1 = MRI->createVirtualRegister(IntRC);
945 BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR1)
946 .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
947 .addImm(S)
948 .addImm(32-S);
949 Register TmpR2 = MRI->createVirtualRegister(IntRC);
950 BuildMI(B, MI, DL, TII->get(A2_or), TmpR2)
951 .addReg(Op1.getReg(), RS1, HiSR)
952 .addReg(TmpR1);
953 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
954 .addReg(TmpR2)
955 .addReg(Op2.getReg(), RS2, HiSR)
956 .addImm(S);
957 } else if (S == 32) {
958 // DR = or (R1, asl(R2, #32))
959 // -> or R1, R2.lo
960 // LoR = R1.lo
961 // HiR = or R1.hi, R2.lo
962 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
963 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
964 BuildMI(B, MI, DL, TII->get(A2_or), HiR)
965 .addReg(Op1.getReg(), RS1, HiSR)
966 .addReg(Op2.getReg(), RS2, LoSR);
967 } else if (S < 64) {
968 // DR = or (R1, asl(R2, #s))
969 //
970 // LoR = R1:lo
971 // HiR = or (R1:hi, asl(R2:lo, #s-32))
972 S -= 32;
973 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
974 .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
975 BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
976 .addReg(Op1.getReg(), RS1, HiSR)
977 .addReg(Op2.getReg(), RS2, LoSR)
978 .addImm(S);
979 }
980}
981
982bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI,
983 const UUPairMap &PairMap) {
984 using namespace Hexagon;
985
986 LLVM_DEBUG(dbgs() << "Splitting: " << *MI);
987 bool Split = false;
988 unsigned Opc = MI->getOpcode();
989
990 switch (Opc) {
991 case TargetOpcode::PHI:
992 case TargetOpcode::COPY: {
993 Register DstR = MI->getOperand(0).getReg();
994 if (MRI->getRegClass(DstR) == DoubleRC) {
995 createHalfInstr(Opc, MI, PairMap, isub_lo);
996 createHalfInstr(Opc, MI, PairMap, isub_hi);
997 Split = true;
998 }
999 break;
1000 }
1001 case A2_andp:
1002 createHalfInstr(A2_and, MI, PairMap, isub_lo);
1003 createHalfInstr(A2_and, MI, PairMap, isub_hi);
1004 Split = true;
1005 break;
1006 case A2_orp:
1007 createHalfInstr(A2_or, MI, PairMap, isub_lo);
1008 createHalfInstr(A2_or, MI, PairMap, isub_hi);
1009 Split = true;
1010 break;
1011 case A2_xorp:
1012 createHalfInstr(A2_xor, MI, PairMap, isub_lo);
1013 createHalfInstr(A2_xor, MI, PairMap, isub_hi);
1014 Split = true;
1015 break;
1016
1017 case L2_loadrd_io:
1018 case L2_loadrd_pi:
1019 case S2_storerd_io:
1020 case S2_storerd_pi:
1021 splitMemRef(MI, PairMap);
1022 Split = true;
1023 break;
1024
1025 case A2_tfrpi:
1026 case CONST64:
1027 splitImmediate(MI, PairMap);
1028 Split = true;
1029 break;
1030
1031 case A2_combineii:
1032 case A4_combineir:
1033 case A4_combineii:
1034 case A4_combineri:
1035 case A2_combinew:
1036 splitCombine(MI, PairMap);
1037 Split = true;
1038 break;
1039
1040 case A2_sxtw:
1041 splitExt(MI, PairMap);
1042 Split = true;
1043 break;
1044
1045 case S2_asl_i_p:
1046 case S2_asr_i_p:
1047 case S2_lsr_i_p:
1048 splitShift(MI, PairMap);
1049 Split = true;
1050 break;
1051
1052 case S2_asl_i_p_or:
1053 splitAslOr(MI, PairMap);
1054 Split = true;
1055 break;
1056
1057 default:
1058 llvm_unreachable("Instruction not splitable");
1059 return false;
1060 }
1061
1062 return Split;
1063}
1064
1065void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI,
1066 const UUPairMap &PairMap) {
1067 for (auto &Op : MI->operands()) {
1068 if (!Op.isReg() || !Op.isUse() || !Op.getSubReg())
1069 continue;
1070 Register R = Op.getReg();
1071 UUPairMap::const_iterator F = PairMap.find(R);
1072 if (F == PairMap.end())
1073 continue;
1074 const UUPair &P = F->second;
1075 switch (Op.getSubReg()) {
1076 case Hexagon::isub_lo:
1077 Op.setReg(P.first);
1078 break;
1079 case Hexagon::isub_hi:
1080 Op.setReg(P.second);
1081 break;
1082 }
1083 Op.setSubReg(0);
1084 }
1085}
1086
1087void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI,
1088 const UUPairMap &PairMap) {
1089 MachineBasicBlock &B = *MI->getParent();
1090 DebugLoc DL = MI->getDebugLoc();
1091
1092 for (auto &Op : MI->operands()) {
1093 if (!Op.isReg() || !Op.isUse())
1094 continue;
1095 Register R = Op.getReg();
1096 if (!R.isVirtual())
1097 continue;
1098 if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg())
1099 continue;
1100 UUPairMap::const_iterator F = PairMap.find(R);
1101 if (F == PairMap.end())
1102 continue;
1103 const UUPair &Pr = F->second;
1104 Register NewDR = MRI->createVirtualRegister(DoubleRC);
1105 BuildMI(B, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), NewDR)
1106 .addReg(Pr.first)
1107 .addImm(Hexagon::isub_lo)
1108 .addReg(Pr.second)
1109 .addImm(Hexagon::isub_hi);
1110 Op.setReg(NewDR);
1111 }
1112}
1113
1114bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) {
1115 using MISet = std::set<MachineInstr *>;
1116
1117 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
1118 bool Changed = false;
1119
1120 LLVM_DEBUG(dbgs() << "Splitting partition: ";
1121 dump_partition(dbgs(), Part, *TRI); dbgs() << '\n');
1122
1123 UUPairMap PairMap;
1124
1125 MISet SplitIns;
1126 for (unsigned DR : Part) {
1127 MachineInstr *DefI = MRI->getVRegDef(DR);
1128 SplitIns.insert(DefI);
1129
1130 // Collect all instructions, including fixed ones. We won't split them,
1131 // but we need to visit them again to insert the REG_SEQUENCE instructions.
1132 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
1133 U != W; ++U)
1134 SplitIns.insert(U->getParent());
1135
1136 Register LoR = MRI->createVirtualRegister(IntRC);
1137 Register HiR = MRI->createVirtualRegister(IntRC);
1138 LLVM_DEBUG(dbgs() << "Created mapping: " << printReg(DR, TRI) << " -> "
1139 << printReg(HiR, TRI) << ':' << printReg(LoR, TRI)
1140 << '\n');
1141 PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));
1142 }
1143
1144 MISet Erase;
1145 for (auto *MI : SplitIns) {
1146 if (isFixedInstr(MI)) {
1147 collapseRegPairs(MI, PairMap);
1148 } else {
1149 bool Done = splitInstr(MI, PairMap);
1150 if (Done)
1151 Erase.insert(MI);
1152 Changed |= Done;
1153 }
1154 }
1155
1156 for (unsigned DR : Part) {
1157 // Before erasing "double" instructions, revisit all uses of the double
1158 // registers in this partition, and replace all uses of them with subre-
1159 // gisters, with the corresponding single registers.
1160 MISet Uses;
1161 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
1162 U != W; ++U)
1163 Uses.insert(U->getParent());
1164 for (auto *M : Uses)
1165 replaceSubregUses(M, PairMap);
1166 }
1167
1168 for (auto *MI : Erase) {
1169 MachineBasicBlock *B = MI->getParent();
1170 B->erase(MI);
1171 }
1172
1173 return Changed;
1174}
1175
1176bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) {
1177 if (skipFunction(MF.getFunction()))
1178 return false;
1179
1180 LLVM_DEBUG(dbgs() << "Splitting double registers in function: "
1181 << MF.getName() << '\n');
1182
1183 auto &ST = MF.getSubtarget<HexagonSubtarget>();
1184 TRI = ST.getRegisterInfo();
1185 TII = ST.getInstrInfo();
1186 MRI = &MF.getRegInfo();
1187 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1188
1189 UUSetMap P2Rs;
1190 LoopRegMap IRM;
1191
1192 collectIndRegs(IRM);
1193 partitionRegisters(P2Rs);
1194
1195 LLVM_DEBUG({
1196 dbgs() << "Register partitioning: (partition #0 is fixed)\n";
1197 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
1198 dbgs() << '#' << I->first << " -> ";
1199 dump_partition(dbgs(), I->second, *TRI);
1200 dbgs() << '\n';
1201 }
1202 });
1203
1204 bool Changed = false;
1205 int Limit = MaxHSDR;
1206
1207 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
1208 if (I->first == 0)
1209 continue;
1210 if (Limit >= 0 && Counter >= Limit)
1211 break;
1212 USet &Part = I->second;
1213 LLVM_DEBUG(dbgs() << "Calculating profit for partition #" << I->first
1214 << '\n');
1215 if (!isProfitable(Part, IRM))
1216 continue;
1217 Counter++;
1218 Changed |= splitPartition(Part);
1219 }
1220
1221 return Changed;
1222}
1223
1225 return new HexagonSplitDoubleRegs();
1226}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
@ PostInc
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:678
const HexagonInstrInfo * TII
static cl::opt< bool > MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true), cl::desc("Do not split loads or stores"))
static cl::opt< bool > SplitAll("hsdr-split-all", cl::Hidden, cl::init(false), cl::desc("Split all partitions"))
static cl::opt< int > MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1), cl::desc("Maximum number of split partitions"))
static int32_t profitImm(unsigned Imm)
IRTranslator LLVM IR MI
SmallVector< Loop *, 4 > LoopVector
Definition LoopFuse.cpp:362
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
static bool isReg(const MCInst &MI, unsigned OpNo)
#define P(N)
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static const MCPhysReg DoubleRegs[32]
static bool isProfitable(const StableFunctionMap::StableFunctionEntries &SFS)
#define LLVM_DEBUG(...)
Definition Debug.h:119
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const override
For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...
bool PredOpcodeHasJMP_c(unsigned Opcode) const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
mop_range operands()
LLVM_ABI void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
Flags
Flags values. These may be or'd together.
unsigned getSubReg() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
static use_nodbg_iterator use_nodbg_end()
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
RegState
Flags to represent properties of register accesses.
@ Done
Definition Threading.h:60
@ Load
The value being inserted comes from a load (InsertElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1784
DWARFExpression::Operation Op
FunctionPass * createHexagonSplitDoubleRegs()
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58