xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonGenPredicate.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- HexagonGenPredicate.cpp --------------------------------------------===//
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 
9*0b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
10*0b57cec5SDimitry Andric #include "HexagonSubtarget.h"
11*0b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
12*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
13*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
14*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
22*0b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
23*0b57cec5SDimitry Andric #include "llvm/Pass.h"
24*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
25*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
27*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
28*0b57cec5SDimitry Andric #include <cassert>
29*0b57cec5SDimitry Andric #include <iterator>
30*0b57cec5SDimitry Andric #include <map>
31*0b57cec5SDimitry Andric #include <queue>
32*0b57cec5SDimitry Andric #include <set>
33*0b57cec5SDimitry Andric #include <utility>
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric #define DEBUG_TYPE "gen-pred"
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric using namespace llvm;
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric namespace llvm {
40*0b57cec5SDimitry Andric 
41*0b57cec5SDimitry Andric   void initializeHexagonGenPredicatePass(PassRegistry& Registry);
42*0b57cec5SDimitry Andric   FunctionPass *createHexagonGenPredicate();
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric } // end namespace llvm
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric namespace {
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric   // FIXME: Use TargetInstrInfo::RegSubRegPair
49*0b57cec5SDimitry Andric   struct RegisterSubReg {
50*0b57cec5SDimitry Andric     unsigned R, S;
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric     RegisterSubReg(unsigned r = 0, unsigned s = 0) : R(r), S(s) {}
53*0b57cec5SDimitry Andric     RegisterSubReg(const MachineOperand &MO) : R(MO.getReg()), S(MO.getSubReg()) {}
54*0b57cec5SDimitry Andric     RegisterSubReg(const Register &Reg) : R(Reg), S(0) {}
55*0b57cec5SDimitry Andric 
56*0b57cec5SDimitry Andric     bool operator== (const RegisterSubReg &Reg) const {
57*0b57cec5SDimitry Andric       return R == Reg.R && S == Reg.S;
58*0b57cec5SDimitry Andric     }
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric     bool operator< (const RegisterSubReg &Reg) const {
61*0b57cec5SDimitry Andric       return R < Reg.R || (R == Reg.R && S < Reg.S);
62*0b57cec5SDimitry Andric     }
63*0b57cec5SDimitry Andric   };
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric   struct PrintRegister {
66*0b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR);
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric     PrintRegister(RegisterSubReg R, const TargetRegisterInfo &I) : Reg(R), TRI(I) {}
69*0b57cec5SDimitry Andric 
70*0b57cec5SDimitry Andric   private:
71*0b57cec5SDimitry Andric     RegisterSubReg Reg;
72*0b57cec5SDimitry Andric     const TargetRegisterInfo &TRI;
73*0b57cec5SDimitry Andric   };
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR)
76*0b57cec5SDimitry Andric     LLVM_ATTRIBUTE_UNUSED;
77*0b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR) {
78*0b57cec5SDimitry Andric     return OS << printReg(PR.Reg.R, &PR.TRI, PR.Reg.S);
79*0b57cec5SDimitry Andric   }
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric   class HexagonGenPredicate : public MachineFunctionPass {
82*0b57cec5SDimitry Andric   public:
83*0b57cec5SDimitry Andric     static char ID;
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric     HexagonGenPredicate() : MachineFunctionPass(ID) {
86*0b57cec5SDimitry Andric       initializeHexagonGenPredicatePass(*PassRegistry::getPassRegistry());
87*0b57cec5SDimitry Andric     }
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric     StringRef getPassName() const override {
90*0b57cec5SDimitry Andric       return "Hexagon generate predicate operations";
91*0b57cec5SDimitry Andric     }
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
94*0b57cec5SDimitry Andric       AU.addRequired<MachineDominatorTree>();
95*0b57cec5SDimitry Andric       AU.addPreserved<MachineDominatorTree>();
96*0b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
97*0b57cec5SDimitry Andric     }
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   private:
102*0b57cec5SDimitry Andric     using VectOfInst = SetVector<MachineInstr *>;
103*0b57cec5SDimitry Andric     using SetOfReg = std::set<RegisterSubReg>;
104*0b57cec5SDimitry Andric     using RegToRegMap = std::map<RegisterSubReg, RegisterSubReg>;
105*0b57cec5SDimitry Andric 
106*0b57cec5SDimitry Andric     const HexagonInstrInfo *TII = nullptr;
107*0b57cec5SDimitry Andric     const HexagonRegisterInfo *TRI = nullptr;
108*0b57cec5SDimitry Andric     MachineRegisterInfo *MRI = nullptr;
109*0b57cec5SDimitry Andric     SetOfReg PredGPRs;
110*0b57cec5SDimitry Andric     VectOfInst PUsers;
111*0b57cec5SDimitry Andric     RegToRegMap G2P;
112*0b57cec5SDimitry Andric 
113*0b57cec5SDimitry Andric     bool isPredReg(unsigned R);
114*0b57cec5SDimitry Andric     void collectPredicateGPR(MachineFunction &MF);
115*0b57cec5SDimitry Andric     void processPredicateGPR(const RegisterSubReg &Reg);
116*0b57cec5SDimitry Andric     unsigned getPredForm(unsigned Opc);
117*0b57cec5SDimitry Andric     bool isConvertibleToPredForm(const MachineInstr *MI);
118*0b57cec5SDimitry Andric     bool isScalarCmp(unsigned Opc);
119*0b57cec5SDimitry Andric     bool isScalarPred(RegisterSubReg PredReg);
120*0b57cec5SDimitry Andric     RegisterSubReg getPredRegFor(const RegisterSubReg &Reg);
121*0b57cec5SDimitry Andric     bool convertToPredForm(MachineInstr *MI);
122*0b57cec5SDimitry Andric     bool eliminatePredCopies(MachineFunction &MF);
123*0b57cec5SDimitry Andric   };
124*0b57cec5SDimitry Andric 
125*0b57cec5SDimitry Andric } // end anonymous namespace
126*0b57cec5SDimitry Andric 
127*0b57cec5SDimitry Andric char HexagonGenPredicate::ID = 0;
128*0b57cec5SDimitry Andric 
129*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonGenPredicate, "hexagon-gen-pred",
130*0b57cec5SDimitry Andric   "Hexagon generate predicate operations", false, false)
131*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
132*0b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonGenPredicate, "hexagon-gen-pred",
133*0b57cec5SDimitry Andric   "Hexagon generate predicate operations", false, false)
134*0b57cec5SDimitry Andric 
135*0b57cec5SDimitry Andric bool HexagonGenPredicate::isPredReg(unsigned R) {
136*0b57cec5SDimitry Andric   if (!TargetRegisterInfo::isVirtualRegister(R))
137*0b57cec5SDimitry Andric     return false;
138*0b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(R);
139*0b57cec5SDimitry Andric   return RC == &Hexagon::PredRegsRegClass;
140*0b57cec5SDimitry Andric }
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric unsigned HexagonGenPredicate::getPredForm(unsigned Opc) {
143*0b57cec5SDimitry Andric   using namespace Hexagon;
144*0b57cec5SDimitry Andric 
145*0b57cec5SDimitry Andric   switch (Opc) {
146*0b57cec5SDimitry Andric     case A2_and:
147*0b57cec5SDimitry Andric     case A2_andp:
148*0b57cec5SDimitry Andric       return C2_and;
149*0b57cec5SDimitry Andric     case A4_andn:
150*0b57cec5SDimitry Andric     case A4_andnp:
151*0b57cec5SDimitry Andric       return C2_andn;
152*0b57cec5SDimitry Andric     case M4_and_and:
153*0b57cec5SDimitry Andric       return C4_and_and;
154*0b57cec5SDimitry Andric     case M4_and_andn:
155*0b57cec5SDimitry Andric       return C4_and_andn;
156*0b57cec5SDimitry Andric     case M4_and_or:
157*0b57cec5SDimitry Andric       return C4_and_or;
158*0b57cec5SDimitry Andric 
159*0b57cec5SDimitry Andric     case A2_or:
160*0b57cec5SDimitry Andric     case A2_orp:
161*0b57cec5SDimitry Andric       return C2_or;
162*0b57cec5SDimitry Andric     case A4_orn:
163*0b57cec5SDimitry Andric     case A4_ornp:
164*0b57cec5SDimitry Andric       return C2_orn;
165*0b57cec5SDimitry Andric     case M4_or_and:
166*0b57cec5SDimitry Andric       return C4_or_and;
167*0b57cec5SDimitry Andric     case M4_or_andn:
168*0b57cec5SDimitry Andric       return C4_or_andn;
169*0b57cec5SDimitry Andric     case M4_or_or:
170*0b57cec5SDimitry Andric       return C4_or_or;
171*0b57cec5SDimitry Andric 
172*0b57cec5SDimitry Andric     case A2_xor:
173*0b57cec5SDimitry Andric     case A2_xorp:
174*0b57cec5SDimitry Andric       return C2_xor;
175*0b57cec5SDimitry Andric 
176*0b57cec5SDimitry Andric     case C2_tfrrp:
177*0b57cec5SDimitry Andric       return COPY;
178*0b57cec5SDimitry Andric   }
179*0b57cec5SDimitry Andric   // The opcode corresponding to 0 is TargetOpcode::PHI. We can use 0 here
180*0b57cec5SDimitry Andric   // to denote "none", but we need to make sure that none of the valid opcodes
181*0b57cec5SDimitry Andric   // that we return will ever be 0.
182*0b57cec5SDimitry Andric   static_assert(PHI == 0, "Use different value for <none>");
183*0b57cec5SDimitry Andric   return 0;
184*0b57cec5SDimitry Andric }
185*0b57cec5SDimitry Andric 
186*0b57cec5SDimitry Andric bool HexagonGenPredicate::isConvertibleToPredForm(const MachineInstr *MI) {
187*0b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
188*0b57cec5SDimitry Andric   if (getPredForm(Opc) != 0)
189*0b57cec5SDimitry Andric     return true;
190*0b57cec5SDimitry Andric 
191*0b57cec5SDimitry Andric   // Comparisons against 0 are also convertible. This does not apply to
192*0b57cec5SDimitry Andric   // A4_rcmpeqi or A4_rcmpneqi, since they produce values 0 or 1, which
193*0b57cec5SDimitry Andric   // may not match the value that the predicate register would have if
194*0b57cec5SDimitry Andric   // it was converted to a predicate form.
195*0b57cec5SDimitry Andric   switch (Opc) {
196*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
197*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:
198*0b57cec5SDimitry Andric       if (MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0)
199*0b57cec5SDimitry Andric         return true;
200*0b57cec5SDimitry Andric       break;
201*0b57cec5SDimitry Andric   }
202*0b57cec5SDimitry Andric   return false;
203*0b57cec5SDimitry Andric }
204*0b57cec5SDimitry Andric 
205*0b57cec5SDimitry Andric void HexagonGenPredicate::collectPredicateGPR(MachineFunction &MF) {
206*0b57cec5SDimitry Andric   for (MachineFunction::iterator A = MF.begin(), Z = MF.end(); A != Z; ++A) {
207*0b57cec5SDimitry Andric     MachineBasicBlock &B = *A;
208*0b57cec5SDimitry Andric     for (MachineBasicBlock::iterator I = B.begin(), E = B.end(); I != E; ++I) {
209*0b57cec5SDimitry Andric       MachineInstr *MI = &*I;
210*0b57cec5SDimitry Andric       unsigned Opc = MI->getOpcode();
211*0b57cec5SDimitry Andric       switch (Opc) {
212*0b57cec5SDimitry Andric         case Hexagon::C2_tfrpr:
213*0b57cec5SDimitry Andric         case TargetOpcode::COPY:
214*0b57cec5SDimitry Andric           if (isPredReg(MI->getOperand(1).getReg())) {
215*0b57cec5SDimitry Andric             RegisterSubReg RD = MI->getOperand(0);
216*0b57cec5SDimitry Andric             if (TargetRegisterInfo::isVirtualRegister(RD.R))
217*0b57cec5SDimitry Andric               PredGPRs.insert(RD);
218*0b57cec5SDimitry Andric           }
219*0b57cec5SDimitry Andric           break;
220*0b57cec5SDimitry Andric       }
221*0b57cec5SDimitry Andric     }
222*0b57cec5SDimitry Andric   }
223*0b57cec5SDimitry Andric }
224*0b57cec5SDimitry Andric 
225*0b57cec5SDimitry Andric void HexagonGenPredicate::processPredicateGPR(const RegisterSubReg &Reg) {
226*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << ": " << printReg(Reg.R, TRI, Reg.S) << "\n");
227*0b57cec5SDimitry Andric   using use_iterator = MachineRegisterInfo::use_iterator;
228*0b57cec5SDimitry Andric 
229*0b57cec5SDimitry Andric   use_iterator I = MRI->use_begin(Reg.R), E = MRI->use_end();
230*0b57cec5SDimitry Andric   if (I == E) {
231*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Dead reg: " << printReg(Reg.R, TRI, Reg.S) << '\n');
232*0b57cec5SDimitry Andric     MachineInstr *DefI = MRI->getVRegDef(Reg.R);
233*0b57cec5SDimitry Andric     DefI->eraseFromParent();
234*0b57cec5SDimitry Andric     return;
235*0b57cec5SDimitry Andric   }
236*0b57cec5SDimitry Andric 
237*0b57cec5SDimitry Andric   for (; I != E; ++I) {
238*0b57cec5SDimitry Andric     MachineInstr *UseI = I->getParent();
239*0b57cec5SDimitry Andric     if (isConvertibleToPredForm(UseI))
240*0b57cec5SDimitry Andric       PUsers.insert(UseI);
241*0b57cec5SDimitry Andric   }
242*0b57cec5SDimitry Andric }
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric RegisterSubReg HexagonGenPredicate::getPredRegFor(const RegisterSubReg &Reg) {
245*0b57cec5SDimitry Andric   // Create a predicate register for a given Reg. The newly created register
246*0b57cec5SDimitry Andric   // will have its value copied from Reg, so that it can be later used as
247*0b57cec5SDimitry Andric   // an operand in other instructions.
248*0b57cec5SDimitry Andric   assert(TargetRegisterInfo::isVirtualRegister(Reg.R));
249*0b57cec5SDimitry Andric   RegToRegMap::iterator F = G2P.find(Reg);
250*0b57cec5SDimitry Andric   if (F != G2P.end())
251*0b57cec5SDimitry Andric     return F->second;
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << ": " << PrintRegister(Reg, *TRI));
254*0b57cec5SDimitry Andric   MachineInstr *DefI = MRI->getVRegDef(Reg.R);
255*0b57cec5SDimitry Andric   assert(DefI);
256*0b57cec5SDimitry Andric   unsigned Opc = DefI->getOpcode();
257*0b57cec5SDimitry Andric   if (Opc == Hexagon::C2_tfrpr || Opc == TargetOpcode::COPY) {
258*0b57cec5SDimitry Andric     assert(DefI->getOperand(0).isDef() && DefI->getOperand(1).isUse());
259*0b57cec5SDimitry Andric     RegisterSubReg PR = DefI->getOperand(1);
260*0b57cec5SDimitry Andric     G2P.insert(std::make_pair(Reg, PR));
261*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " -> " << PrintRegister(PR, *TRI) << '\n');
262*0b57cec5SDimitry Andric     return PR;
263*0b57cec5SDimitry Andric   }
264*0b57cec5SDimitry Andric 
265*0b57cec5SDimitry Andric   MachineBasicBlock &B = *DefI->getParent();
266*0b57cec5SDimitry Andric   DebugLoc DL = DefI->getDebugLoc();
267*0b57cec5SDimitry Andric   const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
268*0b57cec5SDimitry Andric   unsigned NewPR = MRI->createVirtualRegister(PredRC);
269*0b57cec5SDimitry Andric 
270*0b57cec5SDimitry Andric   // For convertible instructions, do not modify them, so that they can
271*0b57cec5SDimitry Andric   // be converted later.  Generate a copy from Reg to NewPR.
272*0b57cec5SDimitry Andric   if (isConvertibleToPredForm(DefI)) {
273*0b57cec5SDimitry Andric     MachineBasicBlock::iterator DefIt = DefI;
274*0b57cec5SDimitry Andric     BuildMI(B, std::next(DefIt), DL, TII->get(TargetOpcode::COPY), NewPR)
275*0b57cec5SDimitry Andric       .addReg(Reg.R, 0, Reg.S);
276*0b57cec5SDimitry Andric     G2P.insert(std::make_pair(Reg, RegisterSubReg(NewPR)));
277*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " -> !" << PrintRegister(RegisterSubReg(NewPR), *TRI)
278*0b57cec5SDimitry Andric                       << '\n');
279*0b57cec5SDimitry Andric     return RegisterSubReg(NewPR);
280*0b57cec5SDimitry Andric   }
281*0b57cec5SDimitry Andric 
282*0b57cec5SDimitry Andric   llvm_unreachable("Invalid argument");
283*0b57cec5SDimitry Andric }
284*0b57cec5SDimitry Andric 
285*0b57cec5SDimitry Andric bool HexagonGenPredicate::isScalarCmp(unsigned Opc) {
286*0b57cec5SDimitry Andric   switch (Opc) {
287*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeq:
288*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgt:
289*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtu:
290*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqp:
291*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtp:
292*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtup:
293*0b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
294*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:
295*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:
296*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgei:
297*0b57cec5SDimitry Andric     case Hexagon::C2_cmpgeui:
298*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:
299*0b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:
300*0b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:
301*0b57cec5SDimitry Andric     case Hexagon::C4_cmpneq:
302*0b57cec5SDimitry Andric     case Hexagon::C4_cmplte:
303*0b57cec5SDimitry Andric     case Hexagon::C4_cmplteu:
304*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbeq:
305*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:
306*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtu:
307*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:
308*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgt:
309*0b57cec5SDimitry Andric     case Hexagon::A4_cmpbgti:
310*0b57cec5SDimitry Andric     case Hexagon::A4_cmpheq:
311*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgt:
312*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgtu:
313*0b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:
314*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgti:
315*0b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:
316*0b57cec5SDimitry Andric       return true;
317*0b57cec5SDimitry Andric   }
318*0b57cec5SDimitry Andric   return false;
319*0b57cec5SDimitry Andric }
320*0b57cec5SDimitry Andric 
321*0b57cec5SDimitry Andric bool HexagonGenPredicate::isScalarPred(RegisterSubReg PredReg) {
322*0b57cec5SDimitry Andric   std::queue<RegisterSubReg> WorkQ;
323*0b57cec5SDimitry Andric   WorkQ.push(PredReg);
324*0b57cec5SDimitry Andric 
325*0b57cec5SDimitry Andric   while (!WorkQ.empty()) {
326*0b57cec5SDimitry Andric     RegisterSubReg PR = WorkQ.front();
327*0b57cec5SDimitry Andric     WorkQ.pop();
328*0b57cec5SDimitry Andric     const MachineInstr *DefI = MRI->getVRegDef(PR.R);
329*0b57cec5SDimitry Andric     if (!DefI)
330*0b57cec5SDimitry Andric       return false;
331*0b57cec5SDimitry Andric     unsigned DefOpc = DefI->getOpcode();
332*0b57cec5SDimitry Andric     switch (DefOpc) {
333*0b57cec5SDimitry Andric       case TargetOpcode::COPY: {
334*0b57cec5SDimitry Andric         const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
335*0b57cec5SDimitry Andric         if (MRI->getRegClass(PR.R) != PredRC)
336*0b57cec5SDimitry Andric           return false;
337*0b57cec5SDimitry Andric         // If it is a copy between two predicate registers, fall through.
338*0b57cec5SDimitry Andric         LLVM_FALLTHROUGH;
339*0b57cec5SDimitry Andric       }
340*0b57cec5SDimitry Andric       case Hexagon::C2_and:
341*0b57cec5SDimitry Andric       case Hexagon::C2_andn:
342*0b57cec5SDimitry Andric       case Hexagon::C4_and_and:
343*0b57cec5SDimitry Andric       case Hexagon::C4_and_andn:
344*0b57cec5SDimitry Andric       case Hexagon::C4_and_or:
345*0b57cec5SDimitry Andric       case Hexagon::C2_or:
346*0b57cec5SDimitry Andric       case Hexagon::C2_orn:
347*0b57cec5SDimitry Andric       case Hexagon::C4_or_and:
348*0b57cec5SDimitry Andric       case Hexagon::C4_or_andn:
349*0b57cec5SDimitry Andric       case Hexagon::C4_or_or:
350*0b57cec5SDimitry Andric       case Hexagon::C4_or_orn:
351*0b57cec5SDimitry Andric       case Hexagon::C2_xor:
352*0b57cec5SDimitry Andric         // Add operands to the queue.
353*0b57cec5SDimitry Andric         for (const MachineOperand &MO : DefI->operands())
354*0b57cec5SDimitry Andric           if (MO.isReg() && MO.isUse())
355*0b57cec5SDimitry Andric             WorkQ.push(RegisterSubReg(MO.getReg()));
356*0b57cec5SDimitry Andric         break;
357*0b57cec5SDimitry Andric 
358*0b57cec5SDimitry Andric       // All non-vector compares are ok, everything else is bad.
359*0b57cec5SDimitry Andric       default:
360*0b57cec5SDimitry Andric         return isScalarCmp(DefOpc);
361*0b57cec5SDimitry Andric     }
362*0b57cec5SDimitry Andric   }
363*0b57cec5SDimitry Andric 
364*0b57cec5SDimitry Andric   return true;
365*0b57cec5SDimitry Andric }
366*0b57cec5SDimitry Andric 
367*0b57cec5SDimitry Andric bool HexagonGenPredicate::convertToPredForm(MachineInstr *MI) {
368*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << ": " << MI << " " << *MI);
369*0b57cec5SDimitry Andric 
370*0b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
371*0b57cec5SDimitry Andric   assert(isConvertibleToPredForm(MI));
372*0b57cec5SDimitry Andric   unsigned NumOps = MI->getNumOperands();
373*0b57cec5SDimitry Andric   for (unsigned i = 0; i < NumOps; ++i) {
374*0b57cec5SDimitry Andric     MachineOperand &MO = MI->getOperand(i);
375*0b57cec5SDimitry Andric     if (!MO.isReg() || !MO.isUse())
376*0b57cec5SDimitry Andric       continue;
377*0b57cec5SDimitry Andric     RegisterSubReg Reg(MO);
378*0b57cec5SDimitry Andric     if (Reg.S && Reg.S != Hexagon::isub_lo)
379*0b57cec5SDimitry Andric       return false;
380*0b57cec5SDimitry Andric     if (!PredGPRs.count(Reg))
381*0b57cec5SDimitry Andric       return false;
382*0b57cec5SDimitry Andric   }
383*0b57cec5SDimitry Andric 
384*0b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
385*0b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
386*0b57cec5SDimitry Andric 
387*0b57cec5SDimitry Andric   unsigned NewOpc = getPredForm(Opc);
388*0b57cec5SDimitry Andric   // Special case for comparisons against 0.
389*0b57cec5SDimitry Andric   if (NewOpc == 0) {
390*0b57cec5SDimitry Andric     switch (Opc) {
391*0b57cec5SDimitry Andric       case Hexagon::C2_cmpeqi:
392*0b57cec5SDimitry Andric         NewOpc = Hexagon::C2_not;
393*0b57cec5SDimitry Andric         break;
394*0b57cec5SDimitry Andric       case Hexagon::C4_cmpneqi:
395*0b57cec5SDimitry Andric         NewOpc = TargetOpcode::COPY;
396*0b57cec5SDimitry Andric         break;
397*0b57cec5SDimitry Andric       default:
398*0b57cec5SDimitry Andric         return false;
399*0b57cec5SDimitry Andric     }
400*0b57cec5SDimitry Andric 
401*0b57cec5SDimitry Andric     // If it's a scalar predicate register, then all bits in it are
402*0b57cec5SDimitry Andric     // the same. Otherwise, to determine whether all bits are 0 or not
403*0b57cec5SDimitry Andric     // we would need to use any8.
404*0b57cec5SDimitry Andric     RegisterSubReg PR = getPredRegFor(MI->getOperand(1));
405*0b57cec5SDimitry Andric     if (!isScalarPred(PR))
406*0b57cec5SDimitry Andric       return false;
407*0b57cec5SDimitry Andric     // This will skip the immediate argument when creating the predicate
408*0b57cec5SDimitry Andric     // version instruction.
409*0b57cec5SDimitry Andric     NumOps = 2;
410*0b57cec5SDimitry Andric   }
411*0b57cec5SDimitry Andric 
412*0b57cec5SDimitry Andric   // Some sanity: check that def is in operand #0.
413*0b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
414*0b57cec5SDimitry Andric   assert(Op0.isDef());
415*0b57cec5SDimitry Andric   RegisterSubReg OutR(Op0);
416*0b57cec5SDimitry Andric 
417*0b57cec5SDimitry Andric   // Don't use getPredRegFor, since it will create an association between
418*0b57cec5SDimitry Andric   // the argument and a created predicate register (i.e. it will insert a
419*0b57cec5SDimitry Andric   // copy if a new predicate register is created).
420*0b57cec5SDimitry Andric   const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
421*0b57cec5SDimitry Andric   RegisterSubReg NewPR = MRI->createVirtualRegister(PredRC);
422*0b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(B, MI, DL, TII->get(NewOpc), NewPR.R);
423*0b57cec5SDimitry Andric 
424*0b57cec5SDimitry Andric   // Add predicate counterparts of the GPRs.
425*0b57cec5SDimitry Andric   for (unsigned i = 1; i < NumOps; ++i) {
426*0b57cec5SDimitry Andric     RegisterSubReg GPR = MI->getOperand(i);
427*0b57cec5SDimitry Andric     RegisterSubReg Pred = getPredRegFor(GPR);
428*0b57cec5SDimitry Andric     MIB.addReg(Pred.R, 0, Pred.S);
429*0b57cec5SDimitry Andric   }
430*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "generated: " << *MIB);
431*0b57cec5SDimitry Andric 
432*0b57cec5SDimitry Andric   // Generate a copy-out: NewGPR = NewPR, and replace all uses of OutR
433*0b57cec5SDimitry Andric   // with NewGPR.
434*0b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(OutR.R);
435*0b57cec5SDimitry Andric   unsigned NewOutR = MRI->createVirtualRegister(RC);
436*0b57cec5SDimitry Andric   BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), NewOutR)
437*0b57cec5SDimitry Andric     .addReg(NewPR.R, 0, NewPR.S);
438*0b57cec5SDimitry Andric   MRI->replaceRegWith(OutR.R, NewOutR);
439*0b57cec5SDimitry Andric   MI->eraseFromParent();
440*0b57cec5SDimitry Andric 
441*0b57cec5SDimitry Andric   // If the processed instruction was C2_tfrrp (i.e. Rn = Pm; Pk = Rn),
442*0b57cec5SDimitry Andric   // then the output will be a predicate register.  Do not visit the
443*0b57cec5SDimitry Andric   // users of it.
444*0b57cec5SDimitry Andric   if (!isPredReg(NewOutR)) {
445*0b57cec5SDimitry Andric     RegisterSubReg R(NewOutR);
446*0b57cec5SDimitry Andric     PredGPRs.insert(R);
447*0b57cec5SDimitry Andric     processPredicateGPR(R);
448*0b57cec5SDimitry Andric   }
449*0b57cec5SDimitry Andric   return true;
450*0b57cec5SDimitry Andric }
451*0b57cec5SDimitry Andric 
452*0b57cec5SDimitry Andric bool HexagonGenPredicate::eliminatePredCopies(MachineFunction &MF) {
453*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << "\n");
454*0b57cec5SDimitry Andric   const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
455*0b57cec5SDimitry Andric   bool Changed = false;
456*0b57cec5SDimitry Andric   VectOfInst Erase;
457*0b57cec5SDimitry Andric 
458*0b57cec5SDimitry Andric   // First, replace copies
459*0b57cec5SDimitry Andric   //   IntR = PredR1
460*0b57cec5SDimitry Andric   //   PredR2 = IntR
461*0b57cec5SDimitry Andric   // with
462*0b57cec5SDimitry Andric   //   PredR2 = PredR1
463*0b57cec5SDimitry Andric   // Such sequences can be generated when a copy-into-pred is generated from
464*0b57cec5SDimitry Andric   // a gpr register holding a result of a convertible instruction. After
465*0b57cec5SDimitry Andric   // the convertible instruction is converted, its predicate result will be
466*0b57cec5SDimitry Andric   // copied back into the original gpr.
467*0b57cec5SDimitry Andric 
468*0b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
469*0b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
470*0b57cec5SDimitry Andric       if (MI.getOpcode() != TargetOpcode::COPY)
471*0b57cec5SDimitry Andric         continue;
472*0b57cec5SDimitry Andric       RegisterSubReg DR = MI.getOperand(0);
473*0b57cec5SDimitry Andric       RegisterSubReg SR = MI.getOperand(1);
474*0b57cec5SDimitry Andric       if (!TargetRegisterInfo::isVirtualRegister(DR.R))
475*0b57cec5SDimitry Andric         continue;
476*0b57cec5SDimitry Andric       if (!TargetRegisterInfo::isVirtualRegister(SR.R))
477*0b57cec5SDimitry Andric         continue;
478*0b57cec5SDimitry Andric       if (MRI->getRegClass(DR.R) != PredRC)
479*0b57cec5SDimitry Andric         continue;
480*0b57cec5SDimitry Andric       if (MRI->getRegClass(SR.R) != PredRC)
481*0b57cec5SDimitry Andric         continue;
482*0b57cec5SDimitry Andric       assert(!DR.S && !SR.S && "Unexpected subregister");
483*0b57cec5SDimitry Andric       MRI->replaceRegWith(DR.R, SR.R);
484*0b57cec5SDimitry Andric       Erase.insert(&MI);
485*0b57cec5SDimitry Andric       Changed = true;
486*0b57cec5SDimitry Andric     }
487*0b57cec5SDimitry Andric   }
488*0b57cec5SDimitry Andric 
489*0b57cec5SDimitry Andric   for (VectOfInst::iterator I = Erase.begin(), E = Erase.end(); I != E; ++I)
490*0b57cec5SDimitry Andric     (*I)->eraseFromParent();
491*0b57cec5SDimitry Andric 
492*0b57cec5SDimitry Andric   return Changed;
493*0b57cec5SDimitry Andric }
494*0b57cec5SDimitry Andric 
495*0b57cec5SDimitry Andric bool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {
496*0b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
497*0b57cec5SDimitry Andric     return false;
498*0b57cec5SDimitry Andric 
499*0b57cec5SDimitry Andric   TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
500*0b57cec5SDimitry Andric   TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
501*0b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
502*0b57cec5SDimitry Andric   PredGPRs.clear();
503*0b57cec5SDimitry Andric   PUsers.clear();
504*0b57cec5SDimitry Andric   G2P.clear();
505*0b57cec5SDimitry Andric 
506*0b57cec5SDimitry Andric   bool Changed = false;
507*0b57cec5SDimitry Andric   collectPredicateGPR(MF);
508*0b57cec5SDimitry Andric   for (SetOfReg::iterator I = PredGPRs.begin(), E = PredGPRs.end(); I != E; ++I)
509*0b57cec5SDimitry Andric     processPredicateGPR(*I);
510*0b57cec5SDimitry Andric 
511*0b57cec5SDimitry Andric   bool Again;
512*0b57cec5SDimitry Andric   do {
513*0b57cec5SDimitry Andric     Again = false;
514*0b57cec5SDimitry Andric     VectOfInst Processed, Copy;
515*0b57cec5SDimitry Andric 
516*0b57cec5SDimitry Andric     using iterator = VectOfInst::iterator;
517*0b57cec5SDimitry Andric 
518*0b57cec5SDimitry Andric     Copy = PUsers;
519*0b57cec5SDimitry Andric     for (iterator I = Copy.begin(), E = Copy.end(); I != E; ++I) {
520*0b57cec5SDimitry Andric       MachineInstr *MI = *I;
521*0b57cec5SDimitry Andric       bool Done = convertToPredForm(MI);
522*0b57cec5SDimitry Andric       if (Done) {
523*0b57cec5SDimitry Andric         Processed.insert(MI);
524*0b57cec5SDimitry Andric         Again = true;
525*0b57cec5SDimitry Andric       }
526*0b57cec5SDimitry Andric     }
527*0b57cec5SDimitry Andric     Changed |= Again;
528*0b57cec5SDimitry Andric 
529*0b57cec5SDimitry Andric     auto Done = [Processed] (MachineInstr *MI) -> bool {
530*0b57cec5SDimitry Andric       return Processed.count(MI);
531*0b57cec5SDimitry Andric     };
532*0b57cec5SDimitry Andric     PUsers.remove_if(Done);
533*0b57cec5SDimitry Andric   } while (Again);
534*0b57cec5SDimitry Andric 
535*0b57cec5SDimitry Andric   Changed |= eliminatePredCopies(MF);
536*0b57cec5SDimitry Andric   return Changed;
537*0b57cec5SDimitry Andric }
538*0b57cec5SDimitry Andric 
539*0b57cec5SDimitry Andric FunctionPass *llvm::createHexagonGenPredicate() {
540*0b57cec5SDimitry Andric   return new HexagonGenPredicate();
541*0b57cec5SDimitry Andric }
542