1 //===- HexagonVExtract.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // This pass will replace multiple occurrences of V6_extractw from the same 9 // vector register with a combination of a vector store and scalar loads. 10 //===----------------------------------------------------------------------===// 11 12 #include "Hexagon.h" 13 #include "HexagonInstrInfo.h" 14 #include "HexagonRegisterInfo.h" 15 #include "HexagonSubtarget.h" 16 #include "llvm/ADT/SmallVector.h" 17 #include "llvm/PassSupport.h" 18 #include "llvm/CodeGen/MachineBasicBlock.h" 19 #include "llvm/CodeGen/MachineFunction.h" 20 #include "llvm/CodeGen/MachineFunctionPass.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineRegisterInfo.h" 23 #include "llvm/Support/CommandLine.h" 24 25 #include <map> 26 27 using namespace llvm; 28 29 static cl::opt<unsigned> VExtractThreshold("hexagon-vextract-threshold", 30 cl::Hidden, cl::ZeroOrMore, cl::init(1), 31 cl::desc("Threshold for triggering vextract replacement")); 32 33 namespace llvm { 34 void initializeHexagonVExtractPass(PassRegistry& Registry); 35 FunctionPass *createHexagonVExtract(); 36 } 37 38 namespace { 39 class HexagonVExtract : public MachineFunctionPass { 40 public: 41 static char ID; 42 HexagonVExtract() : MachineFunctionPass(ID) {} 43 44 StringRef getPassName() const override { 45 return "Hexagon optimize vextract"; 46 } 47 void getAnalysisUsage(AnalysisUsage &AU) const override { 48 MachineFunctionPass::getAnalysisUsage(AU); 49 } 50 bool runOnMachineFunction(MachineFunction &MF) override; 51 52 private: 53 const HexagonSubtarget *HST = nullptr; 54 const HexagonInstrInfo *HII = nullptr; 55 56 unsigned genElemLoad(MachineInstr *ExtI, unsigned BaseR, 57 MachineRegisterInfo &MRI); 58 }; 59 60 char HexagonVExtract::ID = 0; 61 } 62 63 INITIALIZE_PASS(HexagonVExtract, "hexagon-vextract", 64 "Hexagon optimize vextract", false, false) 65 66 unsigned HexagonVExtract::genElemLoad(MachineInstr *ExtI, unsigned BaseR, 67 MachineRegisterInfo &MRI) { 68 MachineBasicBlock &ExtB = *ExtI->getParent(); 69 DebugLoc DL = ExtI->getDebugLoc(); 70 Register ElemR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass); 71 72 Register ExtIdxR = ExtI->getOperand(2).getReg(); 73 unsigned ExtIdxS = ExtI->getOperand(2).getSubReg(); 74 75 // Simplified check for a compile-time constant value of ExtIdxR. 76 if (ExtIdxS == 0) { 77 MachineInstr *DI = MRI.getVRegDef(ExtIdxR); 78 if (DI->getOpcode() == Hexagon::A2_tfrsi) { 79 unsigned V = DI->getOperand(1).getImm(); 80 V &= (HST->getVectorLength()-1) & -4u; 81 82 BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::L2_loadri_io), ElemR) 83 .addReg(BaseR) 84 .addImm(V); 85 return ElemR; 86 } 87 } 88 89 Register IdxR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass); 90 BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::A2_andir), IdxR) 91 .add(ExtI->getOperand(2)) 92 .addImm(-4); 93 BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::L4_loadri_rr), ElemR) 94 .addReg(BaseR) 95 .addReg(IdxR) 96 .addImm(0); 97 return ElemR; 98 } 99 100 bool HexagonVExtract::runOnMachineFunction(MachineFunction &MF) { 101 HST = &MF.getSubtarget<HexagonSubtarget>(); 102 HII = HST->getInstrInfo(); 103 const auto &HRI = *HST->getRegisterInfo(); 104 MachineRegisterInfo &MRI = MF.getRegInfo(); 105 MachineFrameInfo &MFI = MF.getFrameInfo(); 106 std::map<unsigned, SmallVector<MachineInstr*,4>> VExtractMap; 107 bool Changed = false; 108 109 for (MachineBasicBlock &MBB : MF) { 110 for (MachineInstr &MI : MBB) { 111 unsigned Opc = MI.getOpcode(); 112 if (Opc != Hexagon::V6_extractw) 113 continue; 114 Register VecR = MI.getOperand(1).getReg(); 115 VExtractMap[VecR].push_back(&MI); 116 } 117 } 118 119 for (auto &P : VExtractMap) { 120 unsigned VecR = P.first; 121 if (P.second.size() <= VExtractThreshold) 122 continue; 123 124 const auto &VecRC = *MRI.getRegClass(VecR); 125 int FI = MFI.CreateSpillStackObject(HRI.getSpillSize(VecRC), 126 HRI.getSpillAlignment(VecRC)); 127 MachineInstr *DefI = MRI.getVRegDef(VecR); 128 MachineBasicBlock::iterator At = std::next(DefI->getIterator()); 129 MachineBasicBlock &DefB = *DefI->getParent(); 130 unsigned StoreOpc = VecRC.getID() == Hexagon::HvxVRRegClassID 131 ? Hexagon::V6_vS32b_ai 132 : Hexagon::PS_vstorerw_ai; 133 BuildMI(DefB, At, DefI->getDebugLoc(), HII->get(StoreOpc)) 134 .addFrameIndex(FI) 135 .addImm(0) 136 .addReg(VecR); 137 138 unsigned VecSize = HRI.getRegSizeInBits(VecRC) / 8; 139 140 for (MachineInstr *ExtI : P.second) { 141 assert(ExtI->getOpcode() == Hexagon::V6_extractw); 142 unsigned SR = ExtI->getOperand(1).getSubReg(); 143 assert(ExtI->getOperand(1).getReg() == VecR); 144 145 MachineBasicBlock &ExtB = *ExtI->getParent(); 146 DebugLoc DL = ExtI->getDebugLoc(); 147 Register BaseR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass); 148 BuildMI(ExtB, ExtI, DL, HII->get(Hexagon::PS_fi), BaseR) 149 .addFrameIndex(FI) 150 .addImm(SR == 0 ? 0 : VecSize/2); 151 152 unsigned ElemR = genElemLoad(ExtI, BaseR, MRI); 153 Register ExtR = ExtI->getOperand(0).getReg(); 154 MRI.replaceRegWith(ExtR, ElemR); 155 ExtB.erase(ExtI); 156 Changed = true; 157 } 158 } 159 160 return Changed; 161 } 162 163 FunctionPass *llvm::createHexagonVExtract() { 164 return new HexagonVExtract(); 165 } 166