xref: /openbsd-src/gnu/llvm/llvm/lib/Target/Hexagon/HexagonSplitDouble.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- HexagonSplitDouble.cpp ---------------------------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "HexagonInstrInfo.h"
1009467b48Spatrick #include "HexagonRegisterInfo.h"
1109467b48Spatrick #include "HexagonSubtarget.h"
1209467b48Spatrick #include "llvm/ADT/BitVector.h"
1309467b48Spatrick #include "llvm/ADT/STLExtras.h"
1409467b48Spatrick #include "llvm/ADT/SmallVector.h"
1509467b48Spatrick #include "llvm/ADT/StringRef.h"
1609467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
1709467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
1809467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
1909467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
2009467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
2109467b48Spatrick #include "llvm/CodeGen/MachineLoopInfo.h"
2209467b48Spatrick #include "llvm/CodeGen/MachineMemOperand.h"
2309467b48Spatrick #include "llvm/CodeGen/MachineOperand.h"
2409467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2509467b48Spatrick #include "llvm/CodeGen/TargetRegisterInfo.h"
2609467b48Spatrick #include "llvm/Config/llvm-config.h"
2709467b48Spatrick #include "llvm/IR/DebugLoc.h"
2809467b48Spatrick #include "llvm/Pass.h"
2909467b48Spatrick #include "llvm/Support/CommandLine.h"
3009467b48Spatrick #include "llvm/Support/Compiler.h"
3109467b48Spatrick #include "llvm/Support/Debug.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3309467b48Spatrick #include "llvm/Support/raw_ostream.h"
3409467b48Spatrick #include <algorithm>
3509467b48Spatrick #include <cassert>
3609467b48Spatrick #include <cstdint>
3709467b48Spatrick #include <limits>
3809467b48Spatrick #include <map>
3909467b48Spatrick #include <set>
4009467b48Spatrick #include <utility>
4109467b48Spatrick #include <vector>
4209467b48Spatrick 
4373471bf0Spatrick #define DEBUG_TYPE "hsdr"
4473471bf0Spatrick 
4509467b48Spatrick using namespace llvm;
4609467b48Spatrick 
4709467b48Spatrick namespace llvm {
4809467b48Spatrick 
4909467b48Spatrick   FunctionPass *createHexagonSplitDoubleRegs();
5009467b48Spatrick   void initializeHexagonSplitDoubleRegsPass(PassRegistry&);
5109467b48Spatrick 
5209467b48Spatrick } // end namespace llvm
5309467b48Spatrick 
5409467b48Spatrick static cl::opt<int> MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1),
5509467b48Spatrick     cl::desc("Maximum number of split partitions"));
5609467b48Spatrick static cl::opt<bool> MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true),
5709467b48Spatrick     cl::desc("Do not split loads or stores"));
5809467b48Spatrick   static cl::opt<bool> SplitAll("hsdr-split-all", cl::Hidden, cl::init(false),
5909467b48Spatrick       cl::desc("Split all partitions"));
6009467b48Spatrick 
6109467b48Spatrick namespace {
6209467b48Spatrick 
6309467b48Spatrick   class HexagonSplitDoubleRegs : public MachineFunctionPass {
6409467b48Spatrick   public:
6509467b48Spatrick     static char ID;
6609467b48Spatrick 
HexagonSplitDoubleRegs()6709467b48Spatrick     HexagonSplitDoubleRegs() : MachineFunctionPass(ID) {}
6809467b48Spatrick 
getPassName() const6909467b48Spatrick     StringRef getPassName() const override {
7009467b48Spatrick       return "Hexagon Split Double Registers";
7109467b48Spatrick     }
7209467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const7309467b48Spatrick     void getAnalysisUsage(AnalysisUsage &AU) const override {
7409467b48Spatrick       AU.addRequired<MachineLoopInfo>();
7509467b48Spatrick       AU.addPreserved<MachineLoopInfo>();
7609467b48Spatrick       MachineFunctionPass::getAnalysisUsage(AU);
7709467b48Spatrick     }
7809467b48Spatrick 
7909467b48Spatrick     bool runOnMachineFunction(MachineFunction &MF) override;
8009467b48Spatrick 
8109467b48Spatrick   private:
8209467b48Spatrick     static const TargetRegisterClass *const DoubleRC;
8309467b48Spatrick 
8409467b48Spatrick     const HexagonRegisterInfo *TRI = nullptr;
8509467b48Spatrick     const HexagonInstrInfo *TII = nullptr;
8609467b48Spatrick     const MachineLoopInfo *MLI;
8709467b48Spatrick     MachineRegisterInfo *MRI;
8809467b48Spatrick 
8909467b48Spatrick     using USet = std::set<unsigned>;
9009467b48Spatrick     using UUSetMap = std::map<unsigned, USet>;
9109467b48Spatrick     using UUPair = std::pair<unsigned, unsigned>;
9209467b48Spatrick     using UUPairMap = std::map<unsigned, UUPair>;
9309467b48Spatrick     using LoopRegMap = std::map<const MachineLoop *, USet>;
9409467b48Spatrick 
9509467b48Spatrick     bool isInduction(unsigned Reg, LoopRegMap &IRM) const;
9609467b48Spatrick     bool isVolatileInstr(const MachineInstr *MI) const;
9709467b48Spatrick     bool isFixedInstr(const MachineInstr *MI) const;
9809467b48Spatrick     void partitionRegisters(UUSetMap &P2Rs);
9909467b48Spatrick     int32_t profit(const MachineInstr *MI) const;
10073471bf0Spatrick     int32_t profit(Register Reg) const;
10109467b48Spatrick     bool isProfitable(const USet &Part, LoopRegMap &IRM) const;
10209467b48Spatrick 
10309467b48Spatrick     void collectIndRegsForLoop(const MachineLoop *L, USet &Rs);
10409467b48Spatrick     void collectIndRegs(LoopRegMap &IRM);
10509467b48Spatrick 
10609467b48Spatrick     void createHalfInstr(unsigned Opc, MachineInstr *MI,
10709467b48Spatrick         const UUPairMap &PairMap, unsigned SubR);
10809467b48Spatrick     void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap);
10909467b48Spatrick     void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap);
11009467b48Spatrick     void splitCombine(MachineInstr *MI, const UUPairMap &PairMap);
11109467b48Spatrick     void splitExt(MachineInstr *MI, const UUPairMap &PairMap);
11209467b48Spatrick     void splitShift(MachineInstr *MI, const UUPairMap &PairMap);
11309467b48Spatrick     void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap);
11409467b48Spatrick     bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap);
11509467b48Spatrick     void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap);
11609467b48Spatrick     void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap);
11709467b48Spatrick     bool splitPartition(const USet &Part);
11809467b48Spatrick 
11909467b48Spatrick     static int Counter;
12009467b48Spatrick 
12109467b48Spatrick     static void dump_partition(raw_ostream&, const USet&,
12209467b48Spatrick        const TargetRegisterInfo&);
12309467b48Spatrick   };
12409467b48Spatrick 
12509467b48Spatrick } // end anonymous namespace
12609467b48Spatrick 
12709467b48Spatrick char HexagonSplitDoubleRegs::ID;
12809467b48Spatrick int HexagonSplitDoubleRegs::Counter = 0;
12909467b48Spatrick const TargetRegisterClass *const HexagonSplitDoubleRegs::DoubleRC =
13009467b48Spatrick     &Hexagon::DoubleRegsRegClass;
13109467b48Spatrick 
13209467b48Spatrick INITIALIZE_PASS(HexagonSplitDoubleRegs, "hexagon-split-double",
13309467b48Spatrick   "Hexagon Split Double Registers", false, false)
13409467b48Spatrick 
13509467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump_partition(raw_ostream & os,const USet & Part,const TargetRegisterInfo & TRI)13609467b48Spatrick LLVM_DUMP_METHOD void HexagonSplitDoubleRegs::dump_partition(raw_ostream &os,
13709467b48Spatrick       const USet &Part, const TargetRegisterInfo &TRI) {
13809467b48Spatrick   dbgs() << '{';
13909467b48Spatrick   for (auto I : Part)
14009467b48Spatrick     dbgs() << ' ' << printReg(I, &TRI);
14109467b48Spatrick   dbgs() << " }";
14209467b48Spatrick }
14309467b48Spatrick #endif
14409467b48Spatrick 
isInduction(unsigned Reg,LoopRegMap & IRM) const14509467b48Spatrick bool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const {
14609467b48Spatrick   for (auto I : IRM) {
14709467b48Spatrick     const USet &Rs = I.second;
14809467b48Spatrick     if (Rs.find(Reg) != Rs.end())
14909467b48Spatrick       return true;
15009467b48Spatrick   }
15109467b48Spatrick   return false;
15209467b48Spatrick }
15309467b48Spatrick 
isVolatileInstr(const MachineInstr * MI) const15409467b48Spatrick bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const {
15509467b48Spatrick   for (auto &MO : MI->memoperands())
15609467b48Spatrick     if (MO->isVolatile() || MO->isAtomic())
15709467b48Spatrick       return true;
15809467b48Spatrick   return false;
15909467b48Spatrick }
16009467b48Spatrick 
isFixedInstr(const MachineInstr * MI) const16109467b48Spatrick bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const {
16209467b48Spatrick   if (MI->mayLoadOrStore())
16309467b48Spatrick     if (MemRefsFixed || isVolatileInstr(MI))
16409467b48Spatrick       return true;
16509467b48Spatrick   if (MI->isDebugInstr())
16609467b48Spatrick     return false;
16709467b48Spatrick 
16809467b48Spatrick   unsigned Opc = MI->getOpcode();
16909467b48Spatrick   switch (Opc) {
17009467b48Spatrick     default:
17109467b48Spatrick       return true;
17209467b48Spatrick 
17309467b48Spatrick     case TargetOpcode::PHI:
17409467b48Spatrick     case TargetOpcode::COPY:
17509467b48Spatrick       break;
17609467b48Spatrick 
17709467b48Spatrick     case Hexagon::L2_loadrd_io:
17809467b48Spatrick       // Not handling stack stores (only reg-based addresses).
17909467b48Spatrick       if (MI->getOperand(1).isReg())
18009467b48Spatrick         break;
18109467b48Spatrick       return true;
18209467b48Spatrick     case Hexagon::S2_storerd_io:
18309467b48Spatrick       // Not handling stack stores (only reg-based addresses).
18409467b48Spatrick       if (MI->getOperand(0).isReg())
18509467b48Spatrick         break;
18609467b48Spatrick       return true;
18709467b48Spatrick     case Hexagon::L2_loadrd_pi:
18809467b48Spatrick     case Hexagon::S2_storerd_pi:
18909467b48Spatrick 
19009467b48Spatrick     case Hexagon::A2_tfrpi:
19109467b48Spatrick     case Hexagon::A2_combineii:
19209467b48Spatrick     case Hexagon::A4_combineir:
19309467b48Spatrick     case Hexagon::A4_combineii:
19409467b48Spatrick     case Hexagon::A4_combineri:
19509467b48Spatrick     case Hexagon::A2_combinew:
19609467b48Spatrick     case Hexagon::CONST64:
19709467b48Spatrick 
19809467b48Spatrick     case Hexagon::A2_sxtw:
19909467b48Spatrick 
20009467b48Spatrick     case Hexagon::A2_andp:
20109467b48Spatrick     case Hexagon::A2_orp:
20209467b48Spatrick     case Hexagon::A2_xorp:
20309467b48Spatrick     case Hexagon::S2_asl_i_p_or:
20409467b48Spatrick     case Hexagon::S2_asl_i_p:
20509467b48Spatrick     case Hexagon::S2_asr_i_p:
20609467b48Spatrick     case Hexagon::S2_lsr_i_p:
20709467b48Spatrick       break;
20809467b48Spatrick   }
20909467b48Spatrick 
21009467b48Spatrick   for (auto &Op : MI->operands()) {
21109467b48Spatrick     if (!Op.isReg())
21209467b48Spatrick       continue;
21309467b48Spatrick     Register R = Op.getReg();
21473471bf0Spatrick     if (!R.isVirtual())
21509467b48Spatrick       return true;
21609467b48Spatrick   }
21709467b48Spatrick   return false;
21809467b48Spatrick }
21909467b48Spatrick 
partitionRegisters(UUSetMap & P2Rs)22009467b48Spatrick void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {
22109467b48Spatrick   using UUMap = std::map<unsigned, unsigned>;
22209467b48Spatrick   using UVect = std::vector<unsigned>;
22309467b48Spatrick 
22409467b48Spatrick   unsigned NumRegs = MRI->getNumVirtRegs();
22509467b48Spatrick   BitVector DoubleRegs(NumRegs);
22609467b48Spatrick   for (unsigned i = 0; i < NumRegs; ++i) {
227*d415bd75Srobert     Register R = Register::index2VirtReg(i);
22809467b48Spatrick     if (MRI->getRegClass(R) == DoubleRC)
22909467b48Spatrick       DoubleRegs.set(i);
23009467b48Spatrick   }
23109467b48Spatrick 
23209467b48Spatrick   BitVector FixedRegs(NumRegs);
23309467b48Spatrick   for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
234*d415bd75Srobert     Register R = Register::index2VirtReg(x);
23509467b48Spatrick     MachineInstr *DefI = MRI->getVRegDef(R);
23609467b48Spatrick     // In some cases a register may exist, but never be defined or used.
23709467b48Spatrick     // It should never appear anywhere, but mark it as "fixed", just to be
23809467b48Spatrick     // safe.
23909467b48Spatrick     if (!DefI || isFixedInstr(DefI))
24009467b48Spatrick       FixedRegs.set(x);
24109467b48Spatrick   }
24209467b48Spatrick 
24309467b48Spatrick   UUSetMap AssocMap;
24409467b48Spatrick   for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
24509467b48Spatrick     if (FixedRegs[x])
24609467b48Spatrick       continue;
247*d415bd75Srobert     Register R = Register::index2VirtReg(x);
24809467b48Spatrick     LLVM_DEBUG(dbgs() << printReg(R, TRI) << " ~~");
24909467b48Spatrick     USet &Asc = AssocMap[R];
25009467b48Spatrick     for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end();
25109467b48Spatrick          U != Z; ++U) {
25209467b48Spatrick       MachineOperand &Op = *U;
25309467b48Spatrick       MachineInstr *UseI = Op.getParent();
25409467b48Spatrick       if (isFixedInstr(UseI))
25509467b48Spatrick         continue;
25609467b48Spatrick       for (unsigned i = 0, n = UseI->getNumOperands(); i < n; ++i) {
25709467b48Spatrick         MachineOperand &MO = UseI->getOperand(i);
25809467b48Spatrick         // Skip non-registers or registers with subregisters.
25909467b48Spatrick         if (&MO == &Op || !MO.isReg() || MO.getSubReg())
26009467b48Spatrick           continue;
26109467b48Spatrick         Register T = MO.getReg();
26273471bf0Spatrick         if (!T.isVirtual()) {
26309467b48Spatrick           FixedRegs.set(x);
26409467b48Spatrick           continue;
26509467b48Spatrick         }
26609467b48Spatrick         if (MRI->getRegClass(T) != DoubleRC)
26709467b48Spatrick           continue;
26809467b48Spatrick         unsigned u = Register::virtReg2Index(T);
26909467b48Spatrick         if (FixedRegs[u])
27009467b48Spatrick           continue;
27109467b48Spatrick         LLVM_DEBUG(dbgs() << ' ' << printReg(T, TRI));
27209467b48Spatrick         Asc.insert(T);
27309467b48Spatrick         // Make it symmetric.
27409467b48Spatrick         AssocMap[T].insert(R);
27509467b48Spatrick       }
27609467b48Spatrick     }
27709467b48Spatrick     LLVM_DEBUG(dbgs() << '\n');
27809467b48Spatrick   }
27909467b48Spatrick 
28009467b48Spatrick   UUMap R2P;
28109467b48Spatrick   unsigned NextP = 1;
28209467b48Spatrick   USet Visited;
28309467b48Spatrick   for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
284*d415bd75Srobert     Register R = Register::index2VirtReg(x);
28509467b48Spatrick     if (Visited.count(R))
28609467b48Spatrick       continue;
28709467b48Spatrick     // Create a new partition for R.
28809467b48Spatrick     unsigned ThisP = FixedRegs[x] ? 0 : NextP++;
28909467b48Spatrick     UVect WorkQ;
29009467b48Spatrick     WorkQ.push_back(R);
29109467b48Spatrick     for (unsigned i = 0; i < WorkQ.size(); ++i) {
29209467b48Spatrick       unsigned T = WorkQ[i];
29309467b48Spatrick       if (Visited.count(T))
29409467b48Spatrick         continue;
29509467b48Spatrick       R2P[T] = ThisP;
29609467b48Spatrick       Visited.insert(T);
29709467b48Spatrick       // Add all registers associated with T.
29809467b48Spatrick       USet &Asc = AssocMap[T];
29973471bf0Spatrick       append_range(WorkQ, Asc);
30009467b48Spatrick     }
30109467b48Spatrick   }
30209467b48Spatrick 
30309467b48Spatrick   for (auto I : R2P)
30409467b48Spatrick     P2Rs[I.second].insert(I.first);
30509467b48Spatrick }
30609467b48Spatrick 
profitImm(unsigned Imm)30709467b48Spatrick static inline int32_t profitImm(unsigned Imm) {
30809467b48Spatrick   int32_t P = 0;
30909467b48Spatrick   if (Imm == 0 || Imm == 0xFFFFFFFF)
31009467b48Spatrick     P += 10;
31109467b48Spatrick   return P;
31209467b48Spatrick }
31309467b48Spatrick 
profit(const MachineInstr * MI) const31409467b48Spatrick int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const {
31509467b48Spatrick   unsigned ImmX = 0;
31609467b48Spatrick   unsigned Opc = MI->getOpcode();
31709467b48Spatrick   switch (Opc) {
31809467b48Spatrick     case TargetOpcode::PHI:
31909467b48Spatrick       for (const auto &Op : MI->operands())
32009467b48Spatrick         if (!Op.getSubReg())
32109467b48Spatrick           return 0;
32209467b48Spatrick       return 10;
32309467b48Spatrick     case TargetOpcode::COPY:
32409467b48Spatrick       if (MI->getOperand(1).getSubReg() != 0)
32509467b48Spatrick         return 10;
32609467b48Spatrick       return 0;
32709467b48Spatrick 
32809467b48Spatrick     case Hexagon::L2_loadrd_io:
32909467b48Spatrick     case Hexagon::S2_storerd_io:
33009467b48Spatrick       return -1;
33109467b48Spatrick     case Hexagon::L2_loadrd_pi:
33209467b48Spatrick     case Hexagon::S2_storerd_pi:
33309467b48Spatrick       return 2;
33409467b48Spatrick 
33509467b48Spatrick     case Hexagon::A2_tfrpi:
33609467b48Spatrick     case Hexagon::CONST64: {
33709467b48Spatrick       uint64_t D = MI->getOperand(1).getImm();
33809467b48Spatrick       unsigned Lo = D & 0xFFFFFFFFULL;
33909467b48Spatrick       unsigned Hi = D >> 32;
34009467b48Spatrick       return profitImm(Lo) + profitImm(Hi);
34109467b48Spatrick     }
34209467b48Spatrick     case Hexagon::A2_combineii:
34309467b48Spatrick     case Hexagon::A4_combineii: {
34409467b48Spatrick       const MachineOperand &Op1 = MI->getOperand(1);
34509467b48Spatrick       const MachineOperand &Op2 = MI->getOperand(2);
34609467b48Spatrick       int32_t Prof1 = Op1.isImm() ? profitImm(Op1.getImm()) : 0;
34709467b48Spatrick       int32_t Prof2 = Op2.isImm() ? profitImm(Op2.getImm()) : 0;
34809467b48Spatrick       return Prof1 + Prof2;
34909467b48Spatrick     }
35009467b48Spatrick     case Hexagon::A4_combineri:
35109467b48Spatrick       ImmX++;
35209467b48Spatrick       // Fall through into A4_combineir.
353*d415bd75Srobert       [[fallthrough]];
35409467b48Spatrick     case Hexagon::A4_combineir: {
35509467b48Spatrick       ImmX++;
35609467b48Spatrick       const MachineOperand &OpX = MI->getOperand(ImmX);
35709467b48Spatrick       if (OpX.isImm()) {
35809467b48Spatrick         int64_t V = OpX.getImm();
35909467b48Spatrick         if (V == 0 || V == -1)
36009467b48Spatrick           return 10;
36109467b48Spatrick       }
36209467b48Spatrick       // Fall through into A2_combinew.
363*d415bd75Srobert       [[fallthrough]];
36409467b48Spatrick     }
36509467b48Spatrick     case Hexagon::A2_combinew:
36609467b48Spatrick       return 2;
36709467b48Spatrick 
36809467b48Spatrick     case Hexagon::A2_sxtw:
36909467b48Spatrick       return 3;
37009467b48Spatrick 
37109467b48Spatrick     case Hexagon::A2_andp:
37209467b48Spatrick     case Hexagon::A2_orp:
37309467b48Spatrick     case Hexagon::A2_xorp: {
37409467b48Spatrick       Register Rs = MI->getOperand(1).getReg();
37509467b48Spatrick       Register Rt = MI->getOperand(2).getReg();
37609467b48Spatrick       return profit(Rs) + profit(Rt);
37709467b48Spatrick     }
37809467b48Spatrick 
37909467b48Spatrick     case Hexagon::S2_asl_i_p_or: {
38009467b48Spatrick       unsigned S = MI->getOperand(3).getImm();
38109467b48Spatrick       if (S == 0 || S == 32)
38209467b48Spatrick         return 10;
38309467b48Spatrick       return -1;
38409467b48Spatrick     }
38509467b48Spatrick     case Hexagon::S2_asl_i_p:
38609467b48Spatrick     case Hexagon::S2_asr_i_p:
38709467b48Spatrick     case Hexagon::S2_lsr_i_p:
38809467b48Spatrick       unsigned S = MI->getOperand(2).getImm();
38909467b48Spatrick       if (S == 0 || S == 32)
39009467b48Spatrick         return 10;
39109467b48Spatrick       if (S == 16)
39209467b48Spatrick         return 5;
39309467b48Spatrick       if (S == 48)
39409467b48Spatrick         return 7;
39509467b48Spatrick       return -10;
39609467b48Spatrick   }
39709467b48Spatrick 
39809467b48Spatrick   return 0;
39909467b48Spatrick }
40009467b48Spatrick 
profit(Register Reg) const40173471bf0Spatrick int32_t HexagonSplitDoubleRegs::profit(Register Reg) const {
40273471bf0Spatrick   assert(Reg.isVirtual());
40309467b48Spatrick 
40409467b48Spatrick   const MachineInstr *DefI = MRI->getVRegDef(Reg);
40509467b48Spatrick   switch (DefI->getOpcode()) {
40609467b48Spatrick     case Hexagon::A2_tfrpi:
40709467b48Spatrick     case Hexagon::CONST64:
40809467b48Spatrick     case Hexagon::A2_combineii:
40909467b48Spatrick     case Hexagon::A4_combineii:
41009467b48Spatrick     case Hexagon::A4_combineri:
41109467b48Spatrick     case Hexagon::A4_combineir:
41209467b48Spatrick     case Hexagon::A2_combinew:
41309467b48Spatrick       return profit(DefI);
41409467b48Spatrick     default:
41509467b48Spatrick       break;
41609467b48Spatrick   }
41709467b48Spatrick   return 0;
41809467b48Spatrick }
41909467b48Spatrick 
isProfitable(const USet & Part,LoopRegMap & IRM) const42009467b48Spatrick bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM)
42109467b48Spatrick       const {
42209467b48Spatrick   unsigned FixedNum = 0, LoopPhiNum = 0;
42309467b48Spatrick   int32_t TotalP = 0;
42409467b48Spatrick 
42509467b48Spatrick   for (unsigned DR : Part) {
42609467b48Spatrick     MachineInstr *DefI = MRI->getVRegDef(DR);
42709467b48Spatrick     int32_t P = profit(DefI);
42809467b48Spatrick     if (P == std::numeric_limits<int>::min())
42909467b48Spatrick       return false;
43009467b48Spatrick     TotalP += P;
43109467b48Spatrick     // Reduce the profitability of splitting induction registers.
43209467b48Spatrick     if (isInduction(DR, IRM))
43309467b48Spatrick       TotalP -= 30;
43409467b48Spatrick 
43509467b48Spatrick     for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
43609467b48Spatrick          U != W; ++U) {
43709467b48Spatrick       MachineInstr *UseI = U->getParent();
43809467b48Spatrick       if (isFixedInstr(UseI)) {
43909467b48Spatrick         FixedNum++;
44009467b48Spatrick         // Calculate the cost of generating REG_SEQUENCE instructions.
44109467b48Spatrick         for (auto &Op : UseI->operands()) {
44209467b48Spatrick           if (Op.isReg() && Part.count(Op.getReg()))
44309467b48Spatrick             if (Op.getSubReg())
44409467b48Spatrick               TotalP -= 2;
44509467b48Spatrick         }
44609467b48Spatrick         continue;
44709467b48Spatrick       }
44809467b48Spatrick       // If a register from this partition is used in a fixed instruction,
44909467b48Spatrick       // and there is also a register in this partition that is used in
45009467b48Spatrick       // a loop phi node, then decrease the splitting profit as this can
45109467b48Spatrick       // confuse the modulo scheduler.
45209467b48Spatrick       if (UseI->isPHI()) {
45309467b48Spatrick         const MachineBasicBlock *PB = UseI->getParent();
45409467b48Spatrick         const MachineLoop *L = MLI->getLoopFor(PB);
45509467b48Spatrick         if (L && L->getHeader() == PB)
45609467b48Spatrick           LoopPhiNum++;
45709467b48Spatrick       }
45809467b48Spatrick       // Splittable instruction.
45909467b48Spatrick       int32_t P = profit(UseI);
46009467b48Spatrick       if (P == std::numeric_limits<int>::min())
46109467b48Spatrick         return false;
46209467b48Spatrick       TotalP += P;
46309467b48Spatrick     }
46409467b48Spatrick   }
46509467b48Spatrick 
46609467b48Spatrick   if (FixedNum > 0 && LoopPhiNum > 0)
46709467b48Spatrick     TotalP -= 20*LoopPhiNum;
46809467b48Spatrick 
46909467b48Spatrick   LLVM_DEBUG(dbgs() << "Partition profit: " << TotalP << '\n');
47009467b48Spatrick   if (SplitAll)
47109467b48Spatrick     return true;
47209467b48Spatrick   return TotalP > 0;
47309467b48Spatrick }
47409467b48Spatrick 
collectIndRegsForLoop(const MachineLoop * L,USet & Rs)47509467b48Spatrick void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L,
47609467b48Spatrick       USet &Rs) {
47709467b48Spatrick   const MachineBasicBlock *HB = L->getHeader();
47809467b48Spatrick   const MachineBasicBlock *LB = L->getLoopLatch();
47909467b48Spatrick   if (!HB || !LB)
48009467b48Spatrick     return;
48109467b48Spatrick 
48209467b48Spatrick   // Examine the latch branch. Expect it to be a conditional branch to
48309467b48Spatrick   // the header (either "br-cond header" or "br-cond exit; br header").
48409467b48Spatrick   MachineBasicBlock *TB = nullptr, *FB = nullptr;
48509467b48Spatrick   MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB);
48609467b48Spatrick   SmallVector<MachineOperand,2> Cond;
48709467b48Spatrick   bool BadLB = TII->analyzeBranch(*TmpLB, TB, FB, Cond, false);
48809467b48Spatrick   // Only analyzable conditional branches. HII::analyzeBranch will put
48909467b48Spatrick   // the branch opcode as the first element of Cond, and the predicate
49009467b48Spatrick   // operand as the second.
49109467b48Spatrick   if (BadLB || Cond.size() != 2)
49209467b48Spatrick     return;
49309467b48Spatrick   // Only simple jump-conditional (with or without negation).
49409467b48Spatrick   if (!TII->PredOpcodeHasJMP_c(Cond[0].getImm()))
49509467b48Spatrick     return;
49609467b48Spatrick   // Must go to the header.
49709467b48Spatrick   if (TB != HB && FB != HB)
49809467b48Spatrick     return;
49909467b48Spatrick   assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch");
50009467b48Spatrick   // Expect a predicate register.
50109467b48Spatrick   Register PR = Cond[1].getReg();
50209467b48Spatrick   assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);
50309467b48Spatrick 
50409467b48Spatrick   // Get the registers on which the loop controlling compare instruction
50509467b48Spatrick   // depends.
506097a140dSpatrick   Register CmpR1, CmpR2;
50709467b48Spatrick   const MachineInstr *CmpI = MRI->getVRegDef(PR);
50809467b48Spatrick   while (CmpI->getOpcode() == Hexagon::C2_not)
50909467b48Spatrick     CmpI = MRI->getVRegDef(CmpI->getOperand(1).getReg());
51009467b48Spatrick 
511*d415bd75Srobert   int64_t Mask = 0, Val = 0;
51209467b48Spatrick   bool OkCI = TII->analyzeCompare(*CmpI, CmpR1, CmpR2, Mask, Val);
51309467b48Spatrick   if (!OkCI)
51409467b48Spatrick     return;
51509467b48Spatrick   // Eliminate non-double input registers.
51609467b48Spatrick   if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC)
51709467b48Spatrick     CmpR1 = 0;
51809467b48Spatrick   if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC)
51909467b48Spatrick     CmpR2 = 0;
52009467b48Spatrick   if (!CmpR1 && !CmpR2)
52109467b48Spatrick     return;
52209467b48Spatrick 
52309467b48Spatrick   // Now examine the top of the loop: the phi nodes that could poten-
52409467b48Spatrick   // tially define loop induction registers. The registers defined by
52509467b48Spatrick   // such a phi node would be used in a 64-bit add, which then would
52609467b48Spatrick   // be used in the loop compare instruction.
52709467b48Spatrick 
52809467b48Spatrick   // Get the set of all double registers defined by phi nodes in the
52909467b48Spatrick   // loop header.
53009467b48Spatrick   using UVect = std::vector<unsigned>;
53109467b48Spatrick 
53209467b48Spatrick   UVect DP;
53309467b48Spatrick   for (auto &MI : *HB) {
53409467b48Spatrick     if (!MI.isPHI())
53509467b48Spatrick       break;
53609467b48Spatrick     const MachineOperand &MD = MI.getOperand(0);
53709467b48Spatrick     Register R = MD.getReg();
53809467b48Spatrick     if (MRI->getRegClass(R) == DoubleRC)
53909467b48Spatrick       DP.push_back(R);
54009467b48Spatrick   }
54109467b48Spatrick   if (DP.empty())
54209467b48Spatrick     return;
54309467b48Spatrick 
54409467b48Spatrick   auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool {
54509467b48Spatrick     for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end();
54609467b48Spatrick          I != E; ++I) {
54709467b48Spatrick       const MachineInstr *UseI = I->getParent();
54809467b48Spatrick       if (UseI->getOpcode() != Hexagon::A2_addp)
54909467b48Spatrick         continue;
55009467b48Spatrick       // Get the output from the add. If it is one of the inputs to the
55109467b48Spatrick       // loop-controlling compare instruction, then R is likely an induc-
55209467b48Spatrick       // tion register.
55309467b48Spatrick       Register T = UseI->getOperand(0).getReg();
55409467b48Spatrick       if (T == CmpR1 || T == CmpR2)
55509467b48Spatrick         return false;
55609467b48Spatrick     }
55709467b48Spatrick     return true;
55809467b48Spatrick   };
55909467b48Spatrick   UVect::iterator End = llvm::remove_if(DP, NoIndOp);
56009467b48Spatrick   Rs.insert(DP.begin(), End);
56109467b48Spatrick   Rs.insert(CmpR1);
56209467b48Spatrick   Rs.insert(CmpR2);
56309467b48Spatrick 
56409467b48Spatrick   LLVM_DEBUG({
56509467b48Spatrick     dbgs() << "For loop at " << printMBBReference(*HB) << " ind regs: ";
56609467b48Spatrick     dump_partition(dbgs(), Rs, *TRI);
56709467b48Spatrick     dbgs() << '\n';
56809467b48Spatrick   });
56909467b48Spatrick }
57009467b48Spatrick 
collectIndRegs(LoopRegMap & IRM)57109467b48Spatrick void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {
57209467b48Spatrick   using LoopVector = std::vector<MachineLoop *>;
57309467b48Spatrick 
57409467b48Spatrick   LoopVector WorkQ;
57509467b48Spatrick 
57673471bf0Spatrick   append_range(WorkQ, *MLI);
57773471bf0Spatrick   for (unsigned i = 0; i < WorkQ.size(); ++i)
57873471bf0Spatrick     append_range(WorkQ, *WorkQ[i]);
57909467b48Spatrick 
58009467b48Spatrick   USet Rs;
581*d415bd75Srobert   for (MachineLoop *L : WorkQ) {
58209467b48Spatrick     Rs.clear();
58309467b48Spatrick     collectIndRegsForLoop(L, Rs);
58409467b48Spatrick     if (!Rs.empty())
58509467b48Spatrick       IRM.insert(std::make_pair(L, Rs));
58609467b48Spatrick   }
58709467b48Spatrick }
58809467b48Spatrick 
createHalfInstr(unsigned Opc,MachineInstr * MI,const UUPairMap & PairMap,unsigned SubR)58909467b48Spatrick void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI,
59009467b48Spatrick       const UUPairMap &PairMap, unsigned SubR) {
59109467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
59209467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
59309467b48Spatrick   MachineInstr *NewI = BuildMI(B, MI, DL, TII->get(Opc));
59409467b48Spatrick 
59509467b48Spatrick   for (auto &Op : MI->operands()) {
59609467b48Spatrick     if (!Op.isReg()) {
59709467b48Spatrick       NewI->addOperand(Op);
59809467b48Spatrick       continue;
59909467b48Spatrick     }
60009467b48Spatrick     // For register operands, set the subregister.
60109467b48Spatrick     Register R = Op.getReg();
60209467b48Spatrick     unsigned SR = Op.getSubReg();
60373471bf0Spatrick     bool isVirtReg = R.isVirtual();
60409467b48Spatrick     bool isKill = Op.isKill();
60509467b48Spatrick     if (isVirtReg && MRI->getRegClass(R) == DoubleRC) {
60609467b48Spatrick       isKill = false;
60709467b48Spatrick       UUPairMap::const_iterator F = PairMap.find(R);
60809467b48Spatrick       if (F == PairMap.end()) {
60909467b48Spatrick         SR = SubR;
61009467b48Spatrick       } else {
61109467b48Spatrick         const UUPair &P = F->second;
61209467b48Spatrick         R = (SubR == Hexagon::isub_lo) ? P.first : P.second;
61309467b48Spatrick         SR = 0;
61409467b48Spatrick       }
61509467b48Spatrick     }
61609467b48Spatrick     auto CO = MachineOperand::CreateReg(R, Op.isDef(), Op.isImplicit(), isKill,
61709467b48Spatrick           Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(),
61809467b48Spatrick           Op.isInternalRead());
61909467b48Spatrick     NewI->addOperand(CO);
62009467b48Spatrick   }
62109467b48Spatrick }
62209467b48Spatrick 
splitMemRef(MachineInstr * MI,const UUPairMap & PairMap)62309467b48Spatrick void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI,
62409467b48Spatrick       const UUPairMap &PairMap) {
62509467b48Spatrick   bool Load = MI->mayLoad();
62609467b48Spatrick   unsigned OrigOpc = MI->getOpcode();
62709467b48Spatrick   bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||
62809467b48Spatrick                   OrigOpc == Hexagon::S2_storerd_pi);
62909467b48Spatrick   MachineInstr *LowI, *HighI;
63009467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
63109467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
63209467b48Spatrick 
63309467b48Spatrick   // Index of the base-address-register operand.
63409467b48Spatrick   unsigned AdrX = PostInc ? (Load ? 2 : 1)
63509467b48Spatrick                           : (Load ? 1 : 0);
63609467b48Spatrick   MachineOperand &AdrOp = MI->getOperand(AdrX);
63709467b48Spatrick   unsigned RSA = getRegState(AdrOp);
63809467b48Spatrick   MachineOperand &ValOp = Load ? MI->getOperand(0)
63909467b48Spatrick                                : (PostInc ? MI->getOperand(3)
64009467b48Spatrick                                           : MI->getOperand(2));
64109467b48Spatrick   UUPairMap::const_iterator F = PairMap.find(ValOp.getReg());
64209467b48Spatrick   assert(F != PairMap.end());
64309467b48Spatrick 
64409467b48Spatrick   if (Load) {
64509467b48Spatrick     const UUPair &P = F->second;
64609467b48Spatrick     int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm();
64709467b48Spatrick     LowI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.first)
64809467b48Spatrick              .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
64909467b48Spatrick              .addImm(Off);
65009467b48Spatrick     HighI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.second)
65109467b48Spatrick               .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
65209467b48Spatrick               .addImm(Off+4);
65309467b48Spatrick   } else {
65409467b48Spatrick     const UUPair &P = F->second;
65509467b48Spatrick     int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm();
65609467b48Spatrick     LowI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
65709467b48Spatrick              .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
65809467b48Spatrick              .addImm(Off)
65909467b48Spatrick              .addReg(P.first);
66009467b48Spatrick     HighI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
66109467b48Spatrick               .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
66209467b48Spatrick               .addImm(Off+4)
66309467b48Spatrick               .addReg(P.second);
66409467b48Spatrick   }
66509467b48Spatrick 
66609467b48Spatrick   if (PostInc) {
66709467b48Spatrick     // Create the increment of the address register.
66809467b48Spatrick     int64_t Inc = Load ? MI->getOperand(3).getImm()
66909467b48Spatrick                        : MI->getOperand(2).getImm();
67009467b48Spatrick     MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0);
67109467b48Spatrick     const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg());
67209467b48Spatrick     Register NewR = MRI->createVirtualRegister(RC);
67309467b48Spatrick     assert(!UpdOp.getSubReg() && "Def operand with subreg");
67409467b48Spatrick     BuildMI(B, MI, DL, TII->get(Hexagon::A2_addi), NewR)
67509467b48Spatrick       .addReg(AdrOp.getReg(), RSA)
67609467b48Spatrick       .addImm(Inc);
67709467b48Spatrick     MRI->replaceRegWith(UpdOp.getReg(), NewR);
67809467b48Spatrick     // The original instruction will be deleted later.
67909467b48Spatrick   }
68009467b48Spatrick 
68109467b48Spatrick   // Generate a new pair of memory-operands.
68209467b48Spatrick   MachineFunction &MF = *B.getParent();
68309467b48Spatrick   for (auto &MO : MI->memoperands()) {
68409467b48Spatrick     const MachinePointerInfo &Ptr = MO->getPointerInfo();
68509467b48Spatrick     MachineMemOperand::Flags F = MO->getFlags();
686097a140dSpatrick     Align A = MO->getAlign();
68709467b48Spatrick 
68809467b48Spatrick     auto *Tmp1 = MF.getMachineMemOperand(Ptr, F, 4 /*size*/, A);
68909467b48Spatrick     LowI->addMemOperand(MF, Tmp1);
690097a140dSpatrick     auto *Tmp2 =
691097a140dSpatrick         MF.getMachineMemOperand(Ptr, F, 4 /*size*/, std::min(A, Align(4)));
69209467b48Spatrick     HighI->addMemOperand(MF, Tmp2);
69309467b48Spatrick   }
69409467b48Spatrick }
69509467b48Spatrick 
splitImmediate(MachineInstr * MI,const UUPairMap & PairMap)69609467b48Spatrick void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI,
69709467b48Spatrick       const UUPairMap &PairMap) {
69809467b48Spatrick   MachineOperand &Op0 = MI->getOperand(0);
69909467b48Spatrick   MachineOperand &Op1 = MI->getOperand(1);
70009467b48Spatrick   assert(Op0.isReg() && Op1.isImm());
70109467b48Spatrick   uint64_t V = Op1.getImm();
70209467b48Spatrick 
70309467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
70409467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
70509467b48Spatrick   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
70609467b48Spatrick   assert(F != PairMap.end());
70709467b48Spatrick   const UUPair &P = F->second;
70809467b48Spatrick 
70909467b48Spatrick   // The operand to A2_tfrsi can only have 32 significant bits. Immediate
71009467b48Spatrick   // values in MachineOperand are stored as 64-bit integers, and so the
71109467b48Spatrick   // value -1 may be represented either as 64-bit -1, or 4294967295. Both
71209467b48Spatrick   // will have the 32 higher bits truncated in the end, but -1 will remain
71309467b48Spatrick   // as -1, while the latter may appear to be a large unsigned value
71409467b48Spatrick   // requiring a constant extender. The casting to int32_t will select the
71509467b48Spatrick   // former representation. (The same reasoning applies to all 32-bit
71609467b48Spatrick   // values.)
71709467b48Spatrick   BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
71809467b48Spatrick     .addImm(int32_t(V & 0xFFFFFFFFULL));
71909467b48Spatrick   BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
72009467b48Spatrick     .addImm(int32_t(V >> 32));
72109467b48Spatrick }
72209467b48Spatrick 
splitCombine(MachineInstr * MI,const UUPairMap & PairMap)72309467b48Spatrick void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI,
72409467b48Spatrick       const UUPairMap &PairMap) {
72509467b48Spatrick   MachineOperand &Op0 = MI->getOperand(0);
72609467b48Spatrick   MachineOperand &Op1 = MI->getOperand(1);
72709467b48Spatrick   MachineOperand &Op2 = MI->getOperand(2);
72809467b48Spatrick   assert(Op0.isReg());
72909467b48Spatrick 
73009467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
73109467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
73209467b48Spatrick   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
73309467b48Spatrick   assert(F != PairMap.end());
73409467b48Spatrick   const UUPair &P = F->second;
73509467b48Spatrick 
73609467b48Spatrick   if (!Op1.isReg()) {
73709467b48Spatrick     BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
73809467b48Spatrick       .add(Op1);
73909467b48Spatrick   } else {
74009467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.second)
74109467b48Spatrick       .addReg(Op1.getReg(), getRegState(Op1), Op1.getSubReg());
74209467b48Spatrick   }
74309467b48Spatrick 
74409467b48Spatrick   if (!Op2.isReg()) {
74509467b48Spatrick     BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
74609467b48Spatrick       .add(Op2);
74709467b48Spatrick   } else {
74809467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
74909467b48Spatrick       .addReg(Op2.getReg(), getRegState(Op2), Op2.getSubReg());
75009467b48Spatrick   }
75109467b48Spatrick }
75209467b48Spatrick 
splitExt(MachineInstr * MI,const UUPairMap & PairMap)75309467b48Spatrick void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI,
75409467b48Spatrick       const UUPairMap &PairMap) {
75509467b48Spatrick   MachineOperand &Op0 = MI->getOperand(0);
75609467b48Spatrick   MachineOperand &Op1 = MI->getOperand(1);
75709467b48Spatrick   assert(Op0.isReg() && Op1.isReg());
75809467b48Spatrick 
75909467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
76009467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
76109467b48Spatrick   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
76209467b48Spatrick   assert(F != PairMap.end());
76309467b48Spatrick   const UUPair &P = F->second;
76409467b48Spatrick   unsigned RS = getRegState(Op1);
76509467b48Spatrick 
76609467b48Spatrick   BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
76709467b48Spatrick     .addReg(Op1.getReg(), RS & ~RegState::Kill, Op1.getSubReg());
76809467b48Spatrick   BuildMI(B, MI, DL, TII->get(Hexagon::S2_asr_i_r), P.second)
76909467b48Spatrick     .addReg(Op1.getReg(), RS, Op1.getSubReg())
77009467b48Spatrick     .addImm(31);
77109467b48Spatrick }
77209467b48Spatrick 
splitShift(MachineInstr * MI,const UUPairMap & PairMap)77309467b48Spatrick void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI,
77409467b48Spatrick       const UUPairMap &PairMap) {
77509467b48Spatrick   using namespace Hexagon;
77609467b48Spatrick 
77709467b48Spatrick   MachineOperand &Op0 = MI->getOperand(0);
77809467b48Spatrick   MachineOperand &Op1 = MI->getOperand(1);
77909467b48Spatrick   MachineOperand &Op2 = MI->getOperand(2);
78009467b48Spatrick   assert(Op0.isReg() && Op1.isReg() && Op2.isImm());
78109467b48Spatrick   int64_t Sh64 = Op2.getImm();
78209467b48Spatrick   assert(Sh64 >= 0 && Sh64 < 64);
78309467b48Spatrick   unsigned S = Sh64;
78409467b48Spatrick 
78509467b48Spatrick   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
78609467b48Spatrick   assert(F != PairMap.end());
78709467b48Spatrick   const UUPair &P = F->second;
78809467b48Spatrick   Register LoR = P.first;
78909467b48Spatrick   Register HiR = P.second;
79009467b48Spatrick 
79109467b48Spatrick   unsigned Opc = MI->getOpcode();
79209467b48Spatrick   bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);
79309467b48Spatrick   bool Left = !Right;
79409467b48Spatrick   bool Signed = (Opc == S2_asr_i_p);
79509467b48Spatrick 
79609467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
79709467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
79809467b48Spatrick   unsigned RS = getRegState(Op1);
79909467b48Spatrick   unsigned ShiftOpc = Left ? S2_asl_i_r
80009467b48Spatrick                            : (Signed ? S2_asr_i_r : S2_lsr_i_r);
80109467b48Spatrick   unsigned LoSR = isub_lo;
80209467b48Spatrick   unsigned HiSR = isub_hi;
80309467b48Spatrick 
80409467b48Spatrick   if (S == 0) {
80509467b48Spatrick     // No shift, subregister copy.
80609467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
80709467b48Spatrick       .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
80809467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), HiR)
80909467b48Spatrick       .addReg(Op1.getReg(), RS, HiSR);
81009467b48Spatrick   } else if (S < 32) {
81109467b48Spatrick     const TargetRegisterClass *IntRC = &IntRegsRegClass;
81209467b48Spatrick     Register TmpR = MRI->createVirtualRegister(IntRC);
81309467b48Spatrick     // Expansion:
81409467b48Spatrick     // Shift left:    DR = shl R, #s
81509467b48Spatrick     //   LoR  = shl R.lo, #s
81609467b48Spatrick     //   TmpR = extractu R.lo, #s, #32-s
81709467b48Spatrick     //   HiR  = or (TmpR, asl(R.hi, #s))
81809467b48Spatrick     // Shift right:   DR = shr R, #s
81909467b48Spatrick     //   HiR  = shr R.hi, #s
82009467b48Spatrick     //   TmpR = shr R.lo, #s
82109467b48Spatrick     //   LoR  = insert TmpR, R.hi, #s, #32-s
82209467b48Spatrick 
82309467b48Spatrick     // Shift left:
82409467b48Spatrick     //   LoR  = shl R.lo, #s
82509467b48Spatrick     // Shift right:
82609467b48Spatrick     //   TmpR = shr R.lo, #s
82709467b48Spatrick 
82809467b48Spatrick     // Make a special case for A2_aslh and A2_asrh (they are predicable as
82909467b48Spatrick     // opposed to S2_asl_i_r/S2_asr_i_r).
83009467b48Spatrick     if (S == 16 && Left)
83109467b48Spatrick       BuildMI(B, MI, DL, TII->get(A2_aslh), LoR)
83209467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
83309467b48Spatrick     else if (S == 16 && Signed)
83409467b48Spatrick       BuildMI(B, MI, DL, TII->get(A2_asrh), TmpR)
83509467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
83609467b48Spatrick     else
83709467b48Spatrick       BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? LoR : TmpR))
83809467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
83909467b48Spatrick         .addImm(S);
84009467b48Spatrick 
84109467b48Spatrick     if (Left) {
84209467b48Spatrick       // TmpR = extractu R.lo, #s, #32-s
84309467b48Spatrick       BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR)
84409467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
84509467b48Spatrick         .addImm(S)
84609467b48Spatrick         .addImm(32-S);
84709467b48Spatrick       // HiR  = or (TmpR, asl(R.hi, #s))
84809467b48Spatrick       BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
84909467b48Spatrick         .addReg(TmpR)
85009467b48Spatrick         .addReg(Op1.getReg(), RS, HiSR)
85109467b48Spatrick         .addImm(S);
85209467b48Spatrick     } else {
85309467b48Spatrick       // HiR  = shr R.hi, #s
85409467b48Spatrick       BuildMI(B, MI, DL, TII->get(ShiftOpc), HiR)
85509467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR)
85609467b48Spatrick         .addImm(S);
85709467b48Spatrick       // LoR  = insert TmpR, R.hi, #s, #32-s
85809467b48Spatrick       BuildMI(B, MI, DL, TII->get(S2_insert), LoR)
85909467b48Spatrick         .addReg(TmpR)
86009467b48Spatrick         .addReg(Op1.getReg(), RS, HiSR)
86109467b48Spatrick         .addImm(S)
86209467b48Spatrick         .addImm(32-S);
86309467b48Spatrick     }
86409467b48Spatrick   } else if (S == 32) {
86509467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), (Left ? HiR : LoR))
86609467b48Spatrick       .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR));
86709467b48Spatrick     if (!Signed)
86809467b48Spatrick       BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
86909467b48Spatrick         .addImm(0);
87009467b48Spatrick     else  // Must be right shift.
87109467b48Spatrick       BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
87209467b48Spatrick         .addReg(Op1.getReg(), RS, HiSR)
87309467b48Spatrick         .addImm(31);
87409467b48Spatrick   } else if (S < 64) {
87509467b48Spatrick     S -= 32;
87609467b48Spatrick     if (S == 16 && Left)
87709467b48Spatrick       BuildMI(B, MI, DL, TII->get(A2_aslh), HiR)
87809467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
87909467b48Spatrick     else if (S == 16 && Signed)
88009467b48Spatrick       BuildMI(B, MI, DL, TII->get(A2_asrh), LoR)
88109467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR);
88209467b48Spatrick     else
88309467b48Spatrick       BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? HiR : LoR))
88409467b48Spatrick         .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR))
88509467b48Spatrick         .addImm(S);
88609467b48Spatrick 
88709467b48Spatrick     if (Signed)
88809467b48Spatrick       BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
88909467b48Spatrick         .addReg(Op1.getReg(), RS, HiSR)
89009467b48Spatrick         .addImm(31);
89109467b48Spatrick     else
89209467b48Spatrick       BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
89309467b48Spatrick         .addImm(0);
89409467b48Spatrick   }
89509467b48Spatrick }
89609467b48Spatrick 
splitAslOr(MachineInstr * MI,const UUPairMap & PairMap)89709467b48Spatrick void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI,
89809467b48Spatrick       const UUPairMap &PairMap) {
89909467b48Spatrick   using namespace Hexagon;
90009467b48Spatrick 
90109467b48Spatrick   MachineOperand &Op0 = MI->getOperand(0);
90209467b48Spatrick   MachineOperand &Op1 = MI->getOperand(1);
90309467b48Spatrick   MachineOperand &Op2 = MI->getOperand(2);
90409467b48Spatrick   MachineOperand &Op3 = MI->getOperand(3);
90509467b48Spatrick   assert(Op0.isReg() && Op1.isReg() && Op2.isReg() && Op3.isImm());
90609467b48Spatrick   int64_t Sh64 = Op3.getImm();
90709467b48Spatrick   assert(Sh64 >= 0 && Sh64 < 64);
90809467b48Spatrick   unsigned S = Sh64;
90909467b48Spatrick 
91009467b48Spatrick   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
91109467b48Spatrick   assert(F != PairMap.end());
91209467b48Spatrick   const UUPair &P = F->second;
91309467b48Spatrick   unsigned LoR = P.first;
91409467b48Spatrick   unsigned HiR = P.second;
91509467b48Spatrick 
91609467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
91709467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
91809467b48Spatrick   unsigned RS1 = getRegState(Op1);
91909467b48Spatrick   unsigned RS2 = getRegState(Op2);
92009467b48Spatrick   const TargetRegisterClass *IntRC = &IntRegsRegClass;
92109467b48Spatrick 
92209467b48Spatrick   unsigned LoSR = isub_lo;
92309467b48Spatrick   unsigned HiSR = isub_hi;
92409467b48Spatrick 
92509467b48Spatrick   // Op0 = S2_asl_i_p_or Op1, Op2, Op3
92609467b48Spatrick   // means:  Op0 = or (Op1, asl(Op2, Op3))
92709467b48Spatrick 
92809467b48Spatrick   // Expansion of
92909467b48Spatrick   //   DR = or (R1, asl(R2, #s))
93009467b48Spatrick   //
93109467b48Spatrick   //   LoR  = or (R1.lo, asl(R2.lo, #s))
93209467b48Spatrick   //   Tmp1 = extractu R2.lo, #s, #32-s
93309467b48Spatrick   //   Tmp2 = or R1.hi, Tmp1
93409467b48Spatrick   //   HiR  = or (Tmp2, asl(R2.hi, #s))
93509467b48Spatrick 
93609467b48Spatrick   if (S == 0) {
93709467b48Spatrick     // DR  = or (R1, asl(R2, #0))
93809467b48Spatrick     //    -> or (R1, R2)
93909467b48Spatrick     // i.e. LoR = or R1.lo, R2.lo
94009467b48Spatrick     //      HiR = or R1.hi, R2.hi
94109467b48Spatrick     BuildMI(B, MI, DL, TII->get(A2_or), LoR)
94209467b48Spatrick       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
94309467b48Spatrick       .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR);
94409467b48Spatrick     BuildMI(B, MI, DL, TII->get(A2_or), HiR)
94509467b48Spatrick       .addReg(Op1.getReg(), RS1, HiSR)
94609467b48Spatrick       .addReg(Op2.getReg(), RS2, HiSR);
94709467b48Spatrick   } else if (S < 32) {
94809467b48Spatrick     BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), LoR)
94909467b48Spatrick       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
95009467b48Spatrick       .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
95109467b48Spatrick       .addImm(S);
95209467b48Spatrick     Register TmpR1 = MRI->createVirtualRegister(IntRC);
95309467b48Spatrick     BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR1)
95409467b48Spatrick       .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
95509467b48Spatrick       .addImm(S)
95609467b48Spatrick       .addImm(32-S);
95709467b48Spatrick     Register TmpR2 = MRI->createVirtualRegister(IntRC);
95809467b48Spatrick     BuildMI(B, MI, DL, TII->get(A2_or), TmpR2)
95909467b48Spatrick       .addReg(Op1.getReg(), RS1, HiSR)
96009467b48Spatrick       .addReg(TmpR1);
96109467b48Spatrick     BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
96209467b48Spatrick       .addReg(TmpR2)
96309467b48Spatrick       .addReg(Op2.getReg(), RS2, HiSR)
96409467b48Spatrick       .addImm(S);
96509467b48Spatrick   } else if (S == 32) {
96609467b48Spatrick     // DR  = or (R1, asl(R2, #32))
96709467b48Spatrick     //    -> or R1, R2.lo
96809467b48Spatrick     // LoR = R1.lo
96909467b48Spatrick     // HiR = or R1.hi, R2.lo
97009467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
97109467b48Spatrick       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
97209467b48Spatrick     BuildMI(B, MI, DL, TII->get(A2_or), HiR)
97309467b48Spatrick       .addReg(Op1.getReg(), RS1, HiSR)
97409467b48Spatrick       .addReg(Op2.getReg(), RS2, LoSR);
97509467b48Spatrick   } else if (S < 64) {
97609467b48Spatrick     // DR  = or (R1, asl(R2, #s))
97709467b48Spatrick     //
97809467b48Spatrick     // LoR = R1:lo
97909467b48Spatrick     // HiR = or (R1:hi, asl(R2:lo, #s-32))
98009467b48Spatrick     S -= 32;
98109467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
98209467b48Spatrick       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
98309467b48Spatrick     BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
98409467b48Spatrick       .addReg(Op1.getReg(), RS1, HiSR)
98509467b48Spatrick       .addReg(Op2.getReg(), RS2, LoSR)
98609467b48Spatrick       .addImm(S);
98709467b48Spatrick   }
98809467b48Spatrick }
98909467b48Spatrick 
splitInstr(MachineInstr * MI,const UUPairMap & PairMap)99009467b48Spatrick bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI,
99109467b48Spatrick       const UUPairMap &PairMap) {
99209467b48Spatrick   using namespace Hexagon;
99309467b48Spatrick 
99409467b48Spatrick   LLVM_DEBUG(dbgs() << "Splitting: " << *MI);
99509467b48Spatrick   bool Split = false;
99609467b48Spatrick   unsigned Opc = MI->getOpcode();
99709467b48Spatrick 
99809467b48Spatrick   switch (Opc) {
99909467b48Spatrick     case TargetOpcode::PHI:
100009467b48Spatrick     case TargetOpcode::COPY: {
100109467b48Spatrick       Register DstR = MI->getOperand(0).getReg();
100209467b48Spatrick       if (MRI->getRegClass(DstR) == DoubleRC) {
100309467b48Spatrick         createHalfInstr(Opc, MI, PairMap, isub_lo);
100409467b48Spatrick         createHalfInstr(Opc, MI, PairMap, isub_hi);
100509467b48Spatrick         Split = true;
100609467b48Spatrick       }
100709467b48Spatrick       break;
100809467b48Spatrick     }
100909467b48Spatrick     case A2_andp:
101009467b48Spatrick       createHalfInstr(A2_and, MI, PairMap, isub_lo);
101109467b48Spatrick       createHalfInstr(A2_and, MI, PairMap, isub_hi);
101209467b48Spatrick       Split = true;
101309467b48Spatrick       break;
101409467b48Spatrick     case A2_orp:
101509467b48Spatrick       createHalfInstr(A2_or, MI, PairMap, isub_lo);
101609467b48Spatrick       createHalfInstr(A2_or, MI, PairMap, isub_hi);
101709467b48Spatrick       Split = true;
101809467b48Spatrick       break;
101909467b48Spatrick     case A2_xorp:
102009467b48Spatrick       createHalfInstr(A2_xor, MI, PairMap, isub_lo);
102109467b48Spatrick       createHalfInstr(A2_xor, MI, PairMap, isub_hi);
102209467b48Spatrick       Split = true;
102309467b48Spatrick       break;
102409467b48Spatrick 
102509467b48Spatrick     case L2_loadrd_io:
102609467b48Spatrick     case L2_loadrd_pi:
102709467b48Spatrick     case S2_storerd_io:
102809467b48Spatrick     case S2_storerd_pi:
102909467b48Spatrick       splitMemRef(MI, PairMap);
103009467b48Spatrick       Split = true;
103109467b48Spatrick       break;
103209467b48Spatrick 
103309467b48Spatrick     case A2_tfrpi:
103409467b48Spatrick     case CONST64:
103509467b48Spatrick       splitImmediate(MI, PairMap);
103609467b48Spatrick       Split = true;
103709467b48Spatrick       break;
103809467b48Spatrick 
103909467b48Spatrick     case A2_combineii:
104009467b48Spatrick     case A4_combineir:
104109467b48Spatrick     case A4_combineii:
104209467b48Spatrick     case A4_combineri:
104309467b48Spatrick     case A2_combinew:
104409467b48Spatrick       splitCombine(MI, PairMap);
104509467b48Spatrick       Split = true;
104609467b48Spatrick       break;
104709467b48Spatrick 
104809467b48Spatrick     case A2_sxtw:
104909467b48Spatrick       splitExt(MI, PairMap);
105009467b48Spatrick       Split = true;
105109467b48Spatrick       break;
105209467b48Spatrick 
105309467b48Spatrick     case S2_asl_i_p:
105409467b48Spatrick     case S2_asr_i_p:
105509467b48Spatrick     case S2_lsr_i_p:
105609467b48Spatrick       splitShift(MI, PairMap);
105709467b48Spatrick       Split = true;
105809467b48Spatrick       break;
105909467b48Spatrick 
106009467b48Spatrick     case S2_asl_i_p_or:
106109467b48Spatrick       splitAslOr(MI, PairMap);
106209467b48Spatrick       Split = true;
106309467b48Spatrick       break;
106409467b48Spatrick 
106509467b48Spatrick     default:
106609467b48Spatrick       llvm_unreachable("Instruction not splitable");
106709467b48Spatrick       return false;
106809467b48Spatrick   }
106909467b48Spatrick 
107009467b48Spatrick   return Split;
107109467b48Spatrick }
107209467b48Spatrick 
replaceSubregUses(MachineInstr * MI,const UUPairMap & PairMap)107309467b48Spatrick void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI,
107409467b48Spatrick       const UUPairMap &PairMap) {
107509467b48Spatrick   for (auto &Op : MI->operands()) {
107609467b48Spatrick     if (!Op.isReg() || !Op.isUse() || !Op.getSubReg())
107709467b48Spatrick       continue;
107809467b48Spatrick     Register R = Op.getReg();
107909467b48Spatrick     UUPairMap::const_iterator F = PairMap.find(R);
108009467b48Spatrick     if (F == PairMap.end())
108109467b48Spatrick       continue;
108209467b48Spatrick     const UUPair &P = F->second;
108309467b48Spatrick     switch (Op.getSubReg()) {
108409467b48Spatrick       case Hexagon::isub_lo:
108509467b48Spatrick         Op.setReg(P.first);
108609467b48Spatrick         break;
108709467b48Spatrick       case Hexagon::isub_hi:
108809467b48Spatrick         Op.setReg(P.second);
108909467b48Spatrick         break;
109009467b48Spatrick     }
109109467b48Spatrick     Op.setSubReg(0);
109209467b48Spatrick   }
109309467b48Spatrick }
109409467b48Spatrick 
collapseRegPairs(MachineInstr * MI,const UUPairMap & PairMap)109509467b48Spatrick void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI,
109609467b48Spatrick       const UUPairMap &PairMap) {
109709467b48Spatrick   MachineBasicBlock &B = *MI->getParent();
109809467b48Spatrick   DebugLoc DL = MI->getDebugLoc();
109909467b48Spatrick 
110009467b48Spatrick   for (auto &Op : MI->operands()) {
110109467b48Spatrick     if (!Op.isReg() || !Op.isUse())
110209467b48Spatrick       continue;
110309467b48Spatrick     Register R = Op.getReg();
110473471bf0Spatrick     if (!R.isVirtual())
110509467b48Spatrick       continue;
110609467b48Spatrick     if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg())
110709467b48Spatrick       continue;
110809467b48Spatrick     UUPairMap::const_iterator F = PairMap.find(R);
110909467b48Spatrick     if (F == PairMap.end())
111009467b48Spatrick       continue;
111109467b48Spatrick     const UUPair &Pr = F->second;
111209467b48Spatrick     Register NewDR = MRI->createVirtualRegister(DoubleRC);
111309467b48Spatrick     BuildMI(B, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), NewDR)
111409467b48Spatrick       .addReg(Pr.first)
111509467b48Spatrick       .addImm(Hexagon::isub_lo)
111609467b48Spatrick       .addReg(Pr.second)
111709467b48Spatrick       .addImm(Hexagon::isub_hi);
111809467b48Spatrick     Op.setReg(NewDR);
111909467b48Spatrick   }
112009467b48Spatrick }
112109467b48Spatrick 
splitPartition(const USet & Part)112209467b48Spatrick bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) {
112309467b48Spatrick   using MISet = std::set<MachineInstr *>;
112409467b48Spatrick 
112509467b48Spatrick   const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
112609467b48Spatrick   bool Changed = false;
112709467b48Spatrick 
112809467b48Spatrick   LLVM_DEBUG(dbgs() << "Splitting partition: ";
112909467b48Spatrick              dump_partition(dbgs(), Part, *TRI); dbgs() << '\n');
113009467b48Spatrick 
113109467b48Spatrick   UUPairMap PairMap;
113209467b48Spatrick 
113309467b48Spatrick   MISet SplitIns;
113409467b48Spatrick   for (unsigned DR : Part) {
113509467b48Spatrick     MachineInstr *DefI = MRI->getVRegDef(DR);
113609467b48Spatrick     SplitIns.insert(DefI);
113709467b48Spatrick 
113809467b48Spatrick     // Collect all instructions, including fixed ones.  We won't split them,
113909467b48Spatrick     // but we need to visit them again to insert the REG_SEQUENCE instructions.
114009467b48Spatrick     for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
114109467b48Spatrick          U != W; ++U)
114209467b48Spatrick       SplitIns.insert(U->getParent());
114309467b48Spatrick 
114409467b48Spatrick     Register LoR = MRI->createVirtualRegister(IntRC);
114509467b48Spatrick     Register HiR = MRI->createVirtualRegister(IntRC);
114609467b48Spatrick     LLVM_DEBUG(dbgs() << "Created mapping: " << printReg(DR, TRI) << " -> "
114709467b48Spatrick                       << printReg(HiR, TRI) << ':' << printReg(LoR, TRI)
114809467b48Spatrick                       << '\n');
114909467b48Spatrick     PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));
115009467b48Spatrick   }
115109467b48Spatrick 
115209467b48Spatrick   MISet Erase;
1153*d415bd75Srobert   for (auto *MI : SplitIns) {
115409467b48Spatrick     if (isFixedInstr(MI)) {
115509467b48Spatrick       collapseRegPairs(MI, PairMap);
115609467b48Spatrick     } else {
115709467b48Spatrick       bool Done = splitInstr(MI, PairMap);
115809467b48Spatrick       if (Done)
115909467b48Spatrick         Erase.insert(MI);
116009467b48Spatrick       Changed |= Done;
116109467b48Spatrick     }
116209467b48Spatrick   }
116309467b48Spatrick 
116409467b48Spatrick   for (unsigned DR : Part) {
116509467b48Spatrick     // Before erasing "double" instructions, revisit all uses of the double
116609467b48Spatrick     // registers in this partition, and replace all uses of them with subre-
116709467b48Spatrick     // gisters, with the corresponding single registers.
116809467b48Spatrick     MISet Uses;
116909467b48Spatrick     for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
117009467b48Spatrick          U != W; ++U)
117109467b48Spatrick       Uses.insert(U->getParent());
1172*d415bd75Srobert     for (auto *M : Uses)
117309467b48Spatrick       replaceSubregUses(M, PairMap);
117409467b48Spatrick   }
117509467b48Spatrick 
1176*d415bd75Srobert   for (auto *MI : Erase) {
117709467b48Spatrick     MachineBasicBlock *B = MI->getParent();
117809467b48Spatrick     B->erase(MI);
117909467b48Spatrick   }
118009467b48Spatrick 
118109467b48Spatrick   return Changed;
118209467b48Spatrick }
118309467b48Spatrick 
runOnMachineFunction(MachineFunction & MF)118409467b48Spatrick bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) {
118509467b48Spatrick   if (skipFunction(MF.getFunction()))
118609467b48Spatrick     return false;
118709467b48Spatrick 
118809467b48Spatrick   LLVM_DEBUG(dbgs() << "Splitting double registers in function: "
118909467b48Spatrick                     << MF.getName() << '\n');
119009467b48Spatrick 
119109467b48Spatrick   auto &ST = MF.getSubtarget<HexagonSubtarget>();
119209467b48Spatrick   TRI = ST.getRegisterInfo();
119309467b48Spatrick   TII = ST.getInstrInfo();
119409467b48Spatrick   MRI = &MF.getRegInfo();
119509467b48Spatrick   MLI = &getAnalysis<MachineLoopInfo>();
119609467b48Spatrick 
119709467b48Spatrick   UUSetMap P2Rs;
119809467b48Spatrick   LoopRegMap IRM;
119909467b48Spatrick 
120009467b48Spatrick   collectIndRegs(IRM);
120109467b48Spatrick   partitionRegisters(P2Rs);
120209467b48Spatrick 
120309467b48Spatrick   LLVM_DEBUG({
120409467b48Spatrick     dbgs() << "Register partitioning: (partition #0 is fixed)\n";
120509467b48Spatrick     for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
120609467b48Spatrick       dbgs() << '#' << I->first << " -> ";
120709467b48Spatrick       dump_partition(dbgs(), I->second, *TRI);
120809467b48Spatrick       dbgs() << '\n';
120909467b48Spatrick     }
121009467b48Spatrick   });
121109467b48Spatrick 
121209467b48Spatrick   bool Changed = false;
121309467b48Spatrick   int Limit = MaxHSDR;
121409467b48Spatrick 
121509467b48Spatrick   for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
121609467b48Spatrick     if (I->first == 0)
121709467b48Spatrick       continue;
121809467b48Spatrick     if (Limit >= 0 && Counter >= Limit)
121909467b48Spatrick       break;
122009467b48Spatrick     USet &Part = I->second;
122109467b48Spatrick     LLVM_DEBUG(dbgs() << "Calculating profit for partition #" << I->first
122209467b48Spatrick                       << '\n');
122309467b48Spatrick     if (!isProfitable(Part, IRM))
122409467b48Spatrick       continue;
122509467b48Spatrick     Counter++;
122609467b48Spatrick     Changed |= splitPartition(Part);
122709467b48Spatrick   }
122809467b48Spatrick 
122909467b48Spatrick   return Changed;
123009467b48Spatrick }
123109467b48Spatrick 
createHexagonSplitDoubleRegs()123209467b48Spatrick FunctionPass *llvm::createHexagonSplitDoubleRegs() {
123309467b48Spatrick   return new HexagonSplitDoubleRegs();
123409467b48Spatrick }
1235