58 #define DEBUG_TYPE "vec-merger" 64 return (*It).isImplicitDef();
79 std::vector<unsigned> UndefReg;
87 UndefReg.push_back(Chan);
89 RegToChan[MO.
getReg()] = Chan;
93 RegSeqInfo() =
default;
96 return RSI.Instr == Instr;
107 InstructionSetMap PreviousRegSeqByReg;
108 InstructionSetMap PreviousRegSeqByUndefCount;
111 bool areAllUsesSwizzeable(
unsigned Reg)
const;
113 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const;
114 bool tryMergeVector(
const RegSeqInfo *Untouched, RegSeqInfo *ToMerge,
115 std::vector<std::pair<unsigned, unsigned>> &Remap)
const;
116 bool tryMergeUsingCommonSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI,
117 std::vector<std::pair<unsigned, unsigned>> &RemapChan);
118 bool tryMergeUsingFreeSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI,
119 std::vector<std::pair<unsigned, unsigned>> &RemapChan);
120 MachineInstr *RebuildVector(RegSeqInfo *MI,
const RegSeqInfo *BaseVec,
121 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const;
123 void trackRSI(
const RegSeqInfo &RSI);
140 return "R600 Vector Registers Merge Pass";
149 "R600 Vector Reg Merger",
false,
false)
153 char R600VectorRegMerger::
ID = 0;
161 switch (
MI.getOpcode()) {
162 case R600::R600_ExportSwz:
163 case R600::EG_ExportSwz:
170 bool R600VectorRegMerger::tryMergeVector(
const RegSeqInfo *Untouched,
171 RegSeqInfo *ToMerge, std::vector< std::pair<unsigned, unsigned>> &Remap)
173 unsigned CurrentUndexIdx = 0;
175 E = ToMerge->RegToChan.end(); It !=
E; ++It) {
177 Untouched->RegToChan.find((*It).first);
178 if (PosInUntouched != Untouched->RegToChan.end()) {
179 Remap.push_back(std::pair<unsigned, unsigned>
180 ((*It).second, (*PosInUntouched).second));
183 if (CurrentUndexIdx >= Untouched->UndefReg.size())
185 Remap.push_back(std::pair<unsigned, unsigned>
186 ((*It).second, Untouched->UndefReg[CurrentUndexIdx++]));
194 const std::vector<std::pair<unsigned, unsigned>> &RemapChan,
196 for (
unsigned j = 0, je = RemapChan.size(); j < je; j++) {
197 if (RemapChan[j].
first == Chan)
198 return RemapChan[j].second;
204 RegSeqInfo *RSI,
const RegSeqInfo *BaseRSI,
205 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const {
206 unsigned Reg = RSI->Instr->getOperand(0).getReg();
211 unsigned SrcVec = BaseRSI->Instr->getOperand(0).getReg();
213 std::vector<unsigned> UpdatedUndef = BaseRSI->UndefReg;
215 E = RSI->RegToChan.end(); It !=
E; ++It) {
216 unsigned DstReg =
MRI->createVirtualRegister(&R600::R600_Reg128RegClass);
217 unsigned SubReg = (*It).first;
218 unsigned Swizzle = (*It).second;
226 UpdatedRegToChan[
SubReg] = Chan;
227 std::vector<unsigned>::iterator ChanPos =
llvm::find(UpdatedUndef, Chan);
228 if (ChanPos != UpdatedUndef.end())
229 UpdatedUndef.erase(ChanPos);
231 "UpdatedUndef shouldn't contain Chan more than once!");
237 BuildMI(MBB, Pos, DL,
TII->get(R600::COPY),
Reg).addReg(SrcVec);
242 E =
MRI->use_instr_end(); It !=
E; ++It) {
244 SwizzleInput(*It, RemapChan);
247 RSI->Instr->eraseFromParent();
251 RSI->RegToChan = UpdatedRegToChan;
252 RSI->UndefReg = UpdatedUndef;
258 for (InstructionSetMap::iterator It = PreviousRegSeqByReg.begin(),
259 E = PreviousRegSeqByReg.end(); It !=
E; ++It) {
260 std::vector<MachineInstr *> &MIs = (*It).second;
263 for (InstructionSetMap::iterator It = PreviousRegSeqByUndefCount.begin(),
264 E = PreviousRegSeqByUndefCount.end(); It !=
E; ++It) {
265 std::vector<MachineInstr *> &MIs = (*It).second;
270 void R600VectorRegMerger::SwizzleInput(
MachineInstr &MI,
271 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const {
277 for (
unsigned i = 0; i < 4; i++) {
279 for (
unsigned j = 0, e = RemapChan.size(); j < e; j++) {
280 if (RemapChan[j].
first == Swizzle) {
288 bool R600VectorRegMerger::areAllUsesSwizzeable(
unsigned Reg)
const {
290 E =
MRI->use_instr_end(); It !=
E; ++It) {
291 if (!canSwizzle(*It))
297 bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI,
298 RegSeqInfo &CompatibleRSI,
299 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
301 MOE = RSI.Instr->operands_end(); MOp != MOE; ++MOp) {
304 if (PreviousRegSeqByReg[MOp->getReg()].empty())
306 for (
MachineInstr *MI : PreviousRegSeqByReg[MOp->getReg()]) {
307 CompatibleRSI = PreviousRegSeq[
MI];
308 if (RSI == CompatibleRSI)
310 if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan))
317 bool R600VectorRegMerger::tryMergeUsingFreeSlot(RegSeqInfo &RSI,
318 RegSeqInfo &CompatibleRSI,
319 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
320 unsigned NeededUndefs = 4 - RSI.UndefReg.size();
321 if (PreviousRegSeqByUndefCount[NeededUndefs].
empty())
323 std::vector<MachineInstr *> &MIs =
324 PreviousRegSeqByUndefCount[NeededUndefs];
325 CompatibleRSI = PreviousRegSeq[MIs.back()];
326 tryMergeVector(&CompatibleRSI, &RSI, RemapChan);
330 void R600VectorRegMerger::trackRSI(
const RegSeqInfo &RSI) {
332 It = RSI.RegToChan.begin(),
E = RSI.RegToChan.end(); It !=
E; ++It) {
333 PreviousRegSeqByReg[(*It).first].push_back(RSI.Instr);
335 PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr);
336 PreviousRegSeq[RSI.Instr] = RSI;
348 MBB != MBBe; ++MBB) {
350 PreviousRegSeq.
clear();
351 PreviousRegSeqByReg.clear();
352 PreviousRegSeqByUndefCount.clear();
355 MII != MIIE; ++MII) {
357 if (MI.
getOpcode() != R600::REG_SEQUENCE) {
361 It =
MRI->def_instr_begin(Reg),
E =
MRI->def_instr_end();
369 RegSeqInfo RSI(*
MRI, &MI);
373 if (!areAllUsesSwizzeable(Reg))
377 dbgs() <<
"Trying to optimize ";
381 RegSeqInfo CandidateRSI;
382 std::vector<std::pair<unsigned, unsigned>> RemapChan;
384 if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) {
386 RemoveMI(CandidateRSI.Instr);
387 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
393 if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) {
394 RemoveMI(CandidateRSI.Instr);
395 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
407 return new R600VectorRegMerger();
INITIALIZE_PASS_BEGIN(R600VectorRegMerger, DEBUG_TYPE, "R600 Vector Reg Merger", false, false) INITIALIZE_PASS_END(R600VectorRegMerger
static bool isImplicitlyDef(MachineRegisterInfo &MRI, unsigned Reg)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
AMDGPU specific subclass of TargetSubtarget.
This class represents lattice values for constants.
Interface definition for R600InstrInfo.
unsigned getReg() const
getReg - Returns the register number.
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned >> Src, R600InstrInfo::BankSwizzle Swz)
static const AMDGPUSubtarget & get(const MachineFunction &MF)
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
defusechain_iterator - This class provides iterator support for machine operands in the function that...
char & R600VectorRegMergerID
static def_instr_iterator def_instr_end()
FunctionPass * createR600VectorRegMerger()
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Represent the analysis usage information of a pass.
const R600InstrInfo * getInstrInfo() const override
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
static unsigned getReassignedChan(const std::vector< std::pair< unsigned, unsigned >> &RemapChan, unsigned Chan)
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Iterator for intrusive lists based on ilist_node.
MachineOperand class - Representation of each machine instruction operand.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
def_instr_iterator def_instr_begin(unsigned RegNo) const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides AMDGPU specific target descriptions.
Representation of each machine instruction.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
bool operator==(uint64_t V1, const APInt &V2)
const MachineOperand & getOperand(unsigned i) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool isReserved(unsigned PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.