LLVM: lib/Target/AMDGPU/R600OptimizeVectorRegisters.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
35
36using namespace llvm;
37
38#define DEBUG_TYPE "vec-merger"
39
41 if (Reg.isPhysical())
42 return false;
44 return MI && MI->isImplicitDef();
45}
46
47namespace {
48
49class RegSeqInfo {
50public:
51 MachineInstr *Instr;
52 DenseMap<Register, unsigned> RegToChan;
53 std::vector UndefReg;
54
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);
62 else
63 RegToChan[MO.getReg()] = Chan;
64 }
65 }
66
67 RegSeqInfo() = default;
68
69 bool operator==(const RegSeqInfo &RSI) const {
70 return RSI.Instr == Instr;
71 }
72};
73
75private:
76 using InstructionSetMap = DenseMap<unsigned, std::vector<MachineInstr *>>;
77
78 MachineRegisterInfo *MRI;
79 const R600InstrInfo *TII = nullptr;
80 DenseMap<MachineInstr *, RegSeqInfo> PreviousRegSeq;
81 InstructionSetMap PreviousRegSeqByReg;
82 InstructionSetMap PreviousRegSeqByUndefCount;
83
84 bool canSwizzle(const MachineInstr &MI) const;
85 bool areAllUsesSwizzeable(Register Reg) 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);
98
99public:
100 static char ID;
101
102 R600VectorRegMerger() : MachineFunctionPass(ID) {}
103
104 void getAnalysisUsage(AnalysisUsage &AU) const override {
106 AU.addRequired();
107 AU.addPreserved();
108 AU.addRequired();
109 AU.addPreserved();
111 }
112
113 MachineFunctionProperties getRequiredProperties() const override {
114 return MachineFunctionProperties().setIsSSA();
115 }
116
117 StringRef getPassName() const override {
118 return "R600 Vector Registers Merge Pass";
119 }
120
121 bool runOnMachineFunction(MachineFunction &Fn) override;
122};
123
124}
125
127 "R600 Vector Reg Merger", false, false)
130
131char R600VectorRegMerger::ID = 0;
132
134
136 const {
138 return true;
139 switch (MI.getOpcode()) {
140 case R600::R600_ExportSwz:
141 case R600::EG_ExportSwz:
142 return true;
143 default:
144 return false;
145 }
146}
147
148bool R600VectorRegMerger::tryMergeVector(const RegSeqInfo *Untouched,
149 RegSeqInfo *ToMerge, std::vector< std::pair<unsigned, unsigned>> &Remap)
150 const {
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);
157 continue;
158 }
159 if (CurrentUndexIdx >= Untouched->UndefReg.size())
160 return false;
161 Remap.emplace_back(It.second, Untouched->UndefReg[CurrentUndexIdx++]);
162 }
163
164 return true;
165}
166
167static
169 const std::vector<std::pair<unsigned, unsigned>> &RemapChan,
170 unsigned Chan) {
171 for (const auto &J : RemapChan) {
172 if (J.first == Chan)
173 return J.second;
174 }
176}
177
178MachineInstr *R600VectorRegMerger::RebuildVector(
179 RegSeqInfo *RSI, const RegSeqInfo *BaseRSI,
180 const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const {
183 MachineBasicBlock &MBB = *Pos->getParent();
185
187 DenseMap<Register, unsigned> UpdatedRegToChan = BaseRSI->RegToChan;
188 std::vector UpdatedUndef = BaseRSI->UndefReg;
189 for (const auto &It : RSI->RegToChan) {
190 Register DstReg = MRI->createVirtualRegister(&R600::R600_Reg128RegClass);
191 unsigned SubReg = It.first;
192 unsigned Swizzle = It.second;
194
195 MachineInstr *Tmp = BuildMI(MBB, Pos, DL, TII->get(R600::INSERT_SUBREG),
196 DstReg)
200 UpdatedRegToChan[SubReg] = Chan;
201 std::vector::iterator ChanPos = llvm::find(UpdatedUndef, Chan);
202 if (ChanPos != UpdatedUndef.end())
203 UpdatedUndef.erase(ChanPos);
205 "UpdatedUndef shouldn't contain Chan more than once!");
207 (void)Tmp;
208 SrcVec = DstReg;
209 }
210 MachineInstr *NewMI =
213
216 E = MRI->use_instr_end(); It != E; ++It) {
218 SwizzleInput(*It, RemapChan);
220 }
222
223
224 RSI->Instr = NewMI;
225 RSI->RegToChan = UpdatedRegToChan;
226 RSI->UndefReg = UpdatedUndef;
227
228 return NewMI;
229}
230
231void R600VectorRegMerger::RemoveMI(MachineInstr *MI) {
232 for (auto &It : PreviousRegSeqByReg) {
233 std::vector<MachineInstr *> &MIs = It.second;
235 }
236 for (auto &It : PreviousRegSeqByUndefCount) {
237 std::vector<MachineInstr *> &MIs = It.second;
239 }
240}
241
242void R600VectorRegMerger::SwizzleInput(MachineInstr &MI,
243 const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const {
247 else
249 for (unsigned i = 0; i < 4; i++) {
250 unsigned Swizzle = MI.getOperand(i + Offset).getImm() + 1;
251 for (const auto &J : RemapChan) {
252 if (J.first == Swizzle) {
253 MI.getOperand(i + Offset).setImm(J.second - 1);
254 break;
255 }
256 }
257 }
258}
259
260bool R600VectorRegMerger::areAllUsesSwizzeable(Register Reg) const {
262 [&](const MachineInstr &MI) { return canSwizzle(MI); });
263}
264
265bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI,
266 RegSeqInfo &CompatibleRSI,
267 std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
269 MOE = RSI.Instr->operands_end(); MOp != MOE; ++MOp) {
270 if (!MOp->isReg())
271 continue;
272 auto &Insts = PreviousRegSeqByReg[MOp->getReg()];
273 if (Insts.empty())
274 continue;
275 for (MachineInstr *MI : Insts) {
276 CompatibleRSI = PreviousRegSeq[MI];
277 if (RSI == CompatibleRSI)
278 continue;
279 if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan))
280 return true;
281 }
282 }
283 return false;
284}
285
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];
292 if (MIs.empty())
293 return false;
294 CompatibleRSI = PreviousRegSeq[MIs.back()];
295 tryMergeVector(&CompatibleRSI, &RSI, RemapChan);
296 return true;
297}
298
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);
303 }
304 PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr);
305 PreviousRegSeq[RSI.Instr] = RSI;
306}
307
308bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) {
310 return false;
311
312 const R600Subtarget &ST = Fn.getSubtarget();
315
316 for (MachineBasicBlock &MB : Fn) {
317 PreviousRegSeq.clear();
318 PreviousRegSeqByReg.clear();
319 PreviousRegSeqByUndefCount.clear();
320
322 MII != MIIE; ++MII) {
323 MachineInstr &MI = *MII;
324 if (MI.getOpcode() != R600::REG_SEQUENCE) {
327 for (MachineInstr &DefMI : MRI->def_instructions(Reg))
328 RemoveMI(&DefMI);
329 }
330 continue;
331 }
332
333 RegSeqInfo RSI(*MRI, &MI);
334
335
337 if (!areAllUsesSwizzeable(Reg))
338 continue;
339
341 dbgs() << "Trying to optimize ";
343 });
344
345 RegSeqInfo CandidateRSI;
346 std::vector<std::pair<unsigned, unsigned>> RemapChan;
348 if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) {
349
350 RemoveMI(CandidateRSI.Instr);
351 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
352 trackRSI(RSI);
353 continue;
354 }
356 RemapChan.clear();
357 if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) {
358 RemoveMI(CandidateRSI.Instr);
359 MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
360 trackRSI(RSI);
361 continue;
362 }
363
364 trackRSI(RSI);
365 }
366 }
367 return false;
368}
369
371 return new R600VectorRegMerger();
372}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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)
Definition R600OptimizeVectorRegisters.cpp:168
static bool isImplicitlyDef(MachineRegisterInfo &MRI, Register Reg)
Definition R600OptimizeVectorRegisters.cpp:40
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.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
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()
Definition R600OptimizeVectorRegisters.cpp:370
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
char & R600VectorRegMergerID
Definition R600OptimizeVectorRegisters.cpp:133