38#define DEBUG_TYPE "vec-merger"
44 return MI &&
MI->isImplicitDef();
52 DenseMap<Register, unsigned> RegToChan;
53 std::vector<Register> UndefReg;
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();
61 UndefReg.emplace_back(Chan);
63 RegToChan[MO.
getReg()] = Chan;
67 RegSeqInfo() =
default;
70 return RSI.Instr == Instr;
76 using InstructionSetMap = DenseMap<unsigned, std::vector<MachineInstr *>>;
78 MachineRegisterInfo *MRI;
79 const R600InstrInfo *TII =
nullptr;
80 DenseMap<MachineInstr *, RegSeqInfo> PreviousRegSeq;
81 InstructionSetMap PreviousRegSeqByReg;
82 InstructionSetMap PreviousRegSeqByUndefCount;
84 bool canSwizzle(
const MachineInstr &
MI)
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);
102 R600VectorRegMerger() : MachineFunctionPass(ID) {}
104 void getAnalysisUsage(AnalysisUsage &AU)
const override {
113 MachineFunctionProperties getRequiredProperties()
const override {
114 return MachineFunctionProperties().setIsSSA();
117 StringRef getPassName()
const override {
118 return "R600 Vector Registers Merge Pass";
121 bool runOnMachineFunction(MachineFunction &Fn)
override;
127 "R600 Vector Reg Merger",
false,
false)
131char R600VectorRegMerger::
ID = 0;
139 switch (
MI.getOpcode()) {
140 case R600::R600_ExportSwz:
141 case R600::EG_ExportSwz:
148bool R600VectorRegMerger::tryMergeVector(
const RegSeqInfo *Untouched,
149 RegSeqInfo *ToMerge, std::vector< std::pair<unsigned, unsigned>> &Remap)
151 unsigned CurrentUndexIdx = 0;
152 for (
auto &It : ToMerge->RegToChan) {
153 auto PosInUntouched = Untouched->RegToChan.find(It.first);
154 if (PosInUntouched != Untouched->RegToChan.end()) {
155 Remap.emplace_back(It.second, (*PosInUntouched).second);
158 if (CurrentUndexIdx >= Untouched->UndefReg.size())
160 Remap.emplace_back(It.second, Untouched->UndefReg[CurrentUndexIdx++]);
168 const std::vector<std::pair<unsigned, unsigned>> &RemapChan,
170 for (
const auto &J : RemapChan) {
177MachineInstr *R600VectorRegMerger::RebuildVector(
178 RegSeqInfo *RSI,
const RegSeqInfo *BaseRSI,
179 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const {
182 MachineBasicBlock &
MBB = *Pos->getParent();
186 DenseMap<Register, unsigned> UpdatedRegToChan = BaseRSI->RegToChan;
187 std::vector<Register> UpdatedUndef = BaseRSI->UndefReg;
188 for (
const auto &It : RSI->RegToChan) {
190 unsigned SubReg = It.first;
194 MachineInstr *Tmp =
BuildMI(
MBB, Pos,
DL,
TII->get(R600::INSERT_SUBREG),
199 UpdatedRegToChan[SubReg] = Chan;
200 std::vector<Register>::iterator ChanPos =
llvm::find(UpdatedUndef, Chan);
201 if (ChanPos != UpdatedUndef.end())
202 UpdatedUndef.erase(ChanPos);
204 "UpdatedUndef shouldn't contain Chan more than once!");
209 MachineInstr *NewMI =
217 SwizzleInput(*It, RemapChan);
224 RSI->RegToChan = std::move(UpdatedRegToChan);
225 RSI->UndefReg = std::move(UpdatedUndef);
230void R600VectorRegMerger::RemoveMI(MachineInstr *
MI) {
231 for (
auto &It : PreviousRegSeqByReg) {
232 std::vector<MachineInstr *> &MIs = It.second;
235 for (
auto &It : PreviousRegSeqByUndefCount) {
236 std::vector<MachineInstr *> &MIs = It.second;
241void R600VectorRegMerger::SwizzleInput(MachineInstr &
MI,
242 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const {
248 for (
unsigned i = 0; i < 4; i++) {
250 for (
const auto &J : RemapChan) {
252 MI.getOperand(i +
Offset).setImm(J.second - 1);
259bool R600VectorRegMerger::areAllUsesSwizzeable(
Register Reg)
const {
261 [&](
const MachineInstr &
MI) { return canSwizzle(MI); });
264bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI,
265 RegSeqInfo &CompatibleRSI,
266 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
271 auto &Insts = PreviousRegSeqByReg[MOp->getReg()];
274 for (MachineInstr *
MI : Insts) {
275 CompatibleRSI = PreviousRegSeq[
MI];
276 if (RSI == CompatibleRSI)
278 if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan))
285bool R600VectorRegMerger::tryMergeUsingFreeSlot(RegSeqInfo &RSI,
286 RegSeqInfo &CompatibleRSI,
287 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
288 unsigned NeededUndefs = 4 - RSI.UndefReg.size();
289 std::vector<MachineInstr *> &MIs =
290 PreviousRegSeqByUndefCount[NeededUndefs];
293 CompatibleRSI = PreviousRegSeq[MIs.back()];
294 tryMergeVector(&CompatibleRSI, &RSI, RemapChan);
298void R600VectorRegMerger::trackRSI(
const RegSeqInfo &RSI) {
299 for (DenseMap<Register, unsigned>::const_iterator
300 It = RSI.RegToChan.begin(),
E = RSI.RegToChan.end(); It !=
E; ++It) {
301 PreviousRegSeqByReg[(*It).first].push_back(RSI.Instr);
303 PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr);
304 PreviousRegSeq[RSI.Instr] = RSI;
307bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) {
312 TII =
ST.getInstrInfo();
315 for (MachineBasicBlock &MB : Fn) {
316 PreviousRegSeq.
clear();
317 PreviousRegSeqByReg.clear();
318 PreviousRegSeqByUndefCount.clear();
321 MII != MIIE; ++MII) {
322 MachineInstr &
MI = *MII;
323 if (
MI.getOpcode() != R600::REG_SEQUENCE) {
332 RegSeqInfo RSI(*MRI, &
MI);
336 if (!areAllUsesSwizzeable(
Reg))
340 dbgs() <<
"Trying to optimize ";
344 RegSeqInfo CandidateRSI;
345 std::vector<std::pair<unsigned, unsigned>> RemapChan;
347 if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) {
349 RemoveMI(CandidateRSI.Instr);
350 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
356 if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) {
357 RemoveMI(CandidateRSI.Instr);
358 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
370 return new R600VectorRegMerger();
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Promote Memory to Register
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned > > Src, R600InstrInfo::BankSwizzle Swz)
Provides R600 specific target descriptions.
static unsigned getReassignedChan(const std::vector< std::pair< unsigned, unsigned > > &RemapChan, unsigned Chan)
static bool isImplicitlyDef(MachineRegisterInfo &MRI, Register Reg)
AMDGPU R600 specific subclass of TargetSubtarget.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
mop_iterator operands_begin()
mop_iterator operands_end()
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
iterator_range< def_instr_iterator > def_instructions(Register Reg) const
use_instr_iterator use_instr_begin(Register RegNo) const
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static use_instr_iterator use_instr_end()
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
Wrapper class representing virtual and physical registers.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createR600VectorRegMerger()
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
char & R600VectorRegMergerID