10b57cec5SDimitry Andric //===- R600MergeVectorRegisters.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 /// \file 100b57cec5SDimitry Andric /// This pass merges inputs of swizzeable instructions into vector sharing 110b57cec5SDimitry Andric /// common data and/or have enough undef subreg using swizzle abilities. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric /// For instance let's consider the following pseudo code : 140b57cec5SDimitry Andric /// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3 150b57cec5SDimitry Andric /// ... 160b57cec5SDimitry Andric /// %7 = REG_SEQ %1, sub0, %3, sub1, undef, sub2, %4, sub3 170b57cec5SDimitry Andric /// (swizzable Inst) %7, SwizzleMask : sub0, sub1, sub2, sub3 180b57cec5SDimitry Andric /// 190b57cec5SDimitry Andric /// is turned into : 200b57cec5SDimitry Andric /// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3 210b57cec5SDimitry Andric /// ... 220b57cec5SDimitry Andric /// %7 = INSERT_SUBREG %4, sub3 230b57cec5SDimitry Andric /// (swizzable Inst) %7, SwizzleMask : sub0, sub2, sub1, sub3 240b57cec5SDimitry Andric /// 250b57cec5SDimitry Andric /// This allow regalloc to reduce register pressure for vector registers and 260b57cec5SDimitry Andric /// to reduce MOV count. 270b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 280b57cec5SDimitry Andric 29349cc55cSDimitry Andric #include "MCTargetDesc/R600MCTargetDesc.h" 30349cc55cSDimitry Andric #include "R600.h" 31e8d8bef9SDimitry Andric #include "R600Defines.h" 32e8d8bef9SDimitry Andric #include "R600Subtarget.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric #define DEBUG_TYPE "vec-merger" 390b57cec5SDimitry Andric 405ffd83dbSDimitry Andric static bool isImplicitlyDef(MachineRegisterInfo &MRI, Register Reg) { 415ffd83dbSDimitry Andric if (Reg.isPhysical()) 420b57cec5SDimitry Andric return false; 430b57cec5SDimitry Andric const MachineInstr *MI = MRI.getUniqueVRegDef(Reg); 440b57cec5SDimitry Andric return MI && MI->isImplicitDef(); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric namespace { 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric class RegSeqInfo { 500b57cec5SDimitry Andric public: 510b57cec5SDimitry Andric MachineInstr *Instr; 525ffd83dbSDimitry Andric DenseMap<Register, unsigned> RegToChan; 535ffd83dbSDimitry Andric std::vector<Register> UndefReg; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric RegSeqInfo(MachineRegisterInfo &MRI, MachineInstr *MI) : Instr(MI) { 560b57cec5SDimitry Andric assert(MI->getOpcode() == R600::REG_SEQUENCE); 570b57cec5SDimitry Andric for (unsigned i = 1, e = Instr->getNumOperands(); i < e; i+=2) { 580b57cec5SDimitry Andric MachineOperand &MO = Instr->getOperand(i); 590b57cec5SDimitry Andric unsigned Chan = Instr->getOperand(i + 1).getImm(); 600b57cec5SDimitry Andric if (isImplicitlyDef(MRI, MO.getReg())) 61*0fca6ea1SDimitry Andric UndefReg.emplace_back(Chan); 620b57cec5SDimitry Andric else 630b57cec5SDimitry Andric RegToChan[MO.getReg()] = Chan; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric RegSeqInfo() = default; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric bool operator==(const RegSeqInfo &RSI) const { 700b57cec5SDimitry Andric return RSI.Instr == Instr; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric }; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric class R600VectorRegMerger : public MachineFunctionPass { 750b57cec5SDimitry Andric private: 760b57cec5SDimitry Andric using InstructionSetMap = DenseMap<unsigned, std::vector<MachineInstr *>>; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric MachineRegisterInfo *MRI; 790b57cec5SDimitry Andric const R600InstrInfo *TII = nullptr; 800b57cec5SDimitry Andric DenseMap<MachineInstr *, RegSeqInfo> PreviousRegSeq; 810b57cec5SDimitry Andric InstructionSetMap PreviousRegSeqByReg; 820b57cec5SDimitry Andric InstructionSetMap PreviousRegSeqByUndefCount; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric bool canSwizzle(const MachineInstr &MI) const; 855ffd83dbSDimitry Andric bool areAllUsesSwizzeable(Register Reg) const; 860b57cec5SDimitry Andric void SwizzleInput(MachineInstr &, 870b57cec5SDimitry Andric const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const; 880b57cec5SDimitry Andric bool tryMergeVector(const RegSeqInfo *Untouched, RegSeqInfo *ToMerge, 890b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> &Remap) const; 900b57cec5SDimitry Andric bool tryMergeUsingCommonSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI, 910b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> &RemapChan); 920b57cec5SDimitry Andric bool tryMergeUsingFreeSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI, 930b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> &RemapChan); 940b57cec5SDimitry Andric MachineInstr *RebuildVector(RegSeqInfo *MI, const RegSeqInfo *BaseVec, 950b57cec5SDimitry Andric const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const; 960b57cec5SDimitry Andric void RemoveMI(MachineInstr *); 970b57cec5SDimitry Andric void trackRSI(const RegSeqInfo &RSI); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric public: 1000b57cec5SDimitry Andric static char ID; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric R600VectorRegMerger() : MachineFunctionPass(ID) {} 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 1050b57cec5SDimitry Andric AU.setPreservesCFG(); 106*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 107*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 108*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>(); 109*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 1100b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1135ffd83dbSDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 1145ffd83dbSDimitry Andric return MachineFunctionProperties() 1155ffd83dbSDimitry Andric .set(MachineFunctionProperties::Property::IsSSA); 1165ffd83dbSDimitry Andric } 1175ffd83dbSDimitry Andric 1180b57cec5SDimitry Andric StringRef getPassName() const override { 1190b57cec5SDimitry Andric return "R600 Vector Registers Merge Pass"; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric } // end anonymous namespace 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(R600VectorRegMerger, DEBUG_TYPE, 1280b57cec5SDimitry Andric "R600 Vector Reg Merger", false, false) 1290b57cec5SDimitry Andric INITIALIZE_PASS_END(R600VectorRegMerger, DEBUG_TYPE, 1300b57cec5SDimitry Andric "R600 Vector Reg Merger", false, false) 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric char R600VectorRegMerger::ID = 0; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric char &llvm::R600VectorRegMergerID = R600VectorRegMerger::ID; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric bool R600VectorRegMerger::canSwizzle(const MachineInstr &MI) 1370b57cec5SDimitry Andric const { 1380b57cec5SDimitry Andric if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) 1390b57cec5SDimitry Andric return true; 1400b57cec5SDimitry Andric switch (MI.getOpcode()) { 1410b57cec5SDimitry Andric case R600::R600_ExportSwz: 1420b57cec5SDimitry Andric case R600::EG_ExportSwz: 1430b57cec5SDimitry Andric return true; 1440b57cec5SDimitry Andric default: 1450b57cec5SDimitry Andric return false; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric bool R600VectorRegMerger::tryMergeVector(const RegSeqInfo *Untouched, 1500b57cec5SDimitry Andric RegSeqInfo *ToMerge, std::vector< std::pair<unsigned, unsigned>> &Remap) 1510b57cec5SDimitry Andric const { 1520b57cec5SDimitry Andric unsigned CurrentUndexIdx = 0; 1530eae32dcSDimitry Andric for (auto &It : ToMerge->RegToChan) { 1545ffd83dbSDimitry Andric DenseMap<Register, unsigned>::const_iterator PosInUntouched = 1550eae32dcSDimitry Andric Untouched->RegToChan.find(It.first); 1560b57cec5SDimitry Andric if (PosInUntouched != Untouched->RegToChan.end()) { 157*0fca6ea1SDimitry Andric Remap.emplace_back(It.second, (*PosInUntouched).second); 1580b57cec5SDimitry Andric continue; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric if (CurrentUndexIdx >= Untouched->UndefReg.size()) 1610b57cec5SDimitry Andric return false; 162*0fca6ea1SDimitry Andric Remap.emplace_back(It.second, Untouched->UndefReg[CurrentUndexIdx++]); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric return true; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric static 1690b57cec5SDimitry Andric unsigned getReassignedChan( 1700b57cec5SDimitry Andric const std::vector<std::pair<unsigned, unsigned>> &RemapChan, 1710b57cec5SDimitry Andric unsigned Chan) { 1720eae32dcSDimitry Andric for (const auto &J : RemapChan) { 1730eae32dcSDimitry Andric if (J.first == Chan) 1740eae32dcSDimitry Andric return J.second; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric llvm_unreachable("Chan wasn't reassigned"); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric MachineInstr *R600VectorRegMerger::RebuildVector( 1800b57cec5SDimitry Andric RegSeqInfo *RSI, const RegSeqInfo *BaseRSI, 1810b57cec5SDimitry Andric const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const { 1828bcb0991SDimitry Andric Register Reg = RSI->Instr->getOperand(0).getReg(); 1830b57cec5SDimitry Andric MachineBasicBlock::iterator Pos = RSI->Instr; 1840b57cec5SDimitry Andric MachineBasicBlock &MBB = *Pos->getParent(); 1850b57cec5SDimitry Andric DebugLoc DL = Pos->getDebugLoc(); 1860b57cec5SDimitry Andric 1878bcb0991SDimitry Andric Register SrcVec = BaseRSI->Instr->getOperand(0).getReg(); 1885ffd83dbSDimitry Andric DenseMap<Register, unsigned> UpdatedRegToChan = BaseRSI->RegToChan; 1895ffd83dbSDimitry Andric std::vector<Register> UpdatedUndef = BaseRSI->UndefReg; 1900eae32dcSDimitry Andric for (const auto &It : RSI->RegToChan) { 1918bcb0991SDimitry Andric Register DstReg = MRI->createVirtualRegister(&R600::R600_Reg128RegClass); 1920eae32dcSDimitry Andric unsigned SubReg = It.first; 1930eae32dcSDimitry Andric unsigned Swizzle = It.second; 1940b57cec5SDimitry Andric unsigned Chan = getReassignedChan(RemapChan, Swizzle); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric MachineInstr *Tmp = BuildMI(MBB, Pos, DL, TII->get(R600::INSERT_SUBREG), 1970b57cec5SDimitry Andric DstReg) 1980b57cec5SDimitry Andric .addReg(SrcVec) 1990b57cec5SDimitry Andric .addReg(SubReg) 2000b57cec5SDimitry Andric .addImm(Chan); 2010b57cec5SDimitry Andric UpdatedRegToChan[SubReg] = Chan; 2025ffd83dbSDimitry Andric std::vector<Register>::iterator ChanPos = llvm::find(UpdatedUndef, Chan); 2030b57cec5SDimitry Andric if (ChanPos != UpdatedUndef.end()) 2040b57cec5SDimitry Andric UpdatedUndef.erase(ChanPos); 2050b57cec5SDimitry Andric assert(!is_contained(UpdatedUndef, Chan) && 2060b57cec5SDimitry Andric "UpdatedUndef shouldn't contain Chan more than once!"); 2070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " ->"; Tmp->dump();); 2080b57cec5SDimitry Andric (void)Tmp; 2090b57cec5SDimitry Andric SrcVec = DstReg; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric MachineInstr *NewMI = 2120b57cec5SDimitry Andric BuildMI(MBB, Pos, DL, TII->get(R600::COPY), Reg).addReg(SrcVec); 2130b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " ->"; NewMI->dump();); 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Updating Swizzle:\n"); 2160b57cec5SDimitry Andric for (MachineRegisterInfo::use_instr_iterator It = MRI->use_instr_begin(Reg), 2170b57cec5SDimitry Andric E = MRI->use_instr_end(); It != E; ++It) { 2180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " "; (*It).dump(); dbgs() << " ->"); 2190b57cec5SDimitry Andric SwizzleInput(*It, RemapChan); 2200b57cec5SDimitry Andric LLVM_DEBUG((*It).dump()); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric RSI->Instr->eraseFromParent(); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric // Update RSI 2250b57cec5SDimitry Andric RSI->Instr = NewMI; 2260b57cec5SDimitry Andric RSI->RegToChan = UpdatedRegToChan; 2270b57cec5SDimitry Andric RSI->UndefReg = UpdatedUndef; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric return NewMI; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric void R600VectorRegMerger::RemoveMI(MachineInstr *MI) { 2330eae32dcSDimitry Andric for (auto &It : PreviousRegSeqByReg) { 2340eae32dcSDimitry Andric std::vector<MachineInstr *> &MIs = It.second; 2350b57cec5SDimitry Andric MIs.erase(llvm::find(MIs, MI), MIs.end()); 2360b57cec5SDimitry Andric } 2370eae32dcSDimitry Andric for (auto &It : PreviousRegSeqByUndefCount) { 2380eae32dcSDimitry Andric std::vector<MachineInstr *> &MIs = It.second; 2390b57cec5SDimitry Andric MIs.erase(llvm::find(MIs, MI), MIs.end()); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric void R600VectorRegMerger::SwizzleInput(MachineInstr &MI, 2440b57cec5SDimitry Andric const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const { 2450b57cec5SDimitry Andric unsigned Offset; 2460b57cec5SDimitry Andric if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) 2470b57cec5SDimitry Andric Offset = 2; 2480b57cec5SDimitry Andric else 2490b57cec5SDimitry Andric Offset = 3; 2500b57cec5SDimitry Andric for (unsigned i = 0; i < 4; i++) { 2510b57cec5SDimitry Andric unsigned Swizzle = MI.getOperand(i + Offset).getImm() + 1; 2520eae32dcSDimitry Andric for (const auto &J : RemapChan) { 2530eae32dcSDimitry Andric if (J.first == Swizzle) { 2540eae32dcSDimitry Andric MI.getOperand(i + Offset).setImm(J.second - 1); 2550b57cec5SDimitry Andric break; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2615ffd83dbSDimitry Andric bool R600VectorRegMerger::areAllUsesSwizzeable(Register Reg) const { 262*0fca6ea1SDimitry Andric return llvm::all_of(MRI->use_instructions(Reg), 263*0fca6ea1SDimitry Andric [&](const MachineInstr &MI) { return canSwizzle(MI); }); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI, 2670b57cec5SDimitry Andric RegSeqInfo &CompatibleRSI, 2680b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> &RemapChan) { 2690b57cec5SDimitry Andric for (MachineInstr::mop_iterator MOp = RSI.Instr->operands_begin(), 2700b57cec5SDimitry Andric MOE = RSI.Instr->operands_end(); MOp != MOE; ++MOp) { 2710b57cec5SDimitry Andric if (!MOp->isReg()) 2720b57cec5SDimitry Andric continue; 2730b57cec5SDimitry Andric if (PreviousRegSeqByReg[MOp->getReg()].empty()) 2740b57cec5SDimitry Andric continue; 2750b57cec5SDimitry Andric for (MachineInstr *MI : PreviousRegSeqByReg[MOp->getReg()]) { 2760b57cec5SDimitry Andric CompatibleRSI = PreviousRegSeq[MI]; 2770b57cec5SDimitry Andric if (RSI == CompatibleRSI) 2780b57cec5SDimitry Andric continue; 2790b57cec5SDimitry Andric if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan)) 2800b57cec5SDimitry Andric return true; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric return false; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric bool R600VectorRegMerger::tryMergeUsingFreeSlot(RegSeqInfo &RSI, 2870b57cec5SDimitry Andric RegSeqInfo &CompatibleRSI, 2880b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> &RemapChan) { 2890b57cec5SDimitry Andric unsigned NeededUndefs = 4 - RSI.UndefReg.size(); 2900b57cec5SDimitry Andric if (PreviousRegSeqByUndefCount[NeededUndefs].empty()) 2910b57cec5SDimitry Andric return false; 2920b57cec5SDimitry Andric std::vector<MachineInstr *> &MIs = 2930b57cec5SDimitry Andric PreviousRegSeqByUndefCount[NeededUndefs]; 2940b57cec5SDimitry Andric CompatibleRSI = PreviousRegSeq[MIs.back()]; 2950b57cec5SDimitry Andric tryMergeVector(&CompatibleRSI, &RSI, RemapChan); 2960b57cec5SDimitry Andric return true; 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric void R600VectorRegMerger::trackRSI(const RegSeqInfo &RSI) { 3005ffd83dbSDimitry Andric for (DenseMap<Register, unsigned>::const_iterator 3010b57cec5SDimitry Andric It = RSI.RegToChan.begin(), E = RSI.RegToChan.end(); It != E; ++It) { 3020b57cec5SDimitry Andric PreviousRegSeqByReg[(*It).first].push_back(RSI.Instr); 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr); 3050b57cec5SDimitry Andric PreviousRegSeq[RSI.Instr] = RSI; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) { 3090b57cec5SDimitry Andric if (skipFunction(Fn.getFunction())) 3100b57cec5SDimitry Andric return false; 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 3130b57cec5SDimitry Andric TII = ST.getInstrInfo(); 3140b57cec5SDimitry Andric MRI = &Fn.getRegInfo(); 3150b57cec5SDimitry Andric 3164824e7fdSDimitry Andric for (MachineBasicBlock &MB : Fn) { 3170b57cec5SDimitry Andric PreviousRegSeq.clear(); 3180b57cec5SDimitry Andric PreviousRegSeqByReg.clear(); 3190b57cec5SDimitry Andric PreviousRegSeqByUndefCount.clear(); 3200b57cec5SDimitry Andric 3214824e7fdSDimitry Andric for (MachineBasicBlock::iterator MII = MB.begin(), MIIE = MB.end(); 3220b57cec5SDimitry Andric MII != MIIE; ++MII) { 3230b57cec5SDimitry Andric MachineInstr &MI = *MII; 3240b57cec5SDimitry Andric if (MI.getOpcode() != R600::REG_SEQUENCE) { 3250b57cec5SDimitry Andric if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) { 3268bcb0991SDimitry Andric Register Reg = MI.getOperand(1).getReg(); 3270b57cec5SDimitry Andric for (MachineRegisterInfo::def_instr_iterator 3280b57cec5SDimitry Andric It = MRI->def_instr_begin(Reg), E = MRI->def_instr_end(); 3290b57cec5SDimitry Andric It != E; ++It) { 3300b57cec5SDimitry Andric RemoveMI(&(*It)); 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric continue; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric RegSeqInfo RSI(*MRI, &MI); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric // All uses of MI are swizzeable ? 3398bcb0991SDimitry Andric Register Reg = MI.getOperand(0).getReg(); 3400b57cec5SDimitry Andric if (!areAllUsesSwizzeable(Reg)) 3410b57cec5SDimitry Andric continue; 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric LLVM_DEBUG({ 3440b57cec5SDimitry Andric dbgs() << "Trying to optimize "; 3450b57cec5SDimitry Andric MI.dump(); 3460b57cec5SDimitry Andric }); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric RegSeqInfo CandidateRSI; 3490b57cec5SDimitry Andric std::vector<std::pair<unsigned, unsigned>> RemapChan; 3500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Using common slots...\n";); 3510b57cec5SDimitry Andric if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) { 3520b57cec5SDimitry Andric // Remove CandidateRSI mapping 3530b57cec5SDimitry Andric RemoveMI(CandidateRSI.Instr); 3540b57cec5SDimitry Andric MII = RebuildVector(&RSI, &CandidateRSI, RemapChan); 3550b57cec5SDimitry Andric trackRSI(RSI); 3560b57cec5SDimitry Andric continue; 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Using free slots...\n";); 3590b57cec5SDimitry Andric RemapChan.clear(); 3600b57cec5SDimitry Andric if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) { 3610b57cec5SDimitry Andric RemoveMI(CandidateRSI.Instr); 3620b57cec5SDimitry Andric MII = RebuildVector(&RSI, &CandidateRSI, RemapChan); 3630b57cec5SDimitry Andric trackRSI(RSI); 3640b57cec5SDimitry Andric continue; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric //Failed to merge 3670b57cec5SDimitry Andric trackRSI(RSI); 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric return false; 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric llvm::FunctionPass *llvm::createR600VectorRegMerger() { 3740b57cec5SDimitry Andric return new R600VectorRegMerger(); 3750b57cec5SDimitry Andric } 376