xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===------- HexagonCopyToCombine.cpp - Hexagon Copy-To-Combine Pass ------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric // This pass replaces transfer instructions by combine instructions.
9*0b57cec5SDimitry Andric // We walk along a basic block and look for two combinable instructions and try
10*0b57cec5SDimitry Andric // to move them together. If we can move them next to each other we do so and
11*0b57cec5SDimitry Andric // replace them with a combine instruction.
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
14*0b57cec5SDimitry Andric #include "HexagonSubtarget.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
22*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
23*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
24*0b57cec5SDimitry Andric #include "llvm/PassSupport.h"
25*0b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
27*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
28*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric using namespace llvm;
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric #define DEBUG_TYPE "hexagon-copy-combine"
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric static
35*0b57cec5SDimitry Andric cl::opt<bool> IsCombinesDisabled("disable-merge-into-combines",
36*0b57cec5SDimitry Andric                                  cl::Hidden, cl::ZeroOrMore,
37*0b57cec5SDimitry Andric                                  cl::init(false),
38*0b57cec5SDimitry Andric                                  cl::desc("Disable merging into combines"));
39*0b57cec5SDimitry Andric static
40*0b57cec5SDimitry Andric cl::opt<bool> IsConst64Disabled("disable-const64",
41*0b57cec5SDimitry Andric                                  cl::Hidden, cl::ZeroOrMore,
42*0b57cec5SDimitry Andric                                  cl::init(false),
43*0b57cec5SDimitry Andric                                  cl::desc("Disable generation of const64"));
44*0b57cec5SDimitry Andric static
45*0b57cec5SDimitry Andric cl::opt<unsigned>
46*0b57cec5SDimitry Andric MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store",
47*0b57cec5SDimitry Andric                    cl::Hidden, cl::init(4),
48*0b57cec5SDimitry Andric                    cl::desc("Maximum distance between a tfr feeding a store we "
49*0b57cec5SDimitry Andric                             "consider the store still to be newifiable"));
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric namespace llvm {
52*0b57cec5SDimitry Andric   FunctionPass *createHexagonCopyToCombine();
53*0b57cec5SDimitry Andric   void initializeHexagonCopyToCombinePass(PassRegistry&);
54*0b57cec5SDimitry Andric }
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric 
57*0b57cec5SDimitry Andric namespace {
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric class HexagonCopyToCombine : public MachineFunctionPass  {
60*0b57cec5SDimitry Andric   const HexagonInstrInfo *TII;
61*0b57cec5SDimitry Andric   const TargetRegisterInfo *TRI;
62*0b57cec5SDimitry Andric   const HexagonSubtarget *ST;
63*0b57cec5SDimitry Andric   bool ShouldCombineAggressively;
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric   DenseSet<MachineInstr *> PotentiallyNewifiableTFR;
66*0b57cec5SDimitry Andric   SmallVector<MachineInstr *, 8> DbgMItoMove;
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric public:
69*0b57cec5SDimitry Andric   static char ID;
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric   HexagonCopyToCombine() : MachineFunctionPass(ID) {
72*0b57cec5SDimitry Andric     initializeHexagonCopyToCombinePass(*PassRegistry::getPassRegistry());
73*0b57cec5SDimitry Andric   }
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
76*0b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
77*0b57cec5SDimitry Andric   }
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric   StringRef getPassName() const override {
80*0b57cec5SDimitry Andric     return "Hexagon Copy-To-Combine Pass";
81*0b57cec5SDimitry Andric   }
82*0b57cec5SDimitry Andric 
83*0b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &Fn) override;
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
86*0b57cec5SDimitry Andric     return MachineFunctionProperties().set(
87*0b57cec5SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
88*0b57cec5SDimitry Andric   }
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric private:
91*0b57cec5SDimitry Andric   MachineInstr *findPairable(MachineInstr &I1, bool &DoInsertAtI1,
92*0b57cec5SDimitry Andric                              bool AllowC64);
93*0b57cec5SDimitry Andric 
94*0b57cec5SDimitry Andric   void findPotentialNewifiableTFRs(MachineBasicBlock &);
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric   void combine(MachineInstr &I1, MachineInstr &I2,
97*0b57cec5SDimitry Andric                MachineBasicBlock::iterator &MI, bool DoInsertAtI1,
98*0b57cec5SDimitry Andric                bool OptForSize);
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric   bool isSafeToMoveTogether(MachineInstr &I1, MachineInstr &I2,
101*0b57cec5SDimitry Andric                             unsigned I1DestReg, unsigned I2DestReg,
102*0b57cec5SDimitry Andric                             bool &DoInsertAtI1);
103*0b57cec5SDimitry Andric 
104*0b57cec5SDimitry Andric   void emitCombineRR(MachineBasicBlock::iterator &Before, unsigned DestReg,
105*0b57cec5SDimitry Andric                      MachineOperand &HiOperand, MachineOperand &LoOperand);
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric   void emitCombineRI(MachineBasicBlock::iterator &Before, unsigned DestReg,
108*0b57cec5SDimitry Andric                      MachineOperand &HiOperand, MachineOperand &LoOperand);
109*0b57cec5SDimitry Andric 
110*0b57cec5SDimitry Andric   void emitCombineIR(MachineBasicBlock::iterator &Before, unsigned DestReg,
111*0b57cec5SDimitry Andric                      MachineOperand &HiOperand, MachineOperand &LoOperand);
112*0b57cec5SDimitry Andric 
113*0b57cec5SDimitry Andric   void emitCombineII(MachineBasicBlock::iterator &Before, unsigned DestReg,
114*0b57cec5SDimitry Andric                      MachineOperand &HiOperand, MachineOperand &LoOperand);
115*0b57cec5SDimitry Andric 
116*0b57cec5SDimitry Andric   void emitConst64(MachineBasicBlock::iterator &Before, unsigned DestReg,
117*0b57cec5SDimitry Andric                    MachineOperand &HiOperand, MachineOperand &LoOperand);
118*0b57cec5SDimitry Andric };
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric } // End anonymous namespace.
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric char HexagonCopyToCombine::ID = 0;
123*0b57cec5SDimitry Andric 
124*0b57cec5SDimitry Andric INITIALIZE_PASS(HexagonCopyToCombine, "hexagon-copy-combine",
125*0b57cec5SDimitry Andric                 "Hexagon Copy-To-Combine Pass", false, false)
126*0b57cec5SDimitry Andric 
127*0b57cec5SDimitry Andric static bool isCombinableInstType(MachineInstr &MI, const HexagonInstrInfo *TII,
128*0b57cec5SDimitry Andric                                  bool ShouldCombineAggressively) {
129*0b57cec5SDimitry Andric   switch (MI.getOpcode()) {
130*0b57cec5SDimitry Andric   case Hexagon::A2_tfr: {
131*0b57cec5SDimitry Andric     // A COPY instruction can be combined if its arguments are IntRegs (32bit).
132*0b57cec5SDimitry Andric     const MachineOperand &Op0 = MI.getOperand(0);
133*0b57cec5SDimitry Andric     const MachineOperand &Op1 = MI.getOperand(1);
134*0b57cec5SDimitry Andric     assert(Op0.isReg() && Op1.isReg());
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric     unsigned DestReg = Op0.getReg();
137*0b57cec5SDimitry Andric     unsigned SrcReg = Op1.getReg();
138*0b57cec5SDimitry Andric     return Hexagon::IntRegsRegClass.contains(DestReg) &&
139*0b57cec5SDimitry Andric            Hexagon::IntRegsRegClass.contains(SrcReg);
140*0b57cec5SDimitry Andric   }
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric   case Hexagon::A2_tfrsi: {
143*0b57cec5SDimitry Andric     // A transfer-immediate can be combined if its argument is a signed 8bit
144*0b57cec5SDimitry Andric     // value.
145*0b57cec5SDimitry Andric     const MachineOperand &Op0 = MI.getOperand(0);
146*0b57cec5SDimitry Andric     const MachineOperand &Op1 = MI.getOperand(1);
147*0b57cec5SDimitry Andric     assert(Op0.isReg());
148*0b57cec5SDimitry Andric 
149*0b57cec5SDimitry Andric     unsigned DestReg = Op0.getReg();
150*0b57cec5SDimitry Andric     // Ensure that TargetFlags are MO_NO_FLAG for a global. This is a
151*0b57cec5SDimitry Andric     // workaround for an ABI bug that prevents GOT relocations on combine
152*0b57cec5SDimitry Andric     // instructions
153*0b57cec5SDimitry Andric     if (!Op1.isImm() && Op1.getTargetFlags() != HexagonII::MO_NO_FLAG)
154*0b57cec5SDimitry Andric       return false;
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric     // Only combine constant extended A2_tfrsi if we are in aggressive mode.
157*0b57cec5SDimitry Andric     bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm());
158*0b57cec5SDimitry Andric     return Hexagon::IntRegsRegClass.contains(DestReg) &&
159*0b57cec5SDimitry Andric            (ShouldCombineAggressively || NotExt);
160*0b57cec5SDimitry Andric   }
161*0b57cec5SDimitry Andric 
162*0b57cec5SDimitry Andric   case Hexagon::V6_vassign:
163*0b57cec5SDimitry Andric     return true;
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric   default:
166*0b57cec5SDimitry Andric     break;
167*0b57cec5SDimitry Andric   }
168*0b57cec5SDimitry Andric 
169*0b57cec5SDimitry Andric   return false;
170*0b57cec5SDimitry Andric }
171*0b57cec5SDimitry Andric 
172*0b57cec5SDimitry Andric template <unsigned N> static bool isGreaterThanNBitTFRI(const MachineInstr &I) {
173*0b57cec5SDimitry Andric   if (I.getOpcode() == Hexagon::TFRI64_V4 ||
174*0b57cec5SDimitry Andric       I.getOpcode() == Hexagon::A2_tfrsi) {
175*0b57cec5SDimitry Andric     const MachineOperand &Op = I.getOperand(1);
176*0b57cec5SDimitry Andric     return !Op.isImm() || !isInt<N>(Op.getImm());
177*0b57cec5SDimitry Andric   }
178*0b57cec5SDimitry Andric   return false;
179*0b57cec5SDimitry Andric }
180*0b57cec5SDimitry Andric 
181*0b57cec5SDimitry Andric /// areCombinableOperations - Returns true if the two instruction can be merge
182*0b57cec5SDimitry Andric /// into a combine (ignoring register constraints).
183*0b57cec5SDimitry Andric static bool areCombinableOperations(const TargetRegisterInfo *TRI,
184*0b57cec5SDimitry Andric                                     MachineInstr &HighRegInst,
185*0b57cec5SDimitry Andric                                     MachineInstr &LowRegInst, bool AllowC64) {
186*0b57cec5SDimitry Andric   unsigned HiOpc = HighRegInst.getOpcode();
187*0b57cec5SDimitry Andric   unsigned LoOpc = LowRegInst.getOpcode();
188*0b57cec5SDimitry Andric 
189*0b57cec5SDimitry Andric   auto verifyOpc = [](unsigned Opc) -> void {
190*0b57cec5SDimitry Andric     switch (Opc) {
191*0b57cec5SDimitry Andric       case Hexagon::A2_tfr:
192*0b57cec5SDimitry Andric       case Hexagon::A2_tfrsi:
193*0b57cec5SDimitry Andric       case Hexagon::V6_vassign:
194*0b57cec5SDimitry Andric         break;
195*0b57cec5SDimitry Andric       default:
196*0b57cec5SDimitry Andric         llvm_unreachable("Unexpected opcode");
197*0b57cec5SDimitry Andric     }
198*0b57cec5SDimitry Andric   };
199*0b57cec5SDimitry Andric   verifyOpc(HiOpc);
200*0b57cec5SDimitry Andric   verifyOpc(LoOpc);
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric   if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)
203*0b57cec5SDimitry Andric     return HiOpc == LoOpc;
204*0b57cec5SDimitry Andric 
205*0b57cec5SDimitry Andric   if (!AllowC64) {
206*0b57cec5SDimitry Andric     // There is no combine of two constant extended values.
207*0b57cec5SDimitry Andric     if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
208*0b57cec5SDimitry Andric         isGreaterThanNBitTFRI<6>(LowRegInst))
209*0b57cec5SDimitry Andric       return false;
210*0b57cec5SDimitry Andric   }
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric   // There is a combine of two constant extended values into CONST64,
213*0b57cec5SDimitry Andric   // provided both constants are true immediates.
214*0b57cec5SDimitry Andric   if (isGreaterThanNBitTFRI<16>(HighRegInst) &&
215*0b57cec5SDimitry Andric       isGreaterThanNBitTFRI<16>(LowRegInst))
216*0b57cec5SDimitry Andric     return (HighRegInst.getOperand(1).isImm() &&
217*0b57cec5SDimitry Andric             LowRegInst.getOperand(1).isImm());
218*0b57cec5SDimitry Andric 
219*0b57cec5SDimitry Andric   // There is no combine of two constant extended values, unless handled above
220*0b57cec5SDimitry Andric   // Make both 8-bit size checks to allow both combine (#,##) and combine(##,#)
221*0b57cec5SDimitry Andric   if (isGreaterThanNBitTFRI<8>(HighRegInst) &&
222*0b57cec5SDimitry Andric       isGreaterThanNBitTFRI<8>(LowRegInst))
223*0b57cec5SDimitry Andric     return false;
224*0b57cec5SDimitry Andric 
225*0b57cec5SDimitry Andric   return true;
226*0b57cec5SDimitry Andric }
227*0b57cec5SDimitry Andric 
228*0b57cec5SDimitry Andric static bool isEvenReg(unsigned Reg) {
229*0b57cec5SDimitry Andric   assert(TargetRegisterInfo::isPhysicalRegister(Reg));
230*0b57cec5SDimitry Andric   if (Hexagon::IntRegsRegClass.contains(Reg))
231*0b57cec5SDimitry Andric     return (Reg - Hexagon::R0) % 2 == 0;
232*0b57cec5SDimitry Andric   if (Hexagon::HvxVRRegClass.contains(Reg))
233*0b57cec5SDimitry Andric     return (Reg - Hexagon::V0) % 2 == 0;
234*0b57cec5SDimitry Andric   llvm_unreachable("Invalid register");
235*0b57cec5SDimitry Andric }
236*0b57cec5SDimitry Andric 
237*0b57cec5SDimitry Andric static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled) {
238*0b57cec5SDimitry Andric   for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
239*0b57cec5SDimitry Andric     MachineOperand &Op = MI.getOperand(I);
240*0b57cec5SDimitry Andric     if (!Op.isReg() || Op.getReg() != RegNotKilled || !Op.isKill())
241*0b57cec5SDimitry Andric       continue;
242*0b57cec5SDimitry Andric     Op.setIsKill(false);
243*0b57cec5SDimitry Andric   }
244*0b57cec5SDimitry Andric }
245*0b57cec5SDimitry Andric 
246*0b57cec5SDimitry Andric /// Returns true if it is unsafe to move a copy instruction from \p UseReg to
247*0b57cec5SDimitry Andric /// \p DestReg over the instruction \p MI.
248*0b57cec5SDimitry Andric static bool isUnsafeToMoveAcross(MachineInstr &MI, unsigned UseReg,
249*0b57cec5SDimitry Andric                                  unsigned DestReg,
250*0b57cec5SDimitry Andric                                  const TargetRegisterInfo *TRI) {
251*0b57cec5SDimitry Andric   return (UseReg && (MI.modifiesRegister(UseReg, TRI))) ||
252*0b57cec5SDimitry Andric          MI.modifiesRegister(DestReg, TRI) || MI.readsRegister(DestReg, TRI) ||
253*0b57cec5SDimitry Andric          MI.hasUnmodeledSideEffects() || MI.isInlineAsm() ||
254*0b57cec5SDimitry Andric          MI.isMetaInstruction();
255*0b57cec5SDimitry Andric }
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric static Register UseReg(const MachineOperand& MO) {
258*0b57cec5SDimitry Andric   return MO.isReg() ? MO.getReg() : Register();
259*0b57cec5SDimitry Andric }
260*0b57cec5SDimitry Andric 
261*0b57cec5SDimitry Andric /// isSafeToMoveTogether - Returns true if it is safe to move I1 next to I2 such
262*0b57cec5SDimitry Andric /// that the two instructions can be paired in a combine.
263*0b57cec5SDimitry Andric bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,
264*0b57cec5SDimitry Andric                                                 MachineInstr &I2,
265*0b57cec5SDimitry Andric                                                 unsigned I1DestReg,
266*0b57cec5SDimitry Andric                                                 unsigned I2DestReg,
267*0b57cec5SDimitry Andric                                                 bool &DoInsertAtI1) {
268*0b57cec5SDimitry Andric   unsigned I2UseReg = UseReg(I2.getOperand(1));
269*0b57cec5SDimitry Andric 
270*0b57cec5SDimitry Andric   // It is not safe to move I1 and I2 into one combine if I2 has a true
271*0b57cec5SDimitry Andric   // dependence on I1.
272*0b57cec5SDimitry Andric   if (I2UseReg && I1.modifiesRegister(I2UseReg, TRI))
273*0b57cec5SDimitry Andric     return false;
274*0b57cec5SDimitry Andric 
275*0b57cec5SDimitry Andric   bool isSafe = true;
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric   // First try to move I2 towards I1.
278*0b57cec5SDimitry Andric   {
279*0b57cec5SDimitry Andric     // A reverse_iterator instantiated like below starts before I2, and I1
280*0b57cec5SDimitry Andric     // respectively.
281*0b57cec5SDimitry Andric     // Look at instructions I in between I2 and (excluding) I1.
282*0b57cec5SDimitry Andric     MachineBasicBlock::reverse_iterator I(I2),
283*0b57cec5SDimitry Andric       End = --(MachineBasicBlock::reverse_iterator(I1));
284*0b57cec5SDimitry Andric     // At 03 we got better results (dhrystone!) by being more conservative.
285*0b57cec5SDimitry Andric     if (!ShouldCombineAggressively)
286*0b57cec5SDimitry Andric       End = MachineBasicBlock::reverse_iterator(I1);
287*0b57cec5SDimitry Andric     // If I2 kills its operand and we move I2 over an instruction that also
288*0b57cec5SDimitry Andric     // uses I2's use reg we need to modify that (first) instruction to now kill
289*0b57cec5SDimitry Andric     // this reg.
290*0b57cec5SDimitry Andric     unsigned KilledOperand = 0;
291*0b57cec5SDimitry Andric     if (I2.killsRegister(I2UseReg))
292*0b57cec5SDimitry Andric       KilledOperand = I2UseReg;
293*0b57cec5SDimitry Andric     MachineInstr *KillingInstr = nullptr;
294*0b57cec5SDimitry Andric 
295*0b57cec5SDimitry Andric     for (; I != End; ++I) {
296*0b57cec5SDimitry Andric       // If the intervening instruction I:
297*0b57cec5SDimitry Andric       //   * modifies I2's use reg
298*0b57cec5SDimitry Andric       //   * modifies I2's def reg
299*0b57cec5SDimitry Andric       //   * reads I2's def reg
300*0b57cec5SDimitry Andric       //   * or has unmodelled side effects
301*0b57cec5SDimitry Andric       // we can't move I2 across it.
302*0b57cec5SDimitry Andric       if (I->isDebugInstr())
303*0b57cec5SDimitry Andric         continue;
304*0b57cec5SDimitry Andric 
305*0b57cec5SDimitry Andric       if (isUnsafeToMoveAcross(*I, I2UseReg, I2DestReg, TRI)) {
306*0b57cec5SDimitry Andric         isSafe = false;
307*0b57cec5SDimitry Andric         break;
308*0b57cec5SDimitry Andric       }
309*0b57cec5SDimitry Andric 
310*0b57cec5SDimitry Andric       // Update first use of the killed operand.
311*0b57cec5SDimitry Andric       if (!KillingInstr && KilledOperand &&
312*0b57cec5SDimitry Andric           I->readsRegister(KilledOperand, TRI))
313*0b57cec5SDimitry Andric         KillingInstr = &*I;
314*0b57cec5SDimitry Andric     }
315*0b57cec5SDimitry Andric     if (isSafe) {
316*0b57cec5SDimitry Andric       // Update the intermediate instruction to with the kill flag.
317*0b57cec5SDimitry Andric       if (KillingInstr) {
318*0b57cec5SDimitry Andric         bool Added = KillingInstr->addRegisterKilled(KilledOperand, TRI, true);
319*0b57cec5SDimitry Andric         (void)Added; // suppress compiler warning
320*0b57cec5SDimitry Andric         assert(Added && "Must successfully update kill flag");
321*0b57cec5SDimitry Andric         removeKillInfo(I2, KilledOperand);
322*0b57cec5SDimitry Andric       }
323*0b57cec5SDimitry Andric       DoInsertAtI1 = true;
324*0b57cec5SDimitry Andric       return true;
325*0b57cec5SDimitry Andric     }
326*0b57cec5SDimitry Andric   }
327*0b57cec5SDimitry Andric 
328*0b57cec5SDimitry Andric   // Try to move I1 towards I2.
329*0b57cec5SDimitry Andric   {
330*0b57cec5SDimitry Andric     // Look at instructions I in between I1 and (excluding) I2.
331*0b57cec5SDimitry Andric     MachineBasicBlock::iterator I(I1), End(I2);
332*0b57cec5SDimitry Andric     // At O3 we got better results (dhrystone) by being more conservative here.
333*0b57cec5SDimitry Andric     if (!ShouldCombineAggressively)
334*0b57cec5SDimitry Andric       End = std::next(MachineBasicBlock::iterator(I2));
335*0b57cec5SDimitry Andric     unsigned I1UseReg = UseReg(I1.getOperand(1));
336*0b57cec5SDimitry Andric     // Track killed operands. If we move across an instruction that kills our
337*0b57cec5SDimitry Andric     // operand, we need to update the kill information on the moved I1. It kills
338*0b57cec5SDimitry Andric     // the operand now.
339*0b57cec5SDimitry Andric     MachineInstr *KillingInstr = nullptr;
340*0b57cec5SDimitry Andric     unsigned KilledOperand = 0;
341*0b57cec5SDimitry Andric 
342*0b57cec5SDimitry Andric     while(++I != End) {
343*0b57cec5SDimitry Andric       MachineInstr &MI = *I;
344*0b57cec5SDimitry Andric       // If the intervening instruction MI:
345*0b57cec5SDimitry Andric       //   * modifies I1's use reg
346*0b57cec5SDimitry Andric       //   * modifies I1's def reg
347*0b57cec5SDimitry Andric       //   * reads I1's def reg
348*0b57cec5SDimitry Andric       //   * or has unmodelled side effects
349*0b57cec5SDimitry Andric       //   We introduce this special case because llvm has no api to remove a
350*0b57cec5SDimitry Andric       //   kill flag for a register (a removeRegisterKilled() analogous to
351*0b57cec5SDimitry Andric       //   addRegisterKilled) that handles aliased register correctly.
352*0b57cec5SDimitry Andric       //   * or has a killed aliased register use of I1's use reg
353*0b57cec5SDimitry Andric       //           %d4 = A2_tfrpi 16
354*0b57cec5SDimitry Andric       //           %r6 = A2_tfr %r9
355*0b57cec5SDimitry Andric       //           %r8 = KILL %r8, implicit killed %d4
356*0b57cec5SDimitry Andric       //      If we want to move R6 = across the KILL instruction we would have
357*0b57cec5SDimitry Andric       //      to remove the implicit killed %d4 operand. For now, we are
358*0b57cec5SDimitry Andric       //      conservative and disallow the move.
359*0b57cec5SDimitry Andric       // we can't move I1 across it.
360*0b57cec5SDimitry Andric       if (MI.isDebugInstr()) {
361*0b57cec5SDimitry Andric         if (MI.readsRegister(I1DestReg, TRI)) // Move this instruction after I2.
362*0b57cec5SDimitry Andric           DbgMItoMove.push_back(&MI);
363*0b57cec5SDimitry Andric         continue;
364*0b57cec5SDimitry Andric       }
365*0b57cec5SDimitry Andric 
366*0b57cec5SDimitry Andric       if (isUnsafeToMoveAcross(MI, I1UseReg, I1DestReg, TRI) ||
367*0b57cec5SDimitry Andric           // Check for an aliased register kill. Bail out if we see one.
368*0b57cec5SDimitry Andric           (!MI.killsRegister(I1UseReg) && MI.killsRegister(I1UseReg, TRI)))
369*0b57cec5SDimitry Andric         return false;
370*0b57cec5SDimitry Andric 
371*0b57cec5SDimitry Andric       // Check for an exact kill (registers match).
372*0b57cec5SDimitry Andric       if (I1UseReg && MI.killsRegister(I1UseReg)) {
373*0b57cec5SDimitry Andric         assert(!KillingInstr && "Should only see one killing instruction");
374*0b57cec5SDimitry Andric         KilledOperand = I1UseReg;
375*0b57cec5SDimitry Andric         KillingInstr = &MI;
376*0b57cec5SDimitry Andric       }
377*0b57cec5SDimitry Andric     }
378*0b57cec5SDimitry Andric     if (KillingInstr) {
379*0b57cec5SDimitry Andric       removeKillInfo(*KillingInstr, KilledOperand);
380*0b57cec5SDimitry Andric       // Update I1 to set the kill flag. This flag will later be picked up by
381*0b57cec5SDimitry Andric       // the new COMBINE instruction.
382*0b57cec5SDimitry Andric       bool Added = I1.addRegisterKilled(KilledOperand, TRI);
383*0b57cec5SDimitry Andric       (void)Added; // suppress compiler warning
384*0b57cec5SDimitry Andric       assert(Added && "Must successfully update kill flag");
385*0b57cec5SDimitry Andric     }
386*0b57cec5SDimitry Andric     DoInsertAtI1 = false;
387*0b57cec5SDimitry Andric   }
388*0b57cec5SDimitry Andric 
389*0b57cec5SDimitry Andric   return true;
390*0b57cec5SDimitry Andric }
391*0b57cec5SDimitry Andric 
392*0b57cec5SDimitry Andric /// findPotentialNewifiableTFRs - Finds tranfers that feed stores that could be
393*0b57cec5SDimitry Andric /// newified. (A use of a 64 bit register define can not be newified)
394*0b57cec5SDimitry Andric void
395*0b57cec5SDimitry Andric HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
396*0b57cec5SDimitry Andric   DenseMap<unsigned, MachineInstr *> LastDef;
397*0b57cec5SDimitry Andric   for (MachineInstr &MI : BB) {
398*0b57cec5SDimitry Andric     if (MI.isDebugInstr())
399*0b57cec5SDimitry Andric       continue;
400*0b57cec5SDimitry Andric 
401*0b57cec5SDimitry Andric     // Mark TFRs that feed a potential new value store as such.
402*0b57cec5SDimitry Andric     if (TII->mayBeNewStore(MI)) {
403*0b57cec5SDimitry Andric       // Look for uses of TFR instructions.
404*0b57cec5SDimitry Andric       for (unsigned OpdIdx = 0, OpdE = MI.getNumOperands(); OpdIdx != OpdE;
405*0b57cec5SDimitry Andric            ++OpdIdx) {
406*0b57cec5SDimitry Andric         MachineOperand &Op = MI.getOperand(OpdIdx);
407*0b57cec5SDimitry Andric 
408*0b57cec5SDimitry Andric         // Skip over anything except register uses.
409*0b57cec5SDimitry Andric         if (!Op.isReg() || !Op.isUse() || !Op.getReg())
410*0b57cec5SDimitry Andric           continue;
411*0b57cec5SDimitry Andric 
412*0b57cec5SDimitry Andric         // Look for the defining instruction.
413*0b57cec5SDimitry Andric         unsigned Reg = Op.getReg();
414*0b57cec5SDimitry Andric         MachineInstr *DefInst = LastDef[Reg];
415*0b57cec5SDimitry Andric         if (!DefInst)
416*0b57cec5SDimitry Andric           continue;
417*0b57cec5SDimitry Andric         if (!isCombinableInstType(*DefInst, TII, ShouldCombineAggressively))
418*0b57cec5SDimitry Andric           continue;
419*0b57cec5SDimitry Andric 
420*0b57cec5SDimitry Andric         // Only close newifiable stores should influence the decision.
421*0b57cec5SDimitry Andric         // Ignore the debug instructions in between.
422*0b57cec5SDimitry Andric         MachineBasicBlock::iterator It(DefInst);
423*0b57cec5SDimitry Andric         unsigned NumInstsToDef = 0;
424*0b57cec5SDimitry Andric         while (&*It != &MI) {
425*0b57cec5SDimitry Andric           if (!It->isDebugInstr())
426*0b57cec5SDimitry Andric             ++NumInstsToDef;
427*0b57cec5SDimitry Andric           ++It;
428*0b57cec5SDimitry Andric         }
429*0b57cec5SDimitry Andric 
430*0b57cec5SDimitry Andric         if (NumInstsToDef > MaxNumOfInstsBetweenNewValueStoreAndTFR)
431*0b57cec5SDimitry Andric           continue;
432*0b57cec5SDimitry Andric 
433*0b57cec5SDimitry Andric         PotentiallyNewifiableTFR.insert(DefInst);
434*0b57cec5SDimitry Andric       }
435*0b57cec5SDimitry Andric       // Skip to next instruction.
436*0b57cec5SDimitry Andric       continue;
437*0b57cec5SDimitry Andric     }
438*0b57cec5SDimitry Andric 
439*0b57cec5SDimitry Andric     // Put instructions that last defined integer or double registers into the
440*0b57cec5SDimitry Andric     // map.
441*0b57cec5SDimitry Andric     for (MachineOperand &Op : MI.operands()) {
442*0b57cec5SDimitry Andric       if (Op.isReg()) {
443*0b57cec5SDimitry Andric         if (!Op.isDef() || !Op.getReg())
444*0b57cec5SDimitry Andric           continue;
445*0b57cec5SDimitry Andric         unsigned Reg = Op.getReg();
446*0b57cec5SDimitry Andric         if (Hexagon::DoubleRegsRegClass.contains(Reg)) {
447*0b57cec5SDimitry Andric           for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs)
448*0b57cec5SDimitry Andric             LastDef[*SubRegs] = &MI;
449*0b57cec5SDimitry Andric         } else if (Hexagon::IntRegsRegClass.contains(Reg))
450*0b57cec5SDimitry Andric           LastDef[Reg] = &MI;
451*0b57cec5SDimitry Andric       } else if (Op.isRegMask()) {
452*0b57cec5SDimitry Andric         for (unsigned Reg : Hexagon::IntRegsRegClass)
453*0b57cec5SDimitry Andric           if (Op.clobbersPhysReg(Reg))
454*0b57cec5SDimitry Andric             LastDef[Reg] = &MI;
455*0b57cec5SDimitry Andric       }
456*0b57cec5SDimitry Andric     }
457*0b57cec5SDimitry Andric   }
458*0b57cec5SDimitry Andric }
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {
461*0b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
462*0b57cec5SDimitry Andric     return false;
463*0b57cec5SDimitry Andric 
464*0b57cec5SDimitry Andric   if (IsCombinesDisabled) return false;
465*0b57cec5SDimitry Andric 
466*0b57cec5SDimitry Andric   bool HasChanged = false;
467*0b57cec5SDimitry Andric 
468*0b57cec5SDimitry Andric   // Get target info.
469*0b57cec5SDimitry Andric   ST = &MF.getSubtarget<HexagonSubtarget>();
470*0b57cec5SDimitry Andric   TRI = ST->getRegisterInfo();
471*0b57cec5SDimitry Andric   TII = ST->getInstrInfo();
472*0b57cec5SDimitry Andric 
473*0b57cec5SDimitry Andric   const Function &F = MF.getFunction();
474*0b57cec5SDimitry Andric   bool OptForSize = F.hasFnAttribute(Attribute::OptimizeForSize);
475*0b57cec5SDimitry Andric 
476*0b57cec5SDimitry Andric   // Combine aggressively (for code size)
477*0b57cec5SDimitry Andric   ShouldCombineAggressively =
478*0b57cec5SDimitry Andric     MF.getTarget().getOptLevel() <= CodeGenOpt::Default;
479*0b57cec5SDimitry Andric 
480*0b57cec5SDimitry Andric   // Traverse basic blocks.
481*0b57cec5SDimitry Andric   for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE;
482*0b57cec5SDimitry Andric        ++BI) {
483*0b57cec5SDimitry Andric     PotentiallyNewifiableTFR.clear();
484*0b57cec5SDimitry Andric     findPotentialNewifiableTFRs(*BI);
485*0b57cec5SDimitry Andric 
486*0b57cec5SDimitry Andric     // Traverse instructions in basic block.
487*0b57cec5SDimitry Andric     for(MachineBasicBlock::iterator MI = BI->begin(), End = BI->end();
488*0b57cec5SDimitry Andric         MI != End;) {
489*0b57cec5SDimitry Andric       MachineInstr &I1 = *MI++;
490*0b57cec5SDimitry Andric 
491*0b57cec5SDimitry Andric       if (I1.isDebugInstr())
492*0b57cec5SDimitry Andric         continue;
493*0b57cec5SDimitry Andric 
494*0b57cec5SDimitry Andric       // Don't combine a TFR whose user could be newified (instructions that
495*0b57cec5SDimitry Andric       // define double registers can not be newified - Programmer's Ref Manual
496*0b57cec5SDimitry Andric       // 5.4.2 New-value stores).
497*0b57cec5SDimitry Andric       if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&I1))
498*0b57cec5SDimitry Andric         continue;
499*0b57cec5SDimitry Andric 
500*0b57cec5SDimitry Andric       // Ignore instructions that are not combinable.
501*0b57cec5SDimitry Andric       if (!isCombinableInstType(I1, TII, ShouldCombineAggressively))
502*0b57cec5SDimitry Andric         continue;
503*0b57cec5SDimitry Andric 
504*0b57cec5SDimitry Andric       // Find a second instruction that can be merged into a combine
505*0b57cec5SDimitry Andric       // instruction. In addition, also find all the debug instructions that
506*0b57cec5SDimitry Andric       // need to be moved along with it.
507*0b57cec5SDimitry Andric       bool DoInsertAtI1 = false;
508*0b57cec5SDimitry Andric       DbgMItoMove.clear();
509*0b57cec5SDimitry Andric       MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);
510*0b57cec5SDimitry Andric       if (I2) {
511*0b57cec5SDimitry Andric         HasChanged = true;
512*0b57cec5SDimitry Andric         combine(I1, *I2, MI, DoInsertAtI1, OptForSize);
513*0b57cec5SDimitry Andric       }
514*0b57cec5SDimitry Andric     }
515*0b57cec5SDimitry Andric   }
516*0b57cec5SDimitry Andric 
517*0b57cec5SDimitry Andric   return HasChanged;
518*0b57cec5SDimitry Andric }
519*0b57cec5SDimitry Andric 
520*0b57cec5SDimitry Andric /// findPairable - Returns an instruction that can be merged with \p I1 into a
521*0b57cec5SDimitry Andric /// COMBINE instruction or 0 if no such instruction can be found. Returns true
522*0b57cec5SDimitry Andric /// in \p DoInsertAtI1 if the combine must be inserted at instruction \p I1
523*0b57cec5SDimitry Andric /// false if the combine must be inserted at the returned instruction.
524*0b57cec5SDimitry Andric MachineInstr *HexagonCopyToCombine::findPairable(MachineInstr &I1,
525*0b57cec5SDimitry Andric                                                  bool &DoInsertAtI1,
526*0b57cec5SDimitry Andric                                                  bool AllowC64) {
527*0b57cec5SDimitry Andric   MachineBasicBlock::iterator I2 = std::next(MachineBasicBlock::iterator(I1));
528*0b57cec5SDimitry Andric   while (I2 != I1.getParent()->end() && I2->isDebugInstr())
529*0b57cec5SDimitry Andric     ++I2;
530*0b57cec5SDimitry Andric 
531*0b57cec5SDimitry Andric   unsigned I1DestReg = I1.getOperand(0).getReg();
532*0b57cec5SDimitry Andric 
533*0b57cec5SDimitry Andric   for (MachineBasicBlock::iterator End = I1.getParent()->end(); I2 != End;
534*0b57cec5SDimitry Andric        ++I2) {
535*0b57cec5SDimitry Andric     // Bail out early if we see a second definition of I1DestReg.
536*0b57cec5SDimitry Andric     if (I2->modifiesRegister(I1DestReg, TRI))
537*0b57cec5SDimitry Andric       break;
538*0b57cec5SDimitry Andric 
539*0b57cec5SDimitry Andric     // Ignore non-combinable instructions.
540*0b57cec5SDimitry Andric     if (!isCombinableInstType(*I2, TII, ShouldCombineAggressively))
541*0b57cec5SDimitry Andric       continue;
542*0b57cec5SDimitry Andric 
543*0b57cec5SDimitry Andric     // Don't combine a TFR whose user could be newified.
544*0b57cec5SDimitry Andric     if (ShouldCombineAggressively && PotentiallyNewifiableTFR.count(&*I2))
545*0b57cec5SDimitry Andric       continue;
546*0b57cec5SDimitry Andric 
547*0b57cec5SDimitry Andric     unsigned I2DestReg = I2->getOperand(0).getReg();
548*0b57cec5SDimitry Andric 
549*0b57cec5SDimitry Andric     // Check that registers are adjacent and that the first destination register
550*0b57cec5SDimitry Andric     // is even.
551*0b57cec5SDimitry Andric     bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;
552*0b57cec5SDimitry Andric     bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;
553*0b57cec5SDimitry Andric     unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;
554*0b57cec5SDimitry Andric     if ((!IsI1LowReg && !IsI2LowReg) || !isEvenReg(FirstRegIndex))
555*0b57cec5SDimitry Andric       continue;
556*0b57cec5SDimitry Andric 
557*0b57cec5SDimitry Andric     // Check that the two instructions are combinable.
558*0b57cec5SDimitry Andric     // The order matters because in a A2_tfrsi we might can encode a int8 as
559*0b57cec5SDimitry Andric     // the hi reg operand but only a uint6 as the low reg operand.
560*0b57cec5SDimitry Andric     if ((IsI2LowReg && !areCombinableOperations(TRI, I1, *I2, AllowC64)) ||
561*0b57cec5SDimitry Andric         (IsI1LowReg && !areCombinableOperations(TRI, *I2, I1, AllowC64)))
562*0b57cec5SDimitry Andric       break;
563*0b57cec5SDimitry Andric 
564*0b57cec5SDimitry Andric     if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))
565*0b57cec5SDimitry Andric       return &*I2;
566*0b57cec5SDimitry Andric 
567*0b57cec5SDimitry Andric     // Not safe. Stop searching.
568*0b57cec5SDimitry Andric     break;
569*0b57cec5SDimitry Andric   }
570*0b57cec5SDimitry Andric   return nullptr;
571*0b57cec5SDimitry Andric }
572*0b57cec5SDimitry Andric 
573*0b57cec5SDimitry Andric void HexagonCopyToCombine::combine(MachineInstr &I1, MachineInstr &I2,
574*0b57cec5SDimitry Andric                                    MachineBasicBlock::iterator &MI,
575*0b57cec5SDimitry Andric                                    bool DoInsertAtI1, bool OptForSize) {
576*0b57cec5SDimitry Andric   // We are going to delete I2. If MI points to I2 advance it to the next
577*0b57cec5SDimitry Andric   // instruction.
578*0b57cec5SDimitry Andric   if (MI == I2.getIterator())
579*0b57cec5SDimitry Andric     ++MI;
580*0b57cec5SDimitry Andric 
581*0b57cec5SDimitry Andric   // Figure out whether I1 or I2 goes into the lowreg part.
582*0b57cec5SDimitry Andric   unsigned I1DestReg = I1.getOperand(0).getReg();
583*0b57cec5SDimitry Andric   unsigned I2DestReg = I2.getOperand(0).getReg();
584*0b57cec5SDimitry Andric   bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;
585*0b57cec5SDimitry Andric   unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;
586*0b57cec5SDimitry Andric   unsigned SubLo;
587*0b57cec5SDimitry Andric 
588*0b57cec5SDimitry Andric   const TargetRegisterClass *SuperRC = nullptr;
589*0b57cec5SDimitry Andric   if (Hexagon::IntRegsRegClass.contains(LoRegDef)) {
590*0b57cec5SDimitry Andric     SuperRC = &Hexagon::DoubleRegsRegClass;
591*0b57cec5SDimitry Andric     SubLo = Hexagon::isub_lo;
592*0b57cec5SDimitry Andric   } else if (Hexagon::HvxVRRegClass.contains(LoRegDef)) {
593*0b57cec5SDimitry Andric     assert(ST->useHVXOps());
594*0b57cec5SDimitry Andric     SuperRC = &Hexagon::HvxWRRegClass;
595*0b57cec5SDimitry Andric     SubLo = Hexagon::vsub_lo;
596*0b57cec5SDimitry Andric   } else
597*0b57cec5SDimitry Andric     llvm_unreachable("Unexpected register class");
598*0b57cec5SDimitry Andric 
599*0b57cec5SDimitry Andric   // Get the double word register.
600*0b57cec5SDimitry Andric   unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);
601*0b57cec5SDimitry Andric   assert(DoubleRegDest != 0 && "Expect a valid register");
602*0b57cec5SDimitry Andric 
603*0b57cec5SDimitry Andric   // Setup source operands.
604*0b57cec5SDimitry Andric   MachineOperand &LoOperand = IsI1Loreg ? I1.getOperand(1) : I2.getOperand(1);
605*0b57cec5SDimitry Andric   MachineOperand &HiOperand = IsI1Loreg ? I2.getOperand(1) : I1.getOperand(1);
606*0b57cec5SDimitry Andric 
607*0b57cec5SDimitry Andric   // Figure out which source is a register and which a constant.
608*0b57cec5SDimitry Andric   bool IsHiReg = HiOperand.isReg();
609*0b57cec5SDimitry Andric   bool IsLoReg = LoOperand.isReg();
610*0b57cec5SDimitry Andric 
611*0b57cec5SDimitry Andric   // There is a combine of two constant extended values into CONST64.
612*0b57cec5SDimitry Andric   bool IsC64 = OptForSize && LoOperand.isImm() && HiOperand.isImm() &&
613*0b57cec5SDimitry Andric                isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);
614*0b57cec5SDimitry Andric 
615*0b57cec5SDimitry Andric   MachineBasicBlock::iterator InsertPt(DoInsertAtI1 ? I1 : I2);
616*0b57cec5SDimitry Andric   // Emit combine.
617*0b57cec5SDimitry Andric   if (IsHiReg && IsLoReg)
618*0b57cec5SDimitry Andric     emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
619*0b57cec5SDimitry Andric   else if (IsHiReg)
620*0b57cec5SDimitry Andric     emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);
621*0b57cec5SDimitry Andric   else if (IsLoReg)
622*0b57cec5SDimitry Andric     emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);
623*0b57cec5SDimitry Andric   else if (IsC64 && !IsConst64Disabled)
624*0b57cec5SDimitry Andric     emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);
625*0b57cec5SDimitry Andric   else
626*0b57cec5SDimitry Andric     emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);
627*0b57cec5SDimitry Andric 
628*0b57cec5SDimitry Andric   // Move debug instructions along with I1 if it's being
629*0b57cec5SDimitry Andric   // moved towards I2.
630*0b57cec5SDimitry Andric   if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {
631*0b57cec5SDimitry Andric     // Insert debug instructions at the new location before I2.
632*0b57cec5SDimitry Andric     MachineBasicBlock *BB = InsertPt->getParent();
633*0b57cec5SDimitry Andric     for (auto NewMI : DbgMItoMove) {
634*0b57cec5SDimitry Andric       // If iterator MI is pointing to DEBUG_VAL, make sure
635*0b57cec5SDimitry Andric       // MI now points to next relevant instruction.
636*0b57cec5SDimitry Andric       if (NewMI == MI)
637*0b57cec5SDimitry Andric         ++MI;
638*0b57cec5SDimitry Andric       BB->splice(InsertPt, BB, NewMI);
639*0b57cec5SDimitry Andric     }
640*0b57cec5SDimitry Andric   }
641*0b57cec5SDimitry Andric 
642*0b57cec5SDimitry Andric   I1.eraseFromParent();
643*0b57cec5SDimitry Andric   I2.eraseFromParent();
644*0b57cec5SDimitry Andric }
645*0b57cec5SDimitry Andric 
646*0b57cec5SDimitry Andric void HexagonCopyToCombine::emitConst64(MachineBasicBlock::iterator &InsertPt,
647*0b57cec5SDimitry Andric                                        unsigned DoubleDestReg,
648*0b57cec5SDimitry Andric                                        MachineOperand &HiOperand,
649*0b57cec5SDimitry Andric                                        MachineOperand &LoOperand) {
650*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Found a CONST64\n");
651*0b57cec5SDimitry Andric 
652*0b57cec5SDimitry Andric   DebugLoc DL = InsertPt->getDebugLoc();
653*0b57cec5SDimitry Andric   MachineBasicBlock *BB = InsertPt->getParent();
654*0b57cec5SDimitry Andric   assert(LoOperand.isImm() && HiOperand.isImm() &&
655*0b57cec5SDimitry Andric          "Both operands must be immediate");
656*0b57cec5SDimitry Andric 
657*0b57cec5SDimitry Andric   int64_t V = HiOperand.getImm();
658*0b57cec5SDimitry Andric   V = (V << 32) | (0x0ffffffffLL & LoOperand.getImm());
659*0b57cec5SDimitry Andric   BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg)
660*0b57cec5SDimitry Andric     .addImm(V);
661*0b57cec5SDimitry Andric }
662*0b57cec5SDimitry Andric 
663*0b57cec5SDimitry Andric void HexagonCopyToCombine::emitCombineII(MachineBasicBlock::iterator &InsertPt,
664*0b57cec5SDimitry Andric                                          unsigned DoubleDestReg,
665*0b57cec5SDimitry Andric                                          MachineOperand &HiOperand,
666*0b57cec5SDimitry Andric                                          MachineOperand &LoOperand) {
667*0b57cec5SDimitry Andric   DebugLoc DL = InsertPt->getDebugLoc();
668*0b57cec5SDimitry Andric   MachineBasicBlock *BB = InsertPt->getParent();
669*0b57cec5SDimitry Andric 
670*0b57cec5SDimitry Andric   // Handle globals.
671*0b57cec5SDimitry Andric   if (HiOperand.isGlobal()) {
672*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
673*0b57cec5SDimitry Andric       .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(),
674*0b57cec5SDimitry Andric                         HiOperand.getTargetFlags())
675*0b57cec5SDimitry Andric       .addImm(LoOperand.getImm());
676*0b57cec5SDimitry Andric     return;
677*0b57cec5SDimitry Andric   }
678*0b57cec5SDimitry Andric   if (LoOperand.isGlobal()) {
679*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
680*0b57cec5SDimitry Andric       .addImm(HiOperand.getImm())
681*0b57cec5SDimitry Andric       .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(),
682*0b57cec5SDimitry Andric                         LoOperand.getTargetFlags());
683*0b57cec5SDimitry Andric     return;
684*0b57cec5SDimitry Andric   }
685*0b57cec5SDimitry Andric 
686*0b57cec5SDimitry Andric   // Handle block addresses.
687*0b57cec5SDimitry Andric   if (HiOperand.isBlockAddress()) {
688*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
689*0b57cec5SDimitry Andric       .addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(),
690*0b57cec5SDimitry Andric                        HiOperand.getTargetFlags())
691*0b57cec5SDimitry Andric       .addImm(LoOperand.getImm());
692*0b57cec5SDimitry Andric     return;
693*0b57cec5SDimitry Andric   }
694*0b57cec5SDimitry Andric   if (LoOperand.isBlockAddress()) {
695*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
696*0b57cec5SDimitry Andric       .addImm(HiOperand.getImm())
697*0b57cec5SDimitry Andric       .addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(),
698*0b57cec5SDimitry Andric                        LoOperand.getTargetFlags());
699*0b57cec5SDimitry Andric     return;
700*0b57cec5SDimitry Andric   }
701*0b57cec5SDimitry Andric 
702*0b57cec5SDimitry Andric   // Handle jump tables.
703*0b57cec5SDimitry Andric   if (HiOperand.isJTI()) {
704*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
705*0b57cec5SDimitry Andric       .addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags())
706*0b57cec5SDimitry Andric       .addImm(LoOperand.getImm());
707*0b57cec5SDimitry Andric     return;
708*0b57cec5SDimitry Andric   }
709*0b57cec5SDimitry Andric   if (LoOperand.isJTI()) {
710*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
711*0b57cec5SDimitry Andric       .addImm(HiOperand.getImm())
712*0b57cec5SDimitry Andric       .addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags());
713*0b57cec5SDimitry Andric     return;
714*0b57cec5SDimitry Andric   }
715*0b57cec5SDimitry Andric 
716*0b57cec5SDimitry Andric   // Handle constant pools.
717*0b57cec5SDimitry Andric   if (HiOperand.isCPI()) {
718*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
719*0b57cec5SDimitry Andric       .addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(),
720*0b57cec5SDimitry Andric                             HiOperand.getTargetFlags())
721*0b57cec5SDimitry Andric       .addImm(LoOperand.getImm());
722*0b57cec5SDimitry Andric     return;
723*0b57cec5SDimitry Andric   }
724*0b57cec5SDimitry Andric   if (LoOperand.isCPI()) {
725*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
726*0b57cec5SDimitry Andric       .addImm(HiOperand.getImm())
727*0b57cec5SDimitry Andric       .addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(),
728*0b57cec5SDimitry Andric                             LoOperand.getTargetFlags());
729*0b57cec5SDimitry Andric     return;
730*0b57cec5SDimitry Andric   }
731*0b57cec5SDimitry Andric 
732*0b57cec5SDimitry Andric   // First preference should be given to Hexagon::A2_combineii instruction
733*0b57cec5SDimitry Andric   // as it can include U6 (in Hexagon::A4_combineii) as well.
734*0b57cec5SDimitry Andric   // In this instruction, HiOperand is const extended, if required.
735*0b57cec5SDimitry Andric   if (isInt<8>(LoOperand.getImm())) {
736*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
737*0b57cec5SDimitry Andric       .addImm(HiOperand.getImm())
738*0b57cec5SDimitry Andric       .addImm(LoOperand.getImm());
739*0b57cec5SDimitry Andric       return;
740*0b57cec5SDimitry Andric   }
741*0b57cec5SDimitry Andric 
742*0b57cec5SDimitry Andric   // In this instruction, LoOperand is const extended, if required.
743*0b57cec5SDimitry Andric   if (isInt<8>(HiOperand.getImm())) {
744*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)
745*0b57cec5SDimitry Andric       .addImm(HiOperand.getImm())
746*0b57cec5SDimitry Andric       .addImm(LoOperand.getImm());
747*0b57cec5SDimitry Andric     return;
748*0b57cec5SDimitry Andric   }
749*0b57cec5SDimitry Andric 
750*0b57cec5SDimitry Andric   // Insert new combine instruction.
751*0b57cec5SDimitry Andric   //  DoubleRegDest = combine #HiImm, #LoImm
752*0b57cec5SDimitry Andric   BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)
753*0b57cec5SDimitry Andric     .addImm(HiOperand.getImm())
754*0b57cec5SDimitry Andric     .addImm(LoOperand.getImm());
755*0b57cec5SDimitry Andric }
756*0b57cec5SDimitry Andric 
757*0b57cec5SDimitry Andric void HexagonCopyToCombine::emitCombineIR(MachineBasicBlock::iterator &InsertPt,
758*0b57cec5SDimitry Andric                                          unsigned DoubleDestReg,
759*0b57cec5SDimitry Andric                                          MachineOperand &HiOperand,
760*0b57cec5SDimitry Andric                                          MachineOperand &LoOperand) {
761*0b57cec5SDimitry Andric   unsigned LoReg = LoOperand.getReg();
762*0b57cec5SDimitry Andric   unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill());
763*0b57cec5SDimitry Andric 
764*0b57cec5SDimitry Andric   DebugLoc DL = InsertPt->getDebugLoc();
765*0b57cec5SDimitry Andric   MachineBasicBlock *BB = InsertPt->getParent();
766*0b57cec5SDimitry Andric 
767*0b57cec5SDimitry Andric   // Handle globals.
768*0b57cec5SDimitry Andric   if (HiOperand.isGlobal()) {
769*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
770*0b57cec5SDimitry Andric       .addGlobalAddress(HiOperand.getGlobal(), HiOperand.getOffset(),
771*0b57cec5SDimitry Andric                         HiOperand.getTargetFlags())
772*0b57cec5SDimitry Andric       .addReg(LoReg, LoRegKillFlag);
773*0b57cec5SDimitry Andric     return;
774*0b57cec5SDimitry Andric   }
775*0b57cec5SDimitry Andric   // Handle block addresses.
776*0b57cec5SDimitry Andric   if (HiOperand.isBlockAddress()) {
777*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
778*0b57cec5SDimitry Andric       .addBlockAddress(HiOperand.getBlockAddress(), HiOperand.getOffset(),
779*0b57cec5SDimitry Andric                        HiOperand.getTargetFlags())
780*0b57cec5SDimitry Andric       .addReg(LoReg, LoRegKillFlag);
781*0b57cec5SDimitry Andric     return;
782*0b57cec5SDimitry Andric   }
783*0b57cec5SDimitry Andric   // Handle jump tables.
784*0b57cec5SDimitry Andric   if (HiOperand.isJTI()) {
785*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
786*0b57cec5SDimitry Andric       .addJumpTableIndex(HiOperand.getIndex(), HiOperand.getTargetFlags())
787*0b57cec5SDimitry Andric       .addReg(LoReg, LoRegKillFlag);
788*0b57cec5SDimitry Andric     return;
789*0b57cec5SDimitry Andric   }
790*0b57cec5SDimitry Andric   // Handle constant pools.
791*0b57cec5SDimitry Andric   if (HiOperand.isCPI()) {
792*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
793*0b57cec5SDimitry Andric       .addConstantPoolIndex(HiOperand.getIndex(), HiOperand.getOffset(),
794*0b57cec5SDimitry Andric                             HiOperand.getTargetFlags())
795*0b57cec5SDimitry Andric       .addReg(LoReg, LoRegKillFlag);
796*0b57cec5SDimitry Andric     return;
797*0b57cec5SDimitry Andric   }
798*0b57cec5SDimitry Andric   // Insert new combine instruction.
799*0b57cec5SDimitry Andric   //  DoubleRegDest = combine #HiImm, LoReg
800*0b57cec5SDimitry Andric   BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)
801*0b57cec5SDimitry Andric     .addImm(HiOperand.getImm())
802*0b57cec5SDimitry Andric     .addReg(LoReg, LoRegKillFlag);
803*0b57cec5SDimitry Andric }
804*0b57cec5SDimitry Andric 
805*0b57cec5SDimitry Andric void HexagonCopyToCombine::emitCombineRI(MachineBasicBlock::iterator &InsertPt,
806*0b57cec5SDimitry Andric                                          unsigned DoubleDestReg,
807*0b57cec5SDimitry Andric                                          MachineOperand &HiOperand,
808*0b57cec5SDimitry Andric                                          MachineOperand &LoOperand) {
809*0b57cec5SDimitry Andric   unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill());
810*0b57cec5SDimitry Andric   unsigned HiReg = HiOperand.getReg();
811*0b57cec5SDimitry Andric 
812*0b57cec5SDimitry Andric   DebugLoc DL = InsertPt->getDebugLoc();
813*0b57cec5SDimitry Andric   MachineBasicBlock *BB = InsertPt->getParent();
814*0b57cec5SDimitry Andric 
815*0b57cec5SDimitry Andric   // Handle global.
816*0b57cec5SDimitry Andric   if (LoOperand.isGlobal()) {
817*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
818*0b57cec5SDimitry Andric       .addReg(HiReg, HiRegKillFlag)
819*0b57cec5SDimitry Andric       .addGlobalAddress(LoOperand.getGlobal(), LoOperand.getOffset(),
820*0b57cec5SDimitry Andric                         LoOperand.getTargetFlags());
821*0b57cec5SDimitry Andric     return;
822*0b57cec5SDimitry Andric   }
823*0b57cec5SDimitry Andric   // Handle block addresses.
824*0b57cec5SDimitry Andric   if (LoOperand.isBlockAddress()) {
825*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
826*0b57cec5SDimitry Andric       .addReg(HiReg, HiRegKillFlag)
827*0b57cec5SDimitry Andric       .addBlockAddress(LoOperand.getBlockAddress(), LoOperand.getOffset(),
828*0b57cec5SDimitry Andric                        LoOperand.getTargetFlags());
829*0b57cec5SDimitry Andric     return;
830*0b57cec5SDimitry Andric   }
831*0b57cec5SDimitry Andric   // Handle jump tables.
832*0b57cec5SDimitry Andric   if (LoOperand.isJTI()) {
833*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
834*0b57cec5SDimitry Andric       .addReg(HiOperand.getReg(), HiRegKillFlag)
835*0b57cec5SDimitry Andric       .addJumpTableIndex(LoOperand.getIndex(), LoOperand.getTargetFlags());
836*0b57cec5SDimitry Andric     return;
837*0b57cec5SDimitry Andric   }
838*0b57cec5SDimitry Andric   // Handle constant pools.
839*0b57cec5SDimitry Andric   if (LoOperand.isCPI()) {
840*0b57cec5SDimitry Andric     BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
841*0b57cec5SDimitry Andric       .addReg(HiOperand.getReg(), HiRegKillFlag)
842*0b57cec5SDimitry Andric       .addConstantPoolIndex(LoOperand.getIndex(), LoOperand.getOffset(),
843*0b57cec5SDimitry Andric                             LoOperand.getTargetFlags());
844*0b57cec5SDimitry Andric     return;
845*0b57cec5SDimitry Andric   }
846*0b57cec5SDimitry Andric 
847*0b57cec5SDimitry Andric   // Insert new combine instruction.
848*0b57cec5SDimitry Andric   //  DoubleRegDest = combine HiReg, #LoImm
849*0b57cec5SDimitry Andric   BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)
850*0b57cec5SDimitry Andric     .addReg(HiReg, HiRegKillFlag)
851*0b57cec5SDimitry Andric     .addImm(LoOperand.getImm());
852*0b57cec5SDimitry Andric }
853*0b57cec5SDimitry Andric 
854*0b57cec5SDimitry Andric void HexagonCopyToCombine::emitCombineRR(MachineBasicBlock::iterator &InsertPt,
855*0b57cec5SDimitry Andric                                          unsigned DoubleDestReg,
856*0b57cec5SDimitry Andric                                          MachineOperand &HiOperand,
857*0b57cec5SDimitry Andric                                          MachineOperand &LoOperand) {
858*0b57cec5SDimitry Andric   unsigned LoRegKillFlag = getKillRegState(LoOperand.isKill());
859*0b57cec5SDimitry Andric   unsigned HiRegKillFlag = getKillRegState(HiOperand.isKill());
860*0b57cec5SDimitry Andric   unsigned LoReg = LoOperand.getReg();
861*0b57cec5SDimitry Andric   unsigned HiReg = HiOperand.getReg();
862*0b57cec5SDimitry Andric 
863*0b57cec5SDimitry Andric   DebugLoc DL = InsertPt->getDebugLoc();
864*0b57cec5SDimitry Andric   MachineBasicBlock *BB = InsertPt->getParent();
865*0b57cec5SDimitry Andric 
866*0b57cec5SDimitry Andric   // Insert new combine instruction.
867*0b57cec5SDimitry Andric   //  DoubleRegDest = combine HiReg, LoReg
868*0b57cec5SDimitry Andric   unsigned NewOpc;
869*0b57cec5SDimitry Andric   if (Hexagon::DoubleRegsRegClass.contains(DoubleDestReg)) {
870*0b57cec5SDimitry Andric     NewOpc = Hexagon::A2_combinew;
871*0b57cec5SDimitry Andric   } else if (Hexagon::HvxWRRegClass.contains(DoubleDestReg)) {
872*0b57cec5SDimitry Andric     assert(ST->useHVXOps());
873*0b57cec5SDimitry Andric     NewOpc = Hexagon::V6_vcombine;
874*0b57cec5SDimitry Andric   } else
875*0b57cec5SDimitry Andric     llvm_unreachable("Unexpected register");
876*0b57cec5SDimitry Andric 
877*0b57cec5SDimitry Andric   BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)
878*0b57cec5SDimitry Andric     .addReg(HiReg, HiRegKillFlag)
879*0b57cec5SDimitry Andric     .addReg(LoReg, LoRegKillFlag);
880*0b57cec5SDimitry Andric }
881*0b57cec5SDimitry Andric 
882*0b57cec5SDimitry Andric FunctionPass *llvm::createHexagonCopyToCombine() {
883*0b57cec5SDimitry Andric   return new HexagonCopyToCombine();
884*0b57cec5SDimitry Andric }
885