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