xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonGenPredicate.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- HexagonGenPredicate.cpp --------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "HexagonInstrInfo.h"
100b57cec5SDimitry Andric #include "HexagonSubtarget.h"
110b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
23480093f4SDimitry Andric #include "llvm/InitializePasses.h"
240b57cec5SDimitry Andric #include "llvm/Pass.h"
250b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
260b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <iterator>
310b57cec5SDimitry Andric #include <map>
320b57cec5SDimitry Andric #include <queue>
330b57cec5SDimitry Andric #include <set>
340b57cec5SDimitry Andric #include <utility>
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #define DEBUG_TYPE "gen-pred"
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric namespace llvm {
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   void initializeHexagonGenPredicatePass(PassRegistry& Registry);
430b57cec5SDimitry Andric   FunctionPass *createHexagonGenPredicate();
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric } // end namespace llvm
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric namespace {
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   // FIXME: Use TargetInstrInfo::RegSubRegPair
500b57cec5SDimitry Andric   struct RegisterSubReg {
51e8d8bef9SDimitry Andric     Register R;
52e8d8bef9SDimitry Andric     unsigned S;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric     RegisterSubReg(unsigned r = 0, unsigned s = 0) : R(r), S(s) {}
550b57cec5SDimitry Andric     RegisterSubReg(const MachineOperand &MO) : R(MO.getReg()), S(MO.getSubReg()) {}
560b57cec5SDimitry Andric     RegisterSubReg(const Register &Reg) : R(Reg), S(0) {}
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric     bool operator== (const RegisterSubReg &Reg) const {
590b57cec5SDimitry Andric       return R == Reg.R && S == Reg.S;
600b57cec5SDimitry Andric     }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric     bool operator< (const RegisterSubReg &Reg) const {
630b57cec5SDimitry Andric       return R < Reg.R || (R == Reg.R && S < Reg.S);
640b57cec5SDimitry Andric     }
650b57cec5SDimitry Andric   };
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   struct PrintRegister {
680b57cec5SDimitry Andric     friend raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric     PrintRegister(RegisterSubReg R, const TargetRegisterInfo &I) : Reg(R), TRI(I) {}
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   private:
730b57cec5SDimitry Andric     RegisterSubReg Reg;
740b57cec5SDimitry Andric     const TargetRegisterInfo &TRI;
750b57cec5SDimitry Andric   };
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR)
780b57cec5SDimitry Andric     LLVM_ATTRIBUTE_UNUSED;
790b57cec5SDimitry Andric   raw_ostream &operator<< (raw_ostream &OS, const PrintRegister &PR) {
800b57cec5SDimitry Andric     return OS << printReg(PR.Reg.R, &PR.TRI, PR.Reg.S);
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   class HexagonGenPredicate : public MachineFunctionPass {
840b57cec5SDimitry Andric   public:
850b57cec5SDimitry Andric     static char ID;
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric     HexagonGenPredicate() : MachineFunctionPass(ID) {
880b57cec5SDimitry Andric       initializeHexagonGenPredicatePass(*PassRegistry::getPassRegistry());
890b57cec5SDimitry Andric     }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     StringRef getPassName() const override {
920b57cec5SDimitry Andric       return "Hexagon generate predicate operations";
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
96*0fca6ea1SDimitry Andric       AU.addRequired<MachineDominatorTreeWrapperPass>();
97*0fca6ea1SDimitry Andric       AU.addPreserved<MachineDominatorTreeWrapperPass>();
980b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
990b57cec5SDimitry Andric     }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   private:
1040b57cec5SDimitry Andric     using VectOfInst = SetVector<MachineInstr *>;
1050b57cec5SDimitry Andric     using SetOfReg = std::set<RegisterSubReg>;
1060b57cec5SDimitry Andric     using RegToRegMap = std::map<RegisterSubReg, RegisterSubReg>;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric     const HexagonInstrInfo *TII = nullptr;
1090b57cec5SDimitry Andric     const HexagonRegisterInfo *TRI = nullptr;
1100b57cec5SDimitry Andric     MachineRegisterInfo *MRI = nullptr;
1110b57cec5SDimitry Andric     SetOfReg PredGPRs;
1120b57cec5SDimitry Andric     VectOfInst PUsers;
1130b57cec5SDimitry Andric     RegToRegMap G2P;
1140b57cec5SDimitry Andric 
115e8d8bef9SDimitry Andric     bool isPredReg(Register R);
1160b57cec5SDimitry Andric     void collectPredicateGPR(MachineFunction &MF);
1170b57cec5SDimitry Andric     void processPredicateGPR(const RegisterSubReg &Reg);
1180b57cec5SDimitry Andric     unsigned getPredForm(unsigned Opc);
1190b57cec5SDimitry Andric     bool isConvertibleToPredForm(const MachineInstr *MI);
1200b57cec5SDimitry Andric     bool isScalarCmp(unsigned Opc);
1210b57cec5SDimitry Andric     bool isScalarPred(RegisterSubReg PredReg);
1220b57cec5SDimitry Andric     RegisterSubReg getPredRegFor(const RegisterSubReg &Reg);
1230b57cec5SDimitry Andric     bool convertToPredForm(MachineInstr *MI);
1240b57cec5SDimitry Andric     bool eliminatePredCopies(MachineFunction &MF);
1250b57cec5SDimitry Andric   };
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric } // end anonymous namespace
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric char HexagonGenPredicate::ID = 0;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonGenPredicate, "hexagon-gen-pred",
1320b57cec5SDimitry Andric   "Hexagon generate predicate operations", false, false)
133*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
1340b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonGenPredicate, "hexagon-gen-pred",
1350b57cec5SDimitry Andric   "Hexagon generate predicate operations", false, false)
1360b57cec5SDimitry Andric 
137e8d8bef9SDimitry Andric bool HexagonGenPredicate::isPredReg(Register R) {
138e8d8bef9SDimitry Andric   if (!R.isVirtual())
1390b57cec5SDimitry Andric     return false;
1400b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(R);
1410b57cec5SDimitry Andric   return RC == &Hexagon::PredRegsRegClass;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric unsigned HexagonGenPredicate::getPredForm(unsigned Opc) {
1450b57cec5SDimitry Andric   using namespace Hexagon;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   switch (Opc) {
1480b57cec5SDimitry Andric     case A2_and:
1490b57cec5SDimitry Andric     case A2_andp:
1500b57cec5SDimitry Andric       return C2_and;
1510b57cec5SDimitry Andric     case A4_andn:
1520b57cec5SDimitry Andric     case A4_andnp:
1530b57cec5SDimitry Andric       return C2_andn;
1540b57cec5SDimitry Andric     case M4_and_and:
1550b57cec5SDimitry Andric       return C4_and_and;
1560b57cec5SDimitry Andric     case M4_and_andn:
1570b57cec5SDimitry Andric       return C4_and_andn;
1580b57cec5SDimitry Andric     case M4_and_or:
1590b57cec5SDimitry Andric       return C4_and_or;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric     case A2_or:
1620b57cec5SDimitry Andric     case A2_orp:
1630b57cec5SDimitry Andric       return C2_or;
1640b57cec5SDimitry Andric     case A4_orn:
1650b57cec5SDimitry Andric     case A4_ornp:
1660b57cec5SDimitry Andric       return C2_orn;
1670b57cec5SDimitry Andric     case M4_or_and:
1680b57cec5SDimitry Andric       return C4_or_and;
1690b57cec5SDimitry Andric     case M4_or_andn:
1700b57cec5SDimitry Andric       return C4_or_andn;
1710b57cec5SDimitry Andric     case M4_or_or:
1720b57cec5SDimitry Andric       return C4_or_or;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     case A2_xor:
1750b57cec5SDimitry Andric     case A2_xorp:
1760b57cec5SDimitry Andric       return C2_xor;
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric     case C2_tfrrp:
1790b57cec5SDimitry Andric       return COPY;
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric   // The opcode corresponding to 0 is TargetOpcode::PHI. We can use 0 here
1820b57cec5SDimitry Andric   // to denote "none", but we need to make sure that none of the valid opcodes
1830b57cec5SDimitry Andric   // that we return will ever be 0.
1840b57cec5SDimitry Andric   static_assert(PHI == 0, "Use different value for <none>");
1850b57cec5SDimitry Andric   return 0;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric bool HexagonGenPredicate::isConvertibleToPredForm(const MachineInstr *MI) {
1890b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
1900b57cec5SDimitry Andric   if (getPredForm(Opc) != 0)
1910b57cec5SDimitry Andric     return true;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // Comparisons against 0 are also convertible. This does not apply to
1940b57cec5SDimitry Andric   // A4_rcmpeqi or A4_rcmpneqi, since they produce values 0 or 1, which
1950b57cec5SDimitry Andric   // may not match the value that the predicate register would have if
1960b57cec5SDimitry Andric   // it was converted to a predicate form.
1970b57cec5SDimitry Andric   switch (Opc) {
1980b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
1990b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:
2000b57cec5SDimitry Andric       if (MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0)
2010b57cec5SDimitry Andric         return true;
2020b57cec5SDimitry Andric       break;
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric   return false;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric void HexagonGenPredicate::collectPredicateGPR(MachineFunction &MF) {
2084824e7fdSDimitry Andric   for (MachineBasicBlock &B : MF) {
2094824e7fdSDimitry Andric     for (MachineInstr &MI : B) {
2104824e7fdSDimitry Andric       unsigned Opc = MI.getOpcode();
2110b57cec5SDimitry Andric       switch (Opc) {
2120b57cec5SDimitry Andric         case Hexagon::C2_tfrpr:
2130b57cec5SDimitry Andric         case TargetOpcode::COPY:
2144824e7fdSDimitry Andric           if (isPredReg(MI.getOperand(1).getReg())) {
2154824e7fdSDimitry Andric             RegisterSubReg RD = MI.getOperand(0);
216e8d8bef9SDimitry Andric             if (RD.R.isVirtual())
2170b57cec5SDimitry Andric               PredGPRs.insert(RD);
2180b57cec5SDimitry Andric           }
2190b57cec5SDimitry Andric           break;
2200b57cec5SDimitry Andric       }
2210b57cec5SDimitry Andric     }
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric void HexagonGenPredicate::processPredicateGPR(const RegisterSubReg &Reg) {
2260b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << ": " << printReg(Reg.R, TRI, Reg.S) << "\n");
2270b57cec5SDimitry Andric   using use_iterator = MachineRegisterInfo::use_iterator;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   use_iterator I = MRI->use_begin(Reg.R), E = MRI->use_end();
2300b57cec5SDimitry Andric   if (I == E) {
2310b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Dead reg: " << printReg(Reg.R, TRI, Reg.S) << '\n');
2320b57cec5SDimitry Andric     MachineInstr *DefI = MRI->getVRegDef(Reg.R);
2330b57cec5SDimitry Andric     DefI->eraseFromParent();
2340b57cec5SDimitry Andric     return;
2350b57cec5SDimitry Andric   }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   for (; I != E; ++I) {
2380b57cec5SDimitry Andric     MachineInstr *UseI = I->getParent();
2390b57cec5SDimitry Andric     if (isConvertibleToPredForm(UseI))
2400b57cec5SDimitry Andric       PUsers.insert(UseI);
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric RegisterSubReg HexagonGenPredicate::getPredRegFor(const RegisterSubReg &Reg) {
2450b57cec5SDimitry Andric   // Create a predicate register for a given Reg. The newly created register
2460b57cec5SDimitry Andric   // will have its value copied from Reg, so that it can be later used as
2470b57cec5SDimitry Andric   // an operand in other instructions.
248e8d8bef9SDimitry Andric   assert(Reg.R.isVirtual());
2490b57cec5SDimitry Andric   RegToRegMap::iterator F = G2P.find(Reg);
2500b57cec5SDimitry Andric   if (F != G2P.end())
2510b57cec5SDimitry Andric     return F->second;
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << ": " << PrintRegister(Reg, *TRI));
2540b57cec5SDimitry Andric   MachineInstr *DefI = MRI->getVRegDef(Reg.R);
2550b57cec5SDimitry Andric   assert(DefI);
2560b57cec5SDimitry Andric   unsigned Opc = DefI->getOpcode();
2570b57cec5SDimitry Andric   if (Opc == Hexagon::C2_tfrpr || Opc == TargetOpcode::COPY) {
2580b57cec5SDimitry Andric     assert(DefI->getOperand(0).isDef() && DefI->getOperand(1).isUse());
2590b57cec5SDimitry Andric     RegisterSubReg PR = DefI->getOperand(1);
2600b57cec5SDimitry Andric     G2P.insert(std::make_pair(Reg, PR));
2610b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " -> " << PrintRegister(PR, *TRI) << '\n');
2620b57cec5SDimitry Andric     return PR;
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   MachineBasicBlock &B = *DefI->getParent();
2660b57cec5SDimitry Andric   DebugLoc DL = DefI->getDebugLoc();
2670b57cec5SDimitry Andric   const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
2688bcb0991SDimitry Andric   Register NewPR = MRI->createVirtualRegister(PredRC);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   // For convertible instructions, do not modify them, so that they can
2710b57cec5SDimitry Andric   // be converted later.  Generate a copy from Reg to NewPR.
2720b57cec5SDimitry Andric   if (isConvertibleToPredForm(DefI)) {
2730b57cec5SDimitry Andric     MachineBasicBlock::iterator DefIt = DefI;
2740b57cec5SDimitry Andric     BuildMI(B, std::next(DefIt), DL, TII->get(TargetOpcode::COPY), NewPR)
2750b57cec5SDimitry Andric       .addReg(Reg.R, 0, Reg.S);
2760b57cec5SDimitry Andric     G2P.insert(std::make_pair(Reg, RegisterSubReg(NewPR)));
2770b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << " -> !" << PrintRegister(RegisterSubReg(NewPR), *TRI)
2780b57cec5SDimitry Andric                       << '\n');
2790b57cec5SDimitry Andric     return RegisterSubReg(NewPR);
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   llvm_unreachable("Invalid argument");
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric bool HexagonGenPredicate::isScalarCmp(unsigned Opc) {
2860b57cec5SDimitry Andric   switch (Opc) {
2870b57cec5SDimitry Andric     case Hexagon::C2_cmpeq:
2880b57cec5SDimitry Andric     case Hexagon::C2_cmpgt:
2890b57cec5SDimitry Andric     case Hexagon::C2_cmpgtu:
2900b57cec5SDimitry Andric     case Hexagon::C2_cmpeqp:
2910b57cec5SDimitry Andric     case Hexagon::C2_cmpgtp:
2920b57cec5SDimitry Andric     case Hexagon::C2_cmpgtup:
2930b57cec5SDimitry Andric     case Hexagon::C2_cmpeqi:
2940b57cec5SDimitry Andric     case Hexagon::C2_cmpgti:
2950b57cec5SDimitry Andric     case Hexagon::C2_cmpgtui:
2960b57cec5SDimitry Andric     case Hexagon::C2_cmpgei:
2970b57cec5SDimitry Andric     case Hexagon::C2_cmpgeui:
2980b57cec5SDimitry Andric     case Hexagon::C4_cmpneqi:
2990b57cec5SDimitry Andric     case Hexagon::C4_cmpltei:
3000b57cec5SDimitry Andric     case Hexagon::C4_cmplteui:
3010b57cec5SDimitry Andric     case Hexagon::C4_cmpneq:
3020b57cec5SDimitry Andric     case Hexagon::C4_cmplte:
3030b57cec5SDimitry Andric     case Hexagon::C4_cmplteu:
3040b57cec5SDimitry Andric     case Hexagon::A4_cmpbeq:
3050b57cec5SDimitry Andric     case Hexagon::A4_cmpbeqi:
3060b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtu:
3070b57cec5SDimitry Andric     case Hexagon::A4_cmpbgtui:
3080b57cec5SDimitry Andric     case Hexagon::A4_cmpbgt:
3090b57cec5SDimitry Andric     case Hexagon::A4_cmpbgti:
3100b57cec5SDimitry Andric     case Hexagon::A4_cmpheq:
3110b57cec5SDimitry Andric     case Hexagon::A4_cmphgt:
3120b57cec5SDimitry Andric     case Hexagon::A4_cmphgtu:
3130b57cec5SDimitry Andric     case Hexagon::A4_cmpheqi:
3140b57cec5SDimitry Andric     case Hexagon::A4_cmphgti:
3150b57cec5SDimitry Andric     case Hexagon::A4_cmphgtui:
3160b57cec5SDimitry Andric       return true;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric   return false;
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric bool HexagonGenPredicate::isScalarPred(RegisterSubReg PredReg) {
3220b57cec5SDimitry Andric   std::queue<RegisterSubReg> WorkQ;
3230b57cec5SDimitry Andric   WorkQ.push(PredReg);
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   while (!WorkQ.empty()) {
3260b57cec5SDimitry Andric     RegisterSubReg PR = WorkQ.front();
3270b57cec5SDimitry Andric     WorkQ.pop();
3280b57cec5SDimitry Andric     const MachineInstr *DefI = MRI->getVRegDef(PR.R);
3290b57cec5SDimitry Andric     if (!DefI)
3300b57cec5SDimitry Andric       return false;
3310b57cec5SDimitry Andric     unsigned DefOpc = DefI->getOpcode();
3320b57cec5SDimitry Andric     switch (DefOpc) {
3330b57cec5SDimitry Andric       case TargetOpcode::COPY: {
3340b57cec5SDimitry Andric         const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
3350b57cec5SDimitry Andric         if (MRI->getRegClass(PR.R) != PredRC)
3360b57cec5SDimitry Andric           return false;
3370b57cec5SDimitry Andric         // If it is a copy between two predicate registers, fall through.
338bdd1243dSDimitry Andric         [[fallthrough]];
3390b57cec5SDimitry Andric       }
3400b57cec5SDimitry Andric       case Hexagon::C2_and:
3410b57cec5SDimitry Andric       case Hexagon::C2_andn:
3420b57cec5SDimitry Andric       case Hexagon::C4_and_and:
3430b57cec5SDimitry Andric       case Hexagon::C4_and_andn:
3440b57cec5SDimitry Andric       case Hexagon::C4_and_or:
3450b57cec5SDimitry Andric       case Hexagon::C2_or:
3460b57cec5SDimitry Andric       case Hexagon::C2_orn:
3470b57cec5SDimitry Andric       case Hexagon::C4_or_and:
3480b57cec5SDimitry Andric       case Hexagon::C4_or_andn:
3490b57cec5SDimitry Andric       case Hexagon::C4_or_or:
3500b57cec5SDimitry Andric       case Hexagon::C4_or_orn:
3510b57cec5SDimitry Andric       case Hexagon::C2_xor:
3520b57cec5SDimitry Andric         // Add operands to the queue.
3530b57cec5SDimitry Andric         for (const MachineOperand &MO : DefI->operands())
3540b57cec5SDimitry Andric           if (MO.isReg() && MO.isUse())
3550b57cec5SDimitry Andric             WorkQ.push(RegisterSubReg(MO.getReg()));
3560b57cec5SDimitry Andric         break;
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric       // All non-vector compares are ok, everything else is bad.
3590b57cec5SDimitry Andric       default:
3600b57cec5SDimitry Andric         return isScalarCmp(DefOpc);
3610b57cec5SDimitry Andric     }
3620b57cec5SDimitry Andric   }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   return true;
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric bool HexagonGenPredicate::convertToPredForm(MachineInstr *MI) {
3680b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << ": " << MI << " " << *MI);
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
3710b57cec5SDimitry Andric   assert(isConvertibleToPredForm(MI));
3720b57cec5SDimitry Andric   unsigned NumOps = MI->getNumOperands();
3730b57cec5SDimitry Andric   for (unsigned i = 0; i < NumOps; ++i) {
3740b57cec5SDimitry Andric     MachineOperand &MO = MI->getOperand(i);
3750b57cec5SDimitry Andric     if (!MO.isReg() || !MO.isUse())
3760b57cec5SDimitry Andric       continue;
3770b57cec5SDimitry Andric     RegisterSubReg Reg(MO);
3780b57cec5SDimitry Andric     if (Reg.S && Reg.S != Hexagon::isub_lo)
3790b57cec5SDimitry Andric       return false;
3800b57cec5SDimitry Andric     if (!PredGPRs.count(Reg))
3810b57cec5SDimitry Andric       return false;
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   MachineBasicBlock &B = *MI->getParent();
3850b57cec5SDimitry Andric   DebugLoc DL = MI->getDebugLoc();
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   unsigned NewOpc = getPredForm(Opc);
3880b57cec5SDimitry Andric   // Special case for comparisons against 0.
3890b57cec5SDimitry Andric   if (NewOpc == 0) {
3900b57cec5SDimitry Andric     switch (Opc) {
3910b57cec5SDimitry Andric       case Hexagon::C2_cmpeqi:
3920b57cec5SDimitry Andric         NewOpc = Hexagon::C2_not;
3930b57cec5SDimitry Andric         break;
3940b57cec5SDimitry Andric       case Hexagon::C4_cmpneqi:
3950b57cec5SDimitry Andric         NewOpc = TargetOpcode::COPY;
3960b57cec5SDimitry Andric         break;
3970b57cec5SDimitry Andric       default:
3980b57cec5SDimitry Andric         return false;
3990b57cec5SDimitry Andric     }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric     // If it's a scalar predicate register, then all bits in it are
4020b57cec5SDimitry Andric     // the same. Otherwise, to determine whether all bits are 0 or not
4030b57cec5SDimitry Andric     // we would need to use any8.
4040b57cec5SDimitry Andric     RegisterSubReg PR = getPredRegFor(MI->getOperand(1));
4050b57cec5SDimitry Andric     if (!isScalarPred(PR))
4060b57cec5SDimitry Andric       return false;
4070b57cec5SDimitry Andric     // This will skip the immediate argument when creating the predicate
4080b57cec5SDimitry Andric     // version instruction.
4090b57cec5SDimitry Andric     NumOps = 2;
4100b57cec5SDimitry Andric   }
4110b57cec5SDimitry Andric 
4124824e7fdSDimitry Andric   // Check that def is in operand #0.
4130b57cec5SDimitry Andric   MachineOperand &Op0 = MI->getOperand(0);
4140b57cec5SDimitry Andric   assert(Op0.isDef());
4150b57cec5SDimitry Andric   RegisterSubReg OutR(Op0);
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   // Don't use getPredRegFor, since it will create an association between
4180b57cec5SDimitry Andric   // the argument and a created predicate register (i.e. it will insert a
4190b57cec5SDimitry Andric   // copy if a new predicate register is created).
4200b57cec5SDimitry Andric   const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
4210b57cec5SDimitry Andric   RegisterSubReg NewPR = MRI->createVirtualRegister(PredRC);
4220b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(B, MI, DL, TII->get(NewOpc), NewPR.R);
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   // Add predicate counterparts of the GPRs.
4250b57cec5SDimitry Andric   for (unsigned i = 1; i < NumOps; ++i) {
4260b57cec5SDimitry Andric     RegisterSubReg GPR = MI->getOperand(i);
4270b57cec5SDimitry Andric     RegisterSubReg Pred = getPredRegFor(GPR);
4280b57cec5SDimitry Andric     MIB.addReg(Pred.R, 0, Pred.S);
4290b57cec5SDimitry Andric   }
4300b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "generated: " << *MIB);
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   // Generate a copy-out: NewGPR = NewPR, and replace all uses of OutR
4330b57cec5SDimitry Andric   // with NewGPR.
4340b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI->getRegClass(OutR.R);
4358bcb0991SDimitry Andric   Register NewOutR = MRI->createVirtualRegister(RC);
4360b57cec5SDimitry Andric   BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), NewOutR)
4370b57cec5SDimitry Andric     .addReg(NewPR.R, 0, NewPR.S);
4380b57cec5SDimitry Andric   MRI->replaceRegWith(OutR.R, NewOutR);
4390b57cec5SDimitry Andric   MI->eraseFromParent();
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   // If the processed instruction was C2_tfrrp (i.e. Rn = Pm; Pk = Rn),
4420b57cec5SDimitry Andric   // then the output will be a predicate register.  Do not visit the
4430b57cec5SDimitry Andric   // users of it.
4440b57cec5SDimitry Andric   if (!isPredReg(NewOutR)) {
4450b57cec5SDimitry Andric     RegisterSubReg R(NewOutR);
4460b57cec5SDimitry Andric     PredGPRs.insert(R);
4470b57cec5SDimitry Andric     processPredicateGPR(R);
4480b57cec5SDimitry Andric   }
4490b57cec5SDimitry Andric   return true;
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric bool HexagonGenPredicate::eliminatePredCopies(MachineFunction &MF) {
4530b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << __func__ << "\n");
4540b57cec5SDimitry Andric   const TargetRegisterClass *PredRC = &Hexagon::PredRegsRegClass;
4550b57cec5SDimitry Andric   bool Changed = false;
4560b57cec5SDimitry Andric   VectOfInst Erase;
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   // First, replace copies
4590b57cec5SDimitry Andric   //   IntR = PredR1
4600b57cec5SDimitry Andric   //   PredR2 = IntR
4610b57cec5SDimitry Andric   // with
4620b57cec5SDimitry Andric   //   PredR2 = PredR1
4630b57cec5SDimitry Andric   // Such sequences can be generated when a copy-into-pred is generated from
4640b57cec5SDimitry Andric   // a gpr register holding a result of a convertible instruction. After
4650b57cec5SDimitry Andric   // the convertible instruction is converted, its predicate result will be
4660b57cec5SDimitry Andric   // copied back into the original gpr.
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
4690b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
4700b57cec5SDimitry Andric       if (MI.getOpcode() != TargetOpcode::COPY)
4710b57cec5SDimitry Andric         continue;
4720b57cec5SDimitry Andric       RegisterSubReg DR = MI.getOperand(0);
4730b57cec5SDimitry Andric       RegisterSubReg SR = MI.getOperand(1);
474e8d8bef9SDimitry Andric       if (!DR.R.isVirtual())
4750b57cec5SDimitry Andric         continue;
476e8d8bef9SDimitry Andric       if (!SR.R.isVirtual())
4770b57cec5SDimitry Andric         continue;
4780b57cec5SDimitry Andric       if (MRI->getRegClass(DR.R) != PredRC)
4790b57cec5SDimitry Andric         continue;
4800b57cec5SDimitry Andric       if (MRI->getRegClass(SR.R) != PredRC)
4810b57cec5SDimitry Andric         continue;
4820b57cec5SDimitry Andric       assert(!DR.S && !SR.S && "Unexpected subregister");
4830b57cec5SDimitry Andric       MRI->replaceRegWith(DR.R, SR.R);
4840b57cec5SDimitry Andric       Erase.insert(&MI);
4850b57cec5SDimitry Andric       Changed = true;
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric 
4894824e7fdSDimitry Andric   for (MachineInstr *MI : Erase)
4904824e7fdSDimitry Andric     MI->eraseFromParent();
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   return Changed;
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric bool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {
4960b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
4970b57cec5SDimitry Andric     return false;
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
5000b57cec5SDimitry Andric   TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
5010b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
5020b57cec5SDimitry Andric   PredGPRs.clear();
5030b57cec5SDimitry Andric   PUsers.clear();
5040b57cec5SDimitry Andric   G2P.clear();
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric   bool Changed = false;
5070b57cec5SDimitry Andric   collectPredicateGPR(MF);
50804eeddc0SDimitry Andric   for (const RegisterSubReg &R : PredGPRs)
50904eeddc0SDimitry Andric     processPredicateGPR(R);
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   bool Again;
5120b57cec5SDimitry Andric   do {
5130b57cec5SDimitry Andric     Again = false;
5140b57cec5SDimitry Andric     VectOfInst Processed, Copy;
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric     Copy = PUsers;
5174824e7fdSDimitry Andric     for (MachineInstr *MI : Copy) {
5180b57cec5SDimitry Andric       bool Done = convertToPredForm(MI);
5190b57cec5SDimitry Andric       if (Done) {
5200b57cec5SDimitry Andric         Processed.insert(MI);
5210b57cec5SDimitry Andric         Again = true;
5220b57cec5SDimitry Andric       }
5230b57cec5SDimitry Andric     }
5240b57cec5SDimitry Andric     Changed |= Again;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric     auto Done = [Processed] (MachineInstr *MI) -> bool {
5270b57cec5SDimitry Andric       return Processed.count(MI);
5280b57cec5SDimitry Andric     };
5290b57cec5SDimitry Andric     PUsers.remove_if(Done);
5300b57cec5SDimitry Andric   } while (Again);
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   Changed |= eliminatePredCopies(MF);
5330b57cec5SDimitry Andric   return Changed;
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric FunctionPass *llvm::createHexagonGenPredicate() {
5370b57cec5SDimitry Andric   return new HexagonGenPredicate();
5380b57cec5SDimitry Andric }
539