1 //===- R600MergeVectorRegisters.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 // 9 /// \file 10 /// This pass merges inputs of swizzeable instructions into vector sharing 11 /// common data and/or have enough undef subreg using swizzle abilities. 12 /// 13 /// For instance let's consider the following pseudo code : 14 /// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3 15 /// ... 16 /// %7 = REG_SEQ %1, sub0, %3, sub1, undef, sub2, %4, sub3 17 /// (swizzable Inst) %7, SwizzleMask : sub0, sub1, sub2, sub3 18 /// 19 /// is turned into : 20 /// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3 21 /// ... 22 /// %7 = INSERT_SUBREG %4, sub3 23 /// (swizzable Inst) %7, SwizzleMask : sub0, sub2, sub1, sub3 24 /// 25 /// This allow regalloc to reduce register pressure for vector registers and 26 /// to reduce MOV count. 27 //===----------------------------------------------------------------------===// 28 29 #include "MCTargetDesc/R600MCTargetDesc.h" 30 #include "R600.h" 31 #include "R600Defines.h" 32 #include "R600Subtarget.h" 33 #include "llvm/CodeGen/MachineDominators.h" 34 #include "llvm/CodeGen/MachineLoopInfo.h" 35 36 using namespace llvm; 37 38 #define DEBUG_TYPE "vec-merger" 39 40 static bool isImplicitlyDef(MachineRegisterInfo &MRI, Register Reg) { 41 if (Reg.isPhysical()) 42 return false; 43 const MachineInstr *MI = MRI.getUniqueVRegDef(Reg); 44 return MI && MI->isImplicitDef(); 45 } 46 47 namespace { 48 49 class RegSeqInfo { 50 public: 51 MachineInstr *Instr; 52 DenseMap<Register, unsigned> RegToChan; 53 std::vector<Register> UndefReg; 54 55 RegSeqInfo(MachineRegisterInfo &MRI, MachineInstr *MI) : Instr(MI) { 56 assert(MI->getOpcode() == R600::REG_SEQUENCE); 57 for (unsigned i = 1, e = Instr->getNumOperands(); i < e; i+=2) { 58 MachineOperand &MO = Instr->getOperand(i); 59 unsigned Chan = Instr->getOperand(i + 1).getImm(); 60 if (isImplicitlyDef(MRI, MO.getReg())) 61 UndefReg.emplace_back(Chan); 62 else 63 RegToChan[MO.getReg()] = Chan; 64 } 65 } 66 67 RegSeqInfo() = default; 68 69 bool operator==(const RegSeqInfo &RSI) const { 70 return RSI.Instr == Instr; 71 } 72 }; 73 74 class R600VectorRegMerger : public MachineFunctionPass { 75 private: 76 using InstructionSetMap = DenseMap<unsigned, std::vector<MachineInstr *>>; 77 78 MachineRegisterInfo *MRI; 79 const R600InstrInfo *TII = nullptr; 80 DenseMap<MachineInstr *, RegSeqInfo> PreviousRegSeq; 81 InstructionSetMap PreviousRegSeqByReg; 82 InstructionSetMap PreviousRegSeqByUndefCount; 83 84 bool canSwizzle(const MachineInstr &MI) const; 85 bool areAllUsesSwizzeable(Register Reg) const; 86 void SwizzleInput(MachineInstr &, 87 const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const; 88 bool tryMergeVector(const RegSeqInfo *Untouched, RegSeqInfo *ToMerge, 89 std::vector<std::pair<unsigned, unsigned>> &Remap) const; 90 bool tryMergeUsingCommonSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI, 91 std::vector<std::pair<unsigned, unsigned>> &RemapChan); 92 bool tryMergeUsingFreeSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI, 93 std::vector<std::pair<unsigned, unsigned>> &RemapChan); 94 MachineInstr *RebuildVector(RegSeqInfo *MI, const RegSeqInfo *BaseVec, 95 const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const; 96 void RemoveMI(MachineInstr *); 97 void trackRSI(const RegSeqInfo &RSI); 98 99 public: 100 static char ID; 101 102 R600VectorRegMerger() : MachineFunctionPass(ID) {} 103 104 void getAnalysisUsage(AnalysisUsage &AU) const override { 105 AU.setPreservesCFG(); 106 AU.addRequired<MachineDominatorTreeWrapperPass>(); 107 AU.addPreserved<MachineDominatorTreeWrapperPass>(); 108 AU.addRequired<MachineLoopInfoWrapperPass>(); 109 AU.addPreserved<MachineLoopInfoWrapperPass>(); 110 MachineFunctionPass::getAnalysisUsage(AU); 111 } 112 113 MachineFunctionProperties getRequiredProperties() const override { 114 return MachineFunctionProperties() 115 .set(MachineFunctionProperties::Property::IsSSA); 116 } 117 118 StringRef getPassName() const override { 119 return "R600 Vector Registers Merge Pass"; 120 } 121 122 bool runOnMachineFunction(MachineFunction &Fn) override; 123 }; 124 125 } // end anonymous namespace 126 127 INITIALIZE_PASS_BEGIN(R600VectorRegMerger, DEBUG_TYPE, 128 "R600 Vector Reg Merger", false, false) 129 INITIALIZE_PASS_END(R600VectorRegMerger, DEBUG_TYPE, 130 "R600 Vector Reg Merger", false, false) 131 132 char R600VectorRegMerger::ID = 0; 133 134 char &llvm::R600VectorRegMergerID = R600VectorRegMerger::ID; 135 136 bool R600VectorRegMerger::canSwizzle(const MachineInstr &MI) 137 const { 138 if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) 139 return true; 140 switch (MI.getOpcode()) { 141 case R600::R600_ExportSwz: 142 case R600::EG_ExportSwz: 143 return true; 144 default: 145 return false; 146 } 147 } 148 149 bool R600VectorRegMerger::tryMergeVector(const RegSeqInfo *Untouched, 150 RegSeqInfo *ToMerge, std::vector< std::pair<unsigned, unsigned>> &Remap) 151 const { 152 unsigned CurrentUndexIdx = 0; 153 for (auto &It : ToMerge->RegToChan) { 154 DenseMap<Register, unsigned>::const_iterator PosInUntouched = 155 Untouched->RegToChan.find(It.first); 156 if (PosInUntouched != Untouched->RegToChan.end()) { 157 Remap.emplace_back(It.second, (*PosInUntouched).second); 158 continue; 159 } 160 if (CurrentUndexIdx >= Untouched->UndefReg.size()) 161 return false; 162 Remap.emplace_back(It.second, Untouched->UndefReg[CurrentUndexIdx++]); 163 } 164 165 return true; 166 } 167 168 static 169 unsigned getReassignedChan( 170 const std::vector<std::pair<unsigned, unsigned>> &RemapChan, 171 unsigned Chan) { 172 for (const auto &J : RemapChan) { 173 if (J.first == Chan) 174 return J.second; 175 } 176 llvm_unreachable("Chan wasn't reassigned"); 177 } 178 179 MachineInstr *R600VectorRegMerger::RebuildVector( 180 RegSeqInfo *RSI, const RegSeqInfo *BaseRSI, 181 const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const { 182 Register Reg = RSI->Instr->getOperand(0).getReg(); 183 MachineBasicBlock::iterator Pos = RSI->Instr; 184 MachineBasicBlock &MBB = *Pos->getParent(); 185 DebugLoc DL = Pos->getDebugLoc(); 186 187 Register SrcVec = BaseRSI->Instr->getOperand(0).getReg(); 188 DenseMap<Register, unsigned> UpdatedRegToChan = BaseRSI->RegToChan; 189 std::vector<Register> UpdatedUndef = BaseRSI->UndefReg; 190 for (const auto &It : RSI->RegToChan) { 191 Register DstReg = MRI->createVirtualRegister(&R600::R600_Reg128RegClass); 192 unsigned SubReg = It.first; 193 unsigned Swizzle = It.second; 194 unsigned Chan = getReassignedChan(RemapChan, Swizzle); 195 196 MachineInstr *Tmp = BuildMI(MBB, Pos, DL, TII->get(R600::INSERT_SUBREG), 197 DstReg) 198 .addReg(SrcVec) 199 .addReg(SubReg) 200 .addImm(Chan); 201 UpdatedRegToChan[SubReg] = Chan; 202 std::vector<Register>::iterator ChanPos = llvm::find(UpdatedUndef, Chan); 203 if (ChanPos != UpdatedUndef.end()) 204 UpdatedUndef.erase(ChanPos); 205 assert(!is_contained(UpdatedUndef, Chan) && 206 "UpdatedUndef shouldn't contain Chan more than once!"); 207 LLVM_DEBUG(dbgs() << " ->"; Tmp->dump();); 208 (void)Tmp; 209 SrcVec = DstReg; 210 } 211 MachineInstr *NewMI = 212 BuildMI(MBB, Pos, DL, TII->get(R600::COPY), Reg).addReg(SrcVec); 213 LLVM_DEBUG(dbgs() << " ->"; NewMI->dump();); 214 215 LLVM_DEBUG(dbgs() << " Updating Swizzle:\n"); 216 for (MachineRegisterInfo::use_instr_iterator It = MRI->use_instr_begin(Reg), 217 E = MRI->use_instr_end(); It != E; ++It) { 218 LLVM_DEBUG(dbgs() << " "; (*It).dump(); dbgs() << " ->"); 219 SwizzleInput(*It, RemapChan); 220 LLVM_DEBUG((*It).dump()); 221 } 222 RSI->Instr->eraseFromParent(); 223 224 // Update RSI 225 RSI->Instr = NewMI; 226 RSI->RegToChan = UpdatedRegToChan; 227 RSI->UndefReg = UpdatedUndef; 228 229 return NewMI; 230 } 231 232 void R600VectorRegMerger::RemoveMI(MachineInstr *MI) { 233 for (auto &It : PreviousRegSeqByReg) { 234 std::vector<MachineInstr *> &MIs = It.second; 235 MIs.erase(llvm::find(MIs, MI), MIs.end()); 236 } 237 for (auto &It : PreviousRegSeqByUndefCount) { 238 std::vector<MachineInstr *> &MIs = It.second; 239 MIs.erase(llvm::find(MIs, MI), MIs.end()); 240 } 241 } 242 243 void R600VectorRegMerger::SwizzleInput(MachineInstr &MI, 244 const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const { 245 unsigned Offset; 246 if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) 247 Offset = 2; 248 else 249 Offset = 3; 250 for (unsigned i = 0; i < 4; i++) { 251 unsigned Swizzle = MI.getOperand(i + Offset).getImm() + 1; 252 for (const auto &J : RemapChan) { 253 if (J.first == Swizzle) { 254 MI.getOperand(i + Offset).setImm(J.second - 1); 255 break; 256 } 257 } 258 } 259 } 260 261 bool R600VectorRegMerger::areAllUsesSwizzeable(Register Reg) const { 262 return llvm::all_of(MRI->use_instructions(Reg), 263 [&](const MachineInstr &MI) { return canSwizzle(MI); }); 264 } 265 266 bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI, 267 RegSeqInfo &CompatibleRSI, 268 std::vector<std::pair<unsigned, unsigned>> &RemapChan) { 269 for (MachineInstr::mop_iterator MOp = RSI.Instr->operands_begin(), 270 MOE = RSI.Instr->operands_end(); MOp != MOE; ++MOp) { 271 if (!MOp->isReg()) 272 continue; 273 if (PreviousRegSeqByReg[MOp->getReg()].empty()) 274 continue; 275 for (MachineInstr *MI : PreviousRegSeqByReg[MOp->getReg()]) { 276 CompatibleRSI = PreviousRegSeq[MI]; 277 if (RSI == CompatibleRSI) 278 continue; 279 if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan)) 280 return true; 281 } 282 } 283 return false; 284 } 285 286 bool R600VectorRegMerger::tryMergeUsingFreeSlot(RegSeqInfo &RSI, 287 RegSeqInfo &CompatibleRSI, 288 std::vector<std::pair<unsigned, unsigned>> &RemapChan) { 289 unsigned NeededUndefs = 4 - RSI.UndefReg.size(); 290 if (PreviousRegSeqByUndefCount[NeededUndefs].empty()) 291 return false; 292 std::vector<MachineInstr *> &MIs = 293 PreviousRegSeqByUndefCount[NeededUndefs]; 294 CompatibleRSI = PreviousRegSeq[MIs.back()]; 295 tryMergeVector(&CompatibleRSI, &RSI, RemapChan); 296 return true; 297 } 298 299 void R600VectorRegMerger::trackRSI(const RegSeqInfo &RSI) { 300 for (DenseMap<Register, unsigned>::const_iterator 301 It = RSI.RegToChan.begin(), E = RSI.RegToChan.end(); It != E; ++It) { 302 PreviousRegSeqByReg[(*It).first].push_back(RSI.Instr); 303 } 304 PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr); 305 PreviousRegSeq[RSI.Instr] = RSI; 306 } 307 308 bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) { 309 if (skipFunction(Fn.getFunction())) 310 return false; 311 312 const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 313 TII = ST.getInstrInfo(); 314 MRI = &Fn.getRegInfo(); 315 316 for (MachineBasicBlock &MB : Fn) { 317 PreviousRegSeq.clear(); 318 PreviousRegSeqByReg.clear(); 319 PreviousRegSeqByUndefCount.clear(); 320 321 for (MachineBasicBlock::iterator MII = MB.begin(), MIIE = MB.end(); 322 MII != MIIE; ++MII) { 323 MachineInstr &MI = *MII; 324 if (MI.getOpcode() != R600::REG_SEQUENCE) { 325 if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) { 326 Register Reg = MI.getOperand(1).getReg(); 327 for (MachineRegisterInfo::def_instr_iterator 328 It = MRI->def_instr_begin(Reg), E = MRI->def_instr_end(); 329 It != E; ++It) { 330 RemoveMI(&(*It)); 331 } 332 } 333 continue; 334 } 335 336 RegSeqInfo RSI(*MRI, &MI); 337 338 // All uses of MI are swizzeable ? 339 Register Reg = MI.getOperand(0).getReg(); 340 if (!areAllUsesSwizzeable(Reg)) 341 continue; 342 343 LLVM_DEBUG({ 344 dbgs() << "Trying to optimize "; 345 MI.dump(); 346 }); 347 348 RegSeqInfo CandidateRSI; 349 std::vector<std::pair<unsigned, unsigned>> RemapChan; 350 LLVM_DEBUG(dbgs() << "Using common slots...\n";); 351 if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) { 352 // Remove CandidateRSI mapping 353 RemoveMI(CandidateRSI.Instr); 354 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan); 355 trackRSI(RSI); 356 continue; 357 } 358 LLVM_DEBUG(dbgs() << "Using free slots...\n";); 359 RemapChan.clear(); 360 if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) { 361 RemoveMI(CandidateRSI.Instr); 362 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan); 363 trackRSI(RSI); 364 continue; 365 } 366 //Failed to merge 367 trackRSI(RSI); 368 } 369 } 370 return false; 371 } 372 373 llvm::FunctionPass *llvm::createR600VectorRegMerger() { 374 return new R600VectorRegMerger(); 375 } 376