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
isImplicitlyDef(MachineRegisterInfo & MRI,Register Reg)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
RegSeqInfo(MachineRegisterInfo & MRI,MachineInstr * MI)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
operator ==(const RegSeqInfo & RSI) const690b57cec5SDimitry 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
R600VectorRegMerger()1020b57cec5SDimitry Andric R600VectorRegMerger() : MachineFunctionPass(ID) {}
1030b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const1040b57cec5SDimitry 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
getRequiredProperties() const1135ffd83dbSDimitry Andric MachineFunctionProperties getRequiredProperties() const override {
1145ffd83dbSDimitry Andric return MachineFunctionProperties()
1155ffd83dbSDimitry Andric .set(MachineFunctionProperties::Property::IsSSA);
1165ffd83dbSDimitry Andric }
1175ffd83dbSDimitry Andric
getPassName() const1180b57cec5SDimitry 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
canSwizzle(const MachineInstr & MI) const1360b57cec5SDimitry 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
tryMergeVector(const RegSeqInfo * Untouched,RegSeqInfo * ToMerge,std::vector<std::pair<unsigned,unsigned>> & Remap) const1490b57cec5SDimitry 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
getReassignedChan(const std::vector<std::pair<unsigned,unsigned>> & RemapChan,unsigned Chan)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
RebuildVector(RegSeqInfo * RSI,const RegSeqInfo * BaseRSI,const std::vector<std::pair<unsigned,unsigned>> & RemapChan) const1790b57cec5SDimitry 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
RemoveMI(MachineInstr * MI)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
SwizzleInput(MachineInstr & MI,const std::vector<std::pair<unsigned,unsigned>> & RemapChan) const2430b57cec5SDimitry 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
areAllUsesSwizzeable(Register Reg) const2615ffd83dbSDimitry 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
tryMergeUsingCommonSlot(RegSeqInfo & RSI,RegSeqInfo & CompatibleRSI,std::vector<std::pair<unsigned,unsigned>> & RemapChan)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
tryMergeUsingFreeSlot(RegSeqInfo & RSI,RegSeqInfo & CompatibleRSI,std::vector<std::pair<unsigned,unsigned>> & RemapChan)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
trackRSI(const RegSeqInfo & RSI)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
runOnMachineFunction(MachineFunction & Fn)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
createR600VectorRegMerger()3730b57cec5SDimitry Andric llvm::FunctionPass *llvm::createR600VectorRegMerger() {
3740b57cec5SDimitry Andric return new R600VectorRegMerger();
3750b57cec5SDimitry Andric }
376