/src/llvm-project/llvm/lib/Target/PowerPC/PPCVSXSwapRemoval.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===----------- PPCVSXSwapRemoval.cpp - Remove VSX LE Swaps -------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===---------------------------------------------------------------------===// |
8 | | // |
9 | | // This pass analyzes vector computations and removes unnecessary |
10 | | // doubleword swaps (xxswapd instructions). This pass is performed |
11 | | // only for little-endian VSX code generation. |
12 | | // |
13 | | // For this specific case, loads and stores of v4i32, v4f32, v2i64, |
14 | | // and v2f64 vectors are inefficient. These are implemented using |
15 | | // the lxvd2x and stxvd2x instructions, which invert the order of |
16 | | // doublewords in a vector register. Thus code generation inserts |
17 | | // an xxswapd after each such load, and prior to each such store. |
18 | | // |
19 | | // The extra xxswapd instructions reduce performance. The purpose |
20 | | // of this pass is to reduce the number of xxswapd instructions |
21 | | // required for correctness. |
22 | | // |
23 | | // The primary insight is that much code that operates on vectors |
24 | | // does not care about the relative order of elements in a register, |
25 | | // so long as the correct memory order is preserved. If we have a |
26 | | // computation where all input values are provided by lxvd2x/xxswapd, |
27 | | // all outputs are stored using xxswapd/lxvd2x, and all intermediate |
28 | | // computations are lane-insensitive (independent of element order), |
29 | | // then all the xxswapd instructions associated with the loads and |
30 | | // stores may be removed without changing observable semantics. |
31 | | // |
32 | | // This pass uses standard equivalence class infrastructure to create |
33 | | // maximal webs of computations fitting the above description. Each |
34 | | // such web is then optimized by removing its unnecessary xxswapd |
35 | | // instructions. |
36 | | // |
37 | | // There are some lane-sensitive operations for which we can still |
38 | | // permit the optimization, provided we modify those operations |
39 | | // accordingly. Such operations are identified as using "special |
40 | | // handling" within this module. |
41 | | // |
42 | | //===---------------------------------------------------------------------===// |
43 | | |
44 | | #include "PPC.h" |
45 | | #include "PPCInstrBuilder.h" |
46 | | #include "PPCInstrInfo.h" |
47 | | #include "PPCTargetMachine.h" |
48 | | #include "llvm/ADT/DenseMap.h" |
49 | | #include "llvm/ADT/EquivalenceClasses.h" |
50 | | #include "llvm/CodeGen/MachineFunctionPass.h" |
51 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
52 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
53 | | #include "llvm/Config/llvm-config.h" |
54 | | #include "llvm/Support/Debug.h" |
55 | | #include "llvm/Support/Format.h" |
56 | | #include "llvm/Support/raw_ostream.h" |
57 | | |
58 | | using namespace llvm; |
59 | | |
60 | | #define DEBUG_TYPE "ppc-vsx-swaps" |
61 | | |
62 | | namespace { |
63 | | |
64 | | // A PPCVSXSwapEntry is created for each machine instruction that |
65 | | // is relevant to a vector computation. |
66 | | struct PPCVSXSwapEntry { |
67 | | // Pointer to the instruction. |
68 | | MachineInstr *VSEMI; |
69 | | |
70 | | // Unique ID (position in the swap vector). |
71 | | int VSEId; |
72 | | |
73 | | // Attributes of this node. |
74 | | unsigned int IsLoad : 1; |
75 | | unsigned int IsStore : 1; |
76 | | unsigned int IsSwap : 1; |
77 | | unsigned int MentionsPhysVR : 1; |
78 | | unsigned int IsSwappable : 1; |
79 | | unsigned int MentionsPartialVR : 1; |
80 | | unsigned int SpecialHandling : 3; |
81 | | unsigned int WebRejected : 1; |
82 | | unsigned int WillRemove : 1; |
83 | | }; |
84 | | |
85 | | enum SHValues { |
86 | | SH_NONE = 0, |
87 | | SH_EXTRACT, |
88 | | SH_INSERT, |
89 | | SH_NOSWAP_LD, |
90 | | SH_NOSWAP_ST, |
91 | | SH_SPLAT, |
92 | | SH_XXPERMDI, |
93 | | SH_COPYWIDEN |
94 | | }; |
95 | | |
96 | | struct PPCVSXSwapRemoval : public MachineFunctionPass { |
97 | | |
98 | | static char ID; |
99 | | const PPCInstrInfo *TII; |
100 | | MachineFunction *MF; |
101 | | MachineRegisterInfo *MRI; |
102 | | |
103 | | // Swap entries are allocated in a vector for better performance. |
104 | | std::vector<PPCVSXSwapEntry> SwapVector; |
105 | | |
106 | | // A mapping is maintained between machine instructions and |
107 | | // their swap entries. The key is the address of the MI. |
108 | | DenseMap<MachineInstr*, int> SwapMap; |
109 | | |
110 | | // Equivalence classes are used to gather webs of related computation. |
111 | | // Swap entries are represented by their VSEId fields. |
112 | | EquivalenceClasses<int> *EC; |
113 | | |
114 | 0 | PPCVSXSwapRemoval() : MachineFunctionPass(ID) { |
115 | 0 | initializePPCVSXSwapRemovalPass(*PassRegistry::getPassRegistry()); |
116 | 0 | } |
117 | | |
118 | | private: |
119 | | // Initialize data structures. |
120 | | void initialize(MachineFunction &MFParm); |
121 | | |
122 | | // Walk the machine instructions to gather vector usage information. |
123 | | // Return true iff vector mentions are present. |
124 | | bool gatherVectorInstructions(); |
125 | | |
126 | | // Add an entry to the swap vector and swap map. |
127 | | int addSwapEntry(MachineInstr *MI, PPCVSXSwapEntry &SwapEntry); |
128 | | |
129 | | // Hunt backwards through COPY and SUBREG_TO_REG chains for a |
130 | | // source register. VecIdx indicates the swap vector entry to |
131 | | // mark as mentioning a physical register if the search leads |
132 | | // to one. |
133 | | unsigned lookThruCopyLike(unsigned SrcReg, unsigned VecIdx); |
134 | | |
135 | | // Generate equivalence classes for related computations (webs). |
136 | | void formWebs(); |
137 | | |
138 | | // Analyze webs and determine those that cannot be optimized. |
139 | | void recordUnoptimizableWebs(); |
140 | | |
141 | | // Record which swap instructions can be safely removed. |
142 | | void markSwapsForRemoval(); |
143 | | |
144 | | // Remove swaps and update other instructions requiring special |
145 | | // handling. Return true iff any changes are made. |
146 | | bool removeSwaps(); |
147 | | |
148 | | // Insert a swap instruction from SrcReg to DstReg at the given |
149 | | // InsertPoint. |
150 | | void insertSwap(MachineInstr *MI, MachineBasicBlock::iterator InsertPoint, |
151 | | unsigned DstReg, unsigned SrcReg); |
152 | | |
153 | | // Update instructions requiring special handling. |
154 | | void handleSpecialSwappables(int EntryIdx); |
155 | | |
156 | | // Dump a description of the entries in the swap vector. |
157 | | void dumpSwapVector(); |
158 | | |
159 | | // Return true iff the given register is in the given class. |
160 | 0 | bool isRegInClass(unsigned Reg, const TargetRegisterClass *RC) { |
161 | 0 | if (Register::isVirtualRegister(Reg)) |
162 | 0 | return RC->hasSubClassEq(MRI->getRegClass(Reg)); |
163 | 0 | return RC->contains(Reg); |
164 | 0 | } |
165 | | |
166 | | // Return true iff the given register is a full vector register. |
167 | 0 | bool isVecReg(unsigned Reg) { |
168 | 0 | return (isRegInClass(Reg, &PPC::VSRCRegClass) || |
169 | 0 | isRegInClass(Reg, &PPC::VRRCRegClass)); |
170 | 0 | } |
171 | | |
172 | | // Return true iff the given register is a partial vector register. |
173 | 0 | bool isScalarVecReg(unsigned Reg) { |
174 | 0 | return (isRegInClass(Reg, &PPC::VSFRCRegClass) || |
175 | 0 | isRegInClass(Reg, &PPC::VSSRCRegClass)); |
176 | 0 | } |
177 | | |
178 | | // Return true iff the given register mentions all or part of a |
179 | | // vector register. Also sets Partial to true if the mention |
180 | | // is for just the floating-point register overlap of the register. |
181 | 0 | bool isAnyVecReg(unsigned Reg, bool &Partial) { |
182 | 0 | if (isScalarVecReg(Reg)) |
183 | 0 | Partial = true; |
184 | 0 | return isScalarVecReg(Reg) || isVecReg(Reg); |
185 | 0 | } |
186 | | |
187 | | public: |
188 | | // Main entry point for this pass. |
189 | 0 | bool runOnMachineFunction(MachineFunction &MF) override { |
190 | 0 | if (skipFunction(MF.getFunction())) |
191 | 0 | return false; |
192 | | |
193 | | // If we don't have VSX on the subtarget, don't do anything. |
194 | | // Also, on Power 9 the load and store ops preserve element order and so |
195 | | // the swaps are not required. |
196 | 0 | const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>(); |
197 | 0 | if (!STI.hasVSX() || !STI.needsSwapsForVSXMemOps()) |
198 | 0 | return false; |
199 | | |
200 | 0 | bool Changed = false; |
201 | 0 | initialize(MF); |
202 | |
|
203 | 0 | if (gatherVectorInstructions()) { |
204 | 0 | formWebs(); |
205 | 0 | recordUnoptimizableWebs(); |
206 | 0 | markSwapsForRemoval(); |
207 | 0 | Changed = removeSwaps(); |
208 | 0 | } |
209 | | |
210 | | // FIXME: See the allocation of EC in initialize(). |
211 | 0 | delete EC; |
212 | 0 | return Changed; |
213 | 0 | } |
214 | | }; |
215 | | |
216 | | // Initialize data structures for this pass. In particular, clear the |
217 | | // swap vector and allocate the equivalence class mapping before |
218 | | // processing each function. |
219 | 0 | void PPCVSXSwapRemoval::initialize(MachineFunction &MFParm) { |
220 | 0 | MF = &MFParm; |
221 | 0 | MRI = &MF->getRegInfo(); |
222 | 0 | TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); |
223 | | |
224 | | // An initial vector size of 256 appears to work well in practice. |
225 | | // Small/medium functions with vector content tend not to incur a |
226 | | // reallocation at this size. Three of the vector tests in |
227 | | // projects/test-suite reallocate, which seems like a reasonable rate. |
228 | 0 | const int InitialVectorSize(256); |
229 | 0 | SwapVector.clear(); |
230 | 0 | SwapVector.reserve(InitialVectorSize); |
231 | | |
232 | | // FIXME: Currently we allocate EC each time because we don't have |
233 | | // access to the set representation on which to call clear(). Should |
234 | | // consider adding a clear() method to the EquivalenceClasses class. |
235 | 0 | EC = new EquivalenceClasses<int>; |
236 | 0 | } |
237 | | |
238 | | // Create an entry in the swap vector for each instruction that mentions |
239 | | // a full vector register, recording various characteristics of the |
240 | | // instructions there. |
241 | 0 | bool PPCVSXSwapRemoval::gatherVectorInstructions() { |
242 | 0 | bool RelevantFunction = false; |
243 | |
|
244 | 0 | for (MachineBasicBlock &MBB : *MF) { |
245 | 0 | for (MachineInstr &MI : MBB) { |
246 | |
|
247 | 0 | if (MI.isDebugInstr()) |
248 | 0 | continue; |
249 | | |
250 | 0 | bool RelevantInstr = false; |
251 | 0 | bool Partial = false; |
252 | |
|
253 | 0 | for (const MachineOperand &MO : MI.operands()) { |
254 | 0 | if (!MO.isReg()) |
255 | 0 | continue; |
256 | 0 | Register Reg = MO.getReg(); |
257 | | // All operands need to be checked because there are instructions that |
258 | | // operate on a partial register and produce a full register (such as |
259 | | // XXPERMDIs). |
260 | 0 | if (isAnyVecReg(Reg, Partial)) |
261 | 0 | RelevantInstr = true; |
262 | 0 | } |
263 | |
|
264 | 0 | if (!RelevantInstr) |
265 | 0 | continue; |
266 | | |
267 | 0 | RelevantFunction = true; |
268 | | |
269 | | // Create a SwapEntry initialized to zeros, then fill in the |
270 | | // instruction and ID fields before pushing it to the back |
271 | | // of the swap vector. |
272 | 0 | PPCVSXSwapEntry SwapEntry{}; |
273 | 0 | int VecIdx = addSwapEntry(&MI, SwapEntry); |
274 | |
|
275 | 0 | switch(MI.getOpcode()) { |
276 | 0 | default: |
277 | | // Unless noted otherwise, an instruction is considered |
278 | | // safe for the optimization. There are a large number of |
279 | | // such true-SIMD instructions (all vector math, logical, |
280 | | // select, compare, etc.). However, if the instruction |
281 | | // mentions a partial vector register and does not have |
282 | | // special handling defined, it is not swappable. |
283 | 0 | if (Partial) |
284 | 0 | SwapVector[VecIdx].MentionsPartialVR = 1; |
285 | 0 | else |
286 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
287 | 0 | break; |
288 | 0 | case PPC::XXPERMDI: { |
289 | | // This is a swap if it is of the form XXPERMDI t, s, s, 2. |
290 | | // Unfortunately, MachineCSE ignores COPY and SUBREG_TO_REG, so we |
291 | | // can also see XXPERMDI t, SUBREG_TO_REG(s), SUBREG_TO_REG(s), 2, |
292 | | // for example. We have to look through chains of COPY and |
293 | | // SUBREG_TO_REG to find the real source value for comparison. |
294 | | // If the real source value is a physical register, then mark the |
295 | | // XXPERMDI as mentioning a physical register. |
296 | 0 | int immed = MI.getOperand(3).getImm(); |
297 | 0 | if (immed == 2) { |
298 | 0 | unsigned trueReg1 = lookThruCopyLike(MI.getOperand(1).getReg(), |
299 | 0 | VecIdx); |
300 | 0 | unsigned trueReg2 = lookThruCopyLike(MI.getOperand(2).getReg(), |
301 | 0 | VecIdx); |
302 | 0 | if (trueReg1 == trueReg2) |
303 | 0 | SwapVector[VecIdx].IsSwap = 1; |
304 | 0 | else { |
305 | | // We can still handle these if the two registers are not |
306 | | // identical, by adjusting the form of the XXPERMDI. |
307 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
308 | 0 | SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI; |
309 | 0 | } |
310 | | // This is a doubleword splat if it is of the form |
311 | | // XXPERMDI t, s, s, 0 or XXPERMDI t, s, s, 3. As above we |
312 | | // must look through chains of copy-likes to find the source |
313 | | // register. We turn off the marking for mention of a physical |
314 | | // register, because splatting it is safe; the optimization |
315 | | // will not swap the value in the physical register. Whether |
316 | | // or not the two input registers are identical, we can handle |
317 | | // these by adjusting the form of the XXPERMDI. |
318 | 0 | } else if (immed == 0 || immed == 3) { |
319 | |
|
320 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
321 | 0 | SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI; |
322 | |
|
323 | 0 | unsigned trueReg1 = lookThruCopyLike(MI.getOperand(1).getReg(), |
324 | 0 | VecIdx); |
325 | 0 | unsigned trueReg2 = lookThruCopyLike(MI.getOperand(2).getReg(), |
326 | 0 | VecIdx); |
327 | 0 | if (trueReg1 == trueReg2) |
328 | 0 | SwapVector[VecIdx].MentionsPhysVR = 0; |
329 | |
|
330 | 0 | } else { |
331 | | // We can still handle these by adjusting the form of the XXPERMDI. |
332 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
333 | 0 | SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI; |
334 | 0 | } |
335 | 0 | break; |
336 | 0 | } |
337 | 0 | case PPC::LVX: |
338 | | // Non-permuting loads are currently unsafe. We can use special |
339 | | // handling for this in the future. By not marking these as |
340 | | // IsSwap, we ensure computations containing them will be rejected |
341 | | // for now. |
342 | 0 | SwapVector[VecIdx].IsLoad = 1; |
343 | 0 | break; |
344 | 0 | case PPC::LXVD2X: |
345 | 0 | case PPC::LXVW4X: |
346 | | // Permuting loads are marked as both load and swap, and are |
347 | | // safe for optimization. |
348 | 0 | SwapVector[VecIdx].IsLoad = 1; |
349 | 0 | SwapVector[VecIdx].IsSwap = 1; |
350 | 0 | break; |
351 | 0 | case PPC::LXSDX: |
352 | 0 | case PPC::LXSSPX: |
353 | 0 | case PPC::XFLOADf64: |
354 | 0 | case PPC::XFLOADf32: |
355 | | // A load of a floating-point value into the high-order half of |
356 | | // a vector register is safe, provided that we introduce a swap |
357 | | // following the load, which will be done by the SUBREG_TO_REG |
358 | | // support. So just mark these as safe. |
359 | 0 | SwapVector[VecIdx].IsLoad = 1; |
360 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
361 | 0 | break; |
362 | 0 | case PPC::STVX: |
363 | | // Non-permuting stores are currently unsafe. We can use special |
364 | | // handling for this in the future. By not marking these as |
365 | | // IsSwap, we ensure computations containing them will be rejected |
366 | | // for now. |
367 | 0 | SwapVector[VecIdx].IsStore = 1; |
368 | 0 | break; |
369 | 0 | case PPC::STXVD2X: |
370 | 0 | case PPC::STXVW4X: |
371 | | // Permuting stores are marked as both store and swap, and are |
372 | | // safe for optimization. |
373 | 0 | SwapVector[VecIdx].IsStore = 1; |
374 | 0 | SwapVector[VecIdx].IsSwap = 1; |
375 | 0 | break; |
376 | 0 | case PPC::COPY: |
377 | | // These are fine provided they are moving between full vector |
378 | | // register classes. |
379 | 0 | if (isVecReg(MI.getOperand(0).getReg()) && |
380 | 0 | isVecReg(MI.getOperand(1).getReg())) |
381 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
382 | | // If we have a copy from one scalar floating-point register |
383 | | // to another, we can accept this even if it is a physical |
384 | | // register. The only way this gets involved is if it feeds |
385 | | // a SUBREG_TO_REG, which is handled by introducing a swap. |
386 | 0 | else if (isScalarVecReg(MI.getOperand(0).getReg()) && |
387 | 0 | isScalarVecReg(MI.getOperand(1).getReg())) |
388 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
389 | 0 | break; |
390 | 0 | case PPC::SUBREG_TO_REG: { |
391 | | // These are fine provided they are moving between full vector |
392 | | // register classes. If they are moving from a scalar |
393 | | // floating-point class to a vector class, we can handle those |
394 | | // as well, provided we introduce a swap. It is generally the |
395 | | // case that we will introduce fewer swaps than we remove, but |
396 | | // (FIXME) a cost model could be used. However, introduced |
397 | | // swaps could potentially be CSEd, so this is not trivial. |
398 | 0 | if (isVecReg(MI.getOperand(0).getReg()) && |
399 | 0 | isVecReg(MI.getOperand(2).getReg())) |
400 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
401 | 0 | else if (isVecReg(MI.getOperand(0).getReg()) && |
402 | 0 | isScalarVecReg(MI.getOperand(2).getReg())) { |
403 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
404 | 0 | SwapVector[VecIdx].SpecialHandling = SHValues::SH_COPYWIDEN; |
405 | 0 | } |
406 | 0 | break; |
407 | 0 | } |
408 | 0 | case PPC::VSPLTB: |
409 | 0 | case PPC::VSPLTH: |
410 | 0 | case PPC::VSPLTW: |
411 | 0 | case PPC::XXSPLTW: |
412 | | // Splats are lane-sensitive, but we can use special handling |
413 | | // to adjust the source lane for the splat. |
414 | 0 | SwapVector[VecIdx].IsSwappable = 1; |
415 | 0 | SwapVector[VecIdx].SpecialHandling = SHValues::SH_SPLAT; |
416 | 0 | break; |
417 | | // The presence of the following lane-sensitive operations in a |
418 | | // web will kill the optimization, at least for now. For these |
419 | | // we do nothing, causing the optimization to fail. |
420 | | // FIXME: Some of these could be permitted with special handling, |
421 | | // and will be phased in as time permits. |
422 | | // FIXME: There is no simple and maintainable way to express a set |
423 | | // of opcodes having a common attribute in TableGen. Should this |
424 | | // change, this is a prime candidate to use such a mechanism. |
425 | 0 | case PPC::INLINEASM: |
426 | 0 | case PPC::INLINEASM_BR: |
427 | 0 | case PPC::EXTRACT_SUBREG: |
428 | 0 | case PPC::INSERT_SUBREG: |
429 | 0 | case PPC::COPY_TO_REGCLASS: |
430 | 0 | case PPC::LVEBX: |
431 | 0 | case PPC::LVEHX: |
432 | 0 | case PPC::LVEWX: |
433 | 0 | case PPC::LVSL: |
434 | 0 | case PPC::LVSR: |
435 | 0 | case PPC::LVXL: |
436 | 0 | case PPC::STVEBX: |
437 | 0 | case PPC::STVEHX: |
438 | 0 | case PPC::STVEWX: |
439 | 0 | case PPC::STVXL: |
440 | | // We can handle STXSDX and STXSSPX similarly to LXSDX and LXSSPX, |
441 | | // by adding special handling for narrowing copies as well as |
442 | | // widening ones. However, I've experimented with this, and in |
443 | | // practice we currently do not appear to use STXSDX fed by |
444 | | // a narrowing copy from a full vector register. Since I can't |
445 | | // generate any useful test cases, I've left this alone for now. |
446 | 0 | case PPC::STXSDX: |
447 | 0 | case PPC::STXSSPX: |
448 | 0 | case PPC::VCIPHER: |
449 | 0 | case PPC::VCIPHERLAST: |
450 | 0 | case PPC::VMRGHB: |
451 | 0 | case PPC::VMRGHH: |
452 | 0 | case PPC::VMRGHW: |
453 | 0 | case PPC::VMRGLB: |
454 | 0 | case PPC::VMRGLH: |
455 | 0 | case PPC::VMRGLW: |
456 | 0 | case PPC::VMULESB: |
457 | 0 | case PPC::VMULESH: |
458 | 0 | case PPC::VMULESW: |
459 | 0 | case PPC::VMULEUB: |
460 | 0 | case PPC::VMULEUH: |
461 | 0 | case PPC::VMULEUW: |
462 | 0 | case PPC::VMULOSB: |
463 | 0 | case PPC::VMULOSH: |
464 | 0 | case PPC::VMULOSW: |
465 | 0 | case PPC::VMULOUB: |
466 | 0 | case PPC::VMULOUH: |
467 | 0 | case PPC::VMULOUW: |
468 | 0 | case PPC::VNCIPHER: |
469 | 0 | case PPC::VNCIPHERLAST: |
470 | 0 | case PPC::VPERM: |
471 | 0 | case PPC::VPERMXOR: |
472 | 0 | case PPC::VPKPX: |
473 | 0 | case PPC::VPKSHSS: |
474 | 0 | case PPC::VPKSHUS: |
475 | 0 | case PPC::VPKSDSS: |
476 | 0 | case PPC::VPKSDUS: |
477 | 0 | case PPC::VPKSWSS: |
478 | 0 | case PPC::VPKSWUS: |
479 | 0 | case PPC::VPKUDUM: |
480 | 0 | case PPC::VPKUDUS: |
481 | 0 | case PPC::VPKUHUM: |
482 | 0 | case PPC::VPKUHUS: |
483 | 0 | case PPC::VPKUWUM: |
484 | 0 | case PPC::VPKUWUS: |
485 | 0 | case PPC::VPMSUMB: |
486 | 0 | case PPC::VPMSUMD: |
487 | 0 | case PPC::VPMSUMH: |
488 | 0 | case PPC::VPMSUMW: |
489 | 0 | case PPC::VRLB: |
490 | 0 | case PPC::VRLD: |
491 | 0 | case PPC::VRLH: |
492 | 0 | case PPC::VRLW: |
493 | 0 | case PPC::VSBOX: |
494 | 0 | case PPC::VSHASIGMAD: |
495 | 0 | case PPC::VSHASIGMAW: |
496 | 0 | case PPC::VSL: |
497 | 0 | case PPC::VSLDOI: |
498 | 0 | case PPC::VSLO: |
499 | 0 | case PPC::VSR: |
500 | 0 | case PPC::VSRO: |
501 | 0 | case PPC::VSUM2SWS: |
502 | 0 | case PPC::VSUM4SBS: |
503 | 0 | case PPC::VSUM4SHS: |
504 | 0 | case PPC::VSUM4UBS: |
505 | 0 | case PPC::VSUMSWS: |
506 | 0 | case PPC::VUPKHPX: |
507 | 0 | case PPC::VUPKHSB: |
508 | 0 | case PPC::VUPKHSH: |
509 | 0 | case PPC::VUPKHSW: |
510 | 0 | case PPC::VUPKLPX: |
511 | 0 | case PPC::VUPKLSB: |
512 | 0 | case PPC::VUPKLSH: |
513 | 0 | case PPC::VUPKLSW: |
514 | 0 | case PPC::XXMRGHW: |
515 | 0 | case PPC::XXMRGLW: |
516 | | // XXSLDWI could be replaced by a general permute with one of three |
517 | | // permute control vectors (for shift values 1, 2, 3). However, |
518 | | // VPERM has a more restrictive register class. |
519 | 0 | case PPC::XXSLDWI: |
520 | 0 | case PPC::XSCVDPSPN: |
521 | 0 | case PPC::XSCVSPDPN: |
522 | 0 | case PPC::MTVSCR: |
523 | 0 | case PPC::MFVSCR: |
524 | 0 | break; |
525 | 0 | } |
526 | 0 | } |
527 | 0 | } |
528 | | |
529 | 0 | if (RelevantFunction) { |
530 | 0 | LLVM_DEBUG(dbgs() << "Swap vector when first built\n\n"); |
531 | 0 | LLVM_DEBUG(dumpSwapVector()); |
532 | 0 | } |
533 | |
|
534 | 0 | return RelevantFunction; |
535 | 0 | } |
536 | | |
537 | | // Add an entry to the swap vector and swap map, and make a |
538 | | // singleton equivalence class for the entry. |
539 | | int PPCVSXSwapRemoval::addSwapEntry(MachineInstr *MI, |
540 | 0 | PPCVSXSwapEntry& SwapEntry) { |
541 | 0 | SwapEntry.VSEMI = MI; |
542 | 0 | SwapEntry.VSEId = SwapVector.size(); |
543 | 0 | SwapVector.push_back(SwapEntry); |
544 | 0 | EC->insert(SwapEntry.VSEId); |
545 | 0 | SwapMap[MI] = SwapEntry.VSEId; |
546 | 0 | return SwapEntry.VSEId; |
547 | 0 | } |
548 | | |
549 | | // This is used to find the "true" source register for an |
550 | | // XXPERMDI instruction, since MachineCSE does not handle the |
551 | | // "copy-like" operations (Copy and SubregToReg). Returns |
552 | | // the original SrcReg unless it is the target of a copy-like |
553 | | // operation, in which case we chain backwards through all |
554 | | // such operations to the ultimate source register. If a |
555 | | // physical register is encountered, we stop the search and |
556 | | // flag the swap entry indicated by VecIdx (the original |
557 | | // XXPERMDI) as mentioning a physical register. |
558 | | unsigned PPCVSXSwapRemoval::lookThruCopyLike(unsigned SrcReg, |
559 | 0 | unsigned VecIdx) { |
560 | 0 | MachineInstr *MI = MRI->getVRegDef(SrcReg); |
561 | 0 | if (!MI->isCopyLike()) |
562 | 0 | return SrcReg; |
563 | | |
564 | 0 | unsigned CopySrcReg; |
565 | 0 | if (MI->isCopy()) |
566 | 0 | CopySrcReg = MI->getOperand(1).getReg(); |
567 | 0 | else { |
568 | 0 | assert(MI->isSubregToReg() && "bad opcode for lookThruCopyLike"); |
569 | 0 | CopySrcReg = MI->getOperand(2).getReg(); |
570 | 0 | } |
571 | | |
572 | 0 | if (!Register::isVirtualRegister(CopySrcReg)) { |
573 | 0 | if (!isScalarVecReg(CopySrcReg)) |
574 | 0 | SwapVector[VecIdx].MentionsPhysVR = 1; |
575 | 0 | return CopySrcReg; |
576 | 0 | } |
577 | | |
578 | 0 | return lookThruCopyLike(CopySrcReg, VecIdx); |
579 | 0 | } |
580 | | |
581 | | // Generate equivalence classes for related computations (webs) by |
582 | | // def-use relationships of virtual registers. Mention of a physical |
583 | | // register terminates the generation of equivalence classes as this |
584 | | // indicates a use of a parameter, definition of a return value, use |
585 | | // of a value returned from a call, or definition of a parameter to a |
586 | | // call. Computations with physical register mentions are flagged |
587 | | // as such so their containing webs will not be optimized. |
588 | 0 | void PPCVSXSwapRemoval::formWebs() { |
589 | |
|
590 | 0 | LLVM_DEBUG(dbgs() << "\n*** Forming webs for swap removal ***\n\n"); |
591 | |
|
592 | 0 | for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { |
593 | |
|
594 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
595 | |
|
596 | 0 | LLVM_DEBUG(dbgs() << "\n" << SwapVector[EntryIdx].VSEId << " "); |
597 | 0 | LLVM_DEBUG(MI->dump()); |
598 | | |
599 | | // It's sufficient to walk vector uses and join them to their unique |
600 | | // definitions. In addition, check full vector register operands |
601 | | // for physical regs. We exclude partial-vector register operands |
602 | | // because we can handle them if copied to a full vector. |
603 | 0 | for (const MachineOperand &MO : MI->operands()) { |
604 | 0 | if (!MO.isReg()) |
605 | 0 | continue; |
606 | | |
607 | 0 | Register Reg = MO.getReg(); |
608 | 0 | if (!isVecReg(Reg) && !isScalarVecReg(Reg)) |
609 | 0 | continue; |
610 | | |
611 | 0 | if (!Reg.isVirtual()) { |
612 | 0 | if (!(MI->isCopy() && isScalarVecReg(Reg))) |
613 | 0 | SwapVector[EntryIdx].MentionsPhysVR = 1; |
614 | 0 | continue; |
615 | 0 | } |
616 | | |
617 | 0 | if (!MO.isUse()) |
618 | 0 | continue; |
619 | | |
620 | 0 | MachineInstr* DefMI = MRI->getVRegDef(Reg); |
621 | 0 | assert(SwapMap.contains(DefMI) && |
622 | 0 | "Inconsistency: def of vector reg not found in swap map!"); |
623 | 0 | int DefIdx = SwapMap[DefMI]; |
624 | 0 | (void)EC->unionSets(SwapVector[DefIdx].VSEId, |
625 | 0 | SwapVector[EntryIdx].VSEId); |
626 | |
|
627 | 0 | LLVM_DEBUG(dbgs() << format("Unioning %d with %d\n", |
628 | 0 | SwapVector[DefIdx].VSEId, |
629 | 0 | SwapVector[EntryIdx].VSEId)); |
630 | 0 | LLVM_DEBUG(dbgs() << " Def: "); |
631 | 0 | LLVM_DEBUG(DefMI->dump()); |
632 | 0 | } |
633 | 0 | } |
634 | 0 | } |
635 | | |
636 | | // Walk the swap vector entries looking for conditions that prevent their |
637 | | // containing computations from being optimized. When such conditions are |
638 | | // found, mark the representative of the computation's equivalence class |
639 | | // as rejected. |
640 | 0 | void PPCVSXSwapRemoval::recordUnoptimizableWebs() { |
641 | |
|
642 | 0 | LLVM_DEBUG(dbgs() << "\n*** Rejecting webs for swap removal ***\n\n"); |
643 | |
|
644 | 0 | for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { |
645 | 0 | int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); |
646 | | |
647 | | // If representative is already rejected, don't waste further time. |
648 | 0 | if (SwapVector[Repr].WebRejected) |
649 | 0 | continue; |
650 | | |
651 | | // Reject webs containing mentions of physical or partial registers, or |
652 | | // containing operations that we don't know how to handle in a lane- |
653 | | // permuted region. |
654 | 0 | if (SwapVector[EntryIdx].MentionsPhysVR || |
655 | 0 | SwapVector[EntryIdx].MentionsPartialVR || |
656 | 0 | !(SwapVector[EntryIdx].IsSwappable || SwapVector[EntryIdx].IsSwap)) { |
657 | |
|
658 | 0 | SwapVector[Repr].WebRejected = 1; |
659 | |
|
660 | 0 | LLVM_DEBUG( |
661 | 0 | dbgs() << format("Web %d rejected for physreg, partial reg, or not " |
662 | 0 | "swap[pable]\n", |
663 | 0 | Repr)); |
664 | 0 | LLVM_DEBUG(dbgs() << " in " << EntryIdx << ": "); |
665 | 0 | LLVM_DEBUG(SwapVector[EntryIdx].VSEMI->dump()); |
666 | 0 | LLVM_DEBUG(dbgs() << "\n"); |
667 | 0 | } |
668 | | |
669 | | // Reject webs than contain swapping loads that feed something other |
670 | | // than a swap instruction. |
671 | 0 | else if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) { |
672 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
673 | 0 | Register DefReg = MI->getOperand(0).getReg(); |
674 | | |
675 | | // We skip debug instructions in the analysis. (Note that debug |
676 | | // location information is still maintained by this optimization |
677 | | // because it remains on the LXVD2X and STXVD2X instructions after |
678 | | // the XXPERMDIs are removed.) |
679 | 0 | for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { |
680 | 0 | int UseIdx = SwapMap[&UseMI]; |
681 | |
|
682 | 0 | if (!SwapVector[UseIdx].IsSwap || SwapVector[UseIdx].IsLoad || |
683 | 0 | SwapVector[UseIdx].IsStore) { |
684 | |
|
685 | 0 | SwapVector[Repr].WebRejected = 1; |
686 | |
|
687 | 0 | LLVM_DEBUG(dbgs() << format( |
688 | 0 | "Web %d rejected for load not feeding swap\n", Repr)); |
689 | 0 | LLVM_DEBUG(dbgs() << " def " << EntryIdx << ": "); |
690 | 0 | LLVM_DEBUG(MI->dump()); |
691 | 0 | LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); |
692 | 0 | LLVM_DEBUG(UseMI.dump()); |
693 | 0 | LLVM_DEBUG(dbgs() << "\n"); |
694 | 0 | } |
695 | | |
696 | | // It is possible that the load feeds a swap and that swap feeds a |
697 | | // store. In such a case, the code is actually trying to store a swapped |
698 | | // vector. We must reject such webs. |
699 | 0 | if (SwapVector[UseIdx].IsSwap && !SwapVector[UseIdx].IsLoad && |
700 | 0 | !SwapVector[UseIdx].IsStore) { |
701 | 0 | Register SwapDefReg = UseMI.getOperand(0).getReg(); |
702 | 0 | for (MachineInstr &UseOfUseMI : |
703 | 0 | MRI->use_nodbg_instructions(SwapDefReg)) { |
704 | 0 | int UseOfUseIdx = SwapMap[&UseOfUseMI]; |
705 | 0 | if (SwapVector[UseOfUseIdx].IsStore) { |
706 | 0 | SwapVector[Repr].WebRejected = 1; |
707 | 0 | LLVM_DEBUG( |
708 | 0 | dbgs() << format( |
709 | 0 | "Web %d rejected for load/swap feeding a store\n", Repr)); |
710 | 0 | LLVM_DEBUG(dbgs() << " def " << EntryIdx << ": "); |
711 | 0 | LLVM_DEBUG(MI->dump()); |
712 | 0 | LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); |
713 | 0 | LLVM_DEBUG(UseMI.dump()); |
714 | 0 | LLVM_DEBUG(dbgs() << "\n"); |
715 | 0 | } |
716 | 0 | } |
717 | 0 | } |
718 | 0 | } |
719 | | |
720 | | // Reject webs that contain swapping stores that are fed by something |
721 | | // other than a swap instruction. |
722 | 0 | } else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) { |
723 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
724 | 0 | Register UseReg = MI->getOperand(0).getReg(); |
725 | 0 | MachineInstr *DefMI = MRI->getVRegDef(UseReg); |
726 | 0 | Register DefReg = DefMI->getOperand(0).getReg(); |
727 | 0 | int DefIdx = SwapMap[DefMI]; |
728 | |
|
729 | 0 | if (!SwapVector[DefIdx].IsSwap || SwapVector[DefIdx].IsLoad || |
730 | 0 | SwapVector[DefIdx].IsStore) { |
731 | |
|
732 | 0 | SwapVector[Repr].WebRejected = 1; |
733 | |
|
734 | 0 | LLVM_DEBUG(dbgs() << format( |
735 | 0 | "Web %d rejected for store not fed by swap\n", Repr)); |
736 | 0 | LLVM_DEBUG(dbgs() << " def " << DefIdx << ": "); |
737 | 0 | LLVM_DEBUG(DefMI->dump()); |
738 | 0 | LLVM_DEBUG(dbgs() << " use " << EntryIdx << ": "); |
739 | 0 | LLVM_DEBUG(MI->dump()); |
740 | 0 | LLVM_DEBUG(dbgs() << "\n"); |
741 | 0 | } |
742 | | |
743 | | // Ensure all uses of the register defined by DefMI feed store |
744 | | // instructions |
745 | 0 | for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { |
746 | 0 | int UseIdx = SwapMap[&UseMI]; |
747 | |
|
748 | 0 | if (SwapVector[UseIdx].VSEMI->getOpcode() != MI->getOpcode()) { |
749 | 0 | SwapVector[Repr].WebRejected = 1; |
750 | |
|
751 | 0 | LLVM_DEBUG( |
752 | 0 | dbgs() << format( |
753 | 0 | "Web %d rejected for swap not feeding only stores\n", Repr)); |
754 | 0 | LLVM_DEBUG(dbgs() << " def " |
755 | 0 | << " : "); |
756 | 0 | LLVM_DEBUG(DefMI->dump()); |
757 | 0 | LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); |
758 | 0 | LLVM_DEBUG(SwapVector[UseIdx].VSEMI->dump()); |
759 | 0 | LLVM_DEBUG(dbgs() << "\n"); |
760 | 0 | } |
761 | 0 | } |
762 | 0 | } |
763 | 0 | } |
764 | |
|
765 | 0 | LLVM_DEBUG(dbgs() << "Swap vector after web analysis:\n\n"); |
766 | 0 | LLVM_DEBUG(dumpSwapVector()); |
767 | 0 | } |
768 | | |
769 | | // Walk the swap vector entries looking for swaps fed by permuting loads |
770 | | // and swaps that feed permuting stores. If the containing computation |
771 | | // has not been marked rejected, mark each such swap for removal. |
772 | | // (Removal is delayed in case optimization has disturbed the pattern, |
773 | | // such that multiple loads feed the same swap, etc.) |
774 | 0 | void PPCVSXSwapRemoval::markSwapsForRemoval() { |
775 | |
|
776 | 0 | LLVM_DEBUG(dbgs() << "\n*** Marking swaps for removal ***\n\n"); |
777 | |
|
778 | 0 | for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { |
779 | |
|
780 | 0 | if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) { |
781 | 0 | int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); |
782 | |
|
783 | 0 | if (!SwapVector[Repr].WebRejected) { |
784 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
785 | 0 | Register DefReg = MI->getOperand(0).getReg(); |
786 | |
|
787 | 0 | for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { |
788 | 0 | int UseIdx = SwapMap[&UseMI]; |
789 | 0 | SwapVector[UseIdx].WillRemove = 1; |
790 | |
|
791 | 0 | LLVM_DEBUG(dbgs() << "Marking swap fed by load for removal: "); |
792 | 0 | LLVM_DEBUG(UseMI.dump()); |
793 | 0 | } |
794 | 0 | } |
795 | |
|
796 | 0 | } else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) { |
797 | 0 | int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); |
798 | |
|
799 | 0 | if (!SwapVector[Repr].WebRejected) { |
800 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
801 | 0 | Register UseReg = MI->getOperand(0).getReg(); |
802 | 0 | MachineInstr *DefMI = MRI->getVRegDef(UseReg); |
803 | 0 | int DefIdx = SwapMap[DefMI]; |
804 | 0 | SwapVector[DefIdx].WillRemove = 1; |
805 | |
|
806 | 0 | LLVM_DEBUG(dbgs() << "Marking swap feeding store for removal: "); |
807 | 0 | LLVM_DEBUG(DefMI->dump()); |
808 | 0 | } |
809 | |
|
810 | 0 | } else if (SwapVector[EntryIdx].IsSwappable && |
811 | 0 | SwapVector[EntryIdx].SpecialHandling != 0) { |
812 | 0 | int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); |
813 | |
|
814 | 0 | if (!SwapVector[Repr].WebRejected) |
815 | 0 | handleSpecialSwappables(EntryIdx); |
816 | 0 | } |
817 | 0 | } |
818 | 0 | } |
819 | | |
820 | | // Create an xxswapd instruction and insert it prior to the given point. |
821 | | // MI is used to determine basic block and debug loc information. |
822 | | // FIXME: When inserting a swap, we should check whether SrcReg is |
823 | | // defined by another swap: SrcReg = XXPERMDI Reg, Reg, 2; If so, |
824 | | // then instead we should generate a copy from Reg to DstReg. |
825 | | void PPCVSXSwapRemoval::insertSwap(MachineInstr *MI, |
826 | | MachineBasicBlock::iterator InsertPoint, |
827 | 0 | unsigned DstReg, unsigned SrcReg) { |
828 | 0 | BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), |
829 | 0 | TII->get(PPC::XXPERMDI), DstReg) |
830 | 0 | .addReg(SrcReg) |
831 | 0 | .addReg(SrcReg) |
832 | 0 | .addImm(2); |
833 | 0 | } |
834 | | |
835 | | // The identified swap entry requires special handling to allow its |
836 | | // containing computation to be optimized. Perform that handling |
837 | | // here. |
838 | | // FIXME: Additional opportunities will be phased in with subsequent |
839 | | // patches. |
840 | 0 | void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { |
841 | 0 | switch (SwapVector[EntryIdx].SpecialHandling) { |
842 | | |
843 | 0 | default: |
844 | 0 | llvm_unreachable("Unexpected special handling type"); |
845 | | |
846 | | // For splats based on an index into a vector, add N/2 modulo N |
847 | | // to the index, where N is the number of vector elements. |
848 | 0 | case SHValues::SH_SPLAT: { |
849 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
850 | 0 | unsigned NElts; |
851 | |
|
852 | 0 | LLVM_DEBUG(dbgs() << "Changing splat: "); |
853 | 0 | LLVM_DEBUG(MI->dump()); |
854 | |
|
855 | 0 | switch (MI->getOpcode()) { |
856 | 0 | default: |
857 | 0 | llvm_unreachable("Unexpected splat opcode"); |
858 | 0 | case PPC::VSPLTB: NElts = 16; break; |
859 | 0 | case PPC::VSPLTH: NElts = 8; break; |
860 | 0 | case PPC::VSPLTW: |
861 | 0 | case PPC::XXSPLTW: NElts = 4; break; |
862 | 0 | } |
863 | | |
864 | 0 | unsigned EltNo; |
865 | 0 | if (MI->getOpcode() == PPC::XXSPLTW) |
866 | 0 | EltNo = MI->getOperand(2).getImm(); |
867 | 0 | else |
868 | 0 | EltNo = MI->getOperand(1).getImm(); |
869 | |
|
870 | 0 | EltNo = (EltNo + NElts / 2) % NElts; |
871 | 0 | if (MI->getOpcode() == PPC::XXSPLTW) |
872 | 0 | MI->getOperand(2).setImm(EltNo); |
873 | 0 | else |
874 | 0 | MI->getOperand(1).setImm(EltNo); |
875 | |
|
876 | 0 | LLVM_DEBUG(dbgs() << " Into: "); |
877 | 0 | LLVM_DEBUG(MI->dump()); |
878 | 0 | break; |
879 | 0 | } |
880 | | |
881 | | // For an XXPERMDI that isn't handled otherwise, we need to |
882 | | // reverse the order of the operands. If the selector operand |
883 | | // has a value of 0 or 3, we need to change it to 3 or 0, |
884 | | // respectively. Otherwise we should leave it alone. (This |
885 | | // is equivalent to reversing the two bits of the selector |
886 | | // operand and complementing the result.) |
887 | 0 | case SHValues::SH_XXPERMDI: { |
888 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
889 | |
|
890 | 0 | LLVM_DEBUG(dbgs() << "Changing XXPERMDI: "); |
891 | 0 | LLVM_DEBUG(MI->dump()); |
892 | |
|
893 | 0 | unsigned Selector = MI->getOperand(3).getImm(); |
894 | 0 | if (Selector == 0 || Selector == 3) |
895 | 0 | Selector = 3 - Selector; |
896 | 0 | MI->getOperand(3).setImm(Selector); |
897 | |
|
898 | 0 | Register Reg1 = MI->getOperand(1).getReg(); |
899 | 0 | Register Reg2 = MI->getOperand(2).getReg(); |
900 | 0 | MI->getOperand(1).setReg(Reg2); |
901 | 0 | MI->getOperand(2).setReg(Reg1); |
902 | | |
903 | | // We also need to swap kill flag associated with the register. |
904 | 0 | bool IsKill1 = MI->getOperand(1).isKill(); |
905 | 0 | bool IsKill2 = MI->getOperand(2).isKill(); |
906 | 0 | MI->getOperand(1).setIsKill(IsKill2); |
907 | 0 | MI->getOperand(2).setIsKill(IsKill1); |
908 | |
|
909 | 0 | LLVM_DEBUG(dbgs() << " Into: "); |
910 | 0 | LLVM_DEBUG(MI->dump()); |
911 | 0 | break; |
912 | 0 | } |
913 | | |
914 | | // For a copy from a scalar floating-point register to a vector |
915 | | // register, removing swaps will leave the copied value in the |
916 | | // wrong lane. Insert a swap following the copy to fix this. |
917 | 0 | case SHValues::SH_COPYWIDEN: { |
918 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
919 | |
|
920 | 0 | LLVM_DEBUG(dbgs() << "Changing SUBREG_TO_REG: "); |
921 | 0 | LLVM_DEBUG(MI->dump()); |
922 | |
|
923 | 0 | Register DstReg = MI->getOperand(0).getReg(); |
924 | 0 | const TargetRegisterClass *DstRC = MRI->getRegClass(DstReg); |
925 | 0 | Register NewVReg = MRI->createVirtualRegister(DstRC); |
926 | |
|
927 | 0 | MI->getOperand(0).setReg(NewVReg); |
928 | 0 | LLVM_DEBUG(dbgs() << " Into: "); |
929 | 0 | LLVM_DEBUG(MI->dump()); |
930 | |
|
931 | 0 | auto InsertPoint = ++MachineBasicBlock::iterator(MI); |
932 | | |
933 | | // Note that an XXPERMDI requires a VSRC, so if the SUBREG_TO_REG |
934 | | // is copying to a VRRC, we need to be careful to avoid a register |
935 | | // assignment problem. In this case we must copy from VRRC to VSRC |
936 | | // prior to the swap, and from VSRC to VRRC following the swap. |
937 | | // Coalescing will usually remove all this mess. |
938 | 0 | if (DstRC == &PPC::VRRCRegClass) { |
939 | 0 | Register VSRCTmp1 = MRI->createVirtualRegister(&PPC::VSRCRegClass); |
940 | 0 | Register VSRCTmp2 = MRI->createVirtualRegister(&PPC::VSRCRegClass); |
941 | |
|
942 | 0 | BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), |
943 | 0 | TII->get(PPC::COPY), VSRCTmp1) |
944 | 0 | .addReg(NewVReg); |
945 | 0 | LLVM_DEBUG(std::prev(InsertPoint)->dump()); |
946 | |
|
947 | 0 | insertSwap(MI, InsertPoint, VSRCTmp2, VSRCTmp1); |
948 | 0 | LLVM_DEBUG(std::prev(InsertPoint)->dump()); |
949 | |
|
950 | 0 | BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), |
951 | 0 | TII->get(PPC::COPY), DstReg) |
952 | 0 | .addReg(VSRCTmp2); |
953 | 0 | LLVM_DEBUG(std::prev(InsertPoint)->dump()); |
954 | |
|
955 | 0 | } else { |
956 | 0 | insertSwap(MI, InsertPoint, DstReg, NewVReg); |
957 | 0 | LLVM_DEBUG(std::prev(InsertPoint)->dump()); |
958 | 0 | } |
959 | 0 | break; |
960 | 0 | } |
961 | 0 | } |
962 | 0 | } |
963 | | |
964 | | // Walk the swap vector and replace each entry marked for removal with |
965 | | // a copy operation. |
966 | 0 | bool PPCVSXSwapRemoval::removeSwaps() { |
967 | |
|
968 | 0 | LLVM_DEBUG(dbgs() << "\n*** Removing swaps ***\n\n"); |
969 | |
|
970 | 0 | bool Changed = false; |
971 | |
|
972 | 0 | for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { |
973 | 0 | if (SwapVector[EntryIdx].WillRemove) { |
974 | 0 | Changed = true; |
975 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
976 | 0 | MachineBasicBlock *MBB = MI->getParent(); |
977 | 0 | BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(TargetOpcode::COPY), |
978 | 0 | MI->getOperand(0).getReg()) |
979 | 0 | .add(MI->getOperand(1)); |
980 | |
|
981 | 0 | LLVM_DEBUG(dbgs() << format("Replaced %d with copy: ", |
982 | 0 | SwapVector[EntryIdx].VSEId)); |
983 | 0 | LLVM_DEBUG(MI->dump()); |
984 | |
|
985 | 0 | MI->eraseFromParent(); |
986 | 0 | } |
987 | 0 | } |
988 | |
|
989 | 0 | return Changed; |
990 | 0 | } |
991 | | |
992 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
993 | | // For debug purposes, dump the contents of the swap vector. |
994 | 0 | LLVM_DUMP_METHOD void PPCVSXSwapRemoval::dumpSwapVector() { |
995 | |
|
996 | 0 | for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { |
997 | |
|
998 | 0 | MachineInstr *MI = SwapVector[EntryIdx].VSEMI; |
999 | 0 | int ID = SwapVector[EntryIdx].VSEId; |
1000 | |
|
1001 | 0 | dbgs() << format("%6d", ID); |
1002 | 0 | dbgs() << format("%6d", EC->getLeaderValue(ID)); |
1003 | 0 | dbgs() << format(" %bb.%3d", MI->getParent()->getNumber()); |
1004 | 0 | dbgs() << format(" %14s ", TII->getName(MI->getOpcode()).str().c_str()); |
1005 | |
|
1006 | 0 | if (SwapVector[EntryIdx].IsLoad) |
1007 | 0 | dbgs() << "load "; |
1008 | 0 | if (SwapVector[EntryIdx].IsStore) |
1009 | 0 | dbgs() << "store "; |
1010 | 0 | if (SwapVector[EntryIdx].IsSwap) |
1011 | 0 | dbgs() << "swap "; |
1012 | 0 | if (SwapVector[EntryIdx].MentionsPhysVR) |
1013 | 0 | dbgs() << "physreg "; |
1014 | 0 | if (SwapVector[EntryIdx].MentionsPartialVR) |
1015 | 0 | dbgs() << "partialreg "; |
1016 | |
|
1017 | 0 | if (SwapVector[EntryIdx].IsSwappable) { |
1018 | 0 | dbgs() << "swappable "; |
1019 | 0 | switch(SwapVector[EntryIdx].SpecialHandling) { |
1020 | 0 | default: |
1021 | 0 | dbgs() << "special:**unknown**"; |
1022 | 0 | break; |
1023 | 0 | case SH_NONE: |
1024 | 0 | break; |
1025 | 0 | case SH_EXTRACT: |
1026 | 0 | dbgs() << "special:extract "; |
1027 | 0 | break; |
1028 | 0 | case SH_INSERT: |
1029 | 0 | dbgs() << "special:insert "; |
1030 | 0 | break; |
1031 | 0 | case SH_NOSWAP_LD: |
1032 | 0 | dbgs() << "special:load "; |
1033 | 0 | break; |
1034 | 0 | case SH_NOSWAP_ST: |
1035 | 0 | dbgs() << "special:store "; |
1036 | 0 | break; |
1037 | 0 | case SH_SPLAT: |
1038 | 0 | dbgs() << "special:splat "; |
1039 | 0 | break; |
1040 | 0 | case SH_XXPERMDI: |
1041 | 0 | dbgs() << "special:xxpermdi "; |
1042 | 0 | break; |
1043 | 0 | case SH_COPYWIDEN: |
1044 | 0 | dbgs() << "special:copywiden "; |
1045 | 0 | break; |
1046 | 0 | } |
1047 | 0 | } |
1048 | | |
1049 | 0 | if (SwapVector[EntryIdx].WebRejected) |
1050 | 0 | dbgs() << "rejected "; |
1051 | 0 | if (SwapVector[EntryIdx].WillRemove) |
1052 | 0 | dbgs() << "remove "; |
1053 | |
|
1054 | 0 | dbgs() << "\n"; |
1055 | | |
1056 | | // For no-asserts builds. |
1057 | 0 | (void)MI; |
1058 | 0 | (void)ID; |
1059 | 0 | } |
1060 | | |
1061 | 0 | dbgs() << "\n"; |
1062 | 0 | } |
1063 | | #endif |
1064 | | |
1065 | | } // end default namespace |
1066 | | |
1067 | 62 | INITIALIZE_PASS_BEGIN(PPCVSXSwapRemoval, DEBUG_TYPE, |
1068 | 62 | "PowerPC VSX Swap Removal", false, false) |
1069 | 62 | INITIALIZE_PASS_END(PPCVSXSwapRemoval, DEBUG_TYPE, |
1070 | | "PowerPC VSX Swap Removal", false, false) |
1071 | | |
1072 | | char PPCVSXSwapRemoval::ID = 0; |
1073 | | FunctionPass* |
1074 | 0 | llvm::createPPCVSXSwapRemovalPass() { return new PPCVSXSwapRemoval(); } |