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