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) {
154 Untouched->RegToChan.find(It.first);
155 if (PosInUntouched != Untouched->RegToChan.end()) {
156 Remap.emplace_back(It.second, (*PosInUntouched).second);
159 if (CurrentUndexIdx >= Untouched->UndefReg.size())
161 Remap.emplace_back(It.second, Untouched->UndefReg[CurrentUndexIdx++]);
169 const std::vector<std::pair<unsigned, unsigned>> &RemapChan,
171 for (
const auto &J : RemapChan) {
178MachineInstr *R600VectorRegMerger::RebuildVector(
179 RegSeqInfo *RSI,
const RegSeqInfo *BaseRSI,
180 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const {
183 MachineBasicBlock &
MBB = *Pos->getParent();
187 DenseMap<Register, unsigned> UpdatedRegToChan = BaseRSI->RegToChan;
188 std::vector<Register> UpdatedUndef = BaseRSI->UndefReg;
189 for (
const auto &It : RSI->RegToChan) {
190 Register DstReg =
MRI->createVirtualRegister(&R600::R600_Reg128RegClass);
191 unsigned SubReg = It.first;
195 MachineInstr *Tmp =
BuildMI(
MBB, Pos,
DL,
TII->get(R600::INSERT_SUBREG),
200 UpdatedRegToChan[
SubReg] = Chan;
201 std::vector<Register>::iterator ChanPos =
llvm::find(UpdatedUndef, Chan);
202 if (ChanPos != UpdatedUndef.end())
203 UpdatedUndef.erase(ChanPos);
205 "UpdatedUndef shouldn't contain Chan more than once!");
210 MachineInstr *NewMI =
216 E =
MRI->use_instr_end(); It !=
E; ++It) {
218 SwizzleInput(*It, RemapChan);
225 RSI->RegToChan = UpdatedRegToChan;
226 RSI->UndefReg = UpdatedUndef;
231void R600VectorRegMerger::RemoveMI(MachineInstr *
MI) {
232 for (
auto &It : PreviousRegSeqByReg) {
233 std::vector<MachineInstr *> &MIs = It.second;
236 for (
auto &It : PreviousRegSeqByUndefCount) {
237 std::vector<MachineInstr *> &MIs = It.second;
242void R600VectorRegMerger::SwizzleInput(MachineInstr &
MI,
243 const std::vector<std::pair<unsigned, unsigned>> &RemapChan)
const {
249 for (
unsigned i = 0; i < 4; i++) {
251 for (
const auto &J : RemapChan) {
253 MI.getOperand(i +
Offset).setImm(J.second - 1);
260bool R600VectorRegMerger::areAllUsesSwizzeable(
Register Reg)
const {
262 [&](
const MachineInstr &
MI) { return canSwizzle(MI); });
265bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI,
266 RegSeqInfo &CompatibleRSI,
267 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
272 auto &Insts = PreviousRegSeqByReg[MOp->getReg()];
275 for (MachineInstr *
MI : Insts) {
276 CompatibleRSI = PreviousRegSeq[
MI];
277 if (RSI == CompatibleRSI)
279 if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan))
286bool R600VectorRegMerger::tryMergeUsingFreeSlot(RegSeqInfo &RSI,
287 RegSeqInfo &CompatibleRSI,
288 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
289 unsigned NeededUndefs = 4 - RSI.UndefReg.size();
290 std::vector<MachineInstr *> &MIs =
291 PreviousRegSeqByUndefCount[NeededUndefs];
294 CompatibleRSI = PreviousRegSeq[MIs.back()];
295 tryMergeVector(&CompatibleRSI, &RSI, RemapChan);
299void 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);
304 PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr);
305 PreviousRegSeq[RSI.Instr] = RSI;
308bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) {
313 TII =
ST.getInstrInfo();
316 for (MachineBasicBlock &MB : Fn) {
317 PreviousRegSeq.
clear();
318 PreviousRegSeqByReg.clear();
319 PreviousRegSeqByUndefCount.clear();
322 MII != MIIE; ++MII) {
323 MachineInstr &
MI = *MII;
324 if (
MI.getOpcode() != R600::REG_SEQUENCE) {
327 for (MachineInstr &
DefMI :
MRI->def_instructions(
Reg))
333 RegSeqInfo RSI(*
MRI, &
MI);
337 if (!areAllUsesSwizzeable(
Reg))
341 dbgs() <<
"Trying to optimize ";
345 RegSeqInfo CandidateRSI;
346 std::vector<std::pair<unsigned, unsigned>> RemapChan;
348 if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) {
350 RemoveMI(CandidateRSI.Instr);
351 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
357 if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) {
358 RemoveMI(CandidateRSI.Instr);
359 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
371 return new R600VectorRegMerger();
unsigned const MachineRegisterInfo * MRI
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register 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 eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
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,...
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