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