xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonSplitDouble.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===- HexagonSplitDouble.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
100b57cec5SDimitry Andric #include "HexagonRegisterInfo.h"
110b57cec5SDimitry Andric #include "HexagonSubtarget.h"
120b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
130b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
260b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
270b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
280b57cec5SDimitry Andric #include "llvm/Pass.h"
290b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
300b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
310b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
330b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
340b57cec5SDimitry Andric #include <algorithm>
350b57cec5SDimitry Andric #include <cassert>
360b57cec5SDimitry Andric #include <cstdint>
370b57cec5SDimitry Andric #include <limits>
380b57cec5SDimitry Andric #include <map>
390b57cec5SDimitry Andric #include <set>
400b57cec5SDimitry Andric #include <utility>
410b57cec5SDimitry Andric #include <vector>
420b57cec5SDimitry Andric 
43*fe6060f1SDimitry Andric #define DEBUG_TYPE "hsdr"
44*fe6060f1SDimitry Andric 
450b57cec5SDimitry Andric using namespace llvm;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric namespace llvm {
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   FunctionPass *createHexagonSplitDoubleRegs();
500b57cec5SDimitry Andric   void initializeHexagonSplitDoubleRegsPass(PassRegistry&);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric } // end namespace llvm
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric static cl::opt<int> MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1),
550b57cec5SDimitry Andric     cl::desc("Maximum number of split partitions"));
560b57cec5SDimitry Andric static cl::opt<bool> MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true),
570b57cec5SDimitry Andric     cl::desc("Do not split loads or stores"));
580b57cec5SDimitry Andric   static cl::opt<bool> SplitAll("hsdr-split-all", cl::Hidden, cl::init(false),
590b57cec5SDimitry Andric       cl::desc("Split all partitions"));
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric namespace {
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   class HexagonSplitDoubleRegs : public MachineFunctionPass {
640b57cec5SDimitry Andric   public:
650b57cec5SDimitry Andric     static char ID;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric     HexagonSplitDoubleRegs() : MachineFunctionPass(ID) {}
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric     StringRef getPassName() const override {
700b57cec5SDimitry Andric       return "Hexagon Split Double Registers";
710b57cec5SDimitry Andric     }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
740b57cec5SDimitry Andric       AU.addRequired<MachineLoopInfo>();
750b57cec5SDimitry Andric       AU.addPreserved<MachineLoopInfo>();
760b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
770b57cec5SDimitry Andric     }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   private:
820b57cec5SDimitry Andric     static const TargetRegisterClass *const DoubleRC;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric     const HexagonRegisterInfo *TRI = nullptr;
850b57cec5SDimitry Andric     const HexagonInstrInfo *TII = nullptr;
860b57cec5SDimitry Andric     const MachineLoopInfo *MLI;
870b57cec5SDimitry Andric     MachineRegisterInfo *MRI;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     using USet = std::set<unsigned>;
900b57cec5SDimitry Andric     using UUSetMap = std::map<unsigned, USet>;
910b57cec5SDimitry Andric     using UUPair = std::pair<unsigned, unsigned>;
920b57cec5SDimitry Andric     using UUPairMap = std::map<unsigned, UUPair>;
930b57cec5SDimitry Andric     using LoopRegMap = std::map<const MachineLoop *, USet>;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric     bool isInduction(unsigned Reg, LoopRegMap &IRM) const;
960b57cec5SDimitry Andric     bool isVolatileInstr(const MachineInstr *MI) const;
970b57cec5SDimitry Andric     bool isFixedInstr(const MachineInstr *MI) const;
980b57cec5SDimitry Andric     void partitionRegisters(UUSetMap &P2Rs);
990b57cec5SDimitry Andric     int32_t profit(const MachineInstr *MI) const;
100e8d8bef9SDimitry Andric     int32_t profit(Register Reg) const;
1010b57cec5SDimitry Andric     bool isProfitable(const USet &Part, LoopRegMap &IRM) const;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric     void collectIndRegsForLoop(const MachineLoop *L, USet &Rs);
1040b57cec5SDimitry Andric     void collectIndRegs(LoopRegMap &IRM);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric     void createHalfInstr(unsigned Opc, MachineInstr *MI,
1070b57cec5SDimitry Andric         const UUPairMap &PairMap, unsigned SubR);
1080b57cec5SDimitry Andric     void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap);
1090b57cec5SDimitry Andric     void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap);
1100b57cec5SDimitry Andric     void splitCombine(MachineInstr *MI, const UUPairMap &PairMap);
1110b57cec5SDimitry Andric     void splitExt(MachineInstr *MI, const UUPairMap &PairMap);
1120b57cec5SDimitry Andric     void splitShift(MachineInstr *MI, const UUPairMap &PairMap);
1130b57cec5SDimitry Andric     void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap);
1140b57cec5SDimitry Andric     bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap);
1150b57cec5SDimitry Andric     void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap);
1160b57cec5SDimitry Andric     void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap);
1170b57cec5SDimitry Andric     bool splitPartition(const USet &Part);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     static int Counter;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     static void dump_partition(raw_ostream&, const USet&,
1220b57cec5SDimitry Andric        const TargetRegisterInfo&);
1230b57cec5SDimitry Andric   };
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric } // end anonymous namespace
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric char HexagonSplitDoubleRegs::ID;
1280b57cec5SDimitry Andric int HexagonSplitDoubleRegs::Counter = 0;
1290b57cec5SDimitry Andric const TargetRegisterClass *const HexagonSplitDoubleRegs::DoubleRC =
1300b57cec5SDimitry Andric     &Hexagon::DoubleRegsRegClass;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric INITIALIZE_PASS(HexagonSplitDoubleRegs, "hexagon-split-double",
1330b57cec5SDimitry Andric   "Hexagon Split Double Registers", false, false)
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1360b57cec5SDimitry Andric LLVM_DUMP_METHOD void HexagonSplitDoubleRegs::dump_partition(raw_ostream &os,
1370b57cec5SDimitry Andric       const USet &Part, const TargetRegisterInfo &TRI) {
1380b57cec5SDimitry Andric   dbgs() << '{';
1390b57cec5SDimitry Andric   for (auto I : Part)
1400b57cec5SDimitry Andric     dbgs() << ' ' << printReg(I, &TRI);
1410b57cec5SDimitry Andric   dbgs() << " }";
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric #endif
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const {
1460b57cec5SDimitry Andric   for (auto I : IRM) {
1470b57cec5SDimitry Andric     const USet &Rs = I.second;
1480b57cec5SDimitry Andric     if (Rs.find(Reg) != Rs.end())
1490b57cec5SDimitry Andric       return true;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric   return false;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const {
1550b57cec5SDimitry Andric   for (auto &MO : MI->memoperands())
1560b57cec5SDimitry Andric     if (MO->isVolatile() || MO->isAtomic())
1570b57cec5SDimitry Andric       return true;
1580b57cec5SDimitry Andric   return false;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const {
162480093f4SDimitry Andric   if (MI->mayLoadOrStore())
1630b57cec5SDimitry Andric     if (MemRefsFixed || isVolatileInstr(MI))
1640b57cec5SDimitry Andric       return true;
1650b57cec5SDimitry Andric   if (MI->isDebugInstr())
1660b57cec5SDimitry Andric     return false;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
1690b57cec5SDimitry Andric   switch (Opc) {
1700b57cec5SDimitry Andric     default:
1710b57cec5SDimitry Andric       return true;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     case TargetOpcode::PHI:
1740b57cec5SDimitry Andric     case TargetOpcode::COPY:
1750b57cec5SDimitry Andric       break;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     case Hexagon::L2_loadrd_io:
1780b57cec5SDimitry Andric       // Not handling stack stores (only reg-based addresses).
1790b57cec5SDimitry Andric       if (MI->getOperand(1).isReg())
1800b57cec5SDimitry Andric         break;
1810b57cec5SDimitry Andric       return true;
1820b57cec5SDimitry Andric     case Hexagon::S2_storerd_io:
1830b57cec5SDimitry Andric       // Not handling stack stores (only reg-based addresses).
1840b57cec5SDimitry Andric       if (MI->getOperand(0).isReg())
1850b57cec5SDimitry Andric         break;
1860b57cec5SDimitry Andric       return true;
1870b57cec5SDimitry Andric     case Hexagon::L2_loadrd_pi:
1880b57cec5SDimitry Andric     case Hexagon::S2_storerd_pi:
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
1910b57cec5SDimitry Andric     case Hexagon::A2_combineii:
1920b57cec5SDimitry Andric     case Hexagon::A4_combineir:
1930b57cec5SDimitry Andric     case Hexagon::A4_combineii:
1940b57cec5SDimitry Andric     case Hexagon::A4_combineri:
1950b57cec5SDimitry Andric     case Hexagon::A2_combinew:
1960b57cec5SDimitry Andric     case Hexagon::CONST64:
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric     case Hexagon::A2_andp:
2010b57cec5SDimitry Andric     case Hexagon::A2_orp:
2020b57cec5SDimitry Andric     case Hexagon::A2_xorp:
2030b57cec5SDimitry Andric     case Hexagon::S2_asl_i_p_or:
2040b57cec5SDimitry Andric     case Hexagon::S2_asl_i_p:
2050b57cec5SDimitry Andric     case Hexagon::S2_asr_i_p:
2060b57cec5SDimitry Andric     case Hexagon::S2_lsr_i_p:
2070b57cec5SDimitry Andric       break;
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   for (auto &Op : MI->operands()) {
2110b57cec5SDimitry Andric     if (!Op.isReg())
2120b57cec5SDimitry Andric       continue;
2138bcb0991SDimitry Andric     Register R = Op.getReg();
214e8d8bef9SDimitry Andric     if (!R.isVirtual())
2150b57cec5SDimitry Andric       return true;
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric   return false;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {
2210b57cec5SDimitry Andric   using UUMap = std::map<unsigned, unsigned>;
2220b57cec5SDimitry Andric   using UVect = std::vector<unsigned>;
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   unsigned NumRegs = MRI->getNumVirtRegs();
2250b57cec5SDimitry Andric   BitVector DoubleRegs(NumRegs);
2260b57cec5SDimitry Andric   for (unsigned i = 0; i < NumRegs; ++i) {
2278bcb0991SDimitry Andric     unsigned R = Register::index2VirtReg(i);
2280b57cec5SDimitry Andric     if (MRI->getRegClass(R) == DoubleRC)
2290b57cec5SDimitry Andric       DoubleRegs.set(i);
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   BitVector FixedRegs(NumRegs);
2330b57cec5SDimitry Andric   for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
2348bcb0991SDimitry Andric     unsigned R = Register::index2VirtReg(x);
2350b57cec5SDimitry Andric     MachineInstr *DefI = MRI->getVRegDef(R);
2360b57cec5SDimitry Andric     // In some cases a register may exist, but never be defined or used.
2370b57cec5SDimitry Andric     // It should never appear anywhere, but mark it as "fixed", just to be
2380b57cec5SDimitry Andric     // safe.
2390b57cec5SDimitry Andric     if (!DefI || isFixedInstr(DefI))
2400b57cec5SDimitry Andric       FixedRegs.set(x);
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   UUSetMap AssocMap;
2440b57cec5SDimitry Andric   for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
2450b57cec5SDimitry Andric     if (FixedRegs[x])
2460b57cec5SDimitry Andric       continue;
2478bcb0991SDimitry Andric     unsigned R = Register::index2VirtReg(x);
2480b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << printReg(R, TRI) << " ~~");
2490b57cec5SDimitry Andric     USet &Asc = AssocMap[R];
2500b57cec5SDimitry Andric     for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end();
2510b57cec5SDimitry Andric          U != Z; ++U) {
2520b57cec5SDimitry Andric       MachineOperand &Op = *U;
2530b57cec5SDimitry Andric       MachineInstr *UseI = Op.getParent();
2540b57cec5SDimitry Andric       if (isFixedInstr(UseI))
2550b57cec5SDimitry Andric         continue;
2560b57cec5SDimitry Andric       for (unsigned i = 0, n = UseI->getNumOperands(); i < n; ++i) {
2570b57cec5SDimitry Andric         MachineOperand &MO = UseI->getOperand(i);
2580b57cec5SDimitry Andric         // Skip non-registers or registers with subregisters.
2590b57cec5SDimitry Andric         if (&MO == &Op || !MO.isReg() || MO.getSubReg())
2600b57cec5SDimitry Andric           continue;
2618bcb0991SDimitry Andric         Register T = MO.getReg();
262e8d8bef9SDimitry Andric         if (!T.isVirtual()) {
2630b57cec5SDimitry Andric           FixedRegs.set(x);
2640b57cec5SDimitry Andric           continue;
2650b57cec5SDimitry Andric         }
2660b57cec5SDimitry Andric         if (MRI->getRegClass(T) != DoubleRC)
2670b57cec5SDimitry Andric           continue;
2688bcb0991SDimitry Andric         unsigned u = Register::virtReg2Index(T);
2690b57cec5SDimitry Andric         if (FixedRegs[u])
2700b57cec5SDimitry Andric           continue;
2710b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << ' ' << printReg(T, TRI));
2720b57cec5SDimitry Andric         Asc.insert(T);
2730b57cec5SDimitry Andric         // Make it symmetric.
2740b57cec5SDimitry Andric         AssocMap[T].insert(R);
2750b57cec5SDimitry Andric       }
2760b57cec5SDimitry Andric     }
2770b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << '\n');
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   UUMap R2P;
2810b57cec5SDimitry Andric   unsigned NextP = 1;
2820b57cec5SDimitry Andric   USet Visited;
2830b57cec5SDimitry Andric   for (int x = DoubleRegs.find_first(); x >= 0; x = DoubleRegs.find_next(x)) {
2848bcb0991SDimitry Andric     unsigned R = Register::index2VirtReg(x);
2850b57cec5SDimitry Andric     if (Visited.count(R))
2860b57cec5SDimitry Andric       continue;
2870b57cec5SDimitry Andric     // Create a new partition for R.
2880b57cec5SDimitry Andric     unsigned ThisP = FixedRegs[x] ? 0 : NextP++;
2890b57cec5SDimitry Andric     UVect WorkQ;
2900b57cec5SDimitry Andric     WorkQ.push_back(R);
2910b57cec5SDimitry Andric     for (unsigned i = 0; i < WorkQ.size(); ++i) {
2920b57cec5SDimitry Andric       unsigned T = WorkQ[i];
2930b57cec5SDimitry Andric       if (Visited.count(T))
2940b57cec5SDimitry Andric         continue;
2950b57cec5SDimitry Andric       R2P[T] = ThisP;
2960b57cec5SDimitry Andric       Visited.insert(T);
2970b57cec5SDimitry Andric       // Add all registers associated with T.
2980b57cec5SDimitry Andric       USet &Asc = AssocMap[T];
299*fe6060f1SDimitry Andric       append_range(WorkQ, Asc);
3000b57cec5SDimitry Andric     }
3010b57cec5SDimitry Andric   }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   for (auto I : R2P)
3040b57cec5SDimitry Andric     P2Rs[I.second].insert(I.first);
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric static inline int32_t profitImm(unsigned Imm) {
3080b57cec5SDimitry Andric   int32_t P = 0;
3090b57cec5SDimitry Andric   if (Imm == 0 || Imm == 0xFFFFFFFF)
3100b57cec5SDimitry Andric     P += 10;
3110b57cec5SDimitry Andric   return P;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const {
3150b57cec5SDimitry Andric   unsigned ImmX = 0;
3160b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
3170b57cec5SDimitry Andric   switch (Opc) {
3180b57cec5SDimitry Andric     case TargetOpcode::PHI:
3190b57cec5SDimitry Andric       for (const auto &Op : MI->operands())
3200b57cec5SDimitry Andric         if (!Op.getSubReg())
3210b57cec5SDimitry Andric           return 0;
3220b57cec5SDimitry Andric       return 10;
3230b57cec5SDimitry Andric     case TargetOpcode::COPY:
3240b57cec5SDimitry Andric       if (MI->getOperand(1).getSubReg() != 0)
3250b57cec5SDimitry Andric         return 10;
3260b57cec5SDimitry Andric       return 0;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric     case Hexagon::L2_loadrd_io:
3290b57cec5SDimitry Andric     case Hexagon::S2_storerd_io:
3300b57cec5SDimitry Andric       return -1;
3310b57cec5SDimitry Andric     case Hexagon::L2_loadrd_pi:
3320b57cec5SDimitry Andric     case Hexagon::S2_storerd_pi:
3330b57cec5SDimitry Andric       return 2;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
3360b57cec5SDimitry Andric     case Hexagon::CONST64: {
3370b57cec5SDimitry Andric       uint64_t D = MI->getOperand(1).getImm();
3380b57cec5SDimitry Andric       unsigned Lo = D & 0xFFFFFFFFULL;
3390b57cec5SDimitry Andric       unsigned Hi = D >> 32;
3400b57cec5SDimitry Andric       return profitImm(Lo) + profitImm(Hi);
3410b57cec5SDimitry Andric     }
3420b57cec5SDimitry Andric     case Hexagon::A2_combineii:
3430b57cec5SDimitry Andric     case Hexagon::A4_combineii: {
3440b57cec5SDimitry Andric       const MachineOperand &Op1 = MI->getOperand(1);
3450b57cec5SDimitry Andric       const MachineOperand &Op2 = MI->getOperand(2);
3460b57cec5SDimitry Andric       int32_t Prof1 = Op1.isImm() ? profitImm(Op1.getImm()) : 0;
3470b57cec5SDimitry Andric       int32_t Prof2 = Op2.isImm() ? profitImm(Op2.getImm()) : 0;
3480b57cec5SDimitry Andric       return Prof1 + Prof2;
3490b57cec5SDimitry Andric     }
3500b57cec5SDimitry Andric     case Hexagon::A4_combineri:
3510b57cec5SDimitry Andric       ImmX++;
3520b57cec5SDimitry Andric       // Fall through into A4_combineir.
3530b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
3540b57cec5SDimitry Andric     case Hexagon::A4_combineir: {
3550b57cec5SDimitry Andric       ImmX++;
3560b57cec5SDimitry Andric       const MachineOperand &OpX = MI->getOperand(ImmX);
3570b57cec5SDimitry Andric       if (OpX.isImm()) {
3580b57cec5SDimitry Andric         int64_t V = OpX.getImm();
3590b57cec5SDimitry Andric         if (V == 0 || V == -1)
3600b57cec5SDimitry Andric           return 10;
3610b57cec5SDimitry Andric       }
3620b57cec5SDimitry Andric       // Fall through into A2_combinew.
3630b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
3640b57cec5SDimitry Andric     }
3650b57cec5SDimitry Andric     case Hexagon::A2_combinew:
3660b57cec5SDimitry Andric       return 2;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric     case Hexagon::A2_sxtw:
3690b57cec5SDimitry Andric       return 3;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric     case Hexagon::A2_andp:
3720b57cec5SDimitry Andric     case Hexagon::A2_orp:
3730b57cec5SDimitry Andric     case Hexagon::A2_xorp: {
3748bcb0991SDimitry Andric       Register Rs = MI->getOperand(1).getReg();
3758bcb0991SDimitry Andric       Register Rt = MI->getOperand(2).getReg();
3760b57cec5SDimitry Andric       return profit(Rs) + profit(Rt);
3770b57cec5SDimitry Andric     }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric     case Hexagon::S2_asl_i_p_or: {
3800b57cec5SDimitry Andric       unsigned S = MI->getOperand(3).getImm();
3810b57cec5SDimitry Andric       if (S == 0 || S == 32)
3820b57cec5SDimitry Andric         return 10;
3830b57cec5SDimitry Andric       return -1;
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric     case Hexagon::S2_asl_i_p:
3860b57cec5SDimitry Andric     case Hexagon::S2_asr_i_p:
3870b57cec5SDimitry Andric     case Hexagon::S2_lsr_i_p:
3880b57cec5SDimitry Andric       unsigned S = MI->getOperand(2).getImm();
3890b57cec5SDimitry Andric       if (S == 0 || S == 32)
3900b57cec5SDimitry Andric         return 10;
3910b57cec5SDimitry Andric       if (S == 16)
3920b57cec5SDimitry Andric         return 5;
3930b57cec5SDimitry Andric       if (S == 48)
3940b57cec5SDimitry Andric         return 7;
3950b57cec5SDimitry Andric       return -10;
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   return 0;
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
401e8d8bef9SDimitry Andric int32_t HexagonSplitDoubleRegs::profit(Register Reg) const {
402e8d8bef9SDimitry Andric   assert(Reg.isVirtual());
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   const MachineInstr *DefI = MRI->getVRegDef(Reg);
4050b57cec5SDimitry Andric   switch (DefI->getOpcode()) {
4060b57cec5SDimitry Andric     case Hexagon::A2_tfrpi:
4070b57cec5SDimitry Andric     case Hexagon::CONST64:
4080b57cec5SDimitry Andric     case Hexagon::A2_combineii:
4090b57cec5SDimitry Andric     case Hexagon::A4_combineii:
4100b57cec5SDimitry Andric     case Hexagon::A4_combineri:
4110b57cec5SDimitry Andric     case Hexagon::A4_combineir:
4120b57cec5SDimitry Andric     case Hexagon::A2_combinew:
4130b57cec5SDimitry Andric       return profit(DefI);
4140b57cec5SDimitry Andric     default:
4150b57cec5SDimitry Andric       break;
4160b57cec5SDimitry Andric   }
4170b57cec5SDimitry Andric   return 0;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM)
4210b57cec5SDimitry Andric       const {
4220b57cec5SDimitry Andric   unsigned FixedNum = 0, LoopPhiNum = 0;
4230b57cec5SDimitry Andric   int32_t TotalP = 0;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   for (unsigned DR : Part) {
4260b57cec5SDimitry Andric     MachineInstr *DefI = MRI->getVRegDef(DR);
4270b57cec5SDimitry Andric     int32_t P = profit(DefI);
4280b57cec5SDimitry Andric     if (P == std::numeric_limits<int>::min())
4290b57cec5SDimitry Andric       return false;
4300b57cec5SDimitry Andric     TotalP += P;
4310b57cec5SDimitry Andric     // Reduce the profitability of splitting induction registers.
4320b57cec5SDimitry Andric     if (isInduction(DR, IRM))
4330b57cec5SDimitry Andric       TotalP -= 30;
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric     for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
4360b57cec5SDimitry Andric          U != W; ++U) {
4370b57cec5SDimitry Andric       MachineInstr *UseI = U->getParent();
4380b57cec5SDimitry Andric       if (isFixedInstr(UseI)) {
4390b57cec5SDimitry Andric         FixedNum++;
4400b57cec5SDimitry Andric         // Calculate the cost of generating REG_SEQUENCE instructions.
4410b57cec5SDimitry Andric         for (auto &Op : UseI->operands()) {
4420b57cec5SDimitry Andric           if (Op.isReg() && Part.count(Op.getReg()))
4430b57cec5SDimitry Andric             if (Op.getSubReg())
4440b57cec5SDimitry Andric               TotalP -= 2;
4450b57cec5SDimitry Andric         }
4460b57cec5SDimitry Andric         continue;
4470b57cec5SDimitry Andric       }
4480b57cec5SDimitry Andric       // If a register from this partition is used in a fixed instruction,
4490b57cec5SDimitry Andric       // and there is also a register in this partition that is used in
4500b57cec5SDimitry Andric       // a loop phi node, then decrease the splitting profit as this can
4510b57cec5SDimitry Andric       // confuse the modulo scheduler.
4520b57cec5SDimitry Andric       if (UseI->isPHI()) {
4530b57cec5SDimitry Andric         const MachineBasicBlock *PB = UseI->getParent();
4540b57cec5SDimitry Andric         const MachineLoop *L = MLI->getLoopFor(PB);
4550b57cec5SDimitry Andric         if (L && L->getHeader() == PB)
4560b57cec5SDimitry Andric           LoopPhiNum++;
4570b57cec5SDimitry Andric       }
4580b57cec5SDimitry Andric       // Splittable instruction.
4590b57cec5SDimitry Andric       int32_t P = profit(UseI);
4600b57cec5SDimitry Andric       if (P == std::numeric_limits<int>::min())
4610b57cec5SDimitry Andric         return false;
4620b57cec5SDimitry Andric       TotalP += P;
4630b57cec5SDimitry Andric     }
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   if (FixedNum > 0 && LoopPhiNum > 0)
4670b57cec5SDimitry Andric     TotalP -= 20*LoopPhiNum;
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Partition profit: " << TotalP << '\n');
4700b57cec5SDimitry Andric   if (SplitAll)
4710b57cec5SDimitry Andric     return true;
4720b57cec5SDimitry Andric   return TotalP > 0;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L,
4760b57cec5SDimitry Andric       USet &Rs) {
4770b57cec5SDimitry Andric   const MachineBasicBlock *HB = L->getHeader();
4780b57cec5SDimitry Andric   const MachineBasicBlock *LB = L->getLoopLatch();
4790b57cec5SDimitry Andric   if (!HB || !LB)
4800b57cec5SDimitry Andric     return;
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   // Examine the latch branch. Expect it to be a conditional branch to
4830b57cec5SDimitry Andric   // the header (either "br-cond header" or "br-cond exit; br header").
4840b57cec5SDimitry Andric   MachineBasicBlock *TB = nullptr, *FB = nullptr;
4850b57cec5SDimitry Andric   MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB);
4860b57cec5SDimitry Andric   SmallVector<MachineOperand,2> Cond;
4870b57cec5SDimitry Andric   bool BadLB = TII->analyzeBranch(*TmpLB, TB, FB, Cond, false);
4880b57cec5SDimitry Andric   // Only analyzable conditional branches. HII::analyzeBranch will put
4890b57cec5SDimitry Andric   // the branch opcode as the first element of Cond, and the predicate
4900b57cec5SDimitry Andric   // operand as the second.
4910b57cec5SDimitry Andric   if (BadLB || Cond.size() != 2)
4920b57cec5SDimitry Andric     return;
4930b57cec5SDimitry Andric   // Only simple jump-conditional (with or without negation).
4940b57cec5SDimitry Andric   if (!TII->PredOpcodeHasJMP_c(Cond[0].getImm()))
4950b57cec5SDimitry Andric     return;
4960b57cec5SDimitry Andric   // Must go to the header.
4970b57cec5SDimitry Andric   if (TB != HB && FB != HB)
4980b57cec5SDimitry Andric     return;
4990b57cec5SDimitry Andric   assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch");
5000b57cec5SDimitry Andric   // Expect a predicate register.
5018bcb0991SDimitry Andric   Register PR = Cond[1].getReg();
5020b57cec5SDimitry Andric   assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   // Get the registers on which the loop controlling compare instruction
5050b57cec5SDimitry Andric   // depends.
5065ffd83dbSDimitry Andric   Register CmpR1, CmpR2;
5070b57cec5SDimitry Andric   const MachineInstr *CmpI = MRI->getVRegDef(PR);
5080b57cec5SDimitry Andric   while (CmpI->getOpcode() == Hexagon::C2_not)
5090b57cec5SDimitry Andric     CmpI = MRI->getVRegDef(CmpI->getOperand(1).getReg());
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   int Mask = 0, Val = 0;
5120b57cec5SDimitry Andric   bool OkCI = TII->analyzeCompare(*CmpI, CmpR1, CmpR2, Mask, Val);
5130b57cec5SDimitry Andric   if (!OkCI)
5140b57cec5SDimitry Andric     return;
5150b57cec5SDimitry Andric   // Eliminate non-double input registers.
5160b57cec5SDimitry Andric   if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC)
5170b57cec5SDimitry Andric     CmpR1 = 0;
5180b57cec5SDimitry Andric   if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC)
5190b57cec5SDimitry Andric     CmpR2 = 0;
5200b57cec5SDimitry Andric   if (!CmpR1 && !CmpR2)
5210b57cec5SDimitry Andric     return;
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   // Now examine the top of the loop: the phi nodes that could poten-
5240b57cec5SDimitry Andric   // tially define loop induction registers. The registers defined by
5250b57cec5SDimitry Andric   // such a phi node would be used in a 64-bit add, which then would
5260b57cec5SDimitry Andric   // be used in the loop compare instruction.
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   // Get the set of all double registers defined by phi nodes in the
5290b57cec5SDimitry Andric   // loop header.
5300b57cec5SDimitry Andric   using UVect = std::vector<unsigned>;
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   UVect DP;
5330b57cec5SDimitry Andric   for (auto &MI : *HB) {
5340b57cec5SDimitry Andric     if (!MI.isPHI())
5350b57cec5SDimitry Andric       break;
5360b57cec5SDimitry Andric     const MachineOperand &MD = MI.getOperand(0);
5378bcb0991SDimitry Andric     Register R = MD.getReg();
5380b57cec5SDimitry Andric     if (MRI->getRegClass(R) == DoubleRC)
5390b57cec5SDimitry Andric       DP.push_back(R);
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric   if (DP.empty())
5420b57cec5SDimitry Andric     return;
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool {
5450b57cec5SDimitry Andric     for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end();
5460b57cec5SDimitry Andric          I != E; ++I) {
5470b57cec5SDimitry Andric       const MachineInstr *UseI = I->getParent();
5480b57cec5SDimitry Andric       if (UseI->getOpcode() != Hexagon::A2_addp)
5490b57cec5SDimitry Andric         continue;
5500b57cec5SDimitry Andric       // Get the output from the add. If it is one of the inputs to the
5510b57cec5SDimitry Andric       // loop-controlling compare instruction, then R is likely an induc-
5520b57cec5SDimitry Andric       // tion register.
5538bcb0991SDimitry Andric       Register T = UseI->getOperand(0).getReg();
5540b57cec5SDimitry Andric       if (T == CmpR1 || T == CmpR2)
5550b57cec5SDimitry Andric         return false;
5560b57cec5SDimitry Andric     }
5570b57cec5SDimitry Andric     return true;
5580b57cec5SDimitry Andric   };
5590b57cec5SDimitry Andric   UVect::iterator End = llvm::remove_if(DP, NoIndOp);
5600b57cec5SDimitry Andric   Rs.insert(DP.begin(), End);
5610b57cec5SDimitry Andric   Rs.insert(CmpR1);
5620b57cec5SDimitry Andric   Rs.insert(CmpR2);
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   LLVM_DEBUG({
5650b57cec5SDimitry Andric     dbgs() << "For loop at " << printMBBReference(*HB) << " ind regs: ";
5660b57cec5SDimitry Andric     dump_partition(dbgs(), Rs, *TRI);
5670b57cec5SDimitry Andric     dbgs() << '\n';
5680b57cec5SDimitry Andric   });
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {
5720b57cec5SDimitry Andric   using LoopVector = std::vector<MachineLoop *>;
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   LoopVector WorkQ;
5750b57cec5SDimitry Andric 
576e8d8bef9SDimitry Andric   append_range(WorkQ, *MLI);
577e8d8bef9SDimitry Andric   for (unsigned i = 0; i < WorkQ.size(); ++i)
578e8d8bef9SDimitry Andric     append_range(WorkQ, *WorkQ[i]);
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   USet Rs;
5810b57cec5SDimitry Andric   for (unsigned i = 0, n = WorkQ.size(); i < n; ++i) {
5820b57cec5SDimitry Andric     MachineLoop *L = WorkQ[i];
5830b57cec5SDimitry Andric     Rs.clear();
5840b57cec5SDimitry Andric     collectIndRegsForLoop(L, Rs);
5850b57cec5SDimitry Andric     if (!Rs.empty())
5860b57cec5SDimitry Andric       IRM.insert(std::make_pair(L, Rs));
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI,
5910b57cec5SDimitry Andric       const UUPairMap &PairMap, unsigned SubR) {
5920b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
5930b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
5940b57cec5SDimitry Andric   MachineInstr *NewI = BuildMI(B, MI, DL, TII->get(Opc));
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   for (auto &Op : MI->operands()) {
5970b57cec5SDimitry Andric     if (!Op.isReg()) {
5980b57cec5SDimitry Andric       NewI->addOperand(Op);
5990b57cec5SDimitry Andric       continue;
6000b57cec5SDimitry Andric     }
6010b57cec5SDimitry Andric     // For register operands, set the subregister.
6028bcb0991SDimitry Andric     Register R = Op.getReg();
6030b57cec5SDimitry Andric     unsigned SR = Op.getSubReg();
604e8d8bef9SDimitry Andric     bool isVirtReg = R.isVirtual();
6050b57cec5SDimitry Andric     bool isKill = Op.isKill();
6060b57cec5SDimitry Andric     if (isVirtReg && MRI->getRegClass(R) == DoubleRC) {
6070b57cec5SDimitry Andric       isKill = false;
6080b57cec5SDimitry Andric       UUPairMap::const_iterator F = PairMap.find(R);
6090b57cec5SDimitry Andric       if (F == PairMap.end()) {
6100b57cec5SDimitry Andric         SR = SubR;
6110b57cec5SDimitry Andric       } else {
6120b57cec5SDimitry Andric         const UUPair &P = F->second;
6130b57cec5SDimitry Andric         R = (SubR == Hexagon::isub_lo) ? P.first : P.second;
6140b57cec5SDimitry Andric         SR = 0;
6150b57cec5SDimitry Andric       }
6160b57cec5SDimitry Andric     }
6170b57cec5SDimitry Andric     auto CO = MachineOperand::CreateReg(R, Op.isDef(), Op.isImplicit(), isKill,
6180b57cec5SDimitry Andric           Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(),
6190b57cec5SDimitry Andric           Op.isInternalRead());
6200b57cec5SDimitry Andric     NewI->addOperand(CO);
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI,
6250b57cec5SDimitry Andric       const UUPairMap &PairMap) {
6260b57cec5SDimitry Andric   bool Load = MI->mayLoad();
6270b57cec5SDimitry Andric   unsigned OrigOpc = MI->getOpcode();
6280b57cec5SDimitry Andric   bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||
6290b57cec5SDimitry Andric                   OrigOpc == Hexagon::S2_storerd_pi);
6300b57cec5SDimitry Andric   MachineInstr *LowI, *HighI;
6310b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
6320b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   // Index of the base-address-register operand.
6350b57cec5SDimitry Andric   unsigned AdrX = PostInc ? (Load ? 2 : 1)
6360b57cec5SDimitry Andric                           : (Load ? 1 : 0);
6370b57cec5SDimitry Andric   MachineOperand &AdrOp = MI->getOperand(AdrX);
6380b57cec5SDimitry Andric   unsigned RSA = getRegState(AdrOp);
6390b57cec5SDimitry Andric   MachineOperand &ValOp = Load ? MI->getOperand(0)
6400b57cec5SDimitry Andric                                : (PostInc ? MI->getOperand(3)
6410b57cec5SDimitry Andric                                           : MI->getOperand(2));
6420b57cec5SDimitry Andric   UUPairMap::const_iterator F = PairMap.find(ValOp.getReg());
6430b57cec5SDimitry Andric   assert(F != PairMap.end());
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   if (Load) {
6460b57cec5SDimitry Andric     const UUPair &P = F->second;
6470b57cec5SDimitry Andric     int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm();
6480b57cec5SDimitry Andric     LowI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.first)
6490b57cec5SDimitry Andric              .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
6500b57cec5SDimitry Andric              .addImm(Off);
6510b57cec5SDimitry Andric     HighI = BuildMI(B, MI, DL, TII->get(Hexagon::L2_loadri_io), P.second)
6520b57cec5SDimitry Andric               .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
6530b57cec5SDimitry Andric               .addImm(Off+4);
6540b57cec5SDimitry Andric   } else {
6550b57cec5SDimitry Andric     const UUPair &P = F->second;
6560b57cec5SDimitry Andric     int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm();
6570b57cec5SDimitry Andric     LowI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
6580b57cec5SDimitry Andric              .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
6590b57cec5SDimitry Andric              .addImm(Off)
6600b57cec5SDimitry Andric              .addReg(P.first);
6610b57cec5SDimitry Andric     HighI = BuildMI(B, MI, DL, TII->get(Hexagon::S2_storeri_io))
6620b57cec5SDimitry Andric               .addReg(AdrOp.getReg(), RSA & ~RegState::Kill, AdrOp.getSubReg())
6630b57cec5SDimitry Andric               .addImm(Off+4)
6640b57cec5SDimitry Andric               .addReg(P.second);
6650b57cec5SDimitry Andric   }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   if (PostInc) {
6680b57cec5SDimitry Andric     // Create the increment of the address register.
6690b57cec5SDimitry Andric     int64_t Inc = Load ? MI->getOperand(3).getImm()
6700b57cec5SDimitry Andric                        : MI->getOperand(2).getImm();
6710b57cec5SDimitry Andric     MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0);
6720b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg());
6738bcb0991SDimitry Andric     Register NewR = MRI->createVirtualRegister(RC);
6740b57cec5SDimitry Andric     assert(!UpdOp.getSubReg() && "Def operand with subreg");
6750b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(Hexagon::A2_addi), NewR)
6760b57cec5SDimitry Andric       .addReg(AdrOp.getReg(), RSA)
6770b57cec5SDimitry Andric       .addImm(Inc);
6780b57cec5SDimitry Andric     MRI->replaceRegWith(UpdOp.getReg(), NewR);
6790b57cec5SDimitry Andric     // The original instruction will be deleted later.
6800b57cec5SDimitry Andric   }
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // Generate a new pair of memory-operands.
6830b57cec5SDimitry Andric   MachineFunction &MF = *B.getParent();
6840b57cec5SDimitry Andric   for (auto &MO : MI->memoperands()) {
6850b57cec5SDimitry Andric     const MachinePointerInfo &Ptr = MO->getPointerInfo();
6860b57cec5SDimitry Andric     MachineMemOperand::Flags F = MO->getFlags();
6875ffd83dbSDimitry Andric     Align A = MO->getAlign();
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric     auto *Tmp1 = MF.getMachineMemOperand(Ptr, F, 4 /*size*/, A);
6900b57cec5SDimitry Andric     LowI->addMemOperand(MF, Tmp1);
6915ffd83dbSDimitry Andric     auto *Tmp2 =
6925ffd83dbSDimitry Andric         MF.getMachineMemOperand(Ptr, F, 4 /*size*/, std::min(A, Align(4)));
6930b57cec5SDimitry Andric     HighI->addMemOperand(MF, Tmp2);
6940b57cec5SDimitry Andric   }
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI,
6980b57cec5SDimitry Andric       const UUPairMap &PairMap) {
6990b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
7000b57cec5SDimitry Andric   MachineOperand &Op1 = MI->getOperand(1);
7010b57cec5SDimitry Andric   assert(Op0.isReg() && Op1.isImm());
7020b57cec5SDimitry Andric   uint64_t V = Op1.getImm();
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
7050b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
7060b57cec5SDimitry Andric   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
7070b57cec5SDimitry Andric   assert(F != PairMap.end());
7080b57cec5SDimitry Andric   const UUPair &P = F->second;
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   // The operand to A2_tfrsi can only have 32 significant bits. Immediate
7110b57cec5SDimitry Andric   // values in MachineOperand are stored as 64-bit integers, and so the
7120b57cec5SDimitry Andric   // value -1 may be represented either as 64-bit -1, or 4294967295. Both
7130b57cec5SDimitry Andric   // will have the 32 higher bits truncated in the end, but -1 will remain
7140b57cec5SDimitry Andric   // as -1, while the latter may appear to be a large unsigned value
7150b57cec5SDimitry Andric   // requiring a constant extender. The casting to int32_t will select the
7160b57cec5SDimitry Andric   // former representation. (The same reasoning applies to all 32-bit
7170b57cec5SDimitry Andric   // values.)
7180b57cec5SDimitry Andric   BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
7190b57cec5SDimitry Andric     .addImm(int32_t(V & 0xFFFFFFFFULL));
7200b57cec5SDimitry Andric   BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
7210b57cec5SDimitry Andric     .addImm(int32_t(V >> 32));
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI,
7250b57cec5SDimitry Andric       const UUPairMap &PairMap) {
7260b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
7270b57cec5SDimitry Andric   MachineOperand &Op1 = MI->getOperand(1);
7280b57cec5SDimitry Andric   MachineOperand &Op2 = MI->getOperand(2);
7290b57cec5SDimitry Andric   assert(Op0.isReg());
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
7320b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
7330b57cec5SDimitry Andric   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
7340b57cec5SDimitry Andric   assert(F != PairMap.end());
7350b57cec5SDimitry Andric   const UUPair &P = F->second;
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric   if (!Op1.isReg()) {
7380b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.second)
7390b57cec5SDimitry Andric       .add(Op1);
7400b57cec5SDimitry Andric   } else {
7410b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.second)
7420b57cec5SDimitry Andric       .addReg(Op1.getReg(), getRegState(Op1), Op1.getSubReg());
7430b57cec5SDimitry Andric   }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   if (!Op2.isReg()) {
7460b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(Hexagon::A2_tfrsi), P.first)
7470b57cec5SDimitry Andric       .add(Op2);
7480b57cec5SDimitry Andric   } else {
7490b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
7500b57cec5SDimitry Andric       .addReg(Op2.getReg(), getRegState(Op2), Op2.getSubReg());
7510b57cec5SDimitry Andric   }
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI,
7550b57cec5SDimitry Andric       const UUPairMap &PairMap) {
7560b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
7570b57cec5SDimitry Andric   MachineOperand &Op1 = MI->getOperand(1);
7580b57cec5SDimitry Andric   assert(Op0.isReg() && Op1.isReg());
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
7610b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
7620b57cec5SDimitry Andric   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
7630b57cec5SDimitry Andric   assert(F != PairMap.end());
7640b57cec5SDimitry Andric   const UUPair &P = F->second;
7650b57cec5SDimitry Andric   unsigned RS = getRegState(Op1);
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric   BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), P.first)
7680b57cec5SDimitry Andric     .addReg(Op1.getReg(), RS & ~RegState::Kill, Op1.getSubReg());
7690b57cec5SDimitry Andric   BuildMI(B, MI, DL, TII->get(Hexagon::S2_asr_i_r), P.second)
7700b57cec5SDimitry Andric     .addReg(Op1.getReg(), RS, Op1.getSubReg())
7710b57cec5SDimitry Andric     .addImm(31);
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI,
7750b57cec5SDimitry Andric       const UUPairMap &PairMap) {
7760b57cec5SDimitry Andric   using namespace Hexagon;
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
7790b57cec5SDimitry Andric   MachineOperand &Op1 = MI->getOperand(1);
7800b57cec5SDimitry Andric   MachineOperand &Op2 = MI->getOperand(2);
7810b57cec5SDimitry Andric   assert(Op0.isReg() && Op1.isReg() && Op2.isImm());
7820b57cec5SDimitry Andric   int64_t Sh64 = Op2.getImm();
7830b57cec5SDimitry Andric   assert(Sh64 >= 0 && Sh64 < 64);
7840b57cec5SDimitry Andric   unsigned S = Sh64;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
7870b57cec5SDimitry Andric   assert(F != PairMap.end());
7880b57cec5SDimitry Andric   const UUPair &P = F->second;
7898bcb0991SDimitry Andric   Register LoR = P.first;
7908bcb0991SDimitry Andric   Register HiR = P.second;
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
7930b57cec5SDimitry Andric   bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);
7940b57cec5SDimitry Andric   bool Left = !Right;
7950b57cec5SDimitry Andric   bool Signed = (Opc == S2_asr_i_p);
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
7980b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
7990b57cec5SDimitry Andric   unsigned RS = getRegState(Op1);
8000b57cec5SDimitry Andric   unsigned ShiftOpc = Left ? S2_asl_i_r
8010b57cec5SDimitry Andric                            : (Signed ? S2_asr_i_r : S2_lsr_i_r);
8020b57cec5SDimitry Andric   unsigned LoSR = isub_lo;
8030b57cec5SDimitry Andric   unsigned HiSR = isub_hi;
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric   if (S == 0) {
8060b57cec5SDimitry Andric     // No shift, subregister copy.
8070b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
8080b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
8090b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), HiR)
8100b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS, HiSR);
8110b57cec5SDimitry Andric   } else if (S < 32) {
8120b57cec5SDimitry Andric     const TargetRegisterClass *IntRC = &IntRegsRegClass;
8138bcb0991SDimitry Andric     Register TmpR = MRI->createVirtualRegister(IntRC);
8140b57cec5SDimitry Andric     // Expansion:
8150b57cec5SDimitry Andric     // Shift left:    DR = shl R, #s
8160b57cec5SDimitry Andric     //   LoR  = shl R.lo, #s
8170b57cec5SDimitry Andric     //   TmpR = extractu R.lo, #s, #32-s
8180b57cec5SDimitry Andric     //   HiR  = or (TmpR, asl(R.hi, #s))
8190b57cec5SDimitry Andric     // Shift right:   DR = shr R, #s
8200b57cec5SDimitry Andric     //   HiR  = shr R.hi, #s
8210b57cec5SDimitry Andric     //   TmpR = shr R.lo, #s
8220b57cec5SDimitry Andric     //   LoR  = insert TmpR, R.hi, #s, #32-s
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     // Shift left:
8250b57cec5SDimitry Andric     //   LoR  = shl R.lo, #s
8260b57cec5SDimitry Andric     // Shift right:
8270b57cec5SDimitry Andric     //   TmpR = shr R.lo, #s
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric     // Make a special case for A2_aslh and A2_asrh (they are predicable as
8300b57cec5SDimitry Andric     // opposed to S2_asl_i_r/S2_asr_i_r).
8310b57cec5SDimitry Andric     if (S == 16 && Left)
8320b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(A2_aslh), LoR)
8330b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
8340b57cec5SDimitry Andric     else if (S == 16 && Signed)
8350b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(A2_asrh), TmpR)
8360b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
8370b57cec5SDimitry Andric     else
8380b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? LoR : TmpR))
8390b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
8400b57cec5SDimitry Andric         .addImm(S);
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric     if (Left) {
8430b57cec5SDimitry Andric       // TmpR = extractu R.lo, #s, #32-s
8440b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR)
8450b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR)
8460b57cec5SDimitry Andric         .addImm(S)
8470b57cec5SDimitry Andric         .addImm(32-S);
8480b57cec5SDimitry Andric       // HiR  = or (TmpR, asl(R.hi, #s))
8490b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
8500b57cec5SDimitry Andric         .addReg(TmpR)
8510b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS, HiSR)
8520b57cec5SDimitry Andric         .addImm(S);
8530b57cec5SDimitry Andric     } else {
8540b57cec5SDimitry Andric       // HiR  = shr R.hi, #s
8550b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(ShiftOpc), HiR)
8560b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR)
8570b57cec5SDimitry Andric         .addImm(S);
8580b57cec5SDimitry Andric       // LoR  = insert TmpR, R.hi, #s, #32-s
8590b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(S2_insert), LoR)
8600b57cec5SDimitry Andric         .addReg(TmpR)
8610b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS, HiSR)
8620b57cec5SDimitry Andric         .addImm(S)
8630b57cec5SDimitry Andric         .addImm(32-S);
8640b57cec5SDimitry Andric     }
8650b57cec5SDimitry Andric   } else if (S == 32) {
8660b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), (Left ? HiR : LoR))
8670b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR));
8680b57cec5SDimitry Andric     if (!Signed)
8690b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
8700b57cec5SDimitry Andric         .addImm(0);
8710b57cec5SDimitry Andric     else  // Must be right shift.
8720b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
8730b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS, HiSR)
8740b57cec5SDimitry Andric         .addImm(31);
8750b57cec5SDimitry Andric   } else if (S < 64) {
8760b57cec5SDimitry Andric     S -= 32;
8770b57cec5SDimitry Andric     if (S == 16 && Left)
8780b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(A2_aslh), HiR)
8790b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, LoSR);
8800b57cec5SDimitry Andric     else if (S == 16 && Signed)
8810b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(A2_asrh), LoR)
8820b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, HiSR);
8830b57cec5SDimitry Andric     else
8840b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(ShiftOpc), (Left ? HiR : LoR))
8850b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS & ~RegState::Kill, (Left ? LoSR : HiSR))
8860b57cec5SDimitry Andric         .addImm(S);
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric     if (Signed)
8890b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(S2_asr_i_r), HiR)
8900b57cec5SDimitry Andric         .addReg(Op1.getReg(), RS, HiSR)
8910b57cec5SDimitry Andric         .addImm(31);
8920b57cec5SDimitry Andric     else
8930b57cec5SDimitry Andric       BuildMI(B, MI, DL, TII->get(A2_tfrsi), (Left ? LoR : HiR))
8940b57cec5SDimitry Andric         .addImm(0);
8950b57cec5SDimitry Andric   }
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI,
8990b57cec5SDimitry Andric       const UUPairMap &PairMap) {
9000b57cec5SDimitry Andric   using namespace Hexagon;
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
9030b57cec5SDimitry Andric   MachineOperand &Op1 = MI->getOperand(1);
9040b57cec5SDimitry Andric   MachineOperand &Op2 = MI->getOperand(2);
9050b57cec5SDimitry Andric   MachineOperand &Op3 = MI->getOperand(3);
9060b57cec5SDimitry Andric   assert(Op0.isReg() && Op1.isReg() && Op2.isReg() && Op3.isImm());
9070b57cec5SDimitry Andric   int64_t Sh64 = Op3.getImm();
9080b57cec5SDimitry Andric   assert(Sh64 >= 0 && Sh64 < 64);
9090b57cec5SDimitry Andric   unsigned S = Sh64;
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   UUPairMap::const_iterator F = PairMap.find(Op0.getReg());
9120b57cec5SDimitry Andric   assert(F != PairMap.end());
9130b57cec5SDimitry Andric   const UUPair &P = F->second;
9140b57cec5SDimitry Andric   unsigned LoR = P.first;
9150b57cec5SDimitry Andric   unsigned HiR = P.second;
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
9180b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
9190b57cec5SDimitry Andric   unsigned RS1 = getRegState(Op1);
9200b57cec5SDimitry Andric   unsigned RS2 = getRegState(Op2);
9210b57cec5SDimitry Andric   const TargetRegisterClass *IntRC = &IntRegsRegClass;
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric   unsigned LoSR = isub_lo;
9240b57cec5SDimitry Andric   unsigned HiSR = isub_hi;
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric   // Op0 = S2_asl_i_p_or Op1, Op2, Op3
9270b57cec5SDimitry Andric   // means:  Op0 = or (Op1, asl(Op2, Op3))
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   // Expansion of
9300b57cec5SDimitry Andric   //   DR = or (R1, asl(R2, #s))
9310b57cec5SDimitry Andric   //
9320b57cec5SDimitry Andric   //   LoR  = or (R1.lo, asl(R2.lo, #s))
9330b57cec5SDimitry Andric   //   Tmp1 = extractu R2.lo, #s, #32-s
9340b57cec5SDimitry Andric   //   Tmp2 = or R1.hi, Tmp1
9350b57cec5SDimitry Andric   //   HiR  = or (Tmp2, asl(R2.hi, #s))
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric   if (S == 0) {
9380b57cec5SDimitry Andric     // DR  = or (R1, asl(R2, #0))
9390b57cec5SDimitry Andric     //    -> or (R1, R2)
9400b57cec5SDimitry Andric     // i.e. LoR = or R1.lo, R2.lo
9410b57cec5SDimitry Andric     //      HiR = or R1.hi, R2.hi
9420b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(A2_or), LoR)
9430b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
9440b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR);
9450b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(A2_or), HiR)
9460b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1, HiSR)
9470b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2, HiSR);
9480b57cec5SDimitry Andric   } else if (S < 32) {
9490b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), LoR)
9500b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR)
9510b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
9520b57cec5SDimitry Andric       .addImm(S);
9538bcb0991SDimitry Andric     Register TmpR1 = MRI->createVirtualRegister(IntRC);
9540b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(S2_extractu), TmpR1)
9550b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2 & ~RegState::Kill, LoSR)
9560b57cec5SDimitry Andric       .addImm(S)
9570b57cec5SDimitry Andric       .addImm(32-S);
9588bcb0991SDimitry Andric     Register TmpR2 = MRI->createVirtualRegister(IntRC);
9590b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(A2_or), TmpR2)
9600b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1, HiSR)
9610b57cec5SDimitry Andric       .addReg(TmpR1);
9620b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
9630b57cec5SDimitry Andric       .addReg(TmpR2)
9640b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2, HiSR)
9650b57cec5SDimitry Andric       .addImm(S);
9660b57cec5SDimitry Andric   } else if (S == 32) {
9670b57cec5SDimitry Andric     // DR  = or (R1, asl(R2, #32))
9680b57cec5SDimitry Andric     //    -> or R1, R2.lo
9690b57cec5SDimitry Andric     // LoR = R1.lo
9700b57cec5SDimitry Andric     // HiR = or R1.hi, R2.lo
9710b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
9720b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
9730b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(A2_or), HiR)
9740b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1, HiSR)
9750b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2, LoSR);
9760b57cec5SDimitry Andric   } else if (S < 64) {
9770b57cec5SDimitry Andric     // DR  = or (R1, asl(R2, #s))
9780b57cec5SDimitry Andric     //
9790b57cec5SDimitry Andric     // LoR = R1:lo
9800b57cec5SDimitry Andric     // HiR = or (R1:hi, asl(R2:lo, #s-32))
9810b57cec5SDimitry Andric     S -= 32;
9820b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), LoR)
9830b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1 & ~RegState::Kill, LoSR);
9840b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(S2_asl_i_r_or), HiR)
9850b57cec5SDimitry Andric       .addReg(Op1.getReg(), RS1, HiSR)
9860b57cec5SDimitry Andric       .addReg(Op2.getReg(), RS2, LoSR)
9870b57cec5SDimitry Andric       .addImm(S);
9880b57cec5SDimitry Andric   }
9890b57cec5SDimitry Andric }
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI,
9920b57cec5SDimitry Andric       const UUPairMap &PairMap) {
9930b57cec5SDimitry Andric   using namespace Hexagon;
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Splitting: " << *MI);
9960b57cec5SDimitry Andric   bool Split = false;
9970b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric   switch (Opc) {
10000b57cec5SDimitry Andric     case TargetOpcode::PHI:
10010b57cec5SDimitry Andric     case TargetOpcode::COPY: {
10028bcb0991SDimitry Andric       Register DstR = MI->getOperand(0).getReg();
10030b57cec5SDimitry Andric       if (MRI->getRegClass(DstR) == DoubleRC) {
10040b57cec5SDimitry Andric         createHalfInstr(Opc, MI, PairMap, isub_lo);
10050b57cec5SDimitry Andric         createHalfInstr(Opc, MI, PairMap, isub_hi);
10060b57cec5SDimitry Andric         Split = true;
10070b57cec5SDimitry Andric       }
10080b57cec5SDimitry Andric       break;
10090b57cec5SDimitry Andric     }
10100b57cec5SDimitry Andric     case A2_andp:
10110b57cec5SDimitry Andric       createHalfInstr(A2_and, MI, PairMap, isub_lo);
10120b57cec5SDimitry Andric       createHalfInstr(A2_and, MI, PairMap, isub_hi);
10130b57cec5SDimitry Andric       Split = true;
10140b57cec5SDimitry Andric       break;
10150b57cec5SDimitry Andric     case A2_orp:
10160b57cec5SDimitry Andric       createHalfInstr(A2_or, MI, PairMap, isub_lo);
10170b57cec5SDimitry Andric       createHalfInstr(A2_or, MI, PairMap, isub_hi);
10180b57cec5SDimitry Andric       Split = true;
10190b57cec5SDimitry Andric       break;
10200b57cec5SDimitry Andric     case A2_xorp:
10210b57cec5SDimitry Andric       createHalfInstr(A2_xor, MI, PairMap, isub_lo);
10220b57cec5SDimitry Andric       createHalfInstr(A2_xor, MI, PairMap, isub_hi);
10230b57cec5SDimitry Andric       Split = true;
10240b57cec5SDimitry Andric       break;
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric     case L2_loadrd_io:
10270b57cec5SDimitry Andric     case L2_loadrd_pi:
10280b57cec5SDimitry Andric     case S2_storerd_io:
10290b57cec5SDimitry Andric     case S2_storerd_pi:
10300b57cec5SDimitry Andric       splitMemRef(MI, PairMap);
10310b57cec5SDimitry Andric       Split = true;
10320b57cec5SDimitry Andric       break;
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric     case A2_tfrpi:
10350b57cec5SDimitry Andric     case CONST64:
10360b57cec5SDimitry Andric       splitImmediate(MI, PairMap);
10370b57cec5SDimitry Andric       Split = true;
10380b57cec5SDimitry Andric       break;
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric     case A2_combineii:
10410b57cec5SDimitry Andric     case A4_combineir:
10420b57cec5SDimitry Andric     case A4_combineii:
10430b57cec5SDimitry Andric     case A4_combineri:
10440b57cec5SDimitry Andric     case A2_combinew:
10450b57cec5SDimitry Andric       splitCombine(MI, PairMap);
10460b57cec5SDimitry Andric       Split = true;
10470b57cec5SDimitry Andric       break;
10480b57cec5SDimitry Andric 
10490b57cec5SDimitry Andric     case A2_sxtw:
10500b57cec5SDimitry Andric       splitExt(MI, PairMap);
10510b57cec5SDimitry Andric       Split = true;
10520b57cec5SDimitry Andric       break;
10530b57cec5SDimitry Andric 
10540b57cec5SDimitry Andric     case S2_asl_i_p:
10550b57cec5SDimitry Andric     case S2_asr_i_p:
10560b57cec5SDimitry Andric     case S2_lsr_i_p:
10570b57cec5SDimitry Andric       splitShift(MI, PairMap);
10580b57cec5SDimitry Andric       Split = true;
10590b57cec5SDimitry Andric       break;
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric     case S2_asl_i_p_or:
10620b57cec5SDimitry Andric       splitAslOr(MI, PairMap);
10630b57cec5SDimitry Andric       Split = true;
10640b57cec5SDimitry Andric       break;
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric     default:
10670b57cec5SDimitry Andric       llvm_unreachable("Instruction not splitable");
10680b57cec5SDimitry Andric       return false;
10690b57cec5SDimitry Andric   }
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   return Split;
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI,
10750b57cec5SDimitry Andric       const UUPairMap &PairMap) {
10760b57cec5SDimitry Andric   for (auto &Op : MI->operands()) {
10770b57cec5SDimitry Andric     if (!Op.isReg() || !Op.isUse() || !Op.getSubReg())
10780b57cec5SDimitry Andric       continue;
10798bcb0991SDimitry Andric     Register R = Op.getReg();
10800b57cec5SDimitry Andric     UUPairMap::const_iterator F = PairMap.find(R);
10810b57cec5SDimitry Andric     if (F == PairMap.end())
10820b57cec5SDimitry Andric       continue;
10830b57cec5SDimitry Andric     const UUPair &P = F->second;
10840b57cec5SDimitry Andric     switch (Op.getSubReg()) {
10850b57cec5SDimitry Andric       case Hexagon::isub_lo:
10860b57cec5SDimitry Andric         Op.setReg(P.first);
10870b57cec5SDimitry Andric         break;
10880b57cec5SDimitry Andric       case Hexagon::isub_hi:
10890b57cec5SDimitry Andric         Op.setReg(P.second);
10900b57cec5SDimitry Andric         break;
10910b57cec5SDimitry Andric     }
10920b57cec5SDimitry Andric     Op.setSubReg(0);
10930b57cec5SDimitry Andric   }
10940b57cec5SDimitry Andric }
10950b57cec5SDimitry Andric 
10960b57cec5SDimitry Andric void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI,
10970b57cec5SDimitry Andric       const UUPairMap &PairMap) {
10980b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
10990b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric   for (auto &Op : MI->operands()) {
11020b57cec5SDimitry Andric     if (!Op.isReg() || !Op.isUse())
11030b57cec5SDimitry Andric       continue;
11048bcb0991SDimitry Andric     Register R = Op.getReg();
1105e8d8bef9SDimitry Andric     if (!R.isVirtual())
11060b57cec5SDimitry Andric       continue;
11070b57cec5SDimitry Andric     if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg())
11080b57cec5SDimitry Andric       continue;
11090b57cec5SDimitry Andric     UUPairMap::const_iterator F = PairMap.find(R);
11100b57cec5SDimitry Andric     if (F == PairMap.end())
11110b57cec5SDimitry Andric       continue;
11120b57cec5SDimitry Andric     const UUPair &Pr = F->second;
11138bcb0991SDimitry Andric     Register NewDR = MRI->createVirtualRegister(DoubleRC);
11140b57cec5SDimitry Andric     BuildMI(B, MI, DL, TII->get(TargetOpcode::REG_SEQUENCE), NewDR)
11150b57cec5SDimitry Andric       .addReg(Pr.first)
11160b57cec5SDimitry Andric       .addImm(Hexagon::isub_lo)
11170b57cec5SDimitry Andric       .addReg(Pr.second)
11180b57cec5SDimitry Andric       .addImm(Hexagon::isub_hi);
11190b57cec5SDimitry Andric     Op.setReg(NewDR);
11200b57cec5SDimitry Andric   }
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) {
11240b57cec5SDimitry Andric   using MISet = std::set<MachineInstr *>;
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;
11270b57cec5SDimitry Andric   bool Changed = false;
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Splitting partition: ";
11300b57cec5SDimitry Andric              dump_partition(dbgs(), Part, *TRI); dbgs() << '\n');
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   UUPairMap PairMap;
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   MISet SplitIns;
11350b57cec5SDimitry Andric   for (unsigned DR : Part) {
11360b57cec5SDimitry Andric     MachineInstr *DefI = MRI->getVRegDef(DR);
11370b57cec5SDimitry Andric     SplitIns.insert(DefI);
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric     // Collect all instructions, including fixed ones.  We won't split them,
11400b57cec5SDimitry Andric     // but we need to visit them again to insert the REG_SEQUENCE instructions.
11410b57cec5SDimitry Andric     for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
11420b57cec5SDimitry Andric          U != W; ++U)
11430b57cec5SDimitry Andric       SplitIns.insert(U->getParent());
11440b57cec5SDimitry Andric 
11458bcb0991SDimitry Andric     Register LoR = MRI->createVirtualRegister(IntRC);
11468bcb0991SDimitry Andric     Register HiR = MRI->createVirtualRegister(IntRC);
11470b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Created mapping: " << printReg(DR, TRI) << " -> "
11480b57cec5SDimitry Andric                       << printReg(HiR, TRI) << ':' << printReg(LoR, TRI)
11490b57cec5SDimitry Andric                       << '\n');
11500b57cec5SDimitry Andric     PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   MISet Erase;
11540b57cec5SDimitry Andric   for (auto MI : SplitIns) {
11550b57cec5SDimitry Andric     if (isFixedInstr(MI)) {
11560b57cec5SDimitry Andric       collapseRegPairs(MI, PairMap);
11570b57cec5SDimitry Andric     } else {
11580b57cec5SDimitry Andric       bool Done = splitInstr(MI, PairMap);
11590b57cec5SDimitry Andric       if (Done)
11600b57cec5SDimitry Andric         Erase.insert(MI);
11610b57cec5SDimitry Andric       Changed |= Done;
11620b57cec5SDimitry Andric     }
11630b57cec5SDimitry Andric   }
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric   for (unsigned DR : Part) {
11660b57cec5SDimitry Andric     // Before erasing "double" instructions, revisit all uses of the double
11670b57cec5SDimitry Andric     // registers in this partition, and replace all uses of them with subre-
11680b57cec5SDimitry Andric     // gisters, with the corresponding single registers.
11690b57cec5SDimitry Andric     MISet Uses;
11700b57cec5SDimitry Andric     for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();
11710b57cec5SDimitry Andric          U != W; ++U)
11720b57cec5SDimitry Andric       Uses.insert(U->getParent());
11730b57cec5SDimitry Andric     for (auto M : Uses)
11740b57cec5SDimitry Andric       replaceSubregUses(M, PairMap);
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   for (auto MI : Erase) {
11780b57cec5SDimitry Andric     MachineBasicBlock *B = MI->getParent();
11790b57cec5SDimitry Andric     B->erase(MI);
11800b57cec5SDimitry Andric   }
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric   return Changed;
11830b57cec5SDimitry Andric }
11840b57cec5SDimitry Andric 
11850b57cec5SDimitry Andric bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) {
11860b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
11870b57cec5SDimitry Andric     return false;
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Splitting double registers in function: "
11900b57cec5SDimitry Andric                     << MF.getName() << '\n');
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric   auto &ST = MF.getSubtarget<HexagonSubtarget>();
11930b57cec5SDimitry Andric   TRI = ST.getRegisterInfo();
11940b57cec5SDimitry Andric   TII = ST.getInstrInfo();
11950b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
11960b57cec5SDimitry Andric   MLI = &getAnalysis<MachineLoopInfo>();
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric   UUSetMap P2Rs;
11990b57cec5SDimitry Andric   LoopRegMap IRM;
12000b57cec5SDimitry Andric 
12010b57cec5SDimitry Andric   collectIndRegs(IRM);
12020b57cec5SDimitry Andric   partitionRegisters(P2Rs);
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric   LLVM_DEBUG({
12050b57cec5SDimitry Andric     dbgs() << "Register partitioning: (partition #0 is fixed)\n";
12060b57cec5SDimitry Andric     for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
12070b57cec5SDimitry Andric       dbgs() << '#' << I->first << " -> ";
12080b57cec5SDimitry Andric       dump_partition(dbgs(), I->second, *TRI);
12090b57cec5SDimitry Andric       dbgs() << '\n';
12100b57cec5SDimitry Andric     }
12110b57cec5SDimitry Andric   });
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric   bool Changed = false;
12140b57cec5SDimitry Andric   int Limit = MaxHSDR;
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric   for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {
12170b57cec5SDimitry Andric     if (I->first == 0)
12180b57cec5SDimitry Andric       continue;
12190b57cec5SDimitry Andric     if (Limit >= 0 && Counter >= Limit)
12200b57cec5SDimitry Andric       break;
12210b57cec5SDimitry Andric     USet &Part = I->second;
12220b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Calculating profit for partition #" << I->first
12230b57cec5SDimitry Andric                       << '\n');
12240b57cec5SDimitry Andric     if (!isProfitable(Part, IRM))
12250b57cec5SDimitry Andric       continue;
12260b57cec5SDimitry Andric     Counter++;
12270b57cec5SDimitry Andric     Changed |= splitPartition(Part);
12280b57cec5SDimitry Andric   }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric   return Changed;
12310b57cec5SDimitry Andric }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric FunctionPass *llvm::createHexagonSplitDoubleRegs() {
12340b57cec5SDimitry Andric   return new HexagonSplitDoubleRegs();
12350b57cec5SDimitry Andric }
1236