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