1327952Sdim//===- HexagonGenPredicate.cpp --------------------------------------------===//
2286425Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6286425Sdim//
7286425Sdim//===----------------------------------------------------------------------===//
8286425Sdim
9314564Sdim#include "HexagonInstrInfo.h"
10314564Sdim#include "HexagonSubtarget.h"
11286425Sdim#include "llvm/ADT/SetVector.h"
12314564Sdim#include "llvm/ADT/StringRef.h"
13314564Sdim#include "llvm/CodeGen/MachineBasicBlock.h"
14286425Sdim#include "llvm/CodeGen/MachineDominators.h"
15314564Sdim#include "llvm/CodeGen/MachineFunction.h"
16286425Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
17314564Sdim#include "llvm/CodeGen/MachineInstr.h"
18286425Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
19314564Sdim#include "llvm/CodeGen/MachineOperand.h"
20286425Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
21327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h"
22314564Sdim#include "llvm/IR/DebugLoc.h"
23360784Sdim#include "llvm/InitializePasses.h"
24314564Sdim#include "llvm/Pass.h"
25314564Sdim#include "llvm/Support/Compiler.h"
26286425Sdim#include "llvm/Support/Debug.h"
27314564Sdim#include "llvm/Support/ErrorHandling.h"
28286425Sdim#include "llvm/Support/raw_ostream.h"
29314564Sdim#include <cassert>
30314564Sdim#include <iterator>
31314564Sdim#include <map>
32286425Sdim#include <queue>
33286425Sdim#include <set>
34314564Sdim#include <utility>
35286425Sdim
36321369Sdim#define DEBUG_TYPE "gen-pred"
37321369Sdim
38286425Sdimusing namespace llvm;
39286425Sdim
40286425Sdimnamespace llvm {
41314564Sdim
42286425Sdim  void initializeHexagonGenPredicatePass(PassRegistry& Registry);
43286425Sdim  FunctionPass *createHexagonGenPredicate();
44286425Sdim
45314564Sdim} // end namespace llvm
46314564Sdim
47286425Sdimnamespace {
48314564Sdim
49353358Sdim  // FIXME: Use TargetInstrInfo::RegSubRegPair
50353358Sdim  struct RegisterSubReg {
51286425Sdim    unsigned R, S;
52314564Sdim
53353358Sdim    RegisterSubReg(unsigned r = 0, unsigned s = 0) : R(r), S(s) {}
54353358Sdim    RegisterSubReg(const MachineOperand &MO) : R(MO.getReg()), S(MO.getSubReg()) {}
55353358Sdim    RegisterSubReg(const Register &Reg) : R(Reg), S(0) {}
56314564Sdim
57353358Sdim    bool operator== (const RegisterSubReg &Reg) const {
58286425Sdim      return R == Reg.R && S == Reg.S;
59286425Sdim    }
60314564Sdim
61353358Sdim    bool operator< (const RegisterSubReg &Reg) const {
62286425Sdim      return R < Reg.R || (R == Reg.R && S < Reg.S);
63286425Sdim    }
64286425Sdim  };
65314564Sdim
66286425Sdim  struct PrintRegister {
67314564Sdim    friend raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR);
68314564Sdim
69353358Sdim    PrintRegister(RegisterSubReg R, const TargetRegisterInfo &I) : Reg(R), TRI(I) {}
70314564Sdim
71286425Sdim  private:
72353358Sdim    RegisterSubReg Reg;
73286425Sdim    const TargetRegisterInfo &TRI;
74286425Sdim  };
75314564Sdim
76286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR)
77286425Sdim    LLVM_ATTRIBUTE_UNUSED;
78286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR) {
79327952Sdim    return OS << printReg(PR.Reg.R, &PR.TRI, PR.Reg.S);
80286425Sdim  }
81286425Sdim
82286425Sdim  class HexagonGenPredicate : public MachineFunctionPass {
83286425Sdim  public:
84286425Sdim    static char ID;
85314564Sdim
86327952Sdim    HexagonGenPredicate() : MachineFunctionPass(ID) {
87286425Sdim      initializeHexagonGenPredicatePass(*PassRegistry::getPassRegistry());
88286425Sdim    }
89314564Sdim
90314564Sdim    StringRef getPassName() const override {
91286425Sdim      return "Hexagon generate predicate operations";
92286425Sdim    }
93314564Sdim
94314564Sdim    void getAnalysisUsage(AnalysisUsage &AU) const override {
95286425Sdim      AU.addRequired<MachineDominatorTree>();
96286425Sdim      AU.addPreserved<MachineDominatorTree>();
97286425Sdim      MachineFunctionPass::getAnalysisUsage(AU);
98286425Sdim    }
99286425Sdim
100314564Sdim    bool runOnMachineFunction(MachineFunction &MF) override;
101314564Sdim
102286425Sdim  private:
103327952Sdim    using VectOfInst = SetVector<MachineInstr *>;
104353358Sdim    using SetOfReg = std::set<RegisterSubReg>;
105353358Sdim    using RegToRegMap = std::map<RegisterSubReg, RegisterSubReg>;
106286425Sdim
107327952Sdim    const HexagonInstrInfo *TII = nullptr;
108327952Sdim    const HexagonRegisterInfo *TRI = nullptr;
109327952Sdim    MachineRegisterInfo *MRI = nullptr;
110286425Sdim    SetOfReg PredGPRs;
111286425Sdim    VectOfInst PUsers;
112286425Sdim    RegToRegMap G2P;
113286425Sdim
114286425Sdim    bool isPredReg(unsigned R);
115286425Sdim    void collectPredicateGPR(MachineFunction &MF);
116353358Sdim    void processPredicateGPR(const RegisterSubReg &Reg);
117286425Sdim    unsigned getPredForm(unsigned Opc);
118286425Sdim    bool isConvertibleToPredForm(const MachineInstr *MI);
119286425Sdim    bool isScalarCmp(unsigned Opc);
120353358Sdim    bool isScalarPred(RegisterSubReg PredReg);
121353358Sdim    RegisterSubReg getPredRegFor(const RegisterSubReg &Reg);
122286425Sdim    bool convertToPredForm(MachineInstr *MI);
123286425Sdim    bool eliminatePredCopies(MachineFunction &MF);
124286425Sdim  };
125286425Sdim
126314564Sdim} // end anonymous namespace
127314564Sdim
128327952Sdimchar HexagonGenPredicate::ID = 0;
129327952Sdim
130286425SdimINITIALIZE_PASS_BEGIN(HexagonGenPredicate, "hexagon-gen-pred",
131286425Sdim  "Hexagon generate predicate operations", false, false)
132286425SdimINITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
133286425SdimINITIALIZE_PASS_END(HexagonGenPredicate, "hexagon-gen-pred",
134286425Sdim  "Hexagon generate predicate operations", false, false)
135286425Sdim
136286425Sdimbool HexagonGenPredicate::isPredReg(unsigned R) {
137360784Sdim  if (!Register::isVirtualRegister(R))
138286425Sdim    return false;
139286425Sdim  const TargetRegisterClass *RC = MRI->getRegClass(R);
140286425Sdim  return RC == &Hexagon::PredRegsRegClass;
141286425Sdim}
142286425Sdim
143286425Sdimunsigned HexagonGenPredicate::getPredForm(unsigned Opc) {
144286425Sdim  using namespace Hexagon;
145286425Sdim
146286425Sdim  switch (Opc) {
147286425Sdim    case A2_and:
148286425Sdim    case A2_andp:
149286425Sdim      return C2_and;
150286425Sdim    case A4_andn:
151286425Sdim    case A4_andnp:
152286425Sdim      return C2_andn;
153286425Sdim    case M4_and_and:
154286425Sdim      return C4_and_and;
155286425Sdim    case M4_and_andn:
156286425Sdim      return C4_and_andn;
157286425Sdim    case M4_and_or:
158286425Sdim      return C4_and_or;
159286425Sdim
160286425Sdim    case A2_or:
161286425Sdim    case A2_orp:
162286425Sdim      return C2_or;
163286425Sdim    case A4_orn:
164286425Sdim    case A4_ornp:
165286425Sdim      return C2_orn;
166286425Sdim    case M4_or_and:
167286425Sdim      return C4_or_and;
168286425Sdim    case M4_or_andn:
169286425Sdim      return C4_or_andn;
170286425Sdim    case M4_or_or:
171286425Sdim      return C4_or_or;
172286425Sdim
173286425Sdim    case A2_xor:
174286425Sdim    case A2_xorp:
175286425Sdim      return C2_xor;
176286425Sdim
177286425Sdim    case C2_tfrrp:
178286425Sdim      return COPY;
179286425Sdim  }
180286425Sdim  // The opcode corresponding to 0 is TargetOpcode::PHI. We can use 0 here
181286425Sdim  // to denote "none", but we need to make sure that none of the valid opcodes
182286425Sdim  // that we return will ever be 0.
183309124Sdim  static_assert(PHI == 0, "Use different value for <none>");
184286425Sdim  return 0;
185286425Sdim}
186286425Sdim
187286425Sdimbool HexagonGenPredicate::isConvertibleToPredForm(const MachineInstr *MI) {
188286425Sdim  unsigned Opc = MI->getOpcode();
189286425Sdim  if (getPredForm(Opc) != 0)
190286425Sdim    return true;
191286425Sdim
192286425Sdim  // Comparisons against 0 are also convertible. This does not apply to
193286425Sdim  // A4_rcmpeqi or A4_rcmpneqi, since they produce values 0 or 1, which
194286425Sdim  // may not match the value that the predicate register would have if
195286425Sdim  // it was converted to a predicate form.
196286425Sdim  switch (Opc) {
197286425Sdim    case Hexagon::C2_cmpeqi:
198286425Sdim    case Hexagon::C4_cmpneqi:
199286425Sdim      if (MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0)
200286425Sdim        return true;
201286425Sdim      break;
202286425Sdim  }
203286425Sdim  return false;
204286425Sdim}
205286425Sdim
206286425Sdimvoid HexagonGenPredicate::collectPredicateGPR(MachineFunction &MF) {
207286425Sdim  for (MachineFunction::iterator A = MF.begin(), Z = MF.end(); A != Z; ++A) {
208286425Sdim    MachineBasicBlock &B = *A;
209286425Sdim    for (MachineBasicBlock::iterator I = B.begin(), E = B.end(); I != E; ++I) {
210286425Sdim      MachineInstr *MI = &*I;
211286425Sdim      unsigned Opc = MI->getOpcode();
212286425Sdim      switch (Opc) {
213286425Sdim        case Hexagon::C2_tfrpr:
214286425Sdim        case TargetOpcode::COPY:
215286425Sdim          if (isPredReg(MI->getOperand(1).getReg())) {
216353358Sdim            RegisterSubReg RD = MI->getOperand(0);
217360784Sdim            if (Register::isVirtualRegister(RD.R))
218286425Sdim              PredGPRs.insert(RD);
219286425Sdim          }
220286425Sdim          break;
221286425Sdim      }
222286425Sdim    }
223286425Sdim  }
224286425Sdim}
225286425Sdim
226353358Sdimvoid HexagonGenPredicate::processPredicateGPR(const RegisterSubReg &Reg) {
227341825Sdim  LLVM_DEBUG(dbgs() << __func__ << ": " << printReg(Reg.R, TRI, Reg.S) << "\n");
228327952Sdim  using use_iterator = MachineRegisterInfo::use_iterator;
229327952Sdim
230286425Sdim  use_iterator I = MRI->use_begin(Reg.R), E = MRI->use_end();
231286425Sdim  if (I == E) {
232341825Sdim    LLVM_DEBUG(dbgs() << "Dead reg: " << printReg(Reg.R, TRI, Reg.S) << '\n');
233286425Sdim    MachineInstr *DefI = MRI->getVRegDef(Reg.R);
234286425Sdim    DefI->eraseFromParent();
235286425Sdim    return;
236286425Sdim  }
237286425Sdim
238286425Sdim  for (; I != E; ++I) {
239286425Sdim    MachineInstr *UseI = I->getParent();
240286425Sdim    if (isConvertibleToPredForm(UseI))
241286425Sdim      PUsers.insert(UseI);
242286425Sdim  }
243286425Sdim}
244286425Sdim
245353358SdimRegisterSubReg HexagonGenPredicate::getPredRegFor(const RegisterSubReg &Reg) {
246286425Sdim  // Create a predicate register for a given Reg. The newly created register
247286425Sdim  // will have its value copied from Reg, so that it can be later used as
248286425Sdim  // an operand in other instructions.
249360784Sdim  assert(Register::isVirtualRegister(Reg.R));
250286425Sdim  RegToRegMap::iterator F = G2P.find(Reg);
251286425Sdim  if (F != G2P.end())
252286425Sdim    return F->second;
253286425Sdim
254341825Sdim  LLVM_DEBUG(dbgs() << __func__ << ": " << PrintRegister(Reg, *TRI));
255286425Sdim  MachineInstr *DefI = MRI->getVRegDef(Reg.R);
256286425Sdim  assert(DefI);
257286425Sdim  unsigned Opc = DefI->getOpcode();
258286425Sdim  if (Opc == Hexagon::C2_tfrpr || Opc == TargetOpcode::COPY) {
259286425Sdim    assert(DefI->getOperand(0).isDef() && DefI->getOperand(1).isUse());
260353358Sdim    RegisterSubReg PR = DefI->getOperand(1);
261286425Sdim    G2P.insert(std::make_pair(Reg, PR));
262341825Sdim    LLVM_DEBUG(dbgs() << " -> " << PrintRegister(PR, *TRI) << '\n');
263286425Sdim    return PR;
264286425Sdim  }
265286425Sdim
266286425Sdim  MachineBasicBlock &B = *DefI->getParent();
267286425Sdim  DebugLoc DL = DefI->getDebugLoc();
268286425Sdim  const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
269360784Sdim  Register NewPR = MRI->createVirtualRegister(PredRC);
270286425Sdim
271286425Sdim  // For convertible instructions, do not modify them, so that they can
272296417Sdim  // be converted later.  Generate a copy from Reg to NewPR.
273286425Sdim  if (isConvertibleToPredForm(DefI)) {
274286425Sdim    MachineBasicBlock::iterator DefIt = DefI;
275286425Sdim    BuildMI(B, std::next(DefIt), DL, TII->get(TargetOpcode::COPY), NewPR)
276286425Sdim      .addReg(Reg.R, 0, Reg.S);
277353358Sdim    G2P.insert(std::make_pair(Reg, RegisterSubReg(NewPR)));
278353358Sdim    LLVM_DEBUG(dbgs() << " -> !" << PrintRegister(RegisterSubReg(NewPR), *TRI)
279341825Sdim                      << '\n');
280353358Sdim    return RegisterSubReg(NewPR);
281286425Sdim  }
282286425Sdim
283286425Sdim  llvm_unreachable("Invalid argument");
284286425Sdim}
285286425Sdim
286286425Sdimbool HexagonGenPredicate::isScalarCmp(unsigned Opc) {
287286425Sdim  switch (Opc) {
288286425Sdim    case Hexagon::C2_cmpeq:
289286425Sdim    case Hexagon::C2_cmpgt:
290286425Sdim    case Hexagon::C2_cmpgtu:
291286425Sdim    case Hexagon::C2_cmpeqp:
292286425Sdim    case Hexagon::C2_cmpgtp:
293286425Sdim    case Hexagon::C2_cmpgtup:
294286425Sdim    case Hexagon::C2_cmpeqi:
295286425Sdim    case Hexagon::C2_cmpgti:
296286425Sdim    case Hexagon::C2_cmpgtui:
297286425Sdim    case Hexagon::C2_cmpgei:
298286425Sdim    case Hexagon::C2_cmpgeui:
299286425Sdim    case Hexagon::C4_cmpneqi:
300286425Sdim    case Hexagon::C4_cmpltei:
301286425Sdim    case Hexagon::C4_cmplteui:
302286425Sdim    case Hexagon::C4_cmpneq:
303286425Sdim    case Hexagon::C4_cmplte:
304286425Sdim    case Hexagon::C4_cmplteu:
305286425Sdim    case Hexagon::A4_cmpbeq:
306286425Sdim    case Hexagon::A4_cmpbeqi:
307286425Sdim    case Hexagon::A4_cmpbgtu:
308286425Sdim    case Hexagon::A4_cmpbgtui:
309286425Sdim    case Hexagon::A4_cmpbgt:
310286425Sdim    case Hexagon::A4_cmpbgti:
311286425Sdim    case Hexagon::A4_cmpheq:
312286425Sdim    case Hexagon::A4_cmphgt:
313286425Sdim    case Hexagon::A4_cmphgtu:
314286425Sdim    case Hexagon::A4_cmpheqi:
315286425Sdim    case Hexagon::A4_cmphgti:
316286425Sdim    case Hexagon::A4_cmphgtui:
317286425Sdim      return true;
318286425Sdim  }
319286425Sdim  return false;
320286425Sdim}
321286425Sdim
322353358Sdimbool HexagonGenPredicate::isScalarPred(RegisterSubReg PredReg) {
323353358Sdim  std::queue<RegisterSubReg> WorkQ;
324286425Sdim  WorkQ.push(PredReg);
325286425Sdim
326286425Sdim  while (!WorkQ.empty()) {
327353358Sdim    RegisterSubReg PR = WorkQ.front();
328286425Sdim    WorkQ.pop();
329286425Sdim    const MachineInstr *DefI = MRI->getVRegDef(PR.R);
330286425Sdim    if (!DefI)
331286425Sdim      return false;
332286425Sdim    unsigned DefOpc = DefI->getOpcode();
333286425Sdim    switch (DefOpc) {
334286425Sdim      case TargetOpcode::COPY: {
335286425Sdim        const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
336286425Sdim        if (MRI->getRegClass(PR.R) != PredRC)
337286425Sdim          return false;
338286425Sdim        // If it is a copy between two predicate registers, fall through.
339321369Sdim        LLVM_FALLTHROUGH;
340286425Sdim      }
341286425Sdim      case Hexagon::C2_and:
342286425Sdim      case Hexagon::C2_andn:
343286425Sdim      case Hexagon::C4_and_and:
344286425Sdim      case Hexagon::C4_and_andn:
345286425Sdim      case Hexagon::C4_and_or:
346286425Sdim      case Hexagon::C2_or:
347286425Sdim      case Hexagon::C2_orn:
348286425Sdim      case Hexagon::C4_or_and:
349286425Sdim      case Hexagon::C4_or_andn:
350286425Sdim      case Hexagon::C4_or_or:
351286425Sdim      case Hexagon::C4_or_orn:
352286425Sdim      case Hexagon::C2_xor:
353286425Sdim        // Add operands to the queue.
354314564Sdim        for (const MachineOperand &MO : DefI->operands())
355314564Sdim          if (MO.isReg() && MO.isUse())
356353358Sdim            WorkQ.push(RegisterSubReg(MO.getReg()));
357286425Sdim        break;
358286425Sdim
359286425Sdim      // All non-vector compares are ok, everything else is bad.
360286425Sdim      default:
361286425Sdim        return isScalarCmp(DefOpc);
362286425Sdim    }
363286425Sdim  }
364286425Sdim
365286425Sdim  return true;
366286425Sdim}
367286425Sdim
368286425Sdimbool HexagonGenPredicate::convertToPredForm(MachineInstr *MI) {
369341825Sdim  LLVM_DEBUG(dbgs() << __func__ << ": " << MI << " " << *MI);
370286425Sdim
371286425Sdim  unsigned Opc = MI->getOpcode();
372286425Sdim  assert(isConvertibleToPredForm(MI));
373286425Sdim  unsigned NumOps = MI->getNumOperands();
374286425Sdim  for (unsigned i = 0; i < NumOps; ++i) {
375286425Sdim    MachineOperand &MO = MI->getOperand(i);
376286425Sdim    if (!MO.isReg() || !MO.isUse())
377286425Sdim      continue;
378353358Sdim    RegisterSubReg Reg(MO);
379314564Sdim    if (Reg.S && Reg.S != Hexagon::isub_lo)
380286425Sdim      return false;
381286425Sdim    if (!PredGPRs.count(Reg))
382286425Sdim      return false;
383286425Sdim  }
384286425Sdim
385286425Sdim  MachineBasicBlock &B = *MI->getParent();
386286425Sdim  DebugLoc DL = MI->getDebugLoc();
387286425Sdim
388286425Sdim  unsigned NewOpc = getPredForm(Opc);
389286425Sdim  // Special case for comparisons against 0.
390286425Sdim  if (NewOpc == 0) {
391286425Sdim    switch (Opc) {
392286425Sdim      case Hexagon::C2_cmpeqi:
393286425Sdim        NewOpc = Hexagon::C2_not;
394286425Sdim        break;
395286425Sdim      case Hexagon::C4_cmpneqi:
396286425Sdim        NewOpc = TargetOpcode::COPY;
397286425Sdim        break;
398286425Sdim      default:
399286425Sdim        return false;
400286425Sdim    }
401286425Sdim
402286425Sdim    // If it's a scalar predicate register, then all bits in it are
403286425Sdim    // the same. Otherwise, to determine whether all bits are 0 or not
404286425Sdim    // we would need to use any8.
405353358Sdim    RegisterSubReg PR = getPredRegFor(MI->getOperand(1));
406286425Sdim    if (!isScalarPred(PR))
407286425Sdim      return false;
408286425Sdim    // This will skip the immediate argument when creating the predicate
409286425Sdim    // version instruction.
410286425Sdim    NumOps = 2;
411286425Sdim  }
412286425Sdim
413286425Sdim  // Some sanity: check that def is in operand #0.
414286425Sdim  MachineOperand &Op0 = MI->getOperand(0);
415286425Sdim  assert(Op0.isDef());
416353358Sdim  RegisterSubReg OutR(Op0);
417286425Sdim
418286425Sdim  // Don't use getPredRegFor, since it will create an association between
419286425Sdim  // the argument and a created predicate register (i.e. it will insert a
420286425Sdim  // copy if a new predicate register is created).
421286425Sdim  const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
422353358Sdim  RegisterSubReg NewPR = MRI->createVirtualRegister(PredRC);
423286425Sdim  MachineInstrBuilder MIB = BuildMI(B, MI, DL, TII->get(NewOpc), NewPR.R);
424286425Sdim
425286425Sdim  // Add predicate counterparts of the GPRs.
426286425Sdim  for (unsigned i = 1; i < NumOps; ++i) {
427353358Sdim    RegisterSubReg GPR = MI->getOperand(i);
428353358Sdim    RegisterSubReg Pred = getPredRegFor(GPR);
429286425Sdim    MIB.addReg(Pred.R, 0, Pred.S);
430286425Sdim  }
431341825Sdim  LLVM_DEBUG(dbgs() << "generated: " << *MIB);
432286425Sdim
433286425Sdim  // Generate a copy-out: NewGPR = NewPR, and replace all uses of OutR
434286425Sdim  // with NewGPR.
435286425Sdim  const TargetRegisterClass *RC = MRI->getRegClass(OutR.R);
436360784Sdim  Register NewOutR = MRI->createVirtualRegister(RC);
437286425Sdim  BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), NewOutR)
438286425Sdim    .addReg(NewPR.R, 0, NewPR.S);
439286425Sdim  MRI->replaceRegWith(OutR.R, NewOutR);
440286425Sdim  MI->eraseFromParent();
441286425Sdim
442286425Sdim  // If the processed instruction was C2_tfrrp (i.e. Rn = Pm; Pk = Rn),
443286425Sdim  // then the output will be a predicate register.  Do not visit the
444286425Sdim  // users of it.
445286425Sdim  if (!isPredReg(NewOutR)) {
446353358Sdim    RegisterSubReg R(NewOutR);
447286425Sdim    PredGPRs.insert(R);
448286425Sdim    processPredicateGPR(R);
449286425Sdim  }
450286425Sdim  return true;
451286425Sdim}
452286425Sdim
453286425Sdimbool HexagonGenPredicate::eliminatePredCopies(MachineFunction &MF) {
454341825Sdim  LLVM_DEBUG(dbgs() << __func__ << "\n");
455286425Sdim  const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
456286425Sdim  bool Changed = false;
457286425Sdim  VectOfInst Erase;
458286425Sdim
459286425Sdim  // First, replace copies
460286425Sdim  //   IntR = PredR1
461286425Sdim  //   PredR2 = IntR
462286425Sdim  // with
463286425Sdim  //   PredR2 = PredR1
464286425Sdim  // Such sequences can be generated when a copy-into-pred is generated from
465286425Sdim  // a gpr register holding a result of a convertible instruction. After
466286425Sdim  // the convertible instruction is converted, its predicate result will be
467286425Sdim  // copied back into the original gpr.
468286425Sdim
469309124Sdim  for (MachineBasicBlock &MBB : MF) {
470309124Sdim    for (MachineInstr &MI : MBB) {
471309124Sdim      if (MI.getOpcode() != TargetOpcode::COPY)
472286425Sdim        continue;
473353358Sdim      RegisterSubReg DR = MI.getOperand(0);
474353358Sdim      RegisterSubReg SR = MI.getOperand(1);
475360784Sdim      if (!Register::isVirtualRegister(DR.R))
476286425Sdim        continue;
477360784Sdim      if (!Register::isVirtualRegister(SR.R))
478286425Sdim        continue;
479286425Sdim      if (MRI->getRegClass(DR.R) != PredRC)
480286425Sdim        continue;
481286425Sdim      if (MRI->getRegClass(SR.R) != PredRC)
482286425Sdim        continue;
483286425Sdim      assert(!DR.S && !SR.S && "Unexpected subregister");
484286425Sdim      MRI->replaceRegWith(DR.R, SR.R);
485309124Sdim      Erase.insert(&MI);
486286425Sdim      Changed = true;
487286425Sdim    }
488286425Sdim  }
489286425Sdim
490286425Sdim  for (VectOfInst::iterator I = Erase.begin(), E = Erase.end(); I != E; ++I)
491286425Sdim    (*I)->eraseFromParent();
492286425Sdim
493286425Sdim  return Changed;
494286425Sdim}
495286425Sdim
496286425Sdimbool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {
497327952Sdim  if (skipFunction(MF.getFunction()))
498309124Sdim    return false;
499309124Sdim
500286425Sdim  TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
501286425Sdim  TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
502286425Sdim  MRI = &MF.getRegInfo();
503286425Sdim  PredGPRs.clear();
504286425Sdim  PUsers.clear();
505286425Sdim  G2P.clear();
506286425Sdim
507286425Sdim  bool Changed = false;
508286425Sdim  collectPredicateGPR(MF);
509286425Sdim  for (SetOfReg::iterator I = PredGPRs.begin(), E = PredGPRs.end(); I != E; ++I)
510286425Sdim    processPredicateGPR(*I);
511286425Sdim
512286425Sdim  bool Again;
513286425Sdim  do {
514286425Sdim    Again = false;
515286425Sdim    VectOfInst Processed, Copy;
516286425Sdim
517327952Sdim    using iterator = VectOfInst::iterator;
518327952Sdim
519286425Sdim    Copy = PUsers;
520286425Sdim    for (iterator I = Copy.begin(), E = Copy.end(); I != E; ++I) {
521286425Sdim      MachineInstr *MI = *I;
522286425Sdim      bool Done = convertToPredForm(MI);
523286425Sdim      if (Done) {
524286425Sdim        Processed.insert(MI);
525286425Sdim        Again = true;
526286425Sdim      }
527286425Sdim    }
528286425Sdim    Changed |= Again;
529286425Sdim
530286425Sdim    auto Done = [Processed] (MachineInstr *MI) -> bool {
531286425Sdim      return Processed.count(MI);
532286425Sdim    };
533286425Sdim    PUsers.remove_if(Done);
534286425Sdim  } while (Again);
535286425Sdim
536286425Sdim  Changed |= eliminatePredCopies(MF);
537286425Sdim  return Changed;
538286425Sdim}
539286425Sdim
540286425SdimFunctionPass *llvm::createHexagonGenPredicate() {
541286425Sdim  return new HexagonGenPredicate();
542286425Sdim}
543