HexagonGenPredicate.cpp revision 341825
1327952Sdim//===- HexagonGenPredicate.cpp --------------------------------------------===//
2286425Sdim//
3286425Sdim//                     The LLVM Compiler Infrastructure
4286425Sdim//
5286425Sdim// This file is distributed under the University of Illinois Open Source
6286425Sdim// License. See LICENSE.TXT for details.
7286425Sdim//
8286425Sdim//===----------------------------------------------------------------------===//
9286425Sdim
10314564Sdim#include "HexagonInstrInfo.h"
11314564Sdim#include "HexagonSubtarget.h"
12286425Sdim#include "llvm/ADT/SetVector.h"
13314564Sdim#include "llvm/ADT/StringRef.h"
14314564Sdim#include "llvm/CodeGen/MachineBasicBlock.h"
15286425Sdim#include "llvm/CodeGen/MachineDominators.h"
16314564Sdim#include "llvm/CodeGen/MachineFunction.h"
17286425Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
18314564Sdim#include "llvm/CodeGen/MachineInstr.h"
19286425Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
20314564Sdim#include "llvm/CodeGen/MachineOperand.h"
21286425Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h"
23314564Sdim#include "llvm/IR/DebugLoc.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
49286425Sdim  struct Register {
50286425Sdim    unsigned R, S;
51314564Sdim
52286425Sdim    Register(unsigned r = 0, unsigned s = 0) : R(r), S(s) {}
53286425Sdim    Register(const MachineOperand &MO) : R(MO.getReg()), S(MO.getSubReg()) {}
54314564Sdim
55286425Sdim    bool operator== (const Register &Reg) const {
56286425Sdim      return R == Reg.R && S == Reg.S;
57286425Sdim    }
58314564Sdim
59286425Sdim    bool operator< (const Register &Reg) const {
60286425Sdim      return R < Reg.R || (R == Reg.R && S < Reg.S);
61286425Sdim    }
62286425Sdim  };
63314564Sdim
64286425Sdim  struct PrintRegister {
65314564Sdim    friend raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR);
66314564Sdim
67286425Sdim    PrintRegister(Register R, const TargetRegisterInfo &I) : Reg(R), TRI(I) {}
68314564Sdim
69286425Sdim  private:
70286425Sdim    Register Reg;
71286425Sdim    const TargetRegisterInfo &TRI;
72286425Sdim  };
73314564Sdim
74286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR)
75286425Sdim    LLVM_ATTRIBUTE_UNUSED;
76286425Sdim  raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR) {
77327952Sdim    return OS << printReg(PR.Reg.R, &PR.TRI, PR.Reg.S);
78286425Sdim  }
79286425Sdim
80286425Sdim  class HexagonGenPredicate : public MachineFunctionPass {
81286425Sdim  public:
82286425Sdim    static char ID;
83314564Sdim
84327952Sdim    HexagonGenPredicate() : MachineFunctionPass(ID) {
85286425Sdim      initializeHexagonGenPredicatePass(*PassRegistry::getPassRegistry());
86286425Sdim    }
87314564Sdim
88314564Sdim    StringRef getPassName() const override {
89286425Sdim      return "Hexagon generate predicate operations";
90286425Sdim    }
91314564Sdim
92314564Sdim    void getAnalysisUsage(AnalysisUsage &AU) const override {
93286425Sdim      AU.addRequired<MachineDominatorTree>();
94286425Sdim      AU.addPreserved<MachineDominatorTree>();
95286425Sdim      MachineFunctionPass::getAnalysisUsage(AU);
96286425Sdim    }
97286425Sdim
98314564Sdim    bool runOnMachineFunction(MachineFunction &MF) override;
99314564Sdim
100286425Sdim  private:
101327952Sdim    using VectOfInst = SetVector<MachineInstr *>;
102327952Sdim    using SetOfReg = std::set<Register>;
103327952Sdim    using RegToRegMap = std::map<Register, Register>;
104286425Sdim
105327952Sdim    const HexagonInstrInfo *TII = nullptr;
106327952Sdim    const HexagonRegisterInfo *TRI = nullptr;
107327952Sdim    MachineRegisterInfo *MRI = nullptr;
108286425Sdim    SetOfReg PredGPRs;
109286425Sdim    VectOfInst PUsers;
110286425Sdim    RegToRegMap G2P;
111286425Sdim
112286425Sdim    bool isPredReg(unsigned R);
113286425Sdim    void collectPredicateGPR(MachineFunction &MF);
114286425Sdim    void processPredicateGPR(const Register &Reg);
115286425Sdim    unsigned getPredForm(unsigned Opc);
116286425Sdim    bool isConvertibleToPredForm(const MachineInstr *MI);
117286425Sdim    bool isScalarCmp(unsigned Opc);
118286425Sdim    bool isScalarPred(Register PredReg);
119286425Sdim    Register getPredRegFor(const Register &Reg);
120286425Sdim    bool convertToPredForm(MachineInstr *MI);
121286425Sdim    bool eliminatePredCopies(MachineFunction &MF);
122286425Sdim  };
123286425Sdim
124314564Sdim} // end anonymous namespace
125314564Sdim
126327952Sdimchar HexagonGenPredicate::ID = 0;
127327952Sdim
128286425SdimINITIALIZE_PASS_BEGIN(HexagonGenPredicate, "hexagon-gen-pred",
129286425Sdim  "Hexagon generate predicate operations", false, false)
130286425SdimINITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
131286425SdimINITIALIZE_PASS_END(HexagonGenPredicate, "hexagon-gen-pred",
132286425Sdim  "Hexagon generate predicate operations", false, false)
133286425Sdim
134286425Sdimbool HexagonGenPredicate::isPredReg(unsigned R) {
135286425Sdim  if (!TargetRegisterInfo::isVirtualRegister(R))
136286425Sdim    return false;
137286425Sdim  const TargetRegisterClass *RC = MRI->getRegClass(R);
138286425Sdim  return RC == &Hexagon::PredRegsRegClass;
139286425Sdim}
140286425Sdim
141286425Sdimunsigned HexagonGenPredicate::getPredForm(unsigned Opc) {
142286425Sdim  using namespace Hexagon;
143286425Sdim
144286425Sdim  switch (Opc) {
145286425Sdim    case A2_and:
146286425Sdim    case A2_andp:
147286425Sdim      return C2_and;
148286425Sdim    case A4_andn:
149286425Sdim    case A4_andnp:
150286425Sdim      return C2_andn;
151286425Sdim    case M4_and_and:
152286425Sdim      return C4_and_and;
153286425Sdim    case M4_and_andn:
154286425Sdim      return C4_and_andn;
155286425Sdim    case M4_and_or:
156286425Sdim      return C4_and_or;
157286425Sdim
158286425Sdim    case A2_or:
159286425Sdim    case A2_orp:
160286425Sdim      return C2_or;
161286425Sdim    case A4_orn:
162286425Sdim    case A4_ornp:
163286425Sdim      return C2_orn;
164286425Sdim    case M4_or_and:
165286425Sdim      return C4_or_and;
166286425Sdim    case M4_or_andn:
167286425Sdim      return C4_or_andn;
168286425Sdim    case M4_or_or:
169286425Sdim      return C4_or_or;
170286425Sdim
171286425Sdim    case A2_xor:
172286425Sdim    case A2_xorp:
173286425Sdim      return C2_xor;
174286425Sdim
175286425Sdim    case C2_tfrrp:
176286425Sdim      return COPY;
177286425Sdim  }
178286425Sdim  // The opcode corresponding to 0 is TargetOpcode::PHI. We can use 0 here
179286425Sdim  // to denote "none", but we need to make sure that none of the valid opcodes
180286425Sdim  // that we return will ever be 0.
181309124Sdim  static_assert(PHI == 0, "Use different value for <none>");
182286425Sdim  return 0;
183286425Sdim}
184286425Sdim
185286425Sdimbool HexagonGenPredicate::isConvertibleToPredForm(const MachineInstr *MI) {
186286425Sdim  unsigned Opc = MI->getOpcode();
187286425Sdim  if (getPredForm(Opc) != 0)
188286425Sdim    return true;
189286425Sdim
190286425Sdim  // Comparisons against 0 are also convertible. This does not apply to
191286425Sdim  // A4_rcmpeqi or A4_rcmpneqi, since they produce values 0 or 1, which
192286425Sdim  // may not match the value that the predicate register would have if
193286425Sdim  // it was converted to a predicate form.
194286425Sdim  switch (Opc) {
195286425Sdim    case Hexagon::C2_cmpeqi:
196286425Sdim    case Hexagon::C4_cmpneqi:
197286425Sdim      if (MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0)
198286425Sdim        return true;
199286425Sdim      break;
200286425Sdim  }
201286425Sdim  return false;
202286425Sdim}
203286425Sdim
204286425Sdimvoid HexagonGenPredicate::collectPredicateGPR(MachineFunction &MF) {
205286425Sdim  for (MachineFunction::iterator A = MF.begin(), Z = MF.end(); A != Z; ++A) {
206286425Sdim    MachineBasicBlock &B = *A;
207286425Sdim    for (MachineBasicBlock::iterator I = B.begin(), E = B.end(); I != E; ++I) {
208286425Sdim      MachineInstr *MI = &*I;
209286425Sdim      unsigned Opc = MI->getOpcode();
210286425Sdim      switch (Opc) {
211286425Sdim        case Hexagon::C2_tfrpr:
212286425Sdim        case TargetOpcode::COPY:
213286425Sdim          if (isPredReg(MI->getOperand(1).getReg())) {
214286425Sdim            Register RD = MI->getOperand(0);
215286425Sdim            if (TargetRegisterInfo::isVirtualRegister(RD.R))
216286425Sdim              PredGPRs.insert(RD);
217286425Sdim          }
218286425Sdim          break;
219286425Sdim      }
220286425Sdim    }
221286425Sdim  }
222286425Sdim}
223286425Sdim
224286425Sdimvoid HexagonGenPredicate::processPredicateGPR(const Register &Reg) {
225341825Sdim  LLVM_DEBUG(dbgs() << __func__ << ": " << printReg(Reg.R, TRI, Reg.S) << "\n");
226327952Sdim  using use_iterator = MachineRegisterInfo::use_iterator;
227327952Sdim
228286425Sdim  use_iterator I = MRI->use_begin(Reg.R), E = MRI->use_end();
229286425Sdim  if (I == E) {
230341825Sdim    LLVM_DEBUG(dbgs() << "Dead reg: " << printReg(Reg.R, TRI, Reg.S) << '\n');
231286425Sdim    MachineInstr *DefI = MRI->getVRegDef(Reg.R);
232286425Sdim    DefI->eraseFromParent();
233286425Sdim    return;
234286425Sdim  }
235286425Sdim
236286425Sdim  for (; I != E; ++I) {
237286425Sdim    MachineInstr *UseI = I->getParent();
238286425Sdim    if (isConvertibleToPredForm(UseI))
239286425Sdim      PUsers.insert(UseI);
240286425Sdim  }
241286425Sdim}
242286425Sdim
243286425SdimRegister HexagonGenPredicate::getPredRegFor(const Register &Reg) {
244286425Sdim  // Create a predicate register for a given Reg. The newly created register
245286425Sdim  // will have its value copied from Reg, so that it can be later used as
246286425Sdim  // an operand in other instructions.
247286425Sdim  assert(TargetRegisterInfo::isVirtualRegister(Reg.R));
248286425Sdim  RegToRegMap::iterator F = G2P.find(Reg);
249286425Sdim  if (F != G2P.end())
250286425Sdim    return F->second;
251286425Sdim
252341825Sdim  LLVM_DEBUG(dbgs() << __func__ << ": " << PrintRegister(Reg, *TRI));
253286425Sdim  MachineInstr *DefI = MRI->getVRegDef(Reg.R);
254286425Sdim  assert(DefI);
255286425Sdim  unsigned Opc = DefI->getOpcode();
256286425Sdim  if (Opc == Hexagon::C2_tfrpr || Opc == TargetOpcode::COPY) {
257286425Sdim    assert(DefI->getOperand(0).isDef() && DefI->getOperand(1).isUse());
258286425Sdim    Register PR = DefI->getOperand(1);
259286425Sdim    G2P.insert(std::make_pair(Reg, PR));
260341825Sdim    LLVM_DEBUG(dbgs() << " -> " << PrintRegister(PR, *TRI) << '\n');
261286425Sdim    return PR;
262286425Sdim  }
263286425Sdim
264286425Sdim  MachineBasicBlock &B = *DefI->getParent();
265286425Sdim  DebugLoc DL = DefI->getDebugLoc();
266286425Sdim  const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
267286425Sdim  unsigned NewPR = MRI->createVirtualRegister(PredRC);
268286425Sdim
269286425Sdim  // For convertible instructions, do not modify them, so that they can
270296417Sdim  // be converted later.  Generate a copy from Reg to NewPR.
271286425Sdim  if (isConvertibleToPredForm(DefI)) {
272286425Sdim    MachineBasicBlock::iterator DefIt = DefI;
273286425Sdim    BuildMI(B, std::next(DefIt), DL, TII->get(TargetOpcode::COPY), NewPR)
274286425Sdim      .addReg(Reg.R, 0, Reg.S);
275286425Sdim    G2P.insert(std::make_pair(Reg, Register(NewPR)));
276341825Sdim    LLVM_DEBUG(dbgs() << " -> !" << PrintRegister(Register(NewPR), *TRI)
277341825Sdim                      << '\n');
278286425Sdim    return Register(NewPR);
279286425Sdim  }
280286425Sdim
281286425Sdim  llvm_unreachable("Invalid argument");
282286425Sdim}
283286425Sdim
284286425Sdimbool HexagonGenPredicate::isScalarCmp(unsigned Opc) {
285286425Sdim  switch (Opc) {
286286425Sdim    case Hexagon::C2_cmpeq:
287286425Sdim    case Hexagon::C2_cmpgt:
288286425Sdim    case Hexagon::C2_cmpgtu:
289286425Sdim    case Hexagon::C2_cmpeqp:
290286425Sdim    case Hexagon::C2_cmpgtp:
291286425Sdim    case Hexagon::C2_cmpgtup:
292286425Sdim    case Hexagon::C2_cmpeqi:
293286425Sdim    case Hexagon::C2_cmpgti:
294286425Sdim    case Hexagon::C2_cmpgtui:
295286425Sdim    case Hexagon::C2_cmpgei:
296286425Sdim    case Hexagon::C2_cmpgeui:
297286425Sdim    case Hexagon::C4_cmpneqi:
298286425Sdim    case Hexagon::C4_cmpltei:
299286425Sdim    case Hexagon::C4_cmplteui:
300286425Sdim    case Hexagon::C4_cmpneq:
301286425Sdim    case Hexagon::C4_cmplte:
302286425Sdim    case Hexagon::C4_cmplteu:
303286425Sdim    case Hexagon::A4_cmpbeq:
304286425Sdim    case Hexagon::A4_cmpbeqi:
305286425Sdim    case Hexagon::A4_cmpbgtu:
306286425Sdim    case Hexagon::A4_cmpbgtui:
307286425Sdim    case Hexagon::A4_cmpbgt:
308286425Sdim    case Hexagon::A4_cmpbgti:
309286425Sdim    case Hexagon::A4_cmpheq:
310286425Sdim    case Hexagon::A4_cmphgt:
311286425Sdim    case Hexagon::A4_cmphgtu:
312286425Sdim    case Hexagon::A4_cmpheqi:
313286425Sdim    case Hexagon::A4_cmphgti:
314286425Sdim    case Hexagon::A4_cmphgtui:
315286425Sdim      return true;
316286425Sdim  }
317286425Sdim  return false;
318286425Sdim}
319286425Sdim
320286425Sdimbool HexagonGenPredicate::isScalarPred(Register PredReg) {
321286425Sdim  std::queue<Register> WorkQ;
322286425Sdim  WorkQ.push(PredReg);
323286425Sdim
324286425Sdim  while (!WorkQ.empty()) {
325286425Sdim    Register PR = WorkQ.front();
326286425Sdim    WorkQ.pop();
327286425Sdim    const MachineInstr *DefI = MRI->getVRegDef(PR.R);
328286425Sdim    if (!DefI)
329286425Sdim      return false;
330286425Sdim    unsigned DefOpc = DefI->getOpcode();
331286425Sdim    switch (DefOpc) {
332286425Sdim      case TargetOpcode::COPY: {
333286425Sdim        const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
334286425Sdim        if (MRI->getRegClass(PR.R) != PredRC)
335286425Sdim          return false;
336286425Sdim        // If it is a copy between two predicate registers, fall through.
337321369Sdim        LLVM_FALLTHROUGH;
338286425Sdim      }
339286425Sdim      case Hexagon::C2_and:
340286425Sdim      case Hexagon::C2_andn:
341286425Sdim      case Hexagon::C4_and_and:
342286425Sdim      case Hexagon::C4_and_andn:
343286425Sdim      case Hexagon::C4_and_or:
344286425Sdim      case Hexagon::C2_or:
345286425Sdim      case Hexagon::C2_orn:
346286425Sdim      case Hexagon::C4_or_and:
347286425Sdim      case Hexagon::C4_or_andn:
348286425Sdim      case Hexagon::C4_or_or:
349286425Sdim      case Hexagon::C4_or_orn:
350286425Sdim      case Hexagon::C2_xor:
351286425Sdim        // Add operands to the queue.
352314564Sdim        for (const MachineOperand &MO : DefI->operands())
353314564Sdim          if (MO.isReg() && MO.isUse())
354314564Sdim            WorkQ.push(Register(MO.getReg()));
355286425Sdim        break;
356286425Sdim
357286425Sdim      // All non-vector compares are ok, everything else is bad.
358286425Sdim      default:
359286425Sdim        return isScalarCmp(DefOpc);
360286425Sdim    }
361286425Sdim  }
362286425Sdim
363286425Sdim  return true;
364286425Sdim}
365286425Sdim
366286425Sdimbool HexagonGenPredicate::convertToPredForm(MachineInstr *MI) {
367341825Sdim  LLVM_DEBUG(dbgs() << __func__ << ": " << MI << " " << *MI);
368286425Sdim
369286425Sdim  unsigned Opc = MI->getOpcode();
370286425Sdim  assert(isConvertibleToPredForm(MI));
371286425Sdim  unsigned NumOps = MI->getNumOperands();
372286425Sdim  for (unsigned i = 0; i < NumOps; ++i) {
373286425Sdim    MachineOperand &MO = MI->getOperand(i);
374286425Sdim    if (!MO.isReg() || !MO.isUse())
375286425Sdim      continue;
376286425Sdim    Register Reg(MO);
377314564Sdim    if (Reg.S && Reg.S != Hexagon::isub_lo)
378286425Sdim      return false;
379286425Sdim    if (!PredGPRs.count(Reg))
380286425Sdim      return false;
381286425Sdim  }
382286425Sdim
383286425Sdim  MachineBasicBlock &B = *MI->getParent();
384286425Sdim  DebugLoc DL = MI->getDebugLoc();
385286425Sdim
386286425Sdim  unsigned NewOpc = getPredForm(Opc);
387286425Sdim  // Special case for comparisons against 0.
388286425Sdim  if (NewOpc == 0) {
389286425Sdim    switch (Opc) {
390286425Sdim      case Hexagon::C2_cmpeqi:
391286425Sdim        NewOpc = Hexagon::C2_not;
392286425Sdim        break;
393286425Sdim      case Hexagon::C4_cmpneqi:
394286425Sdim        NewOpc = TargetOpcode::COPY;
395286425Sdim        break;
396286425Sdim      default:
397286425Sdim        return false;
398286425Sdim    }
399286425Sdim
400286425Sdim    // If it's a scalar predicate register, then all bits in it are
401286425Sdim    // the same. Otherwise, to determine whether all bits are 0 or not
402286425Sdim    // we would need to use any8.
403286425Sdim    Register PR = getPredRegFor(MI->getOperand(1));
404286425Sdim    if (!isScalarPred(PR))
405286425Sdim      return false;
406286425Sdim    // This will skip the immediate argument when creating the predicate
407286425Sdim    // version instruction.
408286425Sdim    NumOps = 2;
409286425Sdim  }
410286425Sdim
411286425Sdim  // Some sanity: check that def is in operand #0.
412286425Sdim  MachineOperand &Op0 = MI->getOperand(0);
413286425Sdim  assert(Op0.isDef());
414286425Sdim  Register OutR(Op0);
415286425Sdim
416286425Sdim  // Don't use getPredRegFor, since it will create an association between
417286425Sdim  // the argument and a created predicate register (i.e. it will insert a
418286425Sdim  // copy if a new predicate register is created).
419286425Sdim  const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
420286425Sdim  Register NewPR = MRI->createVirtualRegister(PredRC);
421286425Sdim  MachineInstrBuilder MIB = BuildMI(B, MI, DL, TII->get(NewOpc), NewPR.R);
422286425Sdim
423286425Sdim  // Add predicate counterparts of the GPRs.
424286425Sdim  for (unsigned i = 1; i < NumOps; ++i) {
425286425Sdim    Register GPR = MI->getOperand(i);
426286425Sdim    Register Pred = getPredRegFor(GPR);
427286425Sdim    MIB.addReg(Pred.R, 0, Pred.S);
428286425Sdim  }
429341825Sdim  LLVM_DEBUG(dbgs() << "generated: " << *MIB);
430286425Sdim
431286425Sdim  // Generate a copy-out: NewGPR = NewPR, and replace all uses of OutR
432286425Sdim  // with NewGPR.
433286425Sdim  const TargetRegisterClass *RC = MRI->getRegClass(OutR.R);
434286425Sdim  unsigned NewOutR = MRI->createVirtualRegister(RC);
435286425Sdim  BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), NewOutR)
436286425Sdim    .addReg(NewPR.R, 0, NewPR.S);
437286425Sdim  MRI->replaceRegWith(OutR.R, NewOutR);
438286425Sdim  MI->eraseFromParent();
439286425Sdim
440286425Sdim  // If the processed instruction was C2_tfrrp (i.e. Rn = Pm; Pk = Rn),
441286425Sdim  // then the output will be a predicate register.  Do not visit the
442286425Sdim  // users of it.
443286425Sdim  if (!isPredReg(NewOutR)) {
444286425Sdim    Register R(NewOutR);
445286425Sdim    PredGPRs.insert(R);
446286425Sdim    processPredicateGPR(R);
447286425Sdim  }
448286425Sdim  return true;
449286425Sdim}
450286425Sdim
451286425Sdimbool HexagonGenPredicate::eliminatePredCopies(MachineFunction &MF) {
452341825Sdim  LLVM_DEBUG(dbgs() << __func__ << "\n");
453286425Sdim  const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
454286425Sdim  bool Changed = false;
455286425Sdim  VectOfInst Erase;
456286425Sdim
457286425Sdim  // First, replace copies
458286425Sdim  //   IntR = PredR1
459286425Sdim  //   PredR2 = IntR
460286425Sdim  // with
461286425Sdim  //   PredR2 = PredR1
462286425Sdim  // Such sequences can be generated when a copy-into-pred is generated from
463286425Sdim  // a gpr register holding a result of a convertible instruction. After
464286425Sdim  // the convertible instruction is converted, its predicate result will be
465286425Sdim  // copied back into the original gpr.
466286425Sdim
467309124Sdim  for (MachineBasicBlock &MBB : MF) {
468309124Sdim    for (MachineInstr &MI : MBB) {
469309124Sdim      if (MI.getOpcode() != TargetOpcode::COPY)
470286425Sdim        continue;
471309124Sdim      Register DR = MI.getOperand(0);
472309124Sdim      Register SR = MI.getOperand(1);
473286425Sdim      if (!TargetRegisterInfo::isVirtualRegister(DR.R))
474286425Sdim        continue;
475286425Sdim      if (!TargetRegisterInfo::isVirtualRegister(SR.R))
476286425Sdim        continue;
477286425Sdim      if (MRI->getRegClass(DR.R) != PredRC)
478286425Sdim        continue;
479286425Sdim      if (MRI->getRegClass(SR.R) != PredRC)
480286425Sdim        continue;
481286425Sdim      assert(!DR.S && !SR.S && "Unexpected subregister");
482286425Sdim      MRI->replaceRegWith(DR.R, SR.R);
483309124Sdim      Erase.insert(&MI);
484286425Sdim      Changed = true;
485286425Sdim    }
486286425Sdim  }
487286425Sdim
488286425Sdim  for (VectOfInst::iterator I = Erase.begin(), E = Erase.end(); I != E; ++I)
489286425Sdim    (*I)->eraseFromParent();
490286425Sdim
491286425Sdim  return Changed;
492286425Sdim}
493286425Sdim
494286425Sdimbool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {
495327952Sdim  if (skipFunction(MF.getFunction()))
496309124Sdim    return false;
497309124Sdim
498286425Sdim  TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
499286425Sdim  TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
500286425Sdim  MRI = &MF.getRegInfo();
501286425Sdim  PredGPRs.clear();
502286425Sdim  PUsers.clear();
503286425Sdim  G2P.clear();
504286425Sdim
505286425Sdim  bool Changed = false;
506286425Sdim  collectPredicateGPR(MF);
507286425Sdim  for (SetOfReg::iterator I = PredGPRs.begin(), E = PredGPRs.end(); I != E; ++I)
508286425Sdim    processPredicateGPR(*I);
509286425Sdim
510286425Sdim  bool Again;
511286425Sdim  do {
512286425Sdim    Again = false;
513286425Sdim    VectOfInst Processed, Copy;
514286425Sdim
515327952Sdim    using iterator = VectOfInst::iterator;
516327952Sdim
517286425Sdim    Copy = PUsers;
518286425Sdim    for (iterator I = Copy.begin(), E = Copy.end(); I != E; ++I) {
519286425Sdim      MachineInstr *MI = *I;
520286425Sdim      bool Done = convertToPredForm(MI);
521286425Sdim      if (Done) {
522286425Sdim        Processed.insert(MI);
523286425Sdim        Again = true;
524286425Sdim      }
525286425Sdim    }
526286425Sdim    Changed |= Again;
527286425Sdim
528286425Sdim    auto Done = [Processed] (MachineInstr *MI) -> bool {
529286425Sdim      return Processed.count(MI);
530286425Sdim    };
531286425Sdim    PUsers.remove_if(Done);
532286425Sdim  } while (Again);
533286425Sdim
534286425Sdim  Changed |= eliminatePredCopies(MF);
535286425Sdim  return Changed;
536286425Sdim}
537286425Sdim
538286425SdimFunctionPass *llvm::createHexagonGenPredicate() {
539286425Sdim  return new HexagonGenPredicate();
540286425Sdim}
541