1 //===- HexagonSplitDouble.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #define DEBUG_TYPE "hsdr"
11 #include "HexagonInstrInfo.h"
12 #include "HexagonRegisterInfo.h"
13 #include "HexagonSubtarget.h"
14 #include "llvm/ADT/BitVector.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineLoopInfo.h"
24 #include "llvm/CodeGen/MachineMemOperand.h"
25 #include "llvm/CodeGen/MachineOperand.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/TargetRegisterInfo.h"
28 #include "llvm/Config/llvm-config.h"
29 #include "llvm/IR/DebugLoc.h"
30 #include "llvm/Pass.h"
31 #include "llvm/Support/CommandLine.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/Debug.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/raw_ostream.h"
49 FunctionPass
*createHexagonSplitDoubleRegs();
50 void initializeHexagonSplitDoubleRegsPass(PassRegistry
&);
52 } // end namespace llvm
54 static cl::opt
<int> MaxHSDR("max-hsdr", cl::Hidden
, cl::init(-1),
55 cl::desc("Maximum number of split partitions"));
56 static cl::opt
<bool> MemRefsFixed("hsdr-no-mem", cl::Hidden
, cl::init(true),
57 cl::desc("Do not split loads or stores"));
58 static cl::opt
<bool> SplitAll("hsdr-split-all", cl::Hidden
, cl::init(false),
59 cl::desc("Split all partitions"));
63 class HexagonSplitDoubleRegs
: public MachineFunctionPass
{
67 HexagonSplitDoubleRegs() : MachineFunctionPass(ID
) {}
69 StringRef
getPassName() const override
{
70 return "Hexagon Split Double Registers";
73 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
74 AU
.addRequired
<MachineLoopInfo
>();
75 AU
.addPreserved
<MachineLoopInfo
>();
76 MachineFunctionPass::getAnalysisUsage(AU
);
79 bool runOnMachineFunction(MachineFunction
&MF
) override
;
82 static const TargetRegisterClass
*const DoubleRC
;
84 const HexagonRegisterInfo
*TRI
= nullptr;
85 const HexagonInstrInfo
*TII
= nullptr;
86 const MachineLoopInfo
*MLI
;
87 MachineRegisterInfo
*MRI
;
89 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
>;
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 int32_t profit(unsigned Reg
) const;
101 bool isProfitable(const USet
&Part
, LoopRegMap
&IRM
) const;
103 void collectIndRegsForLoop(const MachineLoop
*L
, USet
&Rs
);
104 void collectIndRegs(LoopRegMap
&IRM
);
106 void createHalfInstr(unsigned Opc
, MachineInstr
*MI
,
107 const UUPairMap
&PairMap
, unsigned SubR
);
108 void splitMemRef(MachineInstr
*MI
, const UUPairMap
&PairMap
);
109 void splitImmediate(MachineInstr
*MI
, const UUPairMap
&PairMap
);
110 void splitCombine(MachineInstr
*MI
, const UUPairMap
&PairMap
);
111 void splitExt(MachineInstr
*MI
, const UUPairMap
&PairMap
);
112 void splitShift(MachineInstr
*MI
, const UUPairMap
&PairMap
);
113 void splitAslOr(MachineInstr
*MI
, const UUPairMap
&PairMap
);
114 bool splitInstr(MachineInstr
*MI
, const UUPairMap
&PairMap
);
115 void replaceSubregUses(MachineInstr
*MI
, const UUPairMap
&PairMap
);
116 void collapseRegPairs(MachineInstr
*MI
, const UUPairMap
&PairMap
);
117 bool splitPartition(const USet
&Part
);
121 static void dump_partition(raw_ostream
&, const USet
&,
122 const TargetRegisterInfo
&);
125 } // end anonymous namespace
127 char HexagonSplitDoubleRegs::ID
;
128 int HexagonSplitDoubleRegs::Counter
= 0;
129 const TargetRegisterClass
*const HexagonSplitDoubleRegs::DoubleRC
=
130 &Hexagon::DoubleRegsRegClass
;
132 INITIALIZE_PASS(HexagonSplitDoubleRegs
, "hexagon-split-double",
133 "Hexagon Split Double Registers", false, false)
135 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
136 LLVM_DUMP_METHOD
void HexagonSplitDoubleRegs::dump_partition(raw_ostream
&os
,
137 const USet
&Part
, const TargetRegisterInfo
&TRI
) {
140 dbgs() << ' ' << printReg(I
, &TRI
);
145 bool HexagonSplitDoubleRegs::isInduction(unsigned Reg
, LoopRegMap
&IRM
) const {
147 const USet
&Rs
= I
.second
;
148 if (Rs
.find(Reg
) != Rs
.end())
154 bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr
*MI
) const {
155 for (auto &MO
: MI
->memoperands())
156 if (MO
->isVolatile() || MO
->isAtomic())
161 bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr
*MI
) const {
162 if (MI
->mayLoad() || MI
->mayStore())
163 if (MemRefsFixed
|| isVolatileInstr(MI
))
165 if (MI
->isDebugInstr())
168 unsigned Opc
= MI
->getOpcode();
173 case TargetOpcode::PHI
:
174 case TargetOpcode::COPY
:
177 case Hexagon::L2_loadrd_io
:
178 // Not handling stack stores (only reg-based addresses).
179 if (MI
->getOperand(1).isReg())
182 case Hexagon::S2_storerd_io
:
183 // Not handling stack stores (only reg-based addresses).
184 if (MI
->getOperand(0).isReg())
187 case Hexagon::L2_loadrd_pi
:
188 case Hexagon::S2_storerd_pi
:
190 case Hexagon::A2_tfrpi
:
191 case Hexagon::A2_combineii
:
192 case Hexagon::A4_combineir
:
193 case Hexagon::A4_combineii
:
194 case Hexagon::A4_combineri
:
195 case Hexagon::A2_combinew
:
196 case Hexagon::CONST64
:
198 case Hexagon::A2_sxtw
:
200 case Hexagon::A2_andp
:
201 case Hexagon::A2_orp
:
202 case Hexagon::A2_xorp
:
203 case Hexagon::S2_asl_i_p_or
:
204 case Hexagon::S2_asl_i_p
:
205 case Hexagon::S2_asr_i_p
:
206 case Hexagon::S2_lsr_i_p
:
210 for (auto &Op
: MI
->operands()) {
213 Register R
= Op
.getReg();
214 if (!Register::isVirtualRegister(R
))
220 void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap
&P2Rs
) {
221 using UUMap
= std::map
<unsigned, unsigned>;
222 using UVect
= std::vector
<unsigned>;
224 unsigned NumRegs
= MRI
->getNumVirtRegs();
225 BitVector
DoubleRegs(NumRegs
);
226 for (unsigned i
= 0; i
< NumRegs
; ++i
) {
227 unsigned R
= Register::index2VirtReg(i
);
228 if (MRI
->getRegClass(R
) == DoubleRC
)
232 BitVector
FixedRegs(NumRegs
);
233 for (int x
= DoubleRegs
.find_first(); x
>= 0; x
= DoubleRegs
.find_next(x
)) {
234 unsigned R
= Register::index2VirtReg(x
);
235 MachineInstr
*DefI
= MRI
->getVRegDef(R
);
236 // In some cases a register may exist, but never be defined or used.
237 // It should never appear anywhere, but mark it as "fixed", just to be
239 if (!DefI
|| isFixedInstr(DefI
))
244 for (int x
= DoubleRegs
.find_first(); x
>= 0; x
= DoubleRegs
.find_next(x
)) {
247 unsigned R
= Register::index2VirtReg(x
);
248 LLVM_DEBUG(dbgs() << printReg(R
, TRI
) << " ~~");
249 USet
&Asc
= AssocMap
[R
];
250 for (auto U
= MRI
->use_nodbg_begin(R
), Z
= MRI
->use_nodbg_end();
252 MachineOperand
&Op
= *U
;
253 MachineInstr
*UseI
= Op
.getParent();
254 if (isFixedInstr(UseI
))
256 for (unsigned i
= 0, n
= UseI
->getNumOperands(); i
< n
; ++i
) {
257 MachineOperand
&MO
= UseI
->getOperand(i
);
258 // Skip non-registers or registers with subregisters.
259 if (&MO
== &Op
|| !MO
.isReg() || MO
.getSubReg())
261 Register T
= MO
.getReg();
262 if (!Register::isVirtualRegister(T
)) {
266 if (MRI
->getRegClass(T
) != DoubleRC
)
268 unsigned u
= Register::virtReg2Index(T
);
271 LLVM_DEBUG(dbgs() << ' ' << printReg(T
, TRI
));
273 // Make it symmetric.
274 AssocMap
[T
].insert(R
);
277 LLVM_DEBUG(dbgs() << '\n');
283 for (int x
= DoubleRegs
.find_first(); x
>= 0; x
= DoubleRegs
.find_next(x
)) {
284 unsigned R
= Register::index2VirtReg(x
);
285 if (Visited
.count(R
))
287 // Create a new partition for R.
288 unsigned ThisP
= FixedRegs
[x
] ? 0 : NextP
++;
291 for (unsigned i
= 0; i
< WorkQ
.size(); ++i
) {
292 unsigned T
= WorkQ
[i
];
293 if (Visited
.count(T
))
297 // Add all registers associated with T.
298 USet
&Asc
= AssocMap
[T
];
299 for (USet::iterator J
= Asc
.begin(), F
= Asc
.end(); J
!= F
; ++J
)
305 P2Rs
[I
.second
].insert(I
.first
);
308 static inline int32_t profitImm(unsigned Imm
) {
310 if (Imm
== 0 || Imm
== 0xFFFFFFFF)
315 int32_t HexagonSplitDoubleRegs::profit(const MachineInstr
*MI
) const {
317 unsigned Opc
= MI
->getOpcode();
319 case TargetOpcode::PHI
:
320 for (const auto &Op
: MI
->operands())
324 case TargetOpcode::COPY
:
325 if (MI
->getOperand(1).getSubReg() != 0)
329 case Hexagon::L2_loadrd_io
:
330 case Hexagon::S2_storerd_io
:
332 case Hexagon::L2_loadrd_pi
:
333 case Hexagon::S2_storerd_pi
:
336 case Hexagon::A2_tfrpi
:
337 case Hexagon::CONST64
: {
338 uint64_t D
= MI
->getOperand(1).getImm();
339 unsigned Lo
= D
& 0xFFFFFFFFULL
;
340 unsigned Hi
= D
>> 32;
341 return profitImm(Lo
) + profitImm(Hi
);
343 case Hexagon::A2_combineii
:
344 case Hexagon::A4_combineii
: {
345 const MachineOperand
&Op1
= MI
->getOperand(1);
346 const MachineOperand
&Op2
= MI
->getOperand(2);
347 int32_t Prof1
= Op1
.isImm() ? profitImm(Op1
.getImm()) : 0;
348 int32_t Prof2
= Op2
.isImm() ? profitImm(Op2
.getImm()) : 0;
349 return Prof1
+ Prof2
;
351 case Hexagon::A4_combineri
:
353 // Fall through into A4_combineir.
355 case Hexagon::A4_combineir
: {
357 const MachineOperand
&OpX
= MI
->getOperand(ImmX
);
359 int64_t V
= OpX
.getImm();
360 if (V
== 0 || V
== -1)
363 // Fall through into A2_combinew.
366 case Hexagon::A2_combinew
:
369 case Hexagon::A2_sxtw
:
372 case Hexagon::A2_andp
:
373 case Hexagon::A2_orp
:
374 case Hexagon::A2_xorp
: {
375 Register Rs
= MI
->getOperand(1).getReg();
376 Register Rt
= MI
->getOperand(2).getReg();
377 return profit(Rs
) + profit(Rt
);
380 case Hexagon::S2_asl_i_p_or
: {
381 unsigned S
= MI
->getOperand(3).getImm();
382 if (S
== 0 || S
== 32)
386 case Hexagon::S2_asl_i_p
:
387 case Hexagon::S2_asr_i_p
:
388 case Hexagon::S2_lsr_i_p
:
389 unsigned S
= MI
->getOperand(2).getImm();
390 if (S
== 0 || S
== 32)
402 int32_t HexagonSplitDoubleRegs::profit(unsigned Reg
) const {
403 assert(Register::isVirtualRegister(Reg
));
405 const MachineInstr
*DefI
= MRI
->getVRegDef(Reg
);
406 switch (DefI
->getOpcode()) {
407 case Hexagon::A2_tfrpi
:
408 case Hexagon::CONST64
:
409 case Hexagon::A2_combineii
:
410 case Hexagon::A4_combineii
:
411 case Hexagon::A4_combineri
:
412 case Hexagon::A4_combineir
:
413 case Hexagon::A2_combinew
:
421 bool HexagonSplitDoubleRegs::isProfitable(const USet
&Part
, LoopRegMap
&IRM
)
423 unsigned FixedNum
= 0, LoopPhiNum
= 0;
426 for (unsigned DR
: Part
) {
427 MachineInstr
*DefI
= MRI
->getVRegDef(DR
);
428 int32_t P
= profit(DefI
);
429 if (P
== std::numeric_limits
<int>::min())
432 // Reduce the profitability of splitting induction registers.
433 if (isInduction(DR
, IRM
))
436 for (auto U
= MRI
->use_nodbg_begin(DR
), W
= MRI
->use_nodbg_end();
438 MachineInstr
*UseI
= U
->getParent();
439 if (isFixedInstr(UseI
)) {
441 // Calculate the cost of generating REG_SEQUENCE instructions.
442 for (auto &Op
: UseI
->operands()) {
443 if (Op
.isReg() && Part
.count(Op
.getReg()))
449 // If a register from this partition is used in a fixed instruction,
450 // and there is also a register in this partition that is used in
451 // a loop phi node, then decrease the splitting profit as this can
452 // confuse the modulo scheduler.
454 const MachineBasicBlock
*PB
= UseI
->getParent();
455 const MachineLoop
*L
= MLI
->getLoopFor(PB
);
456 if (L
&& L
->getHeader() == PB
)
459 // Splittable instruction.
460 int32_t P
= profit(UseI
);
461 if (P
== std::numeric_limits
<int>::min())
467 if (FixedNum
> 0 && LoopPhiNum
> 0)
468 TotalP
-= 20*LoopPhiNum
;
470 LLVM_DEBUG(dbgs() << "Partition profit: " << TotalP
<< '\n');
476 void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop
*L
,
478 const MachineBasicBlock
*HB
= L
->getHeader();
479 const MachineBasicBlock
*LB
= L
->getLoopLatch();
483 // Examine the latch branch. Expect it to be a conditional branch to
484 // the header (either "br-cond header" or "br-cond exit; br header").
485 MachineBasicBlock
*TB
= nullptr, *FB
= nullptr;
486 MachineBasicBlock
*TmpLB
= const_cast<MachineBasicBlock
*>(LB
);
487 SmallVector
<MachineOperand
,2> Cond
;
488 bool BadLB
= TII
->analyzeBranch(*TmpLB
, TB
, FB
, Cond
, false);
489 // Only analyzable conditional branches. HII::analyzeBranch will put
490 // the branch opcode as the first element of Cond, and the predicate
491 // operand as the second.
492 if (BadLB
|| Cond
.size() != 2)
494 // Only simple jump-conditional (with or without negation).
495 if (!TII
->PredOpcodeHasJMP_c(Cond
[0].getImm()))
497 // Must go to the header.
498 if (TB
!= HB
&& FB
!= HB
)
500 assert(Cond
[1].isReg() && "Unexpected Cond vector from analyzeBranch");
501 // Expect a predicate register.
502 Register PR
= Cond
[1].getReg();
503 assert(MRI
->getRegClass(PR
) == &Hexagon::PredRegsRegClass
);
505 // Get the registers on which the loop controlling compare instruction
507 unsigned CmpR1
= 0, CmpR2
= 0;
508 const MachineInstr
*CmpI
= MRI
->getVRegDef(PR
);
509 while (CmpI
->getOpcode() == Hexagon::C2_not
)
510 CmpI
= MRI
->getVRegDef(CmpI
->getOperand(1).getReg());
512 int Mask
= 0, Val
= 0;
513 bool OkCI
= TII
->analyzeCompare(*CmpI
, CmpR1
, CmpR2
, Mask
, Val
);
516 // Eliminate non-double input registers.
517 if (CmpR1
&& MRI
->getRegClass(CmpR1
) != DoubleRC
)
519 if (CmpR2
&& MRI
->getRegClass(CmpR2
) != DoubleRC
)
521 if (!CmpR1
&& !CmpR2
)
524 // Now examine the top of the loop: the phi nodes that could poten-
525 // tially define loop induction registers. The registers defined by
526 // such a phi node would be used in a 64-bit add, which then would
527 // be used in the loop compare instruction.
529 // Get the set of all double registers defined by phi nodes in the
531 using UVect
= std::vector
<unsigned>;
534 for (auto &MI
: *HB
) {
537 const MachineOperand
&MD
= MI
.getOperand(0);
538 Register R
= MD
.getReg();
539 if (MRI
->getRegClass(R
) == DoubleRC
)
545 auto NoIndOp
= [this, CmpR1
, CmpR2
] (unsigned R
) -> bool {
546 for (auto I
= MRI
->use_nodbg_begin(R
), E
= MRI
->use_nodbg_end();
548 const MachineInstr
*UseI
= I
->getParent();
549 if (UseI
->getOpcode() != Hexagon::A2_addp
)
551 // Get the output from the add. If it is one of the inputs to the
552 // loop-controlling compare instruction, then R is likely an induc-
554 Register T
= UseI
->getOperand(0).getReg();
555 if (T
== CmpR1
|| T
== CmpR2
)
560 UVect::iterator End
= llvm::remove_if(DP
, NoIndOp
);
561 Rs
.insert(DP
.begin(), End
);
566 dbgs() << "For loop at " << printMBBReference(*HB
) << " ind regs: ";
567 dump_partition(dbgs(), Rs
, *TRI
);
572 void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap
&IRM
) {
573 using LoopVector
= std::vector
<MachineLoop
*>;
579 for (unsigned i
= 0; i
< WorkQ
.size(); ++i
) {
580 for (auto I
: *WorkQ
[i
])
585 for (unsigned i
= 0, n
= WorkQ
.size(); i
< n
; ++i
) {
586 MachineLoop
*L
= WorkQ
[i
];
588 collectIndRegsForLoop(L
, Rs
);
590 IRM
.insert(std::make_pair(L
, Rs
));
594 void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc
, MachineInstr
*MI
,
595 const UUPairMap
&PairMap
, unsigned SubR
) {
596 MachineBasicBlock
&B
= *MI
->getParent();
597 DebugLoc DL
= MI
->getDebugLoc();
598 MachineInstr
*NewI
= BuildMI(B
, MI
, DL
, TII
->get(Opc
));
600 for (auto &Op
: MI
->operands()) {
602 NewI
->addOperand(Op
);
605 // For register operands, set the subregister.
606 Register R
= Op
.getReg();
607 unsigned SR
= Op
.getSubReg();
608 bool isVirtReg
= Register::isVirtualRegister(R
);
609 bool isKill
= Op
.isKill();
610 if (isVirtReg
&& MRI
->getRegClass(R
) == DoubleRC
) {
612 UUPairMap::const_iterator F
= PairMap
.find(R
);
613 if (F
== PairMap
.end()) {
616 const UUPair
&P
= F
->second
;
617 R
= (SubR
== Hexagon::isub_lo
) ? P
.first
: P
.second
;
621 auto CO
= MachineOperand::CreateReg(R
, Op
.isDef(), Op
.isImplicit(), isKill
,
622 Op
.isDead(), Op
.isUndef(), Op
.isEarlyClobber(), SR
, Op
.isDebug(),
623 Op
.isInternalRead());
624 NewI
->addOperand(CO
);
628 void HexagonSplitDoubleRegs::splitMemRef(MachineInstr
*MI
,
629 const UUPairMap
&PairMap
) {
630 bool Load
= MI
->mayLoad();
631 unsigned OrigOpc
= MI
->getOpcode();
632 bool PostInc
= (OrigOpc
== Hexagon::L2_loadrd_pi
||
633 OrigOpc
== Hexagon::S2_storerd_pi
);
634 MachineInstr
*LowI
, *HighI
;
635 MachineBasicBlock
&B
= *MI
->getParent();
636 DebugLoc DL
= MI
->getDebugLoc();
638 // Index of the base-address-register operand.
639 unsigned AdrX
= PostInc
? (Load
? 2 : 1)
641 MachineOperand
&AdrOp
= MI
->getOperand(AdrX
);
642 unsigned RSA
= getRegState(AdrOp
);
643 MachineOperand
&ValOp
= Load
? MI
->getOperand(0)
644 : (PostInc
? MI
->getOperand(3)
645 : MI
->getOperand(2));
646 UUPairMap::const_iterator F
= PairMap
.find(ValOp
.getReg());
647 assert(F
!= PairMap
.end());
650 const UUPair
&P
= F
->second
;
651 int64_t Off
= PostInc
? 0 : MI
->getOperand(2).getImm();
652 LowI
= BuildMI(B
, MI
, DL
, TII
->get(Hexagon::L2_loadri_io
), P
.first
)
653 .addReg(AdrOp
.getReg(), RSA
& ~RegState::Kill
, AdrOp
.getSubReg())
655 HighI
= BuildMI(B
, MI
, DL
, TII
->get(Hexagon::L2_loadri_io
), P
.second
)
656 .addReg(AdrOp
.getReg(), RSA
& ~RegState::Kill
, AdrOp
.getSubReg())
659 const UUPair
&P
= F
->second
;
660 int64_t Off
= PostInc
? 0 : MI
->getOperand(1).getImm();
661 LowI
= BuildMI(B
, MI
, DL
, TII
->get(Hexagon::S2_storeri_io
))
662 .addReg(AdrOp
.getReg(), RSA
& ~RegState::Kill
, AdrOp
.getSubReg())
665 HighI
= BuildMI(B
, MI
, DL
, TII
->get(Hexagon::S2_storeri_io
))
666 .addReg(AdrOp
.getReg(), RSA
& ~RegState::Kill
, AdrOp
.getSubReg())
672 // Create the increment of the address register.
673 int64_t Inc
= Load
? MI
->getOperand(3).getImm()
674 : MI
->getOperand(2).getImm();
675 MachineOperand
&UpdOp
= Load
? MI
->getOperand(1) : MI
->getOperand(0);
676 const TargetRegisterClass
*RC
= MRI
->getRegClass(UpdOp
.getReg());
677 Register NewR
= MRI
->createVirtualRegister(RC
);
678 assert(!UpdOp
.getSubReg() && "Def operand with subreg");
679 BuildMI(B
, MI
, DL
, TII
->get(Hexagon::A2_addi
), NewR
)
680 .addReg(AdrOp
.getReg(), RSA
)
682 MRI
->replaceRegWith(UpdOp
.getReg(), NewR
);
683 // The original instruction will be deleted later.
686 // Generate a new pair of memory-operands.
687 MachineFunction
&MF
= *B
.getParent();
688 for (auto &MO
: MI
->memoperands()) {
689 const MachinePointerInfo
&Ptr
= MO
->getPointerInfo();
690 MachineMemOperand::Flags F
= MO
->getFlags();
691 int A
= MO
->getAlignment();
693 auto *Tmp1
= MF
.getMachineMemOperand(Ptr
, F
, 4/*size*/, A
);
694 LowI
->addMemOperand(MF
, Tmp1
);
695 auto *Tmp2
= MF
.getMachineMemOperand(Ptr
, F
, 4/*size*/, std::min(A
, 4));
696 HighI
->addMemOperand(MF
, Tmp2
);
700 void HexagonSplitDoubleRegs::splitImmediate(MachineInstr
*MI
,
701 const UUPairMap
&PairMap
) {
702 MachineOperand
&Op0
= MI
->getOperand(0);
703 MachineOperand
&Op1
= MI
->getOperand(1);
704 assert(Op0
.isReg() && Op1
.isImm());
705 uint64_t V
= Op1
.getImm();
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
;
713 // The operand to A2_tfrsi can only have 32 significant bits. Immediate
714 // values in MachineOperand are stored as 64-bit integers, and so the
715 // value -1 may be represented either as 64-bit -1, or 4294967295. Both
716 // will have the 32 higher bits truncated in the end, but -1 will remain
717 // as -1, while the latter may appear to be a large unsigned value
718 // requiring a constant extender. The casting to int32_t will select the
719 // former representation. (The same reasoning applies to all 32-bit
721 BuildMI(B
, MI
, DL
, TII
->get(Hexagon::A2_tfrsi
), P
.first
)
722 .addImm(int32_t(V
& 0xFFFFFFFFULL
));
723 BuildMI(B
, MI
, DL
, TII
->get(Hexagon::A2_tfrsi
), P
.second
)
724 .addImm(int32_t(V
>> 32));
727 void HexagonSplitDoubleRegs::splitCombine(MachineInstr
*MI
,
728 const UUPairMap
&PairMap
) {
729 MachineOperand
&Op0
= MI
->getOperand(0);
730 MachineOperand
&Op1
= MI
->getOperand(1);
731 MachineOperand
&Op2
= MI
->getOperand(2);
734 MachineBasicBlock
&B
= *MI
->getParent();
735 DebugLoc DL
= MI
->getDebugLoc();
736 UUPairMap::const_iterator F
= PairMap
.find(Op0
.getReg());
737 assert(F
!= PairMap
.end());
738 const UUPair
&P
= F
->second
;
741 BuildMI(B
, MI
, DL
, TII
->get(Hexagon::A2_tfrsi
), P
.second
)
744 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), P
.second
)
745 .addReg(Op1
.getReg(), getRegState(Op1
), Op1
.getSubReg());
749 BuildMI(B
, MI
, DL
, TII
->get(Hexagon::A2_tfrsi
), P
.first
)
752 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), P
.first
)
753 .addReg(Op2
.getReg(), getRegState(Op2
), Op2
.getSubReg());
757 void HexagonSplitDoubleRegs::splitExt(MachineInstr
*MI
,
758 const UUPairMap
&PairMap
) {
759 MachineOperand
&Op0
= MI
->getOperand(0);
760 MachineOperand
&Op1
= MI
->getOperand(1);
761 assert(Op0
.isReg() && Op1
.isReg());
763 MachineBasicBlock
&B
= *MI
->getParent();
764 DebugLoc DL
= MI
->getDebugLoc();
765 UUPairMap::const_iterator F
= PairMap
.find(Op0
.getReg());
766 assert(F
!= PairMap
.end());
767 const UUPair
&P
= F
->second
;
768 unsigned RS
= getRegState(Op1
);
770 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), P
.first
)
771 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, Op1
.getSubReg());
772 BuildMI(B
, MI
, DL
, TII
->get(Hexagon::S2_asr_i_r
), P
.second
)
773 .addReg(Op1
.getReg(), RS
, Op1
.getSubReg())
777 void HexagonSplitDoubleRegs::splitShift(MachineInstr
*MI
,
778 const UUPairMap
&PairMap
) {
779 using namespace Hexagon
;
781 MachineOperand
&Op0
= MI
->getOperand(0);
782 MachineOperand
&Op1
= MI
->getOperand(1);
783 MachineOperand
&Op2
= MI
->getOperand(2);
784 assert(Op0
.isReg() && Op1
.isReg() && Op2
.isImm());
785 int64_t Sh64
= Op2
.getImm();
786 assert(Sh64
>= 0 && Sh64
< 64);
789 UUPairMap::const_iterator F
= PairMap
.find(Op0
.getReg());
790 assert(F
!= PairMap
.end());
791 const UUPair
&P
= F
->second
;
792 Register LoR
= P
.first
;
793 Register HiR
= P
.second
;
795 unsigned Opc
= MI
->getOpcode();
796 bool Right
= (Opc
== S2_lsr_i_p
|| Opc
== S2_asr_i_p
);
798 bool Signed
= (Opc
== S2_asr_i_p
);
800 MachineBasicBlock
&B
= *MI
->getParent();
801 DebugLoc DL
= MI
->getDebugLoc();
802 unsigned RS
= getRegState(Op1
);
803 unsigned ShiftOpc
= Left
? S2_asl_i_r
804 : (Signed
? S2_asr_i_r
: S2_lsr_i_r
);
805 unsigned LoSR
= isub_lo
;
806 unsigned HiSR
= isub_hi
;
809 // No shift, subregister copy.
810 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), LoR
)
811 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, LoSR
);
812 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), HiR
)
813 .addReg(Op1
.getReg(), RS
, HiSR
);
815 const TargetRegisterClass
*IntRC
= &IntRegsRegClass
;
816 Register TmpR
= MRI
->createVirtualRegister(IntRC
);
818 // Shift left: DR = shl R, #s
819 // LoR = shl R.lo, #s
820 // TmpR = extractu R.lo, #s, #32-s
821 // HiR = or (TmpR, asl(R.hi, #s))
822 // Shift right: DR = shr R, #s
823 // HiR = shr R.hi, #s
824 // TmpR = shr R.lo, #s
825 // LoR = insert TmpR, R.hi, #s, #32-s
828 // LoR = shl R.lo, #s
830 // TmpR = shr R.lo, #s
832 // Make a special case for A2_aslh and A2_asrh (they are predicable as
833 // opposed to S2_asl_i_r/S2_asr_i_r).
835 BuildMI(B
, MI
, DL
, TII
->get(A2_aslh
), LoR
)
836 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, LoSR
);
837 else if (S
== 16 && Signed
)
838 BuildMI(B
, MI
, DL
, TII
->get(A2_asrh
), TmpR
)
839 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, LoSR
);
841 BuildMI(B
, MI
, DL
, TII
->get(ShiftOpc
), (Left
? LoR
: TmpR
))
842 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, LoSR
)
846 // TmpR = extractu R.lo, #s, #32-s
847 BuildMI(B
, MI
, DL
, TII
->get(S2_extractu
), TmpR
)
848 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, LoSR
)
851 // HiR = or (TmpR, asl(R.hi, #s))
852 BuildMI(B
, MI
, DL
, TII
->get(S2_asl_i_r_or
), HiR
)
854 .addReg(Op1
.getReg(), RS
, HiSR
)
857 // HiR = shr R.hi, #s
858 BuildMI(B
, MI
, DL
, TII
->get(ShiftOpc
), HiR
)
859 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, HiSR
)
861 // LoR = insert TmpR, R.hi, #s, #32-s
862 BuildMI(B
, MI
, DL
, TII
->get(S2_insert
), LoR
)
864 .addReg(Op1
.getReg(), RS
, HiSR
)
868 } else if (S
== 32) {
869 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), (Left
? HiR
: LoR
))
870 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, (Left
? LoSR
: HiSR
));
872 BuildMI(B
, MI
, DL
, TII
->get(A2_tfrsi
), (Left
? LoR
: HiR
))
874 else // Must be right shift.
875 BuildMI(B
, MI
, DL
, TII
->get(S2_asr_i_r
), HiR
)
876 .addReg(Op1
.getReg(), RS
, HiSR
)
881 BuildMI(B
, MI
, DL
, TII
->get(A2_aslh
), HiR
)
882 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, LoSR
);
883 else if (S
== 16 && Signed
)
884 BuildMI(B
, MI
, DL
, TII
->get(A2_asrh
), LoR
)
885 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, HiSR
);
887 BuildMI(B
, MI
, DL
, TII
->get(ShiftOpc
), (Left
? HiR
: LoR
))
888 .addReg(Op1
.getReg(), RS
& ~RegState::Kill
, (Left
? LoSR
: HiSR
))
892 BuildMI(B
, MI
, DL
, TII
->get(S2_asr_i_r
), HiR
)
893 .addReg(Op1
.getReg(), RS
, HiSR
)
896 BuildMI(B
, MI
, DL
, TII
->get(A2_tfrsi
), (Left
? LoR
: HiR
))
901 void HexagonSplitDoubleRegs::splitAslOr(MachineInstr
*MI
,
902 const UUPairMap
&PairMap
) {
903 using namespace Hexagon
;
905 MachineOperand
&Op0
= MI
->getOperand(0);
906 MachineOperand
&Op1
= MI
->getOperand(1);
907 MachineOperand
&Op2
= MI
->getOperand(2);
908 MachineOperand
&Op3
= MI
->getOperand(3);
909 assert(Op0
.isReg() && Op1
.isReg() && Op2
.isReg() && Op3
.isImm());
910 int64_t Sh64
= Op3
.getImm();
911 assert(Sh64
>= 0 && Sh64
< 64);
914 UUPairMap::const_iterator F
= PairMap
.find(Op0
.getReg());
915 assert(F
!= PairMap
.end());
916 const UUPair
&P
= F
->second
;
917 unsigned LoR
= P
.first
;
918 unsigned HiR
= P
.second
;
920 MachineBasicBlock
&B
= *MI
->getParent();
921 DebugLoc DL
= MI
->getDebugLoc();
922 unsigned RS1
= getRegState(Op1
);
923 unsigned RS2
= getRegState(Op2
);
924 const TargetRegisterClass
*IntRC
= &IntRegsRegClass
;
926 unsigned LoSR
= isub_lo
;
927 unsigned HiSR
= isub_hi
;
929 // Op0 = S2_asl_i_p_or Op1, Op2, Op3
930 // means: Op0 = or (Op1, asl(Op2, Op3))
933 // DR = or (R1, asl(R2, #s))
935 // LoR = or (R1.lo, asl(R2.lo, #s))
936 // Tmp1 = extractu R2.lo, #s, #32-s
937 // Tmp2 = or R1.hi, Tmp1
938 // HiR = or (Tmp2, asl(R2.hi, #s))
941 // DR = or (R1, asl(R2, #0))
943 // i.e. LoR = or R1.lo, R2.lo
944 // HiR = or R1.hi, R2.hi
945 BuildMI(B
, MI
, DL
, TII
->get(A2_or
), LoR
)
946 .addReg(Op1
.getReg(), RS1
& ~RegState::Kill
, LoSR
)
947 .addReg(Op2
.getReg(), RS2
& ~RegState::Kill
, LoSR
);
948 BuildMI(B
, MI
, DL
, TII
->get(A2_or
), HiR
)
949 .addReg(Op1
.getReg(), RS1
, HiSR
)
950 .addReg(Op2
.getReg(), RS2
, HiSR
);
952 BuildMI(B
, MI
, DL
, TII
->get(S2_asl_i_r_or
), LoR
)
953 .addReg(Op1
.getReg(), RS1
& ~RegState::Kill
, LoSR
)
954 .addReg(Op2
.getReg(), RS2
& ~RegState::Kill
, LoSR
)
956 Register TmpR1
= MRI
->createVirtualRegister(IntRC
);
957 BuildMI(B
, MI
, DL
, TII
->get(S2_extractu
), TmpR1
)
958 .addReg(Op2
.getReg(), RS2
& ~RegState::Kill
, LoSR
)
961 Register TmpR2
= MRI
->createVirtualRegister(IntRC
);
962 BuildMI(B
, MI
, DL
, TII
->get(A2_or
), TmpR2
)
963 .addReg(Op1
.getReg(), RS1
, HiSR
)
965 BuildMI(B
, MI
, DL
, TII
->get(S2_asl_i_r_or
), HiR
)
967 .addReg(Op2
.getReg(), RS2
, HiSR
)
969 } else if (S
== 32) {
970 // DR = or (R1, asl(R2, #32))
973 // HiR = or R1.hi, R2.lo
974 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), LoR
)
975 .addReg(Op1
.getReg(), RS1
& ~RegState::Kill
, LoSR
);
976 BuildMI(B
, MI
, DL
, TII
->get(A2_or
), HiR
)
977 .addReg(Op1
.getReg(), RS1
, HiSR
)
978 .addReg(Op2
.getReg(), RS2
, LoSR
);
980 // DR = or (R1, asl(R2, #s))
983 // HiR = or (R1:hi, asl(R2:lo, #s-32))
985 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::COPY
), LoR
)
986 .addReg(Op1
.getReg(), RS1
& ~RegState::Kill
, LoSR
);
987 BuildMI(B
, MI
, DL
, TII
->get(S2_asl_i_r_or
), HiR
)
988 .addReg(Op1
.getReg(), RS1
, HiSR
)
989 .addReg(Op2
.getReg(), RS2
, LoSR
)
994 bool HexagonSplitDoubleRegs::splitInstr(MachineInstr
*MI
,
995 const UUPairMap
&PairMap
) {
996 using namespace Hexagon
;
998 LLVM_DEBUG(dbgs() << "Splitting: " << *MI
);
1000 unsigned Opc
= MI
->getOpcode();
1003 case TargetOpcode::PHI
:
1004 case TargetOpcode::COPY
: {
1005 Register DstR
= MI
->getOperand(0).getReg();
1006 if (MRI
->getRegClass(DstR
) == DoubleRC
) {
1007 createHalfInstr(Opc
, MI
, PairMap
, isub_lo
);
1008 createHalfInstr(Opc
, MI
, PairMap
, isub_hi
);
1014 createHalfInstr(A2_and
, MI
, PairMap
, isub_lo
);
1015 createHalfInstr(A2_and
, MI
, PairMap
, isub_hi
);
1019 createHalfInstr(A2_or
, MI
, PairMap
, isub_lo
);
1020 createHalfInstr(A2_or
, MI
, PairMap
, isub_hi
);
1024 createHalfInstr(A2_xor
, MI
, PairMap
, isub_lo
);
1025 createHalfInstr(A2_xor
, MI
, PairMap
, isub_hi
);
1033 splitMemRef(MI
, PairMap
);
1039 splitImmediate(MI
, PairMap
);
1048 splitCombine(MI
, PairMap
);
1053 splitExt(MI
, PairMap
);
1060 splitShift(MI
, PairMap
);
1065 splitAslOr(MI
, PairMap
);
1070 llvm_unreachable("Instruction not splitable");
1077 void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr
*MI
,
1078 const UUPairMap
&PairMap
) {
1079 for (auto &Op
: MI
->operands()) {
1080 if (!Op
.isReg() || !Op
.isUse() || !Op
.getSubReg())
1082 Register R
= Op
.getReg();
1083 UUPairMap::const_iterator F
= PairMap
.find(R
);
1084 if (F
== PairMap
.end())
1086 const UUPair
&P
= F
->second
;
1087 switch (Op
.getSubReg()) {
1088 case Hexagon::isub_lo
:
1091 case Hexagon::isub_hi
:
1092 Op
.setReg(P
.second
);
1099 void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr
*MI
,
1100 const UUPairMap
&PairMap
) {
1101 MachineBasicBlock
&B
= *MI
->getParent();
1102 DebugLoc DL
= MI
->getDebugLoc();
1104 for (auto &Op
: MI
->operands()) {
1105 if (!Op
.isReg() || !Op
.isUse())
1107 Register R
= Op
.getReg();
1108 if (!Register::isVirtualRegister(R
))
1110 if (MRI
->getRegClass(R
) != DoubleRC
|| Op
.getSubReg())
1112 UUPairMap::const_iterator F
= PairMap
.find(R
);
1113 if (F
== PairMap
.end())
1115 const UUPair
&Pr
= F
->second
;
1116 Register NewDR
= MRI
->createVirtualRegister(DoubleRC
);
1117 BuildMI(B
, MI
, DL
, TII
->get(TargetOpcode::REG_SEQUENCE
), NewDR
)
1119 .addImm(Hexagon::isub_lo
)
1121 .addImm(Hexagon::isub_hi
);
1126 bool HexagonSplitDoubleRegs::splitPartition(const USet
&Part
) {
1127 using MISet
= std::set
<MachineInstr
*>;
1129 const TargetRegisterClass
*IntRC
= &Hexagon::IntRegsRegClass
;
1130 bool Changed
= false;
1132 LLVM_DEBUG(dbgs() << "Splitting partition: ";
1133 dump_partition(dbgs(), Part
, *TRI
); dbgs() << '\n');
1138 for (unsigned DR
: Part
) {
1139 MachineInstr
*DefI
= MRI
->getVRegDef(DR
);
1140 SplitIns
.insert(DefI
);
1142 // Collect all instructions, including fixed ones. We won't split them,
1143 // but we need to visit them again to insert the REG_SEQUENCE instructions.
1144 for (auto U
= MRI
->use_nodbg_begin(DR
), W
= MRI
->use_nodbg_end();
1146 SplitIns
.insert(U
->getParent());
1148 Register LoR
= MRI
->createVirtualRegister(IntRC
);
1149 Register HiR
= MRI
->createVirtualRegister(IntRC
);
1150 LLVM_DEBUG(dbgs() << "Created mapping: " << printReg(DR
, TRI
) << " -> "
1151 << printReg(HiR
, TRI
) << ':' << printReg(LoR
, TRI
)
1153 PairMap
.insert(std::make_pair(DR
, UUPair(LoR
, HiR
)));
1157 for (auto MI
: SplitIns
) {
1158 if (isFixedInstr(MI
)) {
1159 collapseRegPairs(MI
, PairMap
);
1161 bool Done
= splitInstr(MI
, PairMap
);
1168 for (unsigned DR
: Part
) {
1169 // Before erasing "double" instructions, revisit all uses of the double
1170 // registers in this partition, and replace all uses of them with subre-
1171 // gisters, with the corresponding single registers.
1173 for (auto U
= MRI
->use_nodbg_begin(DR
), W
= MRI
->use_nodbg_end();
1175 Uses
.insert(U
->getParent());
1177 replaceSubregUses(M
, PairMap
);
1180 for (auto MI
: Erase
) {
1181 MachineBasicBlock
*B
= MI
->getParent();
1188 bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction
&MF
) {
1189 if (skipFunction(MF
.getFunction()))
1192 LLVM_DEBUG(dbgs() << "Splitting double registers in function: "
1193 << MF
.getName() << '\n');
1195 auto &ST
= MF
.getSubtarget
<HexagonSubtarget
>();
1196 TRI
= ST
.getRegisterInfo();
1197 TII
= ST
.getInstrInfo();
1198 MRI
= &MF
.getRegInfo();
1199 MLI
= &getAnalysis
<MachineLoopInfo
>();
1204 collectIndRegs(IRM
);
1205 partitionRegisters(P2Rs
);
1208 dbgs() << "Register partitioning: (partition #0 is fixed)\n";
1209 for (UUSetMap::iterator I
= P2Rs
.begin(), E
= P2Rs
.end(); I
!= E
; ++I
) {
1210 dbgs() << '#' << I
->first
<< " -> ";
1211 dump_partition(dbgs(), I
->second
, *TRI
);
1216 bool Changed
= false;
1217 int Limit
= MaxHSDR
;
1219 for (UUSetMap::iterator I
= P2Rs
.begin(), E
= P2Rs
.end(); I
!= E
; ++I
) {
1222 if (Limit
>= 0 && Counter
>= Limit
)
1224 USet
&Part
= I
->second
;
1225 LLVM_DEBUG(dbgs() << "Calculating profit for partition #" << I
->first
1227 if (!isProfitable(Part
, IRM
))
1230 Changed
|= splitPartition(Part
);
1236 FunctionPass
*llvm::createHexagonSplitDoubleRegs() {
1237 return new HexagonSplitDoubleRegs();